用樸素貝葉斯處理手機(jī)垃圾短信過(guò)濾

最常見應(yīng)用場(chǎng)景:
1.文本分類/垃圾文本過(guò)濾/情感判別:在文本分類場(chǎng)景中,樸素貝葉斯依舊堅(jiān)挺地占據(jù)著一席之地。因?yàn)槎喾诸惡芎?jiǎn)單,同時(shí)在文本數(shù)據(jù)中,分布獨(dú)立這個(gè)假設(shè)基本是成立的。而垃圾文本過(guò)濾(比如垃圾郵件識(shí)別)和情感分析(微博上的褒貶情緒)用樸素貝葉斯也通常能取得很好的效果。
2.多分類實(shí)時(shí)預(yù)測(cè):對(duì)于文本相關(guān)的多分類實(shí)時(shí)預(yù)測(cè),它因?yàn)樯厦嫣岬降膬?yōu)點(diǎn),被廣泛應(yīng)用,簡(jiǎn)單又高效。
3.推薦系統(tǒng):樸素貝葉斯和協(xié)同過(guò)濾(Collaborative Filtering)是一對(duì)好搭檔,協(xié)同過(guò)濾是強(qiáng)相關(guān)性,但是泛化能力略弱,樸素貝葉斯和協(xié)同過(guò)濾一起,能增強(qiáng)推薦的覆蓋度和效果。
需要注意點(diǎn):
1.如果連續(xù)性特征不具有正態(tài)分布,則應(yīng)采用變換或不同的方法將其轉(zhuǎn)換為正態(tài)分布。
2.如果測(cè)試數(shù)據(jù)集具有零頻率問(wèn)題,則應(yīng)用平滑技術(shù)“拉普拉斯修正”來(lái)預(yù)測(cè)測(cè)試數(shù)據(jù)集的類別。
3.刪除相關(guān)特征,因?yàn)楦叨认嚓P(guān)的特征在模型中被投票兩次,并且可能導(dǎo)致過(guò)度膨脹的重要性。

將訓(xùn)練數(shù)據(jù)集中的每條短信都拆分為獨(dú)立的單詞,存在一個(gè)變量中,對(duì)于要分類的短信同樣也拆分為單詞。這些單詞來(lái)表示短信的特征。
第一列表示短信是否為垃圾短信,spam表示垃圾短信,ham表示正常短信;第二列是具體的短信內(nèi)容。

R語(yǔ)言中的klaR包就提供了樸素貝葉斯算法實(shí)現(xiàn)的函數(shù)NaiveBayes,我們來(lái)看一下該函數(shù)的用法及參數(shù)含義:
NaiveBayes(formula, data, ..., subset, na.action= na.pass)
NaiveBayes(x, grouping, prior, usekernel= FALSE, fL = 0, ...)
formula指定參與模型計(jì)算的變量,以公式形式給出,類似于y=x1+x2+x3;
data用于指定需要分析的數(shù)據(jù)對(duì)象;
na.action指定缺失值的處理方法,默認(rèn)情況下不將缺失值納入模型計(jì)算,也不會(huì)發(fā)生報(bào)錯(cuò)信息,當(dāng)設(shè)為“na.omit”時(shí)則會(huì)刪除含有缺失值的樣本;
x指定需要處理的數(shù)據(jù),可以是數(shù)據(jù)框形式,也可以是矩陣形式;
grouping為每個(gè)觀測(cè)樣本指定所屬類別;
prior可為各個(gè)類別指定先驗(yàn)概率,默認(rèn)下用各個(gè)類別的樣本比例作為先驗(yàn)概率;
usekernel指定密度估計(jì)的方法(在無(wú)法判斷數(shù)據(jù)的分布時(shí),采用密度密度估計(jì)方法),默認(rèn)下使用正態(tài)分布密度估計(jì),設(shè)為TRUE,則使用核密度估計(jì)方法;
fL指定是否進(jìn)行拉普拉斯修正,默認(rèn)情況下不對(duì)數(shù)據(jù)進(jìn)行修正,當(dāng)數(shù)據(jù)量較小時(shí),可以設(shè)置該參數(shù)為1,即進(jìn)行拉普拉斯修正。

