朴素贝叶斯算法描述应用贝叶斯定理进行分类的一个简单应用。
优点:
简单、快速、有效;能处理好噪声数据和缺失数据;需要用来训练的例子相对较少,但同样能处理好大量的例子;很容易获得一个预测的估计概率值。
缺点:
依赖于一个常用的错误假设,即一样的重要性和独立特征;应用在含有大量数值特征的数据集时并不理想;概率的估计值相对于预测的类而言更加不可靠。
贝叶斯分类器已应用于以下方面:
文本分类;
在计算机网络中进行入侵检测或者异常检验;
根据一组观察到的症状,诊断身体状况。
基于贝叶斯算法的手机垃圾短信过滤
第一步——收集数据
数据来源于http://www.dt.fee.unicamp.br/~tiago/sms-spamcollection/
第二步——探索和准备数据
导入数据:
sms_raw<-read.csv("sms_spam.csv",header=T)
将数据中type变量转换为因子:
sms_raw$type<-factor(sms_raw$type)
查看垃圾短信和非垃圾短信的数量:
table(sms_raw$type)
第三步——数据准备——处理和分析文本数据
library(tm)
对text建立语料库:
sms_corpus<-Corpus(VectorSource(sms_raw$text))
数据清洗:
corpus_clean<-tm_map(sms_corpus,removeNumbers)#去除数字
corpus_clean<-tm_map(corpus_clean,removeWords,stopwords())#去除停止词
corpus_clean<-tm_map(corpus_clean,removePunctuation)#去除标点符号
corpus_clean<-tm_map(corpus_clean,stripWhitespace)#去除空格
创建稀疏矩阵,建立文档词条矩阵
sms_dtm<-DocumentTermMatrix(corpus_clean)
第四步——建立训练数据集和测试数据集,75%的训练数据集和25%的测试数据集:
sms_raw_train<-sms_raw[1:4169,]
sms_raw_test<-sms_raw[4170:5559,]
输出文档词条矩阵:
sms_dtm_train<-sms_dtm[1:4169,]
sms_dtm_test<-sms_dtm[4170:5559,]
得到语料库:
sms_corpus_train<-corpus_clean[1:4169]
sms_corpus_test<-corpus_clean[4170:5559]
第五步——可视化文本数据——词云
library(wordcloud)
wordcloud(sms_corpus_train,min.freq=40,random.order=F,col=rainbow(length(sms_corpus_train)))
根据短信类型,通过R中subset()函数来获取其中一种类型的短信数据:
spam<-subset(sms_raw_train,type=="spam")
ham<-subset(sms_raw_train,type=="ham")
wordcloud(spam$text,max.words=40,scale=c(3,1.5,0.5),col=rainbow(length(spam$text)))
wordcloud(ham$text,max.words=40,scale=c(3,1.5,0.5),col=rainbow(length(ham$text)))
findFreqTerms()函数返回一个字符向量,改箱量包含出现次数不少于指定次数的单词
sms_dict<-findFreqTerms(sms_dtm_train,5)
训练数据和测试数据只包含前面词典中的单词:
sms_train<-DocumentTermMatrix(sms_corpus_train,list(dictionary=sms_dict))
sms_test<-DocumentTermMatrix(sms_corpus_test,list(dictionary=sms_dict))
建立一个函数,改变成因子向量,根据单词是否出现,简单表示成YES或NO:
convert_counts<-function(x){
使用apply函数应用于系数矩阵的每一列:
sms_train<-apply(sms_train,2,convert_counts)
sms_test<-apply(sms_test,2,convert_counts)
第七步——基于数据训练模型
采用e1071包中的朴素贝叶斯算法实现:
library(e1071)
创建分类器:m<-naiveBayes(train,class,laplace=0) train为包含训练数据集的数据框或矩阵;class为包含训练数据每一行的分类的一个因子向量;laplace为控制拉普拉斯估计的一个数值(默认0)
sms_classifier<-naiveBayes(sms_train,sms_raw_train$type)
进行预测:p<-predict(m,test,type=c("class","raw") m为函数naiveBayes()训练的一个模型;test为训练数据集;type为标识预测是最可能的类别值或原始预测概率值
sms_test_pred<-predict(sms_classifier,sms_test)
第八步——模型评估
library(gmodels)
CrossTable(sms_test_pred,sms_raw_test$type,prop.chisq=F,prop.t=F,dnn=c("predicted","actual"))#dnn为重新标记行和列
Cell Contents |-------------------------| | N | | N / Row Total | | N / Col Total | |-------------------------| Total Observations in Table: 1390 | actual predicted | ham | spam | Row Total | -------------|-----------|-----------|-----------| ham | 1203 | 30 | 1233 | | 0.976 | 0.024 | 0.887 | | 0.997 | 0.164 | | -------------|-----------|-----------|-----------| spam | 4 | 153 | 157 | | 0.025 | 0.975 | 0.113 | | 0.003 | 0.836 | | -------------|-----------|-----------|-----------| Column Total | 1207 | 183 | 1390 | | 0.868 | 0.132 | | -------------|-----------|-----------|-----------|
第九步——模型的优化
设置laplace值为1
sms_classifier2<-naiveBayes(sms_train,sms_raw_train$type,laplace=1)
sms_test_pred2<-predict(sms_classifier2,sms_test)
CrossTable(sms_test_pred2,sms_raw_test$type,prop.chisq=F,prop.t=F,dnn=c("predicted","actual"))
Cell Contents |-------------------------| | N | | N / Row Total | | N / Col Total | |-------------------------| Total Observations in Table: 1390 | actual predicted | ham | spam | Row Total | -------------|-----------|-----------|-----------| ham | 1204 | 30 | 1234 | | 0.976 | 0.024 | 0.888 | | 0.998 | 0.164 | | -------------|-----------|-----------|-----------| spam | 3 | 153 | 156 | | 0.019 | 0.981 | 0.112 | | 0.002 | 0.836 | | -------------|-----------|-----------|-----------| Column Total | 1207 | 183 | 1390 | | 0.868 | 0.132 | | -------------|-----------|-----------|-----------|