R語(yǔ)言:樸素貝葉斯算法實(shí)現(xiàn)對(duì)中文垃圾郵件的分類


本期主要是實(shí)操在R語(yǔ)言中如何使用樸素貝葉斯算法實(shí)現(xiàn)對(duì)中文垃圾郵件的分類,并嘗試優(yōu)化模型分類效果。本文中所用到的數(shù)據(jù)均為真實(shí)的中文郵件文本數(shù)據(jù),因此整個(gè)過(guò)程十分貼近真實(shí)的操作場(chǎng)景,能夠幫助我們更深入的理解和掌握在R語(yǔ)言中如何進(jìn)行中文文本處理和如何使用樸素貝葉斯算法進(jìn)行分類。關(guān)于算法原理本文將不作介紹,需要了解的同學(xué)可以百度一下,網(wǎng)上有許多非常深入和詳細(xì)解讀。

數(shù)據(jù)基本情況

在開(kāi)始進(jìn)行文本分類之前我們需要了解一下數(shù)據(jù)的基本情況以便我們理清數(shù)據(jù)處理的思路,這是非常重要的一步,對(duì)數(shù)據(jù)結(jié)構(gòu)有了清晰的認(rèn)識(shí)才能夠事半功倍。數(shù)據(jù)獲?。篽ttps://trec.nist.gov/data/spam.html,下載2006垃圾郵件語(yǔ)料庫(kù),其中的trec06c文件為本文中使用的數(shù)據(jù)

首先,我們導(dǎo)入一份郵件,來(lái)看看這份數(shù)據(jù)文件內(nèi)的中文郵件長(zhǎng)什么樣子。

setwd("~/Desktop/R/python/email/trec06c") 
email_exm <- read.table("data/001/005",fill=TRUE,fileEncoding = "GB18030",sep = "|")

該文件內(nèi)包含了一份郵件所應(yīng)該的全部信息,然而我們實(shí)際需要的只是其中郵件的正文部分,其他的信息都是基本用不到,是要被清理掉的,這其中主要是一些英文字符、特殊符號(hào)以及數(shù)字。另外,為了方便后續(xù)對(duì)中文文本進(jìn)行分詞的處理,我們需要將讀入多行的數(shù)據(jù)合并成一行。

粗略閱讀該郵件的內(nèi)容,發(fā)現(xiàn)這是一份翻譯公司的推銷郵件, 顯然這是一份垃圾郵件。full文件夾中的index文件中標(biāo)記了郵件是否為垃圾郵件,我們將index文件導(dǎo)入,查看一下這份數(shù)據(jù)的結(jié)構(gòu)。

library(dplyr)
email_class_full <- read.table("full/index",fill=TRUE,fileEncoding = "GB18030",col.names = c("type","path"))
str(email_class_full)
prop.table(table(email_class_full$type))
head(email_class_full)
filter(email_class_full,path == "../data/001/005")

index文件包含了所有郵件的文件路徑以及郵件的是否為垃圾郵件,一共64620行數(shù)據(jù),即64620份郵件,其中非垃圾郵件占比為33.68%,垃圾郵件占比66.32%;另外我們查看了data/001/005的類型,為spam,其的確為垃圾郵件。后續(xù)的數(shù)據(jù)處理中我們將隨機(jī)抽取其中的10000份郵件,通過(guò)index中的文件路徑將抽樣的文本導(dǎo)入。

文本數(shù)據(jù)導(dǎo)入

library(dplyr)
library(plyr)
library(stringr)
#隨機(jī)抽取10000條數(shù)據(jù)
email_class_full <- email_class_full[sample(1:length(email_class_full$type),size=10000),]
#準(zhǔn)備for循環(huán)中用到的變量
warn_path = c()
emails = c()
num <- length(email_class_full$type)

#逐一讀入文件
for(i in 1:num){
  #截取郵件的文件路徑
  path <- str_sub(email_class_full[i,2],4)
  
  #個(gè)別郵件包含無(wú)法識(shí)別的特殊字符無(wú)法讀入,將其抓取出來(lái)
  warn <-tryCatch(
    {text <- read.table(path,fill=TRUE,fileEncoding = "GB18030",colClasses ="character",sep = "|")},
    warning = function(w){"warning"}
  )
  if(warn == "warning"){  warn_path <- c(warn_path,as.character(email_class_full[i,2]))}
  
  #去除文本中的英文字符、特殊字符
  arrange_text <- gsub("[a-zA-Z]","",as.character(warn)) %>% 
    gsub('[\\(\\.\\\\)-<\n-=@\\>?_]',"",.)
  
  #將處理后的文本保存
  emails <- c(emails,arrange_text)
}
normal_emails <- mutate(email_class_full,text = emails,type = factor(type))  %>% filter(.,text !="")
warn_emails <- mutate(email_class_full,text = emails)  %>% filter(.,text =="")

隨機(jī)抽取10000份郵件導(dǎo)入并進(jìn)行初步的數(shù)據(jù)清洗后,我們查看一下導(dǎo)入后的數(shù)據(jù)情況?;旧衔谋緝?nèi)容均是我們所需要的漢字正文,可以進(jìn)行下一步的分詞提取關(guān)鍵詞了。

文本分詞處理

在用樸素貝葉斯算法進(jìn)行郵件分類之前,需對(duì)整段的中文文本進(jìn)行分詞,并提取關(guān)鍵詞。本文中用的中文分詞包為jiebaR,分詞后的數(shù)據(jù)格式整理用的是tm包,如果是處理英文文本,則可直接使用tm包,其十分強(qiáng)大,能夠很方便的處理英文文本,但是對(duì)中文文本的支持則沒(méi)有那么完善。