在本例中使用e1701包進(jìn)行分析

補(bǔ)充:(未實(shí)現(xiàn))

聚類分析
```{r}
#詞頻過(guò)濾,篩選至多出現(xiàn)10次的詞
findFreqTerms(sms_dtm,lowfreq=0,highfreq=10);
#詞語(yǔ)之間的相關(guān)性計(jì)算
findAssocs(sms_dtm,"winter",0.5)
#因?yàn)樯傻木仃囀且粋€(gè)稀疏矩陣,再進(jìn)行降維處理,之后轉(zhuǎn)為標(biāo)準(zhǔn)數(shù)據(jù)框格式
#sparse為最大允許稀疏性的詞,高于的將被刪除
dtm2<-removeSparseTerms(sms_dtm,sparse=0.95)
data1<-as.data.frame(inspect(dtm2))
#之后就可以利用R語(yǔ)言中任何工具加以研究了,層次聚類
#先進(jìn)行標(biāo)準(zhǔn)化處理,再生成距離矩陣,再用層次聚類
data.scale<-scale(data1)
d<-dist(data.scale,method="euclidean")
fit<-hclust(d,method="ward")
#繪制聚類圖
plot(fit)

正文:

一般來(lái)說(shuō)一個(gè)完整的文本挖掘解決流程是:
網(wǎng)頁(yè)爬取數(shù)據(jù)——數(shù)據(jù)格式轉(zhuǎn)化(分隔)——建立語(yǔ)料庫(kù)——詞頻去噪——提取詞干——?jiǎng)?chuàng)建文檔——聚類分析——詞頻矩陣——詞云分析——數(shù)據(jù)再處理——訓(xùn)練模型——評(píng)估模型性能——提升模型性能

讀取數(shù)據(jù)及格式轉(zhuǎn)換

data<-read.csv("F:\\簡(jiǎn)書\\SMSSpamCollection.csv",header=F,stringsAsFactors=FALSE)
#重新設(shè)置列名時(shí)要在前面加上data<-,否則最后列名仍沒(méi)有被修改
data<-setNames(data,c("type","text"))
str(data)
head(data,3)
#將分類變量因子化
data$type<-as.factor(data$type)
attach(data)

a<-table(type);prop.table(a)
可利用管道函數(shù)方便書寫

#用于加載管道函數(shù)
library(magrittr)
table(type) %>% prop.table()

其中有86.59%左右的短信是正常短信,有13.40%的短信為垃圾短信。下面分別看一下垃圾短信與正常短信的云圖,看看二者在文本內(nèi)容上是否有顯著區(qū)別

建立語(yǔ)料庫(kù)

#加載文本挖掘包
library(tm)
#創(chuàng)建語(yǔ)料庫(kù),VectorSource():輸入文本構(gòu)成的向量,目的是創(chuàng)建矢量源
data_corpus<-VCorpus(VectorSource(data$text))
data_corpus

可以使用print()和summary()查看語(yǔ)料庫(kù)的部分信息。而完整信息的提取則需要使用inspect()函數(shù)

print(data_corpus)
inspect(data_corpus[1:3])

為了進(jìn)行分詞分析,用tm_map對(duì)語(yǔ)料庫(kù)文件進(jìn)行預(yù)處理,我們需要將這些短信劃分成單個(gè)單詞,但是我們要先清理文本,去除標(biāo)點(diǎn)符號(hào),將其轉(zhuǎn)為純文本并去除多余空格,轉(zhuǎn)換小寫,去除常用詞匯,合并異形同義詞匯.通過(guò)使用map的方式將轉(zhuǎn)化函數(shù)應(yīng)用到每一個(gè)語(yǔ)料上

詞頻去噪

library(SnowballC)
#PlainTextDocument對(duì)象,處理為純文本
corpus_clean<-tm_map(data_corpus, PlainTextDocument)
#大小寫轉(zhuǎn)換
corpus_clean<-tm_map(corpus_clean, tolower)
#再除去數(shù)字,由于數(shù)字基本上不會(huì)提供有用的信息
corpus_clean<-tm_map(corpus_clean, removeNumbers)
#去除標(biāo)點(diǎn)符號(hào)
corpus_clean<-tm_map(corpus_clean, removePunctuation)
#消除空格
corpus_clean<-tm_map(corpus_clean, stripWhitespace)
#再去除像to、and、but等出現(xiàn)次數(shù)較多,但是又沒(méi)什么實(shí)際價(jià)值的詞,這些詞我們可以作為停用詞去除
corpus_clean<-tm_map(corpus_clean, removeWords, stopwords())
#新增停用詞
stopwordVector<-c("supplier","order")
#去掉新增停用詞
corpus_clean<-tm_map(corpus_clean, removeWords, stopwordVector)

提取詞干

#去詞干化.詞干化,即詞干提取.指的是去除詞綴得到詞根的過(guò)程:得到單詞最一般的寫法.如以單復(fù)數(shù)等多種形式存在的詞,或多種時(shí)態(tài)形式存在的同一個(gè)詞,它們代表的其實(shí)是同一個(gè)意思.因此需要通過(guò)詞干化將它們的形式進(jìn)行統(tǒng)一
corpus_clean<-tm_map(corpus_clean,stemDocument)

創(chuàng)建文檔

#將處理后的語(yǔ)料庫(kù)進(jìn)行斷字處理,生成詞頻權(quán)重矩陣(稀疏矩陣)也叫詞匯文檔矩陣 行表示文檔,列表示單詞,矩陣單元格表示由列標(biāo)識(shí)的單詞出現(xiàn)在由行標(biāo)識(shí)的文檔中的次數(shù)
#先轉(zhuǎn)化為純文本文件,去除標(biāo)簽  
sms_corpus_clean<-tm_map(corpus_clean,PlainTextDocument)
sms_dtm<-DocumentTermMatrix(sms_corpus_clean)
#查看詞匯文檔矩陣內(nèi)容  
inspect(sms_dtm[1:5, 100:105]) 

Non-/sparse entries: 非0/是0
Sparsity : 稀疏性 稀疏元素占全部元素的比例
Maximal term length: 切詞結(jié)果的字符最長(zhǎng)那個(gè)的長(zhǎng)度
Weighting : term frequency (tf)---詞頻率 `
DocumentTermMatrix生成的矩陣是文檔-詞頻的稀疏矩陣,橫向是文檔文件,縱向是分出來(lái)的詞,矩陣?yán)锩娲碓~頻

