李航(統計學習方法第四章)

第四章 樸素貝葉斯法

  • 樸素貝葉斯法和貝葉斯估計是不同的概念。
    • 基於特徵條件獨立假設學習輸入輸出聯合概率分佈
    • 基於此模型給出後驗概率最大的輸出y
  • 本章敘述:
    • 樸素貝葉斯法
    • 學習與分類
    • 參數估計算法

4.1 樸素貝葉斯法的學習與分類

4.1.1 基本方法

  • 關於貝葉斯定理,以下摘一段 wikipedia 上的簡介:

所謂的貝葉斯定理源於他生前爲解決一個“逆概”問題寫的一篇文章,而這篇文章是在他死後才由他的一位朋友發表出來的。在貝葉斯寫這篇文章之前,人們已經能夠計算“正向概率”,如“假設袋子裏面有 N 個白球,M 個黑球,你伸手進去摸一把,摸出黑球的概率是多大”。而一個自然而然的問題是反過來:“如果我們事先並不知道袋子裏面黑白球的比例,而是閉着眼睛摸出一個(或好幾個)球,觀察這些取出來的球的顏色之後,那麼我們可以就此對袋子裏面的黑白球的比例作出什麼樣的推測”。這個問題,就是所謂的逆向概率問題。

  • 貝葉斯定理是關於隨機事件A和B的條件概率:

P(AB)=P(BA)P(A)P(B)P(A)ABP(AB)BABAP(BA)ABABP(B)Bnormalizingconstant P(A|B)=\frac{P(B|A)P(A)}{P(B)}\\ P(A)是 A 的先驗概率,之所以稱爲“先驗”是因爲它不考慮任何 B 方面的因素。\\ P(A|B)是已知 B 發生後 A 的條件概率,也由於得自 B 的取值而被稱作 A 的後驗概率。\\ P(B|A)是已知 A 發生後 B 的條件概率,也由於得自 A 的取值而被稱作 B 的後驗概率。\\ P(B)是 B 的先驗概率,也作標淮化常量(normalizing constant)。\\

  • 由以上術語得:

A=BA/B=/ A的後驗概率=B的後驗概率*A的先驗概率/B的先驗概率\\ 後驗概率=(相似度*先驗概率)/標準化常量

  • 有時將P(B|A)/P(B)也有時被稱作標淮相似度(standardised likelihood):

= 後驗概率 = 標淮相似度 * 先驗概率

以上原文:http://blog.csdn.net/kesalin/article/details/40370325

  • 證明

條件概率公式:
P(AB)=P(AB)P(B) P(A|B)=\frac{P(AB)}{P(B)}

同樣的:

P(BA)=P(AB)P(A) P(B|A)=\frac{P(AB)}{P(A)}
兩式聯立:
P(AB)P(B)=P(AB)=P(BA)P(A) P(A|B)P(B)=P(AB)=P(B|A)P(A)
上式同時除以P(B)或P(A),若P(B)或P(A)非0,則:
P(AB)=P(BA)P(A)P(B)P(BA)=P(AB)P(B)P(A) P(A|B)=\frac{P(B|A)P(A)}{P(B)}\\ 或:P(B|A)=\frac{P(A|B)P(B)}{P(A)}\\

  • 例子:
  • 醫院早上收6了個病人:
症狀 職業 疾病
打噴嚏 護士 感冒
打噴嚏 農夫 過敏
頭痛 建築工人 腦震盪
頭痛 建築工人 感冒
打噴嚏 教師 感冒
頭痛 教師 腦震盪
  • 現在來了第7個病人,是打噴嚏的建築工人,問患上感冒的概率多大?

由貝葉斯定理得:
P(x)      =P()P()    /P() P(感冒|打噴嚏x建築工人)\\        = P(打噴嚏*建築工人|感冒) * P(感冒)\\     / P(打噴嚏*建築工人)\\
假定“打噴嚏”與“建築工人”兩個特徵是獨立的,則:
P(x)         =P()P()P()     /P()P()P(x)=0.660.330.5/0.50.33=0.66 P(感冒|打噴嚏x建築工人)\\          = P(打噴嚏|感冒) * P(建築工人|感冒) * P(感冒)\\      / P(打噴嚏) * P(建築工人)\\ 即:P(感冒|打噴嚏x建築工人)= 0.66 * 0.33 * 0.5 / 0.5 * 0.33= 0.66

  • 樸素貝葉斯分類器的公式

假設輸入X=x={x(1),x(2),...,x(n)}X=x=\{x^{(1)},x^{(2)},...,x^{(n)}\},現有kk個分類,分別爲c1c2...cmc_1、c_2、...、c_m。貝葉斯分類器就是計算出所有種類中概率最大的那個分類,即:
P(Y=ckX=x)=P(X=xY=ck)P(Y=ck)P(X=x) P(Y=c_k|X=x)= \frac{P(X=x|Y=c_k)P(Y=c_k)}{P(X=x)}
由全概率公式:
P(C)=P(L1)P(CL1)++P(Ln)P(CLn)=i=1nP(Li)P(CLi) P(C)=P(L_1)P(C|L_1)+···+P(L_n)P(C|L_n)=\sum _{i=1}^n P(L_i)P(C|L_i)
即:
P(Y=ckX=x)=P(X=xY=ck)P(Y=ck)i=1kP(Y=ci)P(X=xY=ci) P(Y=c_k|X=x)= \frac{P(X=x|Y=c_k)P(Y=c_k)}{\sum _{i=1}^k P(Y=c_i)P(X=x|Y=c_i)}
由獨立性假設得:
P(X=xY=ck)=P(X(1)=x(1),...,X(n)=x(n)Y=ck)=j=1nP(X(j)=x(j)Y=ck) P(X=x|Y=c_k)=P(X^{(1)}=x^{(1)},...,X^{(n)}=x^{(n)}|Y=c_k)\\ =\prod_{j=1}^n P(X{(j)}=x{(j)}|Y=c_k)
綜合上述,得:
P(Y=ckX=x)=P(X=xY=ck)P(Y=ck)i=1kP(Y=ci)j=1nP(X(j)=x(j)Y=ck) P(Y=c_k|X=x)= \frac{P(X=x|Y=c_k)P(Y=c_k)}{\sum _{i=1}^k P(Y=c_i) \prod_{j=1}^n P(X{(j)}=x{(j)}|Y=c_k) }
於是樸素貝葉斯分類器可表示爲:
y=f(x)=aarg maxckP(X=xY=ck)P(Y=ck)i=1kP(Y=ci)j=1nP(X(j)=x(j)Y=ck) y=f(x)=a\argmax_{c_k} \frac{P(X=x|Y=c_k)P(Y=c_k)}{\sum _{i=1}^k P(Y=c_i) \prod_{j=1}^n P(X{(j)}=x{(j)}|Y=c_k) }
注意到,式子中分母對於所有ckc_k都是相同的,所以:
y=f(x)=aarg maxckP(Y=ck)j=1nP(X(j)=x(j)Y=ck) y=f(x)=a\argmax_{c_k} P(Y=c_k)\prod_{j=1}^n P(X{(j)}=x{(j)}|Y=c_k)

4.1.2 後驗概率最大化的含義

  • 假設選取的是0-1損失函數,

L(Y,f(X))={1Yf(x)0Y=f(x) L(Y,f(X))=\begin{cases} 1 & Y \neq f(x) \\ 0 & Y = f(x) \end{cases}

  • 此時期望風險函數爲:

Rexp(f)=E[L(Y,f(x))]=xyL(Y,f(x))P(x,y)dxdy=xyL(Y,f(x))P(yx)P(X=x)dxdy=xyL(Y,f(x))P(yx)dyP(X=x)dx R_{exp}(f)=E[L(Y,f(x))]\\ =\int _{x·y}L(Y,f(x))P(x,y)\,dxdy\\ =\int _{x·y}L(Y,f(x))P(y|x)P(X=x)\,dxdy\\ =\int _x \overbrace{\int _y L(Y,f(x))P(y|x)dy}^{條件期望} \,P(X=x)dx\\

  • 要使期望風險函數最小,在P(X=x)P(X=x)爲常數情況下,內層積分要最小,即條件期望最小,在離散情況下條件期望:

Rexp(f)=Exk=1K[L(ck,f(X))P(ckX) R_{exp}(f)=E_x \sum _{k=1}^K[L(c_k,f(X))P(c_k|X)

  • 使期望風險最小化,就要對X=xX=x逐個極小化,得:

f(x)=arg minyYk=1KL(ck,y)P(ckX=x)=arg minyYk=1KP(yckX=x)=arg minyY(1P(yckX=x))=arg minyYP(y=ckX=x) f(x)=\argmin_{y\in Y} \sum _{k=1}^K L(c_k,y)P(c_k|X=x)\\ =\argmin_{y\in Y} \sum _{k=1}^K P(y\not ={c_k}|X=x)\\ =\argmin_{y\in Y} (1-P(y\not ={c_k}|X=x))\\ =\argmin_{y\in Y} P(y ={c_k}|X=x)\\

  • 解釋:

以上圖片來自:https://blog.csdn.net/rea_utopia/article/details/78881415

  • 因此,根據期望風險最小化準則得到後驗概率最大化準則:

f(x)=arg minckP(ckX=x) f(x)=\argmin_{c_k} P(c_k|X=x)\\

4.2 樸素貝葉斯法的參數估計

4.2.1 極大似然估計

  • 在樸素貝葉斯法中,學習就意味着估計P(Y=ck)P(Y=c_k)P(X(j)=x(j)Y=ck)P(X^{(j)}=x^{(j)}|Y=c_k),可以使用極大似然估計法。
  • P(Y=ck)P(Y=c_k)得極大似然估計:

P(Y=ck)=i=1NI(yi=ck)N,k=1,2,...,K P(Y=c_k)=\frac{\sum_{i=1}^N I(y_i=c_k)}{N},k=1,2,...,K

  • 設第jj個特徵 可能取值集合爲{aj1,aj2,...,ajSj}\{a_{j1},a_{j2},...,a_{jS_j}\},條件概率P(X(j)=x(j)Y=ck)P(X^{(j)}=x^{(j)}|Y=c_k)的極大似然估計是:

P(X(j)=x(j)Y=ck)=i=1NI(xi(j)=ajl,yi=ck)i=1NI(yi=ck)j=1,2,...,n;l=1,2,...,sj;k=1,2,...,Kxi(j)ijajljl P(X^{(j)}=x^{(j)}|Y=c_k)=\frac{\sum_{i=1}^N I(x_i^{(j)}=a_{jl},y_i=c_k)}{\sum_{i=1}^N I(y_i=c_k)}\\ j=1,2,...,n;l=1,2,...,s_j;k=1,2,...,K\\ 式中,x_i^{(j)}是第i個樣本的第j個特徵,a_{jl}是第j個特徵可能取值的第l個值。

4.2.2 學習與分類算法

  • 算法
  • 例 4.1
import numpy as np

"""
已知條件:
"""
T = np.array([[1, 'S', -1], [1, 'M', -1], [1, 'M', 1], [1, 'S', 1], [1, 'S', -1],
              [2, 'S', -1], [2, 'M', -1], [2, 'M', 1], [2, 'L', 1], [2, 'L', 1],
              [3, 'L', 1], [3, 'M', 1], [3, 'M', 1], [3, 'L', 1], [3, 'L', -1]], dtype=np.str)

Max = 80

Y = np.array([-1, 1], dtype=np.str)
A1 = np.array([1, 2, 3], dtype=np.str)
A2 = np.array(['S', 'M', 'L'], dtype=np.str)

"""
演算:
"""

A = np.array([len(A1), len(A2)])
A_fill = np.array([[1, 2, 3], ['S', 'M', 'L']], dtype=np.str)

N = len(T)
T_j = len(T[0]) - 1  # 特徵數

p_ij = np.zeros(shape=(len(Y), T_j, Max))

global y

x = np.array([2, 'S'])  # 輸入


def P_Y_ck():
    """
    對數據集來說,不同分類的概率
    :return: 不同分類的概率
    """
    global T, N
    _y_1 = 0
    _y_2 = 0
    for i in range(N):
        if T[i][2] == '-1':
            _y_1 += 1
        else:
            _y_2 += 1
    return _y_1, _y_2


def filling_P():
    """
    填充概率矩陣
    :return: None
    """
    global T, N, Y, A_fill, p_ij, y
    for yi in range(len(Y)):
        for xi in range(T_j):
            for _l in range(A[xi]):
                temp = 0
                for t in range(N):

                    if T[t][2] == Y[yi] and T[t][xi] == A_fill[xi][_l]:
                        temp += 1
                p_ij[yi][xi][_l] = temp / y[yi]


def out():
    """
    輸出概率矩陣
    :return: None
    """
    print('計算結果:')
    for yi in range(len(Y)):
        for xi in range(T_j):
            for _l in range(A[xi]):
                print(p_ij[yi][xi][_l], end=' ')
            print()


def prediction():
    """
    進行預測
    :return: 最可能結果及其概率
    """
    global x
    m = np.zeros(T_j, dtype=np.int)
    for i in range(T_j):
        for j in range(A[i]):
            if A_fill[i][j] == x[i]:
                m[i] = j
    _res = 0
    _res_y = 0
    for yi in range(len(Y)):
        p = 1
        for xi in range(T_j):
            p *= p_ij[yi][xi][m[xi]]
        p *= y[yi] / N
        if p >= _res:
            _res = p
            _res_y = Y[yi]
    return _res, _res_y


def main():
    global y
    y_1, y_2 = P_Y_ck()
    y = [y_1, y_2]
    filling_P()
    # out()
    res, res_y = prediction()
    print('預測結果: y = ', res_y, '概率: p = ', res)


if __name__ == '__main__':
    main()
  • 運行結果
預測結果: y =  -1 概率: p =  0.06666666666666667

4.2.3 貝葉斯估計

  • 極大似然估計容易產生概率值爲0的情況,解決該問題的方法是採用貝葉斯估計。

  • 具體的,條件概率的貝葉斯估計(產生矩陣時)是:

Pλ(X(j)=ajlY=ck)=i=1NI(xi(j)=ajl,yi=ck)+λi=1NI(yi=ck)+Sjλλ0λ=0λ=1l=1,2,...,Sj,k=1,2,...,K,Pλ(X(j)=ajlY=ck)>0l=1SjP(X(j)=ajlY=ck)=1 P_\lambda(X^{(j)}=a_{jl}|Y=c_k)=\frac{\sum_{i=1}^N I(x_i^{(j)}=a_{jl},y_i=c_k)+\lambda}{\sum_{i=1}^N I(y_i=c_k)+S_j\lambda}\\ 式中,\lambda \geq0,當\lambda=0時,就是極大似然估計。常取\lambda=1,稱爲拉普拉斯平滑。\\ 顯然,對於任何l=1,2,...,S_j,k=1,2,...,K,有:\\ P_\lambda(X^{(j)}=a_{jl}|Y=c_k)>0\\ \sum_{l=1}^{S_j}P(X^{(j)}=a_{jl}|Y=c_k)=1

  • 同樣,先驗概率的貝葉斯估計是:

Pλ(Y=ck)=i=1NI(yi=ck)+λN+Kλ P_\lambda(Y=c_k)=\frac{\sum_{i=1}^N I(y_i=c_k)+\lambda}{N+K\lambda}

  • 例4.2
import numpy as np

"""
已知條件:
"""
T = np.array([[1, 'S', -1], [1, 'M', -1], [1, 'M', 1], [1, 'S', 1], [1, 'S', -1],
              [2, 'S', -1], [2, 'M', -1], [2, 'M', 1], [2, 'L', 1], [2, 'L', 1],
              [3, 'L', 1], [3, 'M', 1], [3, 'M', 1], [3, 'L', 1], [3, 'L', -1]], dtype=np.str)

Max = 80

Y = np.array([-1, 1], dtype=np.str)
A1 = np.array([1, 2, 3], dtype=np.str)
A2 = np.array(['S', 'M', 'L'], dtype=np.str)

"""
演算:
"""

A = np.array([len(A1), len(A2)])
A_fill = np.array([[1, 2, 3], ['S', 'M', 'L']], dtype=np.str)

N = len(T)
T_j = len(T[0]) - 1  # 特徵數

_lambda = 1

p_ij = np.zeros(shape=(len(Y), T_j, Max))

global y

x = np.array([2, 'S'])  # 輸入


def P_Y_ck():
    """
    對數據集來說,不同分類的概率
    :return: 不同分類的概率
    """
    global T, N, _lambda, T_j
    _y_1 = 0
    _y_2 = 0
    for i in range(N):
        if T[i][2] == '-1':
            _y_1 += 1
        else:
            _y_2 += 1
    return _y_1, _y_2


def filling_P():
    """
    填充概率矩陣
    :return: None
    """
    global T, N, Y, A_fill, p_ij, y, _lambda, T_j, A
    for yi in range(len(Y)):
        for xi in range(T_j):
            for _l in range(A[xi]):
                temp = 0
                for t in range(N):
                    if T[t][2] == Y[yi] and T[t][xi] == A_fill[xi][_l]:
                        temp += 1
                temp += _lambda
                p_ij[yi][xi][_l] = temp / (y[yi] + A[xi])


def out():
    """
    輸出概率矩陣
    :return: None
    """
    print('計算結果:')
    for yi in range(len(Y)):
        for xi in range(T_j):
            for _l in range(A[xi]):
                print(p_ij[yi][xi][_l], end=' ')
            print()


def prediction():
    """
    進行預測
    :return: 最可能結果及其概率
    """
    global x, _lambda, T_j
    m = np.zeros(T_j, dtype=np.int)
    for i in range(T_j):
        for j in range(A[i]):
            if A_fill[i][j] == x[i]:
                m[i] = j
    _res = 0
    _res_y = 0
    for yi in range(len(Y)):
        p = 1
        for xi in range(T_j):
            p *= p_ij[yi][xi][m[xi]]
        p *= (y[yi] + _lambda) / (N + T_j * _lambda)
        if p >= _res:
            _res = p
            _res_y = Y[yi]
    return _res, _res_y


def main():
    global y
    y_1, y_2 = P_Y_ck()
    y = [y_1, y_2]
    filling_P()
    # out()
    res, res_y = prediction()
    print('預測結果: y = ', res_y, '概率: p = ', res)


if __name__ == '__main__':
    main()
  • 運行結果
預測結果: y =  -1 概率: p =  0.061002178649237467
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章