使用 ML-Pack 进行垃圾邮件分类

[ad_1]
[*]

[*]

介绍

ML-Pack 是一个占用空间很小的 C++ 机器学习库,可以轻松集成到其他程序中。 它是一个积极开发的开源项目,并在 BSD-3 许可证. 由于可以收集大量电子数据,机器学习变得流行起来。 其他一些流行的机器学习框架包括 TensorFlow, 网络, 火炬, 链纳桨桨,但是这些是为比 ML-Pack 更复杂的工作流程而设计的。 在 Fedora, ML-Pack 由其主要开发人员打包 瑞安·科廷. 除了命令行界面,ML-Pack 还绑定了 Python朱莉娅. 在这里,我们将重点介绍命令行界面,因为这对于系统管理员集成到他们的工作流程中可能很有用。

安装

您可以在机器上安装 ML-Pack Fedora 命令行使用

$ sudo dnf -y install mlpack mlpack-bin

您还可以使用……安装文档、开发头文件和 Python 绑定。

$ sudo dnf -y install  mlpack-doc 
mlpack-devel mlpack-python3

尽管在本介绍中不会使用它们。

例子

例如,我们将训练一个机器学习模型来对垃圾短信进行分类。 为了保持本文的简洁,linux 命令将不会被完全解释,但是您可以通过使用 man 命令来了解更多关于它们的信息,例如对于下面使用的命令 first 命令,wget

$ man wget

将为您提供 wget 将从网络下载文件的信息以及您可以使用的选项。

获取数据集

我们将使用 Yudi Wibisono 提供的印度尼西亚语垃圾邮件数据集示例

$ wget https://drive.google.com/file/d/1-stKadfTgJLtYsHWqXhGO3nTjKVFxm_Q/view[*]
$ unzip dataset_sms_spam_bhs_indonesia_v1.zip

预处理数据集

我们将尝试通过消息中某个词的出现次数将消息分类为垃圾邮件或火腿。 我们首先更改文件行结尾,删除缺少标签的第 243 行,然后从数据集中删除标题。 然后,我们将数据拆分为两个文件,标签和消息。 由于标签位于消息的末尾,消息被反转,然后标签被移除并放置在一个文件中。 然后删除该消息并放置在另一个文件中。

$ tr 'r' 'n' < dataset_sms_spam_v1.csv > dataset.txt
$ sed '243d' dataset.txt > dataset1.csv
$ sed '1d' dataset1.csv > dataset.csv
$ rev dataset.csv | cut -c1  | rev > labels.txt
$ rev dataset.csv | cut -c2- | rev > messages.txt
$ rm dataset.csv
$ rm dataset1.csv
$ rm dataset.txt

机器学习适用于数字数据,因此我们将使用标签 1 表示火腿,使用 0 表示垃圾邮件。 该数据集包含三个标签,0、正常短信(火腿)、1、欺诈(垃圾邮件)和 2 促销(垃圾邮件)。 我们将所有垃圾邮件标记为 1,因此促销和欺诈将标记为 1。

$ tr '2' '1' < labels.txt > labels.csv
$ rm labels.txt

下一步是将消息中的所有文本转换为小写,并为简单起见删除标点符号和任何不是空格、行尾或范围 az 的符号(需要扩展此范围的符号以供生产使用)

$ tr '[:upper:]' '[:lower:]' < 
messages.txt > messagesLower.txt
$ tr -Cd 'abcdefghijklmnopqrstuvwxyz n' < 
 messagesLower.txt > messagesLetters.txt
$ rm messagesLower.txt

我们现在获得了所使用的唯一词的排序列表(此步骤可能需要几分钟,因此在您继续计算机上的其他任务时,使用 nice 将其设置为低优先级)。

$ nice -20 xargs -n1 < messagesLetters.txt > temp.txt
$ sort temp.txt > temp2.txt
$ uniq temp2.txt > words.txt
$ rm temp.txt
$ rm temp2.txt

然后我们创建一个矩阵,其中对于每条消息,计算单词出现的频率(维基百科上的更多信息, 这里这里)。 这需要几行代码,因此应保存为“makematrix.sh”的完整脚本如下

#!/bin/bash
declare -a words=()
declare -a letterstartind=()
declare -a letterstart=()
letter=" "
i=0
lettercount=0
while IFS= read -r line; do
 labels[$((i))]=$line
 let "i++"
done < labels.csv
i=0
while IFS= read -r line; do
 words[$((i))]=$line
 firstletter="$( echo $line | head -c 1 )"
 if [ "$firstletter" != "$letter" ]
 then
  letterstartind[$((lettercount))]=$((i))
  letterstart[$((lettercount))]=$firstletter
  letter=$firstletter
  let "lettercount++"
 fi
 let "i++"
done < words.txt
letterstartind[$((lettercount))]=$((i))
echo "Created list of letters"