為評(píng)估naive bayes的性能,將數(shù)據(jù)集分成訓(xùn)練集和測(cè)試集,75%的數(shù)據(jù)用于訓(xùn)練,25%的數(shù)據(jù)用于評(píng)估算法的性能

createDataPartition則來(lái)自于caret包,該函數(shù)通過(guò)對(duì)數(shù)據(jù)進(jìn)行抽樣,保證訓(xùn)練集與測(cè)試集中,垃圾短信的比例一致,避免訓(xùn)練集中出現(xiàn)大量的正常短信,而幾乎沒(méi)有垃圾短信這樣的情況。createDataPartition 的第一個(gè)參數(shù)是vector,函數(shù)根據(jù)這個(gè)參數(shù)內(nèi)容進(jìn)行抽樣,p=0.75表示75%的數(shù)據(jù)進(jìn)入訓(xùn)練集,則有25%的數(shù)據(jù)進(jìn)入測(cè)試集,list=FASLE表示返回結(jié)果的格式為常規(guī)的數(shù)組,否則將返回一個(gè)列表

詞頻矩陣

library(caret)
set.seed(1071)
train_index <- createDataPartition(data$type, p = 0.75, list = FALSE)
# 創(chuàng)建測(cè)試數(shù)據(jù)集和訓(xùn)練數(shù)據(jù)集
sms_raw_train <- data[train_index, ]
sms_raw_test <- data[-train_index, ]

