1 目的
我们的目标是利用机器学习技术,根据样本的特征来有效地过滤和识别垃圾信息。通过训练机器学习模型,我们可以使其学会区分正常信息和垃圾信息的特征,从而自动过滤掉不需要的、无用的或有害的信息,提高信息处理的效率和准确性。这将有助于减少信息过载和提高用户体验,特别是在处理大量信息的场景中,如电子邮件、社交媒体和在线论坛等。通过不断优化模型和提高过滤准确率,我们可以为用户提供更加智能、高效和个性化的信息服务。
2 数据来源
该演示数据来源于: 机器学习和智能系统中心
3 案例演示
3.1 探索数据
3.1.1 读取数据并查看数据类型
运行代码:
1. data<-read.csv("G:\\sms_spam.csv",stringsAsFactors = F) 2. str(data)
结果展示:
> str(data) 'data.frame': 5559 obs. of 2 variables: $ type: chr "ham" "ham" "ham" "spam" ... $ text: chr "Hope you are having a good week. Just checking in" "K..give back my thanks." "Am also doing in cbe only. But have to pay." "complimentary 4 STAR Ibiza Holiday or £10,000 cash needs your URGENT collection. 09066364349 NOW from Landline"| __truncated__ ...
通过运行结果我们可以发现type是字符向量,需要利用将其转化为因子。
3.1.2 修改数据格式
运行代码:
1. data$type<-factor(data$type) 2. str(data$type) 3. table(data$type)
结果展示:
> str(data$type) Factor w/ 2 levels "ham","spam": 1 1 1 2 2 1 1 1 2 1 ... > table(data$type) ham spam 4812 747
由运行结果我们可以观察到,type的数据类型已转为为因子,并且案例中垃圾信息、非来及信息数量分别为747,4812。
3.2 数据预处理
3.2.1 清理和标准化数据
1)加载包及语料库创建
运行代码:
1. library("NLP") #加载包 2. library("tm") #加载包 3. data2<-VCorpus(VectorSource(data$text)) #创建语料库 4. print(data2) #打印语料库信息
结果展示:
<<VCorpus>> Metadata: corpus specific: 0, document level (indexed): 0 Content: documents: 5559
由运行结果显示,新建语料库包含训练数据中5559条短信的每一条短信文档。
2)前两条短信信息概要查看
运行代码:
1. lapply(data2[1:2],as.character)
结果展示:
$`1` [1] "Hope you are having a good week. Just checking in" $`2` [1] "K..give back my thanks."
我们可以通过语料库信息查看每条短信文本信息,需要将这些短信划分为单个单词。
3)单词书写规范
运行代码:
1. data2_clearn<-tm_map(data2,content_transformer(tolower)) 2. #清理后文本信息(删除标点影响或其他影响字符并返回小写) 3. as.character(data2[[1]]) 4. as.character(data2_clearn[[1]]) 5. #对比清理前后数据效果
结果展示:
> as.character(data2[[1]]) [1] "Hope you are having a good week. Just checking in" > as.character(data2_clearn[[1]]) [1] "hope you are having a good week. just checking in"
通过运行结果显示,我们已使用小写字母字符标准化单词。
4)去除文本多余标点及停用词
运行代码:
1. data2_clearn2<-tm_map(data2_clearn,removeNumbers) #去除文本信息中的数字 2. data2_clearn3<-tm_map(data2_clearn2,removeWords,stopwords()) #去除文本信息中的停用词 3. data2_clearn4<-tm_map(data2_clearn3,removePunctuation) 4. #去除文本信息中的标点符号 5. removePunctuation("hello...world") #查看removePunctuation函数效果
结果展示:
[1] "helloworld"
通过运行结果,我们可以发现removePunctuation的函数效果,去除了多余标点符号。
5)提取文本词干及去除多余空格
运行代码:
1. library("SnowballC") #加载包 2. wordStem(c("learning","learn","learned","learns"))#词干提取法测试效果 3. data2_clearn5<-tm_map(data2_clearn4,stemDocument) #提取文本词干内容 4. data2_clearn6<-tm_map(data2_clearn5,stripWhitespace)#去除多余空格 5. lapply(data2[1:3],as.character) 6. lapply(data2_clearn6[1:3],as.character)
结果展示:
$`1` [1] "Hope you are having a good week. Just checking in" $`2` [1] "K..give back my thanks." $`3` [1] "Am also doing in cbe only. But have to pay." > lapply(data2_clearn6[1:3],as.character) $`1` [1] "hope good week just check" $`2` [1] "kgive back thank" $`3` [1] "also cbe pay"
前三条信息是处理前信息,后三条信息为标准化单词后信息内容。
3.2.2 将文本文档拆分成词语
运行代码:
1. data3<-DocumentTermMatrix(data2_clearn6) #将数据转化为单词矩阵(DTM稀疏矩阵) 2. data3 #信息概要
结果展示:
> data3 #信息概要 <<DocumentTermMatrix (documents: 5559, terms: 6553)>> Non-/sparse entries: 42135/36385992 Sparsity : 100% Maximal term length: 40 Weighting : term frequency (tf)
为了将消息拆分为由单个单词组成的组,我们创建DTM稀疏矩阵。
3.2.3 建立训练数据集和测试数据集
运行代码:
1. data3_train<-data3[1:4169,] #创建训练集 2. data3_test<-data3[4170:5559,] #创建测试集 3. data3_train_labels<-data[1:4169,]$type #提取训练集标签 4. data3_test_labels<-data[4170:5559,]$type #提取测试集标签 5. prop.table(table(data3_train_labels)) #训练集垃圾信息比例 6. prop.table(table(data3_test_labels))#测试集垃圾信息比例
结果展示:
> prop.table(table(data3_train_labels)) #训练集垃圾信息比例 data3_train_labels ham spam 0.8647158 0.1352842 > prop.table(table(data3_test_labels))#测试集垃圾信息比例 data3_test_labels ham spam 0.8683453 0.1316547
可以看到,训练集和测试集的垃圾信息数量大约含13%,说明垃圾信息被平均分配在两个数据集。
3.2.4 词云图
1)所有邮件信息词云
运行代码:
1. library("RColorBrewer") 2. library("wordcloud") 3. wordcloud(data2_clearn6,min.freq = 50,random.order = F) #数据处理后词云图
结果展示:
由运行结果显示:数据处理后call、now、get、can等单词出现频率相对较高。
2)垃圾/非垃圾信息词云
运行代码:
1. spam<-subset(data,type=="spam") #提取垃圾信息 2. ham<-subset(data,type=="ham") #提取非垃圾信息 3. wordcloud(spam$text,max.words = 40,scale = c(3,0.5)) #垃圾信息词云图 4. wordcloud(ham$text,max.words = 40,scale = c(3,0.5)) #非垃圾信息词云图
结果展示:
垃圾信息词云图
非垃圾信息词云图 由运行结果显示:数据处理后call、now、can等单词出现频率相对较高,通过对垃圾信息及非垃圾信息词云图我们可以看出,垃圾信息中多包含mobile、free,非垃圾信息多包含just、can等单词。
3.2.5 为频繁出现的单词创建指示特征
1)取训练集中出现5次的单词
运行代码:
1. data3_freq_words<-findFreqTerms(data3_train,5) #取训练集中出现5次的单词 2. str(data3_freq_words)
结果展示:
> str(data3_freq_words) chr [1:1137] "£wk" "abiola" "abl" "abt" "accept" "access" "account" "across" "act" "activ" ...
由运行结果显示,有1137个的单词至少出现了5次。
2)提取单词特征
运行代码:
1. data3_freq_train<-data3_train[,data3_freq_words] 2. data3_freq_test<-data3_test[,data3_freq_words] #提取频繁包含频繁出现的词 3. covert_counts<-function(x){ 4. x<-ifelse(x>0,"Yes","No") 5. } #创建函数,将计数转化为字符串Yes或No 6. data3_train1<-apply(data3_freq_train,MARGIN =2,covert_counts) 7. data3_test1<-apply(data3_freq_test,MARGIN =2,covert_counts)#转化稀疏矩阵数据形式
我们已经过滤DTM,将训练集、测试集设置仅包含出现至少5个单词的特征,并用Yes和No替代稀疏矩阵中的数值。
4 模型建立及优化
4.1 基于数据训练模型
运行代码:
1. library("e1071") #加载包 2. data_classifier<-naiveBayes(data3_train1,data3_train_labels) #创建分类器
我们已经成功创建贝叶斯分类器。
4.2 评估模型性能
运行代码:
1. library("e1071") #加载包 2. data_classifier<-naiveBayes(data3_train1,data3_train_labels) #创建分类器 3. data_pred<-predict(data_classifier,data3_test1) #预测测试集 4. library("gmodels") #加载包 5. CrossTable(data_pred,data3_test_labels, 6. prop.chisq = F, 7. prop.t = F, 8. dnn=c("predicted","actual")) #测试集预测结果
结果展示:
actual | |||
predicted | ham | spam | Row Total |
ham | 1201 | 30 | 1231 |
0.976 | 0.024 | 0.886 | |
0.995 | 0.164 | ||
spam | 6 | 153 | 159 |
0.038 | 0.962 | 0.114 | |
0.005 | 0.836 | ||
Column Total | 1207 | 183 | 1390 |
0.868 | 0.132 |
由运行结果显示可以知道,共有36条信息未被正确分类,分类器正确率为97.4%。
4.3 提高模型性能
我们将像之前所做的那样建立朴素贝叶斯模型,但这次我们设置1aplace=1。
运行代码:
1. data_classifier<-naiveBayes(data3_train1,data3_train_labels,1aplace=1) #创建分类器 2. data_pred<-predict(data_classifier,data3_test1) #预测测试集 3. CrossTable(data_pred,data3_test_labels, 4. prop.chisq = F, 5. prop.t = F, 6. dnn=c("predicted","actual")) #测试集预测结果
结果展示:
actual | |||
predicted | ham | spam | Row Total |
ham | 1202 | 28 | 1230 |
0.977 | 0.023 | 0.885 | |
0.996 | 0.153 | ||
spam | 5 | 155 | 160 |
0.031 | 0.969 | 0.115 | |
0.004 | 0.847 | ||
Column Total | 1207 | 183 | 1390 |
0.868 | 0.132 |
由运行结果显示可以知道,共有33条信息未被正确分类,分类器正确率为97.6%。利用拉普拉斯估计优化分类器后,分类器预测正确率被得以提升。