1. 程式人生 > >【機器學習】演算法原理詳細推導與實現(三):樸素貝葉斯

【機器學習】演算法原理詳細推導與實現(三):樸素貝葉斯

【機器學習】演算法原理詳細推導與實現(三):樸素貝葉斯

在上一篇演算法中,邏輯迴歸作為一種二分類的分類器,一般的迴歸模型也是是判別模型,也就根據特徵值來求結果概率。形式化表示為 \(p(y|x;\theta)\),在引數 \(\theta\) 確定的情況下,求解條件概率 \(p(y|x)\) 。通俗的解釋為:在給定特定特徵後預測結果出現的概率。邏輯迴歸的 \(y\) 是離散型,取值為 \(\{0,1\}\) 。這裡將要介紹另一個分類演算法 樸素貝葉斯,用以解決 \(x\) 是離散型的資料,這是判別模型,也是一個生成學習演算法。

貝葉斯定理

定理推導

樸素貝葉斯是基於貝葉斯原理得到的。假設A和B為兩個不相互獨立的事件:

由上圖可以看出,在事件B已經發生的情況下,事件A發生的概率為事件A和事件B的交集除以事件B:

\[ p(A|B)=\frac{p(A\bigcap B)}{p(B)} \]

同理,在事件A已經發生的情況下,事件B發生的概率為事件A和事件B的交集除以事件A:

\[ p(B|A)=\frac{p(B\bigcap A)}{p(A)} \]

結合這兩個方程式,我們可以得到:

\[ p(A|B)p(B)=p(A\bigcap B)=p(B|A)p(A) \]

轉換後貝葉斯定理的公式定義為:

\[ P(A|B) = \frac{P(B|A)P(A)}{P(B)} \]

總的來說,貝葉斯定理可以總結為:

  1. 貝葉斯定理是將先驗概率做一次更新,得到後驗概率
  2. 樸素貝葉斯是輸入先驗概率,找到後驗概率,最後找到最大後驗概率,作為最終的分類結果,以及分類概率

實際問題

假設我們有兩個裝滿了餅乾的碗,第一個碗裡有10個巧克力餅乾和30個普通餅乾,第二個碗裡兩種餅乾都有20個。我們隨機挑一個碗,再在碗裡隨機挑餅乾。那麼我們挑到的普通餅乾來自一號碗的概率有多少?

解決方案

我們用 x1 代表一號碗,x2 代表二號碗。在x1中取到普通餅乾的概率是 \(P(y|x1)=\frac{30}{10+30}\times\frac{1}{2}\),即抽到x1的概率是 \(\frac{1}{2}\) ,再在x1中抽到普通餅乾的概率是 \(\frac{30}{10+30}=\frac{3}{4}\) ,同理可得 \(P(y|x2)=\frac{20}{20+20}\times\frac{1}{2}\) 。而問題中挑到挑到的普通餅乾來自一號碗,已知挑到普通餅乾,那麼這個普通餅乾來自一號碗的概率為:

\[ P(x1|y) = \frac{P(y|x1)P(x1)}{P(y)} \]

根據 全概率公式 可知,其中拿到普通餅乾的概率為: \(P(y)=P(y|x1)P(x1)+ P(y|x2)P(x2)\)

計算為:

\[ \begin{split} P(x1|y)&=\frac{P(y|x1)P(x1)}{P(y)} \\ &=\frac{P(y|x1)P(x1)}{P(y|x1)P(x1)+ P(y|x2)P(x2)} \\ &= \frac{0.75\times0.5}{0.75\times0.5+0.5\times0.5} \\ &=0.6 \end{split} \]

樸素貝葉斯

例如如果想實現一個垃圾郵件分類器,用郵件作為輸入,確定郵件是否為垃圾郵件作為輸出,即 \(y\in \{0,1\}\),1表示是垃圾郵件0表示不是垃圾郵件,那麼問題來了:給你一封郵件,怎麼將郵件轉化為特徵向量 \(\vec x\) 來表示這個郵件,以及怎樣區分這封郵件是否是垃圾郵件

電子郵件僅僅是一段文字,就像是一個詞列表,因此利用詞來構建特徵向量 \(\vec x\) 。首先遍歷詞典,並且得到一個詞典中詞的列表,假設詞典中此的列表如下所示:

word_1
word_2
word_3
...
word_n

假設郵件中存在字典中的詞,那麼特徵向量 \(\vec x\) 就就記為1,不存在就記為0。例如郵件中假設存在詞 \([word_1,word_2,...,word_n]\) ,則該郵件的特徵向量 \(\vec x\) 表示為:

\[ x= \begin{bmatrix} 1 \\ 1 \\ 0 \\ ... \\ 1 \end{bmatrix} \]

則 $x\in {0,1}^n $ ,假設詞典的長度為50000,那麼 \(x\) 就可能有 \(2^{50000}\) 種向量。如果需要簡歷多項式用迴歸模型進行建模分類,那麼可能需要 \(2^{50000-1}\) 個引數 \(\theta\),很明顯看出需要的引數太多了,如果使用梯度下降那麼收斂將會非常慢,因此利用樸素貝葉斯演算法是一個很好的選擇。

演算法推導

在樸素貝葉斯演算法中,我們會對 \(p(x|y)\) 做一個假設,假設給定 \(y\) 的時候,其中\(x \in \{0,1\}^{50000}\), \(x_i\) 是條件獨立的,根據鏈式法則可以得到:

\[ \begin{split} p(x_1,x_2,...,x_{50000}|y)&=p(x_1|y)p(x_1|y,x_1)p(x_2|y,x_1,x_2)...p(x_50000|y,x_1,x_2,...,x_{49999}) \\ &=p(x_1|y)p(x_2|y)...p(x_{50000}|y) \\ &=\prod_{i=1}^n p(x_i|y) \end{split} \]

為了擬合出模型的引數,符號假設為,其中 \(y=1\) 是垃圾郵件, \(y=0\) 是正常郵件:

\[ \phi_{i|y=1}=p(x_i=1|y=1) \phi_{i|y=0}=p(x_i=1|y=0) \phi_y=p(y=1) \]

假設存在 \(m\) 個樣本,那麼 \(y=1\) 和 \(y=0\) 的組合起來的似然估計表示為:

\[ L(\phi_y,\phi_{i|y=0},\phi_{i|y=1})=\prod_{i=1}^m p(x^{(i)}|y^{(i)}) \]

假設訓練樣本為 \(m\) 封郵件,\(x_j=1\)表示包含關鍵詞 \(j\),\(x_j=0\)表示不包含關鍵詞 \(j\),則垃圾郵件 \(y=1\) 裡面包含的單詞 \(j\) 的極大似然估計為:

\[ \phi_{j|y=1}=\frac{\sum_{i=1}^ml\{x_j^{(i)}\bigcap y^{(i)}=1\}}{\sum_{i=1}^ml\{y^{(i)}=1\}} \]

上述公式中,分子的含義是從 1到 \(m\) 遍歷垃圾郵件內容,對於標籤\(x_j=1\)的郵件計算其中詞語 \(j\) 出現的郵件數目之和。換句話說就是,遍歷所有垃圾郵件,統計這些垃圾郵件中包含詞語 \(j\) 的郵件數目。分母是對 \(i\) 從1到 \(m\) 求和,最後得到垃圾郵件的總數,即分母就是垃圾郵件的數目。

同理,正常郵件 \(y=0\) 裡面包含的單詞 \(j\) 的極大似然估計為:

\[ \phi_{j|y=0}=\frac{\sum_{i=1}^ml\{x_j^{(i)}=1\bigcap y^{(i)}=0\}}{\sum_{i=1}^ml\{y^{(i)}=0\}} \]

垃圾郵件 \(y=1\) 的極大似然估計為:

\[ \phi_{j|y=1}=\frac{\sum_{i=1}^ml\{x_j^{(i)}=1\bigcap y^{(i)}=1\}}{\sum_{i=1}^ml\{y^{(i)}=1\}} \]

假設 \(m\) 封郵件裡面的詞向量 \(\vec x\) 和標識 \(y\) 如下所示:

\[ (x^{(1)},y^{(1)}),(x^{(2)},y^{(2)}),...,(x^{(m)},y^{(m)}) \]

所以當垃圾郵件分類器開始訓練時,假設訓練垃圾郵件中包含某些詞 \(x\) 的概率 \(p(y=1|x)\) :

\[ \begin{split} p(y=1|x)&=\frac{p(x|y=1)p(y=1)}{p(x)} \\ &=\frac{(\prod_{i=1}^n p(x_i|y=1))p(y=1)}{(\prod_{i=1}^n p(x_i|y=1))p(y=1)+(\prod_{i=0}^n p(x_i|y=0))p(y=0)} \end{split} \]

上式中分母是由 全概率 計算出詞 \(p(x)\) 的概率,即假設 \(word_3\) 在垃圾郵件中沒有出現,那麼可以得到:

\[ \begin{split} p(y=1|x)&=\frac{p(x|y=1)p(y=1)}{p(x)} \\ &=\frac{(\prod_{i=1}^{50000} p(x_3|y=1))p(y=1)}{(\prod_{i=1}^{50000} p(x_3|y=1))p(y=1)+(\prod_{i=0}^n p(x_i|y=0))p(y=0)} \\ &=\frac{0}{0+0} \end{split} \]

這就意味著如果 \(word_3\) 在垃圾郵件中沒有出現,那麼概率為0,這樣子很明顯是不合理的,無論在數學上會導致無法繼續計算,還是從概率的角度來說直接排除 \(word_3\) 的可能性,其實最好的是 \(word_3\) 沒出現,但是還是會有概率,只是概率很低很低。舉個例子來說,如果某個人投籃球,連續5次都是沒投中,那麼是不是投中的概率為0了,沒投中的概率是1了?

為了修正這個方法,這裡最好是在分子分母加上一個極小數,防止數學上的無效計算和實際中的絕對不可能發生。

拉普拉斯平滑(Laplace smoothing)

繼續上面投籃球的例子,假設沒投中的概率記為 \(p(y=0)\) ,投中的概率記為 \(p(y=1)\) ,原來的概率為:

\[ \begin{split} p(y=0)&=\frac{沒投中的次數}{投籃球的總次數} \\ &=\frac{沒投中的次數}{投中的次數+沒投中的次數} \\ &=\frac{0}{5+0} \end{split} \]

如果給每一項都平滑一個極小數1,代表投中籃球和沒投中籃球在事先都已經發生過一次了,那麼上述式子變成:

\[ \begin{split} p(y=0)&=\frac{0+1}{(5+1)+(0+1)} \\ &=\frac{1}{7} \end{split} \]

那麼同理可以知道, \(m\) 封郵件中,\(x_j=1\)表示包含關鍵詞 \(j\),\(x_j=0\)表示不包含關鍵詞 \(j\),則垃圾郵件 \(y=1\) 裡面包含的單詞 \(j\) 的極大似然估計為:

\[ \phi_{j|y=1}=\frac{\sum_{i=1}^ml\{x_j^{(i)}\bigcap y^{(i)}=1\}+1}{\sum_{i=1}^ml\{y^{(i)=1}\}+2} \]

正常郵件 \(y=0\) 裡面包含的單詞 \(j\) 的極大似然估計為:

\[ \phi_{j|y=0}=\frac{\sum_{i=1}^ml\{x_j^{(i)}=1\bigcap y^{(i)}=0\}+1}{\sum_{i=1}^ml\{y^{(i)}=0\}+2} \]

因為 \(y\) 只有兩種可能,我們這裡也假設事先存在一封垃圾郵件和一封正常郵件,所以分子只需要+1,分母只需要+2。

總結

總的來說,樸素貝葉斯訓練階段為,給定一組已知的訓練樣本 \((\vec{x_1},y_1),(\vec{x_2},y_2),...,(\vec{x_n},y_n)\),可以得到垃圾郵件中,每一個單詞出現的概率:

\[ p(x|y)=(\prod_{i=1}^{n}p(x_i|y_i) \]

而在 預測階段 ,給定一封郵件的單詞向量 \(\vec x\),求這個郵件是否是垃圾郵件,那麼問題就轉化為:已知單詞\(\vec x\)已經發生,求解是否垃圾郵件p(y|x):

\[ argmax_yp(y|x)=argmax_y \frac{p(x|y)p(y)}{p(x)}argmax_y p(x|y)p(y) \]

上述中,\(x\) 的取值只能是 \(x \in \{0,1 \}\),\(n\)的長度應該等於詞典中詞的數目。

例項

樸素貝葉斯是一個非常優秀的文字分類器,現在大部分垃圾郵件過濾的底層也是基於貝葉斯思想。作者收集了 25 封垃圾郵件, 25 封正常郵件,取 40 封郵件做訓練,10 封郵件做測試。

載入資料:

# 開啟資料集,獲取郵件內容,
# spam為垃圾郵件,ham為正常郵件
def loadData():
    # 選取一部分郵件作為測試集
    testIndex = random.sample(range(1, 25), 5)

    dict_word_temp = []

    testList = []
    trainList = []
    testLabel = []
    trainLabel = []

    for i in range(1, 26):
        wordListSpam = textParse(open('./email/spam/%d.txt' % i, 'r').read())
        wordListHam = textParse(open('./email/ham/%d.txt' % i, 'r').read())
        dict_word_temp = dict_word_temp + wordListSpam + wordListHam

        if i in testIndex:
            testList.append(wordListSpam)
            # 用1表示垃圾郵件
            testLabel.append(1)
            testList.append(wordListHam)
            # 用0表示正常郵件
            testLabel.append(0)
        else:
            trainList.append(wordListSpam)
            # 用1表示垃圾郵件
            trainLabel.append(1)
            trainList.append(wordListHam)
            # 用0表示正常郵件
            trainLabel.append(0)

    # 去重得到詞字典
    dict_word = list(set(dict_word_temp))
    trainData = tranWordVec(dict_word, trainList)
    testData = tranWordVec(dict_word, testList)

    return trainData, trainLabel, testData, testLabel

訓練函式為:

# 訓練函式
def train(trainData, trainLabel):
    trainMatrix = np.array(trainData)

    # 計算訓練的文件數目
    trainNum = len(trainMatrix)
    # 計算每篇文件的詞條數
    wordNum = len(trainMatrix[0])
    # 文件屬於垃圾郵件類的概率
    ori_auc = sum(trainLabel) / float(trainNum)
    
    # 拉普拉斯平滑
    # 分子+1
    HamNum = np.ones(wordNum)
    SpamNum = np.ones(wordNum)
    # 分母+2
    HamDenom = 2.0
    SpamDenom = 2.0

    for i in range(trainNum):
        # 統計屬於垃圾郵件的條件概率所需的資料,即P(x0|y=1),P(x1|y=1),P(x2|y=1)···
        if trainLabel[i] == 1:
            SpamNum += trainMatrix[i]
            SpamDenom += sum(trainMatrix[i])
        else:
            # 統計屬於正常郵件的條件概率所需的資料,即P(x0|y=0),P(x1|y=0),P(x2|y=0)···
            HamNum += trainMatrix[i]
            HamDenom += sum(trainMatrix[i])
    # 取對數,防止下溢位
    SpamVec = np.log(SpamNum / SpamDenom)
    HamVec = np.log(HamNum / HamDenom)
    # 返回屬於正常郵件類的條件概率陣列,屬於垃圾郵件類的條件概率陣列,文件屬於垃圾郵件類的概率
    return HamVec, SpamVec, ori_auc

預測函式:

# 預測函式
def predict(testDataVec, HamVec, SpamVec, ori_auc):
    predictToSpam = sum(testDataVec * SpamVec) + np.log(ori_auc)
    predictToHam = sum(testDataVec * HamVec) + np.log(1.0 - ori_auc)
    if predictToSpam > predictToHam:
        return 1
    else:
        return 0

預測錯誤一個,錯誤率 10% ,正確率 90%

資料和程式碼下載請關注公眾號【 TTyb 】,後臺回覆【 機器學習 】即可獲取:

相關推薦

機器學習演算法原理詳細推導實現():樸素

【機器學習】演算法原理詳細推導與實現(三):樸素貝葉斯 在上一篇演算法中,邏輯迴歸作為一種二分類的分類器,一般的迴歸模型也是是判別模型,也就根據特徵值來求結果概率。形式化表示為 \(p(y|x;\theta)\),在引數 \(\theta\) 確定的情況下,求解條件概率 \(p(y|x)\) 。通俗的解釋為:

機器學習演算法原理詳細推導實現(一):線性迴歸

【機器學習】演算法原理詳細推導與實現(一):線性迴歸 今天我們這裡要講第一個有監督學習演算法,他可以用於一個迴歸任務,這個演算法叫做 線性迴歸 房價預測 假設存在如下 m 組房價資料: 面積(m^2) 價格(萬元) 82.35 193 65.00 213 114.20 255 75.

機器學習演算法原理詳細推導實現(二):邏輯迴歸

【機器學習】演算法原理詳細推導與實現(二):邏輯迴歸 在上一篇演算法中,線性迴歸實際上是 連續型 的結果,即 \(y\in R\) ,而邏輯迴歸的 \(y\) 是離散型,只能取兩個值 \(y\in \{0,1\}\),這可以用來處理一些分類的問題。 logistic函式 我們可能會遇到一些分類問題,例如想要劃

機器學習演算法原理詳細推導實現(四):支援向量機(上)

【機器學習】演算法原理詳細推導與實現(四):支援向量機(上) 在之前的文章中,包括線性迴歸和邏輯迴歸,都是以線性分界線進行分割劃分種類的。而本次介紹一種很強的分類器【支援向量機】,它適用於線性和非線性分界線的分類方法。 函式間隔概念 為了更好的理解非線性分界線,區別兩種分界線對於分類的直觀理解,第一種直觀理解

機器學習演算法原理詳細推導實現(五):支援向量機(下)

【機器學習】演算法原理詳細推導與實現(五):支援向量機(下) 上一章節介紹了支援向量機的生成和求解方式,能夠根據訓練集依次得出\(\omega\)、\(b\)的計算方式,但是如何求解需要用到核函式,將在這一章詳細推導實現。 核函式 在講核函式之前,要對上一章節得到的結果列舉出來。之前需要優化的凸函式為: \[

機器學習演算法原理詳細推導實現(六):k-means演算法

【機器學習】演算法原理詳細推導與實現(六):k-means演算法 之前幾個章節都是介紹有監督學習,這個章節介紹無監督學習,這是一個被稱為k-means的聚類演算法,也叫做k均值聚類演算法。 聚類演算法 在講監督學習的時候,通常會畫這樣一張圖: 這時候需要用logistic迴歸或者SVM將這些資料分成正負兩

機器學習演算法原理詳細推導實現(七):決策樹演算法

# 【機器學習】演算法原理詳細推導與實現(七):決策樹演算法 在之前的文章中,對於介紹的分類演算法有[邏輯迴歸演算法](https://www.cnblogs.com/TTyb/p/10976291.html)和[樸素貝葉斯演算法](https://www.cnblogs.com/TTyb/p/109890

機器學習XgBoost 原理詳解 數學推導

XgBoost   (Xtreme Gradient Boosting 極限 梯度 增強) 1.基本描述:             假設Xg-模型有 t 顆決策樹數,t棵樹有序串聯構成整個模型,各決策樹的葉子節點數為 k1,k2,...,kt,             

機器學習AdaBoost 原理詳解 數學推導

AdaBoost 自適應 增強             Boosting系列代表演算法,對同一訓練集訓練出不同的(弱)分類器,然後集合這些弱分類器構成一個更優效能的(強)分類器             

機器學習演算法模型效能中的偏差、方差概念

什麼時候模型的複雜程度該停止? 模型越複雜,單次預測出的結果與真實結果的偏差(bias)就越小。但很容易引發過擬合。 模型越簡單,預測不同資料,預測的準確性差別越小。預測不同資料,所得到的準確性構成序列,序列的方差(variance)也就越小。

機器學習演算法面試知識點整理(持續更新中~)

1、監督學習(SupervisedLearning):有類別標籤的學習,基於訓練樣本的輸入、輸出訓練得到最優模型,再使用該模型預測新輸入的輸出;代表演算法:決策樹、樸素貝葉斯、邏輯迴歸、KNN、SVM、

機器學習邏輯迴歸基礎知識+程式碼實現

1. 基本概念 邏輯迴歸用於二分類,將對輸入的線性表示對映到0和1之間,輸出為label為1的概率。 優點:實現代價低,可輸出分類概率。適用於資料線性不可分。 缺點:容易欠擬合,分類精度可能不高,且僅限二分類。 使用資料型別:數值型和標稱資料。 邏輯迴歸本質也是線性迴歸,但是

機器學習CART分類決策樹+程式碼實現

1. 基礎知識 CART作為二叉決策樹,既可以分類,也可以迴歸。 分類時:基尼指數最小化。 迴歸時:平方誤差最小化。 資料型別:標值型,連續型。連續型分類時採取“二分法”, 取中間值進行左右子樹的劃分。 2. CART分類樹 特徵A有N個取值,將每個取值作為分界點,將資料

概率論條件概率 & 全概率公式 & 樸素公式

  0. 說明   條件概率 & 全概率公式 & 樸素貝葉斯公式 學習筆記     參考   scikit-learn機器學習(五)--條件概率,全概率和貝葉斯定理及python實現   1. 條件概率   【定義】   已知 事件A 發

scikit-learn機器學習(五)--條件概率,全概率和定理及python實現

在理解貝葉斯之前需要先了解一下條件概率和全概率,這樣才能更好地理解貝葉斯定理 一丶條件概率 條件概率定義:已知事件A發生的條件下,另一個事件B發生的概率成為條件概率,即為P(B|A) 如圖A∩B那一部分的發生的概率即為P(AB), P(AB)=發

機器學習EM演算法詳細推導和講解

眾所周知,極大似然估計是一種應用很廣泛的引數估計方法。例如我手頭有一些東北人的身高的資料,又知道身高的概率模型是高斯分佈,那麼利用極大化似然函式的方法可以估計出高斯分佈的兩個引數,均值和方差。這個方法基本上所有概率課本上都會講,我這就不多說了,不清楚的請百度。   然而現在我面臨的是這種情況,我

轉載機器學習EM演算法詳細推導和講解

今天不太想學習,炒個冷飯,講講機器學習十大演算法裡有名的EM演算法,文章裡面有些個人理解,如有錯漏,還請讀者不吝賜教。   眾所周知,極大似然估計是一種應用很廣泛的引數估計方法。例如我手頭有一些東北人的身高的資料,又知道身高的概率模型是高斯分佈,那麼利用極大化似然函式的

機器學習Apriori演算法——原理及程式碼實現(Python版)

Apriopri演算法 Apriori演算法在資料探勘中應用較為廣泛,常用來挖掘屬性與結果之間的相關程度。對於這種尋找資料內部關聯關係的做法,我們稱之為:關聯分析或者關聯規則學習。而Apriori演算法就是其中非常著名的演算法之一。關聯分析,主要是通過演算法在大規模資料集中尋找頻繁項集和關聯規則。

機器學習層次聚類演算法-1HCA(Hierarchical Clustering Alg)的原理講解 + 示例展示數學求解過程

層次聚類(Hierarchical Clustering)是聚類演算法的一種,通過計算不同類別資料點間的相似度來建立一棵有層次的巢狀聚類樹。在聚類樹中,不同類別的原始資料點是樹的最低層,樹的頂層是一個聚類的根節點。建立聚類樹有自下而上合併和自上而下分裂兩種方法,本篇文章介紹合併方法。層次聚類的合併演算法層次聚

機器學習決策樹(上)——從原理演算法實現

前言:決策樹(Decision Tree)是一種基本的分類與迴歸方法,本文主要討論分類決策樹。決策樹模型呈樹形結構,在分類問題中,表示基於特徵對例項進行分類的過程。它可以認為是if-then規則的集合,也可以認為是定義在特徵空間與類空間上的條件概率分佈。相比樸素