下面看看訓(xùn)練集與測(cè)試集中spam/ham郵件的分布情況,通過(guò)上述的抽樣,訓(xùn)練集與測(cè)試集中郵件分布一致

library(magrittr)
table(sms_raw_train$type) %>% prop.table()
table(sms_raw_test$type) %>% prop.table()

然后是文本-單詞矩陣

sms_dtm_train <- sms_dtm[train_index, ]
sms_dtm_test  <- sms_dtm[-train_index,]

最后得到語(yǔ)料庫(kù)

corpus_train <- sms_corpus_clean[train_index]
corpus_test  <- sms_corpus_clean[-train_index]

詞云分析

#如果一個(gè)包不存在,執(zhí)行到library將會(huì)停止執(zhí)行,require則會(huì)繼續(xù)執(zhí)行。
#require將會(huì)根據(jù)包的存在與否返回true或者false
require(dplyr)
require(wordcloud)
require(RColorBrewer)
##調(diào)用brewer.pal包里面的dark2調(diào)色板,從中取出8個(gè)顏色
pal<-brewer.pal(8, "Dark2")

函數(shù):
wordcloud(words,freq,scale=c(4,.5),min.freq=3,max.words=Inf,random.order=TRUE, random.color=FALSE, rot.per=.1,colors="black",ordered.colors=FALSE,use.r.layout=FALSE,...)
常用參數(shù):
(1)words——關(guān)鍵詞列表
(2)freq——關(guān)鍵詞對(duì)應(yīng)的詞頻列表
(3)scale——字號(hào)列表。c(最大字號(hào),最小字號(hào))
(4)min.freq——最小限制頻數(shù)。低于此頻數(shù)的關(guān)鍵詞將不會(huì)被顯示。
(5)max.words——限制詞云圖上關(guān)鍵詞的數(shù)量。最后出現(xiàn)在詞云圖上的關(guān)鍵詞數(shù)量不超過(guò)此限制。
(6)random.order——控制關(guān)鍵詞在圖上的排列順序。T:關(guān)鍵詞隨機(jī)排列;F:關(guān)鍵詞按頻數(shù)從圖中心位置往外降序排列,即頻數(shù)大的詞出現(xiàn)在中心位置。
(7)random.color——控制關(guān)鍵詞的字體顏色。T:字體顏色隨機(jī)分配;F:根據(jù)頻數(shù)分配字體顏色。
(8)rot.per——控制關(guān)鍵詞擺放角度。T:水平擺放;F:旋轉(zhuǎn)90度。
(9)colors——字體顏色列表
(10)ordered.colors——控制字體顏色使用順序。T:按照指定的順序給出每個(gè)關(guān)鍵詞字體顏色,(似乎是要求顏色列表中每個(gè)顏色一一對(duì)應(yīng)關(guān)鍵詞列表);F:任意給出字體顏色。
(11)use.r.layout=T;F

wordcloud(sms_corpus_clean, scale=c(3, 0.5),min.freq=10, min.words = 10, random.order=FALSE, rot.per=.15, colors=pal)
wordcloud(corpus_train , min.freq = 40, random.order = FALSE, rot.per=.15, colors=pal)

訓(xùn)練數(shù)據(jù)區(qū)分垃圾郵件和非垃圾郵件

spam <- subset(sms_raw_train, type == "spam")
ham  <- subset(sms_raw_train, type == "ham")

分別查看垃圾郵件和非垃圾郵件詞云圖,如果需要保存圖片采用png方法

#--png(file = "/Users/chenyangang/01.png", bg = "transparent")
#--dev.off()
wordcloud(spam$text, max.words = 40, scale = c(3, 0.5), random.order = FALSE, rot.per=.15, colors=pal)
wordcloud(ham$text, max.words = 40, scale = c(3, 0.5), random.order = FALSE, rot.per=.15, colors=pal)

數(shù)據(jù)再處理

可以刪除出現(xiàn)次數(shù)過(guò)少的單詞,這些單詞出現(xiàn)較少,刪除這些單詞對(duì)預(yù)測(cè)的結(jié)果沒(méi)有(估計(jì))影響

