還請大家多多指點,一起進步喔。
貝葉斯方法是以貝葉斯原理為基礎,使用概率統計的知識對樣本數據集進行分類。由於其有着堅實的數學基礎,貝葉斯分類算法的誤判率是很低的。貝葉斯方法的特點是結合先驗概率和后驗概率,即避免了只使用先驗概率的主管偏見,也避免了單獨使用樣本信息的過擬合現象。貝葉斯分類算法在數據集較大的情況下表現出較高的准確率,同時算法本身也比較簡單。
朴素貝葉斯法(NPC)是基於貝葉斯定理與特征條件獨立假設的分類方法。
NBC模型假設屬性之間相互獨立,這個假設在實際應用中往往是不成立的,這給NBC模型的正確分類帶來了一定影響,這也是缺點所在。
先認識一下朴素貝葉斯的優缺點:
優點:
朴素貝葉斯算法假設了數據集屬性之間是相互獨立的,因此算法的邏輯性十分簡單,並且算法較為穩定,當數據呈現不同的特點時,朴素貝葉斯的分類性能不會有太大的差異。換句話說就是朴素貝葉斯算法的健壯性比較好,對於不同類型的數據集不會呈現出太大的差異性。當數據集屬性之間的關系相對比較獨立時,朴素貝葉斯分類算法會有較好的效果。
缺點:
屬性獨立性的條件同時也是朴素貝葉斯分類器的不足之處。數據集屬性的獨立性在很多情況下是很難滿足的,因為數據集的屬性之間往往都存在着相互關聯,如果在分類過程中出現這種問題,會導致分類的效果大大降低。
貝葉斯算法屬於有監督的分類算法
思想 : 通過已知類別的訓練數據集,計算樣本的先驗概率,然后利用貝葉斯公式概率公式測算未知類別樣本屬於某個類別的后驗概率, 最終以最大后驗概率所對應的樣本類別作為樣本的預測值。
由全概率公式以及概率乘法可得 貝葉斯公式,y = f(x) = P(CiX)/P(X) = (P(Ci)*P(X|Ci))/sum(P(Ci)*P(X|Ci)) i=1,2,3,4,5,…
最后取argmax y = argmax f(x) = argmax P(CiX)/P(X) 作為最大后驗概率值(一般轉換成計算分子的最大值,因為分子求和公式說明了分子是一個常量)。
如果 分子中P(Ci)未知的話,一般會假設每個類別出現的概率相等,只需計算P(X|Ci)的最大值。大多數情況下P(Ci)是以訓練數據集中類別Ci的頻率作為先驗概率。
現在只剩下分子中的P(X|Ci)待求,就是已知類別的情況下自變量X為某種值的概率。因為計算條件概率(這里是聯合概率)比較費時、復雜,
這時一般假設自變量是條件獨立的: 即 P(X|Ci) = P(x1,x2,x3…xp|Ci) = P(x1|Ci)* P(x2|Ci)* P(x3|Ci)… P(xp|Ci);但是同時也就產生了缺點。
總結三種常見的朴素貝葉斯分類器:
一、高斯貝葉斯分類器
如果數據集中的自變量X均為連續的數值型,則在計算P(X|Ci)是會假設自變量X服從高斯正太分布,
所以自變量X的條件分布表示為:P(Xj|Ci) = 1/(Qji * sqrt(2Pi,1/2)) * exp(-(Xj-Uji)**2 / 2Qji**2)
Qji是訓練數據集中自變量Xj屬於類別Ci的標准差、Uji是訓練數據集中自變量Xj屬於類別Ci的均值,Xj表示第j個自變量的取值。
一個例子:
有如下的數據集,假設某金融公司是否願意放貸給客戶會優先考慮兩個因素,分別是年齡和收入。

