第四章 樸素貝葉斯法
- 樸素貝葉斯法和貝葉斯估計是不同的概念。
- 基於特徵條件獨立假設學習輸入輸出聯合概率分佈
- 基於此模型給出後驗概率最大的輸出y
- 本章敘述:
- 樸素貝葉斯法
- 學習與分類
- 參數估計算法
4.1 樸素貝葉斯法的學習與分類
4.1.1 基本方法
- 關於貝葉斯定理,以下摘一段 wikipedia 上的簡介:
所謂的貝葉斯定理源於他生前爲解決一個“逆概”問題寫的一篇文章,而這篇文章是在他死後才由他的一位朋友發表出來的。在貝葉斯寫這篇文章之前,人們已經能夠計算“正向概率”,如“假設袋子裏面有 N 個白球,M 個黑球,你伸手進去摸一把,摸出黑球的概率是多大”。而一個自然而然的問題是反過來:“如果我們事先並不知道袋子裏面黑白球的比例,而是閉着眼睛摸出一個(或好幾個)球,觀察這些取出來的球的顏色之後,那麼我們可以就此對袋子裏面的黑白球的比例作出什麼樣的推測”。這個問題,就是所謂的逆向概率問題。
- 貝葉斯定理是關於隨機事件A和B的條件概率:
- 由以上術語得:
- 有時將P(B|A)/P(B)也有時被稱作標淮相似度(standardised likelihood):
以上原文:http://blog.csdn.net/kesalin/article/details/40370325
- 證明
條件概率公式:
同樣的:
兩式聯立:
上式同時除以P(B)或P(A),若P(B)或P(A)非0,則:
- 例子:
- 醫院早上收6了個病人:
症狀 職業 疾病 打噴嚏 護士 感冒 打噴嚏 農夫 過敏 頭痛 建築工人 腦震盪 頭痛 建築工人 感冒 打噴嚏 教師 感冒 頭痛 教師 腦震盪
- 現在來了第7個病人,是打噴嚏的建築工人,問患上感冒的概率多大?
由貝葉斯定理得:
假定“打噴嚏”與“建築工人”兩個特徵是獨立的,則:
- 樸素貝葉斯分類器的公式
假設輸入,現有個分類,分別爲。貝葉斯分類器就是計算出所有種類中概率最大的那個分類,即:
由全概率公式:
即:
由獨立性假設得:
綜合上述,得:
於是樸素貝葉斯分類器可表示爲:
注意到,式子中分母對於所有都是相同的,所以:
4.1.2 後驗概率最大化的含義
- 假設選取的是0-1損失函數,
- 此時期望風險函數爲:
- 要使期望風險函數最小,在爲常數情況下,內層積分要最小,即條件期望最小,在離散情況下條件期望:
- 使期望風險最小化,就要對逐個極小化,得:
- 解釋:
以上圖片來自:https://blog.csdn.net/rea_utopia/article/details/78881415
- 因此,根據期望風險最小化準則得到後驗概率最大化準則:
4.2 樸素貝葉斯法的參數估計
4.2.1 極大似然估計
- 在樸素貝葉斯法中,學習就意味着估計和,可以使用極大似然估計法。
- 得極大似然估計:
- 設第個特徵 可能取值集合爲,條件概率的極大似然估計是:
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的情況,解決該問題的方法是採用貝葉斯估計。
-
具體的,條件概率的貝葉斯估計(產生矩陣時)是:
- 同樣,先驗概率的貝葉斯估計是:
- 例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