刪除詞頻少于5的單詞,剩下的單詞做為后續(xù)構(gòu)建dtm的單詞表,其實(shí)是字符串列表,是那些出現(xiàn)頻次超過(guò)5次的單詞

dtm <- findFreqTerms(sms_dtm, 5)

根據(jù)前文構(gòu)建的單詞表,重新構(gòu)建訓(xùn)練集和測(cè)試集的dtm矩陣

dtm_train <- DocumentTermMatrix(
    corpus_train, control = list(dictionary = dtm)
)
dtm_test <- DocumentTermMatrix(
    corpus_test, control = list(dictionary = dtm)
)

在naive bayes的算法中,計(jì)算的是單詞表中,每個(gè)單詞出現(xiàn)與否的概率,上述產(chǎn)生的dtm矩陣記錄的是每條短信中,每個(gè)單詞的出現(xiàn)次數(shù),因此需要做進(jìn)一步的轉(zhuǎn)換。若出現(xiàn)次數(shù)大于0次,表明該單詞出現(xiàn)在短信中

轉(zhuǎn)換為因子變量

convert_counts <- function(x) {
    x <- ifelse(x > 0, "Yes", "No")
}
#將訓(xùn)練數(shù)據(jù)和測(cè)試數(shù)據(jù)按列轉(zhuǎn)換為因子變量
sms_train <- apply(dtm_train, MARGIN = 2, convert_counts)
sms_test  <- apply(dtm_test, MARGIN = 2, convert_counts)

通過(guò)上述的方法,得到一個(gè)跟dtm矩陣同樣大小的矩陣(因?yàn)槭褂昧薬pply,sms_train是普通的矩陣),且各元素是字符“Yes”或者“No”

訓(xùn)練模型

下面調(diào)用e1071中的naive bayes函數(shù),對(duì)訓(xùn)練數(shù)據(jù)進(jìn)行模型訓(xùn)練,得到模型nb_model_0,并在測(cè)試集上使用該模型預(yù)測(cè)

函數(shù):
m <- naiveBayes(train, class, laplace = 0):函數(shù)返回一個(gè)樸素貝葉斯對(duì)象,該對(duì)象能夠用于預(yù)測(cè)
train: 數(shù)據(jù)框或包含訓(xùn)練數(shù)據(jù)的矩陣
class: 包含訓(xùn)練數(shù)據(jù)的每一行的分類的一個(gè)因子向量
laplace: 控制拉普拉斯估計(jì)的一個(gè)數(shù)值(默認(rèn)為0)
預(yù)測(cè):
p <- predict(m, test, type = "class"):該函數(shù)返回一個(gè)向量,根據(jù)參數(shù)type的值,該向量含有預(yù)測(cè)的類別值或者原始的預(yù)測(cè)概率
m:由naiveBayes(train, class, laplace = 0) 訓(xùn)練的模型對(duì)象
test:數(shù)據(jù)框或包含測(cè)試數(shù)據(jù)的矩陣,包含用來(lái)建立分類器的訓(xùn)練數(shù)據(jù)相同的特征
type:值為“class”或“raw”,標(biāo)示預(yù)測(cè)是最可能的類別值或者原始的預(yù)測(cè)概率

library(e1071)
sms_classifier <- naiveBayes(sms_train, sms_raw_train$type)
sms_classifier

......

評(píng)估模型性能

sms_test_pred <- predict(sms_classifier, sms_test)
library(gmodels)
CrossTable(sms_test_pred, sms_raw_test$type,
           prop.chisq = TRUE, prop.t = TRUE, prop.r = TRUE,
           dnn = c('predicted', 'actual'))

提升模型性能(應(yīng)用拉普拉斯估計(jì):本質(zhì)是給頻率數(shù)的每個(gè)計(jì)數(shù)加上一個(gè)較小的數(shù))

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 = FALSE, prop.t = FALSE, prop.r = FALSE,
           dnn = c('predicted', 'actual'))

使用naive bayes預(yù)測(cè)垃圾短信,有(1201+164)/1392 = 98.06%的短信被正確分類

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容