現在有一位客戶年齡24歲,收入為8500元,問公司是否願意給客戶放貸?
則計算步驟如下:(解釋、解答是否願意給該客戶放貸)
1. 因變量各類別的頻率:
P(loan=0) = 5/10 = 0.5
P(loan=1) = 5/10 = 0.5
2. 求非標簽字段的字段的各兩個標簽下的均值與標准差:
均值:
Uage0 = (25+21+18+23+20)/5 = 21.40 Uage1 = (23+27+32+45+22)/5 = 29.8 Uincome0 = (6000+6500+4500+6000+6500)/5 = 5900 Uincome1 = (8000+12000+15000+10000+7500)/5 = 10500
標准差:
Qage0 = (((25-21.40)**2+(21-21.40)**2+(18-21.40)**2+(23-21.40)**2+(20-21.40)2)/5)(1/2) = 2.416 == 2.42 Qage1 = 8.38 Qincome0 = 734.85 Qincome1 = 2576.81
3 單變量的條件概率
P(age =24|loan=0) = 1/(Qji * sqrt(2Pi,1/2)) * exp(-(Xj-Uji)**2 / 2Qji**2) = 0.0926 P(age=24|loan=1) = 0.0375 P(income=8500|loan=0) = 1.0384 * (10**(-6)) P(income=8500|loan=1) = 1.1456 * (10**(-4))
4. 計算后驗概率:
【(1.)計算在age=0和income=8500這兩個事件同時發生的情況下,loan=0的概率】 P(loan=0|(age=24,income=8500)) = P(loan=0)P(age=24|loan=0)P(income=8500|loan=0) = 4.8079(10*(-8)) 【(2.)計算在age=0和income=8500這兩個事件同時發生的情況下,loan=1的概率】 P(loan=1|(age=24,income=8500)) = P(loan=1)P(age=24|loan=1)P(income=8500|loan=1) = 2.1479(10*(-6))
所以,當age=24和income=8500時,被預測為不放貸的概率為 4.8079*(10**(-8))。被預測為放大的概率為2.1479*(10**(-6))。根據最大后驗數的原則,公司決定給該客戶放貸。
一個demo解釋(利用伯努利貝葉斯分類器實現面部皮膚區分的判別)
實現高斯貝葉斯分類器,在sklearn中有naive_bayes模塊中的GaussianNB類。
該類只有一個參數 naive_bayes.GaussianNB(priors=None) ,
priors用於指定因變量各類別的先驗概率,默認以數據集中的類別頻率作為先驗概率。
該數據集含有兩部分,一部分是人類面部皮膚數據,該部分數據是由不同種族、年齡、和性別人群的圖片轉換而成的;另一部分是非人類面部皮膚數據。‘
兩個部分的數據集一共包含245057條樣本和4個變量,自變量為R、G、B,代表圖片中的三原色。因變量為y,屬於二分類變量,1表示人類面部皮膚(正例)
首先使用pandas庫讀入數據並且查看數據的大體結構和信息:

查看數據集是否有空值:skin.isnull().any()
# 設置正例和負例 skin.y = skin.y.map({2:0,1:1}) #把是2的設置為0(負例),把是1的設置為1(正例) skin.y.value_counts() #把數據轉成浮點型 skin = skin.astype(float)
拆分樣本建立模型:
# 樣本拆分 X_train,X_test,y_train,y_test = model_selection.train_test_split(skin.iloc[:,:3], skin.y, test_size = 0.25,random_state=1234) # 調用高斯朴素貝葉斯分類器的“類” gnb = naive_bayes.GaussianNB() # 模型擬合 gnb.fit(X_train, y_train) # 模型在測試數據集上的預測 gnb_pred = gnb.predict(X_test) # 各類別的預測數量 pd.Series(gnb_pred).value_counts() # 預測為負例(0也就是原數據中的2【非人類面部皮膚】)的有50630,正例有10635

可視化預測效果
1.繪制混淆矩陣:
# 導入第三方包 from sklearn import metrics import matplotlib.pyplot as plt import seaborn as sns # 構建混淆矩陣 cm = pd.crosstab(gnb_pred,y_test) # 繪制混淆矩陣圖 sns.heatmap(cm, annot = True, cmap = 'GnBu', fmt = 'd') # 去除x軸和y軸標簽 plt.xlabel('Real') plt.ylabel('Predict') # 顯示圖形 plt.show() print('模型的准確率為:\n',metrics.accuracy_score(y_test, gnb_pred)) print('模型的評估報告:\n',metrics.classification_report(y_test, gnb_pred))

