【機器學(xué)習(xí)基礎(chǔ)】樸素貝葉斯的算法實現(xiàn)
前言
本次我們將梳理下樸素貝葉斯(Naive Bayes)的相關(guān)內(nèi)容。
本文約1.6k字,預(yù)計閱讀10分鐘。
概要
樸素貝葉斯算法是一種適用于二分類和多分類分類問題的「分類算法」。在貝葉斯概率框架下,通過相應(yīng)推導(dǎo)得知,「期望風(fēng)險最小化等價于后驗概率最大化」。對于后驗概率的計算,可以通過「聯(lián)合概率分布建模」,得到后驗概率(「生成模型」);
對于生成模型來說,根據(jù)「貝葉斯定理」,可以將其寫成:
在樸素貝葉斯中,由于條件概率難以計算,因此提出一個強烈的假設(shè):「特征獨立性假設(shè)」,即各個特征是獨立同分布的,不存在交互,這也是樸素貝葉斯名稱的來由。先驗概率和條件概率的估計不作展開,感興趣的可以參考《統(tǒng)計學(xué)習(xí)方法》,通過轉(zhuǎn)化,最終最大化后驗概率(MAP),即「先驗概率與類條件概率的乘積」:
【注】期望風(fēng)險最小化等價于后驗概率最大化的推導(dǎo)可以參考《機器學(xué)習(xí)》,詳細的推導(dǎo),可以參考《統(tǒng)計學(xué)習(xí)方法》。
算法面試
在算法面試中,設(shè)計樸素貝葉斯相關(guān)的問題包括:
為什么樸素貝葉斯如此“樸素”? 樸素貝葉斯基本原理和預(yù)測過程; 簡單說說貝葉斯定理; 使用樸素貝葉斯如何進行垃圾分類?
今天我們討論的問題是:
?樸素貝葉斯的算法實現(xiàn)。
?
對于樸素貝葉斯來說,這既對我們的算法原理進行考察,也檢驗了編程能力。我以建立整個樸素貝葉斯算法模型類來展開,主要分為:
確定樸素貝葉斯的類型(高斯樸素貝葉斯或者伯努利樸素貝葉斯等); 模型的擬合,重點在于模型到底保存了什么內(nèi)容; 后驗概率的計算; 最大后驗概率的輸出;
1. 模型類型
對于類條件概率參數(shù)的估計,我們采用極大似然估計法,首先最重要的是「假設(shè)隨便變量(特征)服從什么分布」,對于不同的假設(shè),也對應(yīng)著不同的樸素貝葉斯,例如伯努利樸素貝葉斯、高斯樸素貝葉斯、多項分布樸素貝葉斯。最常見的是通過假設(shè)「高斯分布」,在模型擬合中,「只需要估計訓(xùn)練數(shù)據(jù)(每個類別的所有樣本的每個特征)的平均值和標(biāo)準(zhǔn)偏差」。
因此,我們可以得到初步的框架:
class?Gaussian_NaiveBayes:
??def?init(self):
?????
???def?mean(self,?X):??#?計算均值
?????return?sum(X)?/?float(len(X))
????
???def?stdev(self,?X):??#?計算標(biāo)準(zhǔn)差
?????avg?=?self.mean(X)
???return?math.sqrt(sum([pow(x-avg,?2)?for?x?in?X])?/?float(len(X)-1))
2. 模型擬合
通過對樸素貝葉斯原理的理解,我們知道,學(xué)習(xí)聯(lián)合概率模型,需要通過極大似然法估計先驗概率(假設(shè)服從伯努利分布)和類條件概率參數(shù),對于高斯樸素貝葉斯來說,整個訓(xùn)練數(shù)據(jù)集,我們需要保存:
每個類對應(yīng)的數(shù)量(可以計算先驗概率)和總樣本數(shù)量(可以作為模型的一個屬性); 每個類的每個特征的均值與標(biāo)準(zhǔn)偏差(可以計算類條件概率);
綜上所述,我們可以通過「字典」的形式進行保存:
因此:
?def?summarize(self,?train_data):
???summaries?=?[(self.mean(column),?self.stdev(column),?len(column))?for?column?in?zip(*train_data)]
??return?summaries
?def?fit(self,?X,?y):
???self.total_rows?=?len(X)
???labels?=?list(set(y))
???data?=?{label:?[]?for?label?in?labels}
???for?f,?label?in?zip(X,?y):
?????data[label].append(f)
???self.model?=?{label:?self.summarize(value)?for?label,?value?in?data.items()}
3. 后驗概率的計算
對于每個類別的后驗概率計算,需要求得先驗概率和類條件概率。首先對于類條件概率,根據(jù)高斯公式求得,
?def?gaussian_probabality(self,?x,?mean,?stdev):
???exponent?=?math.exp(-math.pow(x?-?mean,?2)?/?(2?*?math.pow(stdev,?2)))
???return?(1?/?(math.sqrt(2?*?math.pi)?*?stdev))?*?exponent
然后迭代計算所有類的后驗概率:
?def?calculate_probabalities(self,?input_data):
??????probalalities?=?{}
??????for?label,?summaries?in?self.model.items():
????????probalalities[label]?=?summaries[0][2]?/?self.total_rows?#?先驗
????????for?i?in?range(len(summaries)):
??????????mean,?stdev,?_?=?summaries[i]
??????????probalalities[label]?*=?self.gaussian_probabality(??#?先驗?*?條件概率
????????????input_data[i],?mean,?stdev)
??????return?probalalities
4. 最大后驗概率
最大后驗概率的計算就是排序,得到最大概率對應(yīng)的標(biāo)簽值。對于測試集來說,遍歷所有樣本進行計算。
?def?predict(self,?X_test):
??labels?=?[]
??for?i?in?X_test:
???label?=?sorted(
????self.calculate_probabalities(i).items(),
????key=lambda?x:?x[-1])[-1][0]
???labels.append(label)
??return?np.array(labels)
總結(jié)
以上便是對“樸素貝葉斯算法實現(xiàn)”的總結(jié)。最重要的是需要一個完善的類框架,才能夠好的結(jié)合原理進行代碼的復(fù)現(xiàn)。至于其他幾個問題,比較簡單,這里就不作詳細討論。
往期精彩回顧
本站知識星球“黃博的機器學(xué)習(xí)圈子”(92416895)
本站qq群704220115。
加入微信群請掃碼:
