理論
什么是朴素貝葉斯算法?
朴素貝葉斯分類器是一種基於貝葉斯定理的弱分類器,所有朴素貝葉斯分類器都假定樣本每個特征與其他特征都不相關。舉個例子,如果一種水果其具有紅,圓,直徑大概3英寸等特征,該水果可以被判定為是蘋果。盡管這些特征相互依賴或者有些特征由其他特征決定,然而朴素貝葉斯分類器認為這些屬性在判定該水果是否為蘋果的概率分布上獨立的。
朴素貝葉斯分類器很容易建立,特別適合用於大型數據集,眾所周知,這是一種勝過許多復雜算法的高效分類方法。
貝葉斯公式提供了計算后驗概率P(X|Y)的方式:
其中,
-
P(c|x)是已知某樣本(c,目標),(x,屬性)的概率。稱后驗概率。
-
P(c)是該樣本“c”的概率。稱先驗概率。
-
P(x|c)是已知該樣本“x”,該樣本“c”的概率。
-
P(x)是該樣本“x”的概率。
朴素貝葉斯算法的分類流程
舉一個例子。下面設計了一個天氣和響應目標變量“玩”的訓練數據集(計算“玩”的可能性)。我們需要根據天氣條件進行分類,判斷這個人能不能出去玩,以下是步驟:
步驟1:將數據集轉換成頻率表;
步驟2:計算不同天氣出去玩的概率,並創建似然表,如陰天的概率是0.29;
步驟3:使用貝葉斯公式計算每一類的后驗概率,數據最高那欄就是預測的結果。
問題:如果是晴天,這個人就能出去玩。這個說法是不是正確的?
P(是|晴朗)=P(晴朗|是)×P(是)/P(晴朗)
在這里,P(晴朗|是)= 3/9 = 0.33,P(晴朗)= 5/14 = 0.36,P(是)= 9/14 = 0.64
現在,P(是|晴朗)=0.33×0.64/0.36=0.60,具有較高的概率。
朴素貝葉斯適合預測基於各屬性的不同類的概率,因此在文本分類上有廣泛應用。
朴素貝葉斯的優缺點
優點:
-
既簡單又快速,預測表現良好;
-
如果變量獨立這個條件成立,相比Logistic回歸等其他分類方法,朴素貝葉斯分類器性能更優,且只需少量訓練數據;
-
相較於數值變量,朴素貝葉斯分類器在多個分類變量的情況下表現更好。若是數值變量,需要正態分布假設。
缺點:
-
如果分類變量的類別(測試數據集)沒有在訓練數據集總被觀察到,那這個模型會分配一個0(零)概率給它,同時也會無法進行預測。這通常被稱為“零頻率”。為了解決這個問題,我們可以使用平滑技術,拉普拉斯估計是其中最基礎的技術。
-
朴素貝葉斯也被稱為bad estimator,所以它的概率輸出predict_proba不應被太認真對待。
-
朴素貝葉斯的另一個限制是獨立預測的假設。在現實生活中,這幾乎是不可能的,各變量間或多或少都會存在相互影響。
朴素貝葉斯的4種應用
實時預測:毫無疑問,朴素貝葉斯很快。
多類預測:這個算法以多類別預測功能聞名,因此可以用來預測多類目標變量的概率。
文本分類/垃圾郵件過濾/情感分析:相比較其他算法,朴素貝葉斯的應用主要集中在文本分類(變量類型多,且更獨立),具有較高的成功率。因此被廣泛應用於垃圾郵件過濾(識別垃圾郵件)和情感分析(在社交媒體平台分辨積極情緒和消極情緒的用戶)。
推薦系統:朴素貝葉斯分類器和協同過濾結合使用可以過濾出用戶想看到的和不想看到的東西。
關於朴素貝葉斯分類器的幾個黑科技
以下是一些小方法,可以提升朴素貝葉斯分類器的性能:
-
如果連續特征不是正態分布的,我們應該使用各種不同的方法將其轉換正態分布。
-
如果測試數據集具有“零頻率”的問題,應用平滑技術“拉普拉斯估計”修正數據集。
-
刪除重復出現的高度相關的特征,可能會丟失頻率信息,影響效果。
-
朴素貝葉斯分類在參數調整上選擇有限。我建議把重點放在數據的預處理和特征選擇。
-
大家可能想應用一些分類組合技術 如ensembling、bagging和boosting,但這些方法都於事無補。因為它們的目的是為了減少差異,朴素貝葉斯沒有需要最小化的差異。
如何建立朴素貝葉斯的基本模型(Python和R)
scikit learn里有3種朴素貝葉斯的模型:
高斯模型:適用於多個類型變量,假設特征符合高斯分布。
多項式模型:用於離散計數。如一個句子中某個詞語重復出現,我們視它們每個都是獨立的,所以統計多次,概率指數上出現了次方。
伯努利模型:如果特征向量是二進制(即0和1),那這個模型是非常有用的。不同於多項式,伯努利把出現多次的詞語視為只出現一次,更加簡單方便。
你可以根據特定數據集選取上述3個模型中的合適模型。下面我們以高斯模型為例,談談怎么建立:
- Python
-
#Import Library of Gaussian Naive Bayes model from sklearn.naive_bayes import GaussianNB import numpy as np #assigning predictor and target variables x= np.array([[-3,7],[1,5], [1,2], [-2,0], [2,3], [-4,0], [-1,1], [1,1], [-2,2], [2,7], [-4,1], [-2,7]]) Y = np.array([3, 3, 3, 3, 4, 3, 3, 4, 3, 4, 4, 4]) #Create a Gaussian Classifier model = GaussianNB() # Train the model using the training sets model.fit(x, y) #Predict Output predicted= model.predict([[1,2],[3,4]]) print predicted Output: ([3,4])
- R
-
require(e1071) #Holds the Naive Bayes Classifier Train <- read.csv(file.choose()) Test <- read.csv(file.choose()) #Make sure the target variable is of a two-class classification problem only levels(Train$Item_Fat_Content) model <- naiveBayes(Item_Fat_Content~., data = Train) class(model) pred <- predict(model,Test) table(pred)
文本分類的主要流程
- 樣本數據的獲取
- 樣本數據清洗和分詞
- 建模與評估
- 部署運行
R實現
完整代碼及報告見另一篇博文
分詞
一個好用的包:chinese.misc。說明文檔:https://github.com/githubwwwjjj/chinese.misc
應用示例:
library(jiebaRD) library(NLP) library(chinese.misc) library(jiebaR) library(tm) library(MASS) library(klaR) library(e1071) ##樣本數據 textData <- teld.ml.rQuery("NewsInformation4BDP") textData$NewsContent <-as.character(textData$NewsContent) #自定義分詞器,將需要特殊識別的納入分詞 myCutter<-worker(write=FALSE) myWord<-c("XXX","XX","x","xxx","xx") new_user_word(myCutter,myWord) #去掉英文、字母 slimtextf<-function(x){ x1<-slim_text(x, mycutter = myCutter, rm_place = TRUE, rm_time = TRUE, rm_eng = TRUE, rm_alpha = TRUE, paste = TRUE ) return (x1) } textData$NewsContent <- sapply(as.list(textData$NewsContent),slimtextf,simplify = TRUE); textData$TFlag <-sample(0:1,nrow(textData),replace=T,prob=c(0.7,0.3))#按7:3拆分訓練集和測試集 textData.Train <- textData[textData$TFlag==0,] textData.Test <- textData[textData$TFlag==1,] dim(textData.Train ) dim(textData.Test) head(textData.Train) #生成文檔-詞條矩陣DTM(document term matrix) #stopPattern <- '(quot|app|ev|km|model|suv)',stop_pattern = stopPattern #%>%是管道 函數,即將其左邊的值發送給右邊的表達 式,並作為右邊表達式函數的第一個參數,如x<-y %>% f(z) 等價於x<-f(y,z) dtm.train<-textData.Train$NewsContent%>% corp_or_dtm(from="v",type="D",stop_word="jiebar",mycutter=myCutter,control = list(wordLengths=c(2,25)))%>% removeSparseTerms(0.99)%>% output_dtm(doc_name=textData.Train$SN) #removeSparseTerms的Sparse參數越小,矩陣越稀疏 dim(dtm.train)# 737 382 #write.csv(dtm.train,'dtm.train10.csv') dtm.test<-textData.Test$NewsContent%>% corp_or_dtm(from="v",type="D",stop_word="jiebar",mycutter=myCutter,control = list(wordLengths=c(2,25)))%>% removeSparseTerms(0.99)%>% output_dtm(doc_name=textData.Test$SN) dim(dtm.test)# 334 386
建模
有兩個包可用: e1071和klaR
e1071示例:
#訓練朴素貝葉斯模型 model <- naiveBayes(dtm.train,as.factor(textData.Train$AState),laplace = 1) #預測測試集 pre<-predict(model,dtm.test) #pre<-predict(model,dtm.test,type=c("raw")) #輸出概率,因為兩個概率懸殊太大,無意義,不采用(見理論篇的缺點部分) #默認值type = c("class", "raw")
klaR示例:在建模時報錯,后帶分析說明
#訓練朴素貝葉斯模型 model <- NaiveBayes(dtm.train,as.factor(textData.Train$AState),usekernel=FALSE,fL = 1) #報錯:Zero variances for at least one class in variables: 保時捷, 比亞迪, 戴姆勒, 環保, 混合, 集團, 加快, 開發...... #預測測試集 pre<-predict(model,dtm.test)
報錯:Zero variances for at least one class in variables: 保時捷, 比亞迪, 戴姆勒, 環保, 混合, 集團, 加快, 開發.....
錯誤原因:存在0方差的變量
錯誤信息對應的源碼:
解決方案:如果一定要使用這個包,那就修改源碼,把stop代碼干掉,讓它繼續執行。然后自己編譯這個包。
評估
在應用案例中采用了10折交叉驗證,執行10次取均值。
相關指標的說明見https://www.cnblogs.com/xianhan/p/9277194.html
#性能評價 performance<-prop.table(table(textData.Test$AState,pre)) performance #准確率:4和5預測正確的比例** accuracyrate<-(performance[1,1]+performance[2,2]) accuracyrate # 0.5174603->0.5434783 #靈敏度(查全率\召回率):實際5,其中預測正確的比例***** sensitivity <-performance[2,2]/(performance[2,1]+performance[2,2]) sensitivity #0.8791209->0.816092 #精密性:預測5,其中預測正確的比例** precision <-performance[2,2]/(performance[1,2]+performance[2,2]) precision # 0.361991-> 0.3514851 #特異性:實際4,其中預測正確的比例* specificity <-performance[1,1]/(performance[1,1]+performance[1,2]) specificity #0.3705357->0.4425532
20180731后續:
該服務發布上線后,每次調用耗時2-4s不等,超過系統設置的超時閾值而頻繁報警。經過分析,是自定義分詞器耗時2-3s,將自定義分詞器去掉后,耗時50-80ms。
參考
中文文本分析方便工具R包chinese.misc的中文說明
https://github.com/githubwwwjjj/chinese.misc
R語言-貝葉斯分類器-文本情感分析
https://zhuanlan.zhihu.com/p/26735328
R實戰——大眾點評-漢拿山(深國投店)評論情感淺析
https://mp.weixin.qq.com/s?__biz=MzUyNzU3MTgyOA==&mid=2247483690&idx=1&sn=9b8ea4b159e5885c0b99f3529a25c488&chksm=fa7ccf31cd0b4627d8f7321a392036686c1f59a0e365b3976c8ba4810a407f46b53cff4e63f0#rd