#分詞并提取關(guān)鍵詞
engine <- worker()
keys = worker("keywords",topn=20)
clean_word <- function(data){
  return(paste(unique(vector_keywords(segment(data$text,engine),keys)),collapse=" "))
}
email_words <- ddply(normal_emails,.(type,path),clean_word) %>% rename(.,replace = c("V1" = "words"))

#建立語(yǔ)料庫(kù)
emails_corpus <- Corpus(VectorSource(email_words$words)) %>% tm_map(.,stripWhitespace)
#創(chuàng)建文檔-單詞矩陣
emails_dtm <-  DocumentTermMatrix(emails_corpus)

垃圾郵件分類

在文本數(shù)據(jù)處理完后,則可以開(kāi)始進(jìn)行垃圾郵件分類了!本文中進(jìn)行垃圾郵件分類用的是e1071包。

library(dplyr)
library(plyr)
library(stringr)
library(tm)
library(jiebaR)
library(e1071)
#隨機(jī)抽取70%的數(shù)據(jù)作為訓(xùn)練集,剩下的30%作為測(cè)試集
train_row <- sample(1:length(email_words$type),size = floor((length(email_words$type) *0.7)))
email_words_train <- email_words[train_row,]
email_words_test <-  email_words[-train_row,]

emails_dtm_train <- emails_dtm[train_row,]
emails_dtm_test <- emails_dtm[-train_row,]

emails_corpus_train <- emails_corpus[train_row]
emails_corpus_test <- emails_corpus[-train_row]

#選取詞頻>=5的詞匯
emails_words_dict <- findFreqTerms(emails_dtm_train,5)
emails_corpus_freq_train <- DocumentTermMatrix(emails_corpus_train,list(dictionry = emails_words_dict))
emails_corpus_freq_test <- DocumentTermMatrix(emails_corpus_test,list(dictionry = emails_words_dict))
#將訓(xùn)練集和測(cè)試集中的詞用0,1分別標(biāo)記在文本中未出現(xiàn)、出現(xiàn)某一詞匯
convert_counts <- function(x){
  x <- ifelse(as.numeric(as.character(x))>0,1,0)
  x <- factor(x,levels = c(0,1),labels = c("No","Yes"))
  return(x)
}
emails_corpus_convert_train <- apply(emails_corpus_freq_train,MARGIN = 2,convert_counts)
emails_corpus_convert_test <- apply(emails_corpus_freq_test,MARGIN = 2,convert_counts)
#利用樸素貝葉斯算法進(jìn)行分類
emails_naiveBayes <- naiveBayes(emails_corpus_convert_train,email_words_train$type,laplace = 1)
#測(cè)試分類的效果
emails_predict  <- predict(emails_naiveBayes,emails_corpus_convert_test)

我們來(lái)看一下分類器對(duì)測(cè)試集的分類效果,

library(gmodels)
CrossTable(emails_predict,email_words_test$type)

926條非垃圾郵件數(shù)據(jù)中的14條被誤分為垃圾郵件,占比1.5%;1464條垃圾郵件數(shù)據(jù)中的1295條被正確分類,占比88.5%。詳細(xì)情況如下:

分類過(guò)程中的嘗試

在得到最終的分類結(jié)果之前,還進(jìn)行了一些嘗試,得到分類器效果均不及最終的分類結(jié)果,具體情況如下:
1.在分詞后,關(guān)鍵詞選取文本中出現(xiàn)的名詞、形容詞作為輸入模型的數(shù)據(jù),得到的分類器將926條非垃圾郵件數(shù)據(jù)中的30條誤分為垃圾郵件,占比3.2%;1464條垃圾郵件數(shù)據(jù)中的1202條被正確分類,占比83.3%。
2.以TF-IDF值篩選關(guān)鍵詞,但是訓(xùn)練分類器時(shí)未加入拉普拉斯平滑,得到的分類器將926條非垃圾郵件數(shù)據(jù)中的20條誤分為垃圾郵件,占比2.2%;1464條垃圾郵件數(shù)據(jù)中的1230條被正確分類,占比84%。

以上是在R語(yǔ)言樸素貝葉斯算法進(jìn)行垃圾郵件分類的全過(guò)程。如有做的不好或這不對(duì)的地方還請(qǐng)大家指正!

最后編輯于
?著作權(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)容

  • 后期整理字體以及排版問(wèn)題,修訂不適合的翻譯 “A wealth of information. Smart, ye...
    iamzzz閱讀 830評(píng)論 0 0
  • 2006年,對(duì)那時(shí)的我來(lái)說(shuō),一個(gè)灰暗的時(shí)間,中考失利!在渾渾噩噩度過(guò)了三年初中后,考取了當(dāng)時(shí)我以為是最差的高中! ...
    安語(yǔ)乎閱讀 288評(píng)論 0 0
  • 1.C++函數(shù)參數(shù)個(gè)數(shù)不定(http://blog.csdn.net/huangwwu11/article/det...
    zjh3029閱讀 269評(píng)論 0 0
  • 4月的一個(gè)晚上,我正窩在家里,一邊給傲嬌火辣的小龍蝦剝皮,一邊給喵主子花花踩背。 身后是末尾階層的盛先生,一邊唱著...
    栗五閱讀 251評(píng)論 0 1
  • 01 我是家中的獨(dú)子,家境不錯(cuò),有房有車,有幾間鋪面在出租,老婆是鄉(xiāng)下人,有一個(gè)弟弟,我倆二十多歲的時(shí)候認(rèn)識(shí),樸實(shí)...
    喵嗚么么閱讀 330評(píng)論 0 0

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