touch wordfrequency.txt
rm wordfrequency.txt
touch wordfrequency.txt
messagecount=0
messagenum=0
messages="$( wc -l messages.txt )"
i=0
while IFS= read -r line; do
 let "messagenum++"
 declare -a wordcount=()
 declare -a wordarray=()
 read -r -a wordarray <<< "$line"
 let "messagecount++"
 words=${#wordarray[@]}
 for word in "${wordarray[@]}"; do
  startletter="$( echo $word | head -c 1 )"
  j=-1
  while [ $((j)) -lt $((lettercount)) ]; do
   let "j++"
   if [ "$startletter" == "${letterstart[$((j))]}" ]
   then
    mystart=$((j))
   fi
  done
  myend=$((mystart))+1
  j=${letterstartind[$((mystart))]}
  jend=${letterstartind[$((myend))]}
  while [ $((j)) -le $((jend)) ]; do
   wordcount[$((j))]=0
   if [ "$word" == "${words[$((j))]}" ]
   then
    wordcount[$((j))]="$( echo $line | grep -o $word | wc -l )"
   fi
   let "j++"
  done
 done
 for j in "${!wordcount[@]}"; do
  wordcount[$((j))]=$(echo " scale=4; 
  $((${wordcount[$((j))]})) / $((words))" | bc)
 done
 wordcount[$((words))+1]=$((words))
 echo "${wordcount[*]}" >> wordfrequency.txt
 echo "Processed message ""$messagenum"
 let "i++"
done < messagesLetters.txt
# Create csv file
tr ' '  ',' < wordfrequency.txt > data.csv

自从 重击 是一种解释型语言,这个简单的实现最多需要 30 分钟才能完成。 如果在您的主工作站上使用上述 Bash 脚本,请将其作为低优先级任务运行,以便您可以在等待时继续其他工作:

$ nice -20 bash makematrix.sh

脚本运行完毕后,将数据拆分为测试 (30%) 和训练 (70%) 集:

$ mlpack_preprocess_split                      
    --input_file data.csv                     
    --input_labels_file labels.csv            
    --training_file train.data.csv            
    --training_labels_file train.labels.csv   
    --test_file test.data.csv                 
    --test_labels_file test.labels.csv        
    --test_ratio 0.3                          
    --verbose

训练模型

现在训练一个 逻辑回归模型

$ mlpack_logistic_regression 
--training_file train.data.csv 
--labels_file train.labels.csv --lambda 0.1 
--output_model_file lr_model.bin

测试模型

最后,我们通过产生预测来测试我们的模型,

$ mlpack_logistic_regression 
--input_model_file lr_model.bin 
 --test_file test.data.csv 
--output_file lr_predictions.csv

并将预测与准确结果进行比较,

$ export incorrect=$(diff -U 0 lr_predictions.csv 
test.labels.csv | grep '^@@' | wc -l)
$ export tests=$(wc -l < lr_predictions.csv)
$ echo "scale=2;  100 * ( 1 - $((incorrect)) 
/ $((tests)))"  | bc

这给出了大约 90% 的验证率,类似于获得的 这里.

该数据集由大约 50% 的垃圾邮件组成,因此验证率非常好,无需进行太多参数调整。 在典型情况下,数据集是不平衡的,某些类别中的条目多于其他类别。 在这些情况下,可以通过使用几个条目错误预测类来获得良好的验证率。 因此,为了更好地评估这些模型,可以比较垃圾邮件错误分类的数量和火腿错误分类的数量。 在应用程序中特别重要的是误报垃圾邮件结果的数量,因为这些通常不会被传输。 下面的脚本生成了一个混淆矩阵,它可以更好地指示错误分类。 Save 它作为’confusion.sh’

#!/bin/bash
declare -a labels
declare -a lr
i=0
while IFS= read -r line; do
        labels[i]=$line
        let "i++"
done < test.labels.csv
i=0
while IFS= read -r line; do
        lr[i]=$line
        let "i++"
done < lr_predictions.csv
TruePositiveLR=0
FalsePositiveLR=0
TrueZeroLR=0
FalseZeroLR=0
Positive=0
Zero=0
for i in "${!labels[@]}"; do
        if [ "${labels[$i]}" == "1" ]
        then
                let "Positive++"
                if [ "${lr[$i]}" == "1" ] 
                then
                        let "TruePositiveLR++"
                else
                        let "FalseZeroLR++"
                fi
        fi
        if [ "${labels[$i]}" == "0" ]
        then
                let "Zero++"
                if [ "${lr[$i]}" == "0" ]
                then
                        let "TrueZeroLR++"
                else
                        let "FalsePositiveLR++"
                fi
        fi

done
echo "Logistic Regression"
echo "Total spam"  $Positive
echo "Total ham"  $Zero
echo "Confusion matrix"
echo "             Predicted class"
echo "                 Ham | Spam "
echo "              ---------------"
echo " Actual| Ham  | " $TrueZeroLR "|" $FalseZeroLR
echo " class | Spam | " $FalsePositiveLR " |" $TruePositiveLR
echo ""

然后运行脚本

$ bash confusion.sh

你应该得到类似的输出

逻辑回归[*]垃圾邮件总数 183[*]火腿总数 159[*]混淆矩阵

预测类别
火腿 垃圾邮件
实际班级 火腿 128 26
垃圾邮件 31 157

这表明分类的合理水平。 您可以在 ML-Pack 中尝试解决此问题的其他方法包括 朴素贝叶斯, 随机森林, 决策树, AdaBoost感知器.

为了提高错误率,您可以在初始数据集上尝试其他预处理方法。 神经网络可以提供高达 99.95% 的验证率,参见示例 这里, 这里这里. 但是,目前无法在命令行界面上使用这些技术与 ML-Pack,最好在另一篇文章中介绍。

有关 ML-Pack 的更多信息,请参阅 文件.

[*][ad_2]

Related Posts