如何去解讀這個混淆矩陣和評估報告?
可視化的混淆矩陣中:
左上角第一塊深藍色區域是 表示真實為0預測為0的有47216個樣本;
左下角的區域是 表示 真實為0但預測為1的樣本有1306個樣本;
右上角的區域是 表示 真實為1但預測為0的樣本是有3414個樣本;
右下角的區域是 表示 真實為1,預測也為1的樣本有9329個樣本。
知識補充:
True Positive (真正, TP)被模型預測為正的正樣本;
True Negative(真負 , TN)被模型預測為負的負樣本 ;
False Positive (假正, FP)被模型預測為正的負樣本;
False Negative(假負 , FN)被模型預測為負的正樣本;
分類准確率分數【對應圖中模型准確率】是指所有分類正確的百分比。分類准確率這一衡量分類器的標准比較容易理解,但是它不能告訴你響應值的潛在分布,並且它也不能告訴你分類器犯錯的類型。
准確率(Accuracy) = (TP+FN) / ( TP+FN+FP+TN)
metrics的分類評估報告解讀:
列表左邊上部分的一列為分類的標簽名,左邊下部分的一列為平均值。
precision 精確率 = TP /(TP+FP)
recall 召回率 = TP / (TP+FN)
f1-score可以看作是模型准確率和召回率的一種加權平均,它的最大值是1,最小值是0,計算公式是F1 = 權值* (准確率 *召回率)/(准確率+召回率)。
support : 我也不太了解,看圖形結合數據的相關可以判斷這個是代表對應標簽中的真實值個數。
2.繪制ROC曲線,尋找AUC值(>0.8即可認為模型是好的)
# 計算正例的預測概率,用於生成ROC曲線的數據 y_score = gnb.predict_proba(X_test)[:,1] fpr,tpr,threshold = metrics.roc_curve(y_test, y_score) # 計算AUC的值 roc_auc = metrics.auc(fpr,tpr) # 繪制面積圖 plt.stackplot(fpr, tpr, color='steelblue', alpha = 0.5, edgecolor = 'black') # 添加邊際線 plt.plot(fpr, tpr, color='black', lw = 1) # 添加對角線 plt.plot([0,1],[0,1], color = 'red', linestyle = '--') # 添加文本信息 plt.text(0.5,0.3,'ROC curve (area = %0.2f)' % roc_auc) # 添加x軸與y軸標簽 plt.xlabel('1-Specificity') plt.ylabel('Sensitivity') # 顯示圖形 plt.show()

二、多項式貝葉斯分類器
如果數據集的自變量X都為離散變量時,就無法使用高斯貝葉斯分類器,應該選擇多項式貝葉斯分類器。
多項式貝葉斯分類器構造詳解:
#在計算概率值P(X|Ci)時,有 P(xj = xjk|Ci) = (Nik+ arf)/(Ni+n*arf)
其中,xjk表示自變量xj的值;Nik表示因變量為類別Ci時自變量xj取xjk的樣本個數;Ni表示數據集中類別Ci的樣本個數;arf為平滑系數,用於防止概率值取0可能,通常取值為1,表示對概率值做拉普拉斯平滑;n則表示因變量的類別個數。
- 加入平滑系數是為了防止其單變量概率為0,進而導致所求概率為0.
一個例子解釋多項式貝葉斯分類器:假設影響女孩是否參加相親活動的重要因素有三個,分別時男孩的職業、受教育水平和收入狀況;
如果女孩參加相親活動,則對應的Meet變量為1,否則為0.
問:在如下表中給定的信息下,對於高收入的公務員並且其學歷為碩士的男生來說,女孩是否願意參加他的相親?

求解:
-
因變量各類別頻率:
P(Meet=0) = 4/10 = 0.4 P(Meet=1) = 6/10 = 0.6 -
單變量條件概率(根據題目所求列出所需的單變量條件概率):
P(job=公務員|Meet=0) = (0+1)/(4+21) = 1/6 P(job=公務員|Meet=1) = (4+1)/(6+21) = 1/8 P(edu=碩士|Meet=0) = (2+1)/(4+21) = 3/6 P(edu=碩士|Meet=1) = (2+1)/(4+21) = 3/8 P(income=高|Meet=0) = (0+1)/(4+21) = 1/6 P(income=高|Meet=1) = (2+1)/(6+21) = 4/8
-
尋找貝葉斯后驗概率以及最大后驗概率:
P(Meet=0|job=公務員,edu=碩士,income=高) = P(Meet=0)P(job=公務員|Meet=0)P(edu=碩士|Meet=0)P(income=高|Meet=0)=0.4(1/6)(3/6)(1/6)=1/180 P(Meet=1|job=公務員,edu=碩士,income=高) = 18/256
所以,根據最大后驗概率原則,願意見面的概率(18/256)>不願見面的概率(1/180),所以,該女生選擇參加這位男生的相親。
一個demo解釋:
根據蘑菇的各項特征判斷其是否有毒
因變量為type表示是否有毒,剩余的自變量是關於蘑菇的一些特征。
如何快速實現多項式貝葉斯分類器提高工作效率??? 如下類實現:
naive_bayes.MultinomialNB(alpha=1.0,fit_prior=True,class_prior=None)
1. alpha是用於指定平滑系數的值,默認為1.0
2. fit_prior是布爾類型的參數,意思是是否以數據集中各類別(標簽)的比例作為P(Ci)的先驗概率,默認為True。
3. class_prior是用於人工指定各類別的先驗概率P(Ci)。如果指定該參數,則fit_prior為false或者不再為true或者不再有效。
查看數據的信息:

表中所有變量均為字符型離散變量,由於python建模過程必須要求自變量為數值類型,所以需要做因子化處理,即把字符值轉化為對應的數值。
columns = mushrooms.columns[1:] for column in columns: mushrooms[column] = pd.factorize(mushrooms[column])[0] #因子化處理時factorize()函數返回一個元組,元組的第一個元素是轉換成的數值、第二個元素是數值對應的字符水平 mushrooms.head(5)

拆分數據並建立模型:
# 將數據集拆分為訓練集合測試集 Predictors = mushrooms.columns[1:] X_train,X_test,y_train,y_test = model_selection.train_test_split(mushrooms[Predictors], mushrooms['type'], test_size = 0.25, random_state = 10) # 建立模型 from sklearn import metrics import seaborn as sns import matplotlib.pyplot as plt # 構建多項式貝葉斯分類器的“類” mnb = naive_bayes.MultinomialNB() # 基於訓練數據集的擬合 mnb.fit(X_train, y_train) # 基於測試數據集的預測 mnb_pred = mnb.predict(X_test) #到此為此
三、伯努利貝葉斯分類器
當數據集的自變量X均為0-1二元值時(例如在文本挖掘中判斷某個詞語是否出現在句子中,出現用1表示,不出現用0表示),通常優先選擇伯努利貝葉斯。
利用伯努利貝葉斯計算概率值P(X|Ci)時,會假設自變量X的條件概率滿足伯努利分布,故其P(X|Ci)表示為:
P(xj|Ci) = p * xj+(1-p) * (1-xj)
其中,xj為第j個變量,取值為0或者1;
p表示類別為Ci時自變量取1的概率(該概率值可以用經驗概率代替),即 :
p=P(xj=1|Ci) = (Nxj + arfa)/(Ni+n * arfa)
其中Ni表示類別Ci的樣本個數;Nxj表示樣本在類別為Ci時,xj變量取1的樣本量;arfa為平滑系數;n為因變量中的類別個數。
一個案例解釋伯努利貝葉斯:
假設有10條評論數據做分詞處理后,得到如下表的文檔詞條矩陣,矩陣中有5個詞語和一個表示情感的結果,其中0表示正面情緒,1表示負面情緒。
問:如果一個用戶的評論中包含了“還行”一詞,該用戶的評論屬於哪種情緒?
- 文本挖掘中判斷某個詞語是否出現在句子中,出現用1表示,不出現用0表示.
求解:
1.計算因變量各類別的頻率(作為概率):
P(類別=0)=4/10 = 0.4
P(類別=1)=6/10 = 0.6
2.使用計算單變量的條件概率:
P(x1=0|類別=0) = (Nxj+arfa)/(Ni+n * arfa) = (1+1)/(4+2) = 1/3 P(x1=0|類別=1) = (4+1)/(6+2) = 5/8 P(x2=0|類別=0) = (1+1)/(4+2) = 1/3 P(x2=0|類別=1) = (4+1)/(6+2) = 5/8 P(x3=0|類別=0) = (4+1)/(4+2) = 5/6 P(x3=0|類別=1) = (1+1)/(6+2) = 1/4 P(x4=1|類別=0) = (2+1)/(4+2) = 1/2 P(x4=1|類別=1) = (0+1)/(6+2) = 1/8 P(x5=0|類別=0) = (4+1)/(4+2) = 5/6 P(x5=0|類別=1) = (1+1)/(6+2) = 1/4
3.使用概率乘法公式計算貝葉斯后驗概率:
P(類別=0|x1=0,x2=0,x3=0,x4=1,x5=0) = P(類別=0)* P(x1=0|類別=0) * P(x2=0|類別=0) * P(x3=0|類別=0) * P(x4=1|類別=0) * P(x5=0|類別=0) = 5/324
P(類別=1|x1=0,x2=0,x3=0,x4=1,x5=0) = P(類別=1)* P(x1=0|類別=1) * P(x2=0|類別=1)* P(x3=0|類別=1)* P(x4=1|類別=1) * P(x5=0|類別=1) = 3/4096
所以,用戶的評論中只有“還行”一詞時,正面評論的概率 > 負面評論的概率,所以預判為正面評論。
一個demo:
對用戶的評價數據進行分類,分類的目的是預測用戶的評價內容所表達的情緒(積極或者消極)
數據集包含四個字段,分別是用戶昵稱、評價時間、評價內容、和對應的評價情緒.評價內容中會有一些臟數據。
查看數據信息:

運用正則表達式,將評論中的數字和英文去除
evaluation.Content = evaluation.Content.str.replace('[0-9a-zA-Z]','') #evaluation.head()
引入自定義詞典(詞庫和停止詞詞庫【使用停止詞目的是無用的詞語去掉】)對文本進行切詞:
import jieba # 加載自定義詞庫 jieba.load_userdict(r'all_words.txt') # 讀入停止詞 with open(r'mystopwords.txt', encoding='UTF-8') as words: stop_words = [i.strip() for i in words.readlines()] # 構造切詞的自定義函數,並在切詞過程中刪除停止詞 def cut_word(sentence): words = [i for i in jieba.lcut(sentence) if i not in stop_words] #切詞過程中刪除停止詞 # 切完的詞用空格隔開 result = ' '.join(words) return(result) # 對評論內容進行批量切詞 words = evaluation.Content.apply(cut_word) # 前5行內容的切詞效果 words[0]

利用切好的詞,構造文檔詞條矩陣,矩陣的每一行代表一個評論內容,矩陣的每一列代表切詞后的詞語,矩陣的元素為詞語在文檔中出現的頻次。
from sklearn.feature_extraction.text import CountVectorizer # 計算每個詞在各評論內容中的次數,並將稀疏度為99%以上的詞刪除 counts = CountVectorizer(min_df = 0.001) #作用是留下來的詞語所對應的文檔數目必須在所有文檔中至少占有1%的比例,去除過於稀疏的詞語。 # 文檔詞條矩陣 dtm_counts = counts.fit_transform(words).toarray() # 獲取矩陣的列名稱【其實這里的作用是獲取所有的特征名,因為這時候已經有許多的特征了因為經過了切詞】 columns = counts.get_feature_names() # 將矩陣轉換為數據框--即X變量 X = pd.DataFrame(dtm_counts, columns=columns) # 情感標簽變量 y = evaluation.Type #X.head()

拆分數據並建模訓練:
# 將數據集拆分為訓練集和測試集 X_train,X_test,y_train,y_test = model_selection.train_test_split(X,y,test_size = 0.25, random_state=1) # 構建伯努利貝葉斯分類器 bnb = naive_bayes.BernoulliNB() # 模型在訓練數據集上的擬合 bnb.fit(X_train,y_train) # 模型在測試數據集上的預測 bnb_pred = bnb.predict(X_test) # 模型的預測准確率 print('模型的准確率為:\n',metrics.accuracy_score(y_test, bnb_pred)) print('模型的評估報告:\n',metrics.classification_report(y_test, bnb_pred))

希望大家能給予意見和建議。謝謝!
