分類——樸素貝葉斯分類器以及Python實現
阿新 • • 發佈:2018-12-30
核心思想:
根據訓練資料獲取模型的後驗概率,對應後驗概率越大的類即預測類。
演算法簡介:
模型:
- 先驗概率:
- 條件概率:
- 後驗概率:
樸素的含義:輸入向量x的各個維度間是相互獨立的,那麼條件概率的計算公式可以大大簡化其中n為輸入維度數。
根據貝葉斯定理:
由於對所有的類來說是一樣的,故只需要計算分子(聯合概率分佈)即可。
策略
統計機器學習的策略通常是期望風險最小化,實際學習過程中以經驗風險近似期望風險(或加上正則化項)。在樸素貝葉斯方法中,期望風險最小化等價於後驗概率最大化(具體推導過程參考李航《統計學習方法》)。
學習方法(模型的引數估計):
模型中後驗概率的計算需要先獲取先驗概率以及條件概率分佈,這兩個概率的引數是通過訓練資料集學習得到的,具體的學習方法有:極大似然估計以及後驗期望估計。極大似然估計等同於先驗分佈為均勻分佈的後驗期望估計(具體參看上一篇部落格)。具體公式參考李航《統計學習方法》。注意:書中引數的貝葉斯估計就是先驗分佈為均勻分佈的後驗期望估計。
演算法流程
- Input: 訓練資料集X, y
- Output: 每個類和,每個維度上取值的聯合概率
- Step1: 採用後驗期望估計方法估計後驗概率
- Step2: 採用後驗期望估計方法估計條件概率
- Step3:根據Step1, 2結果,計算聯合分佈概率
程式碼
"""
樸素貝葉斯分類演算法
採用後驗期望估計引數,先驗概率分佈取均勻分佈
"""
from collections import Counter, defaultdict
import numpy as np
class NBayes:
def __init__(self, lambda_=1):
self.lambda_ = lambda_ # 貝葉斯估計方法引數lambda
self.p_prior = {} # 模型的先驗概率, 注意這裡的先驗概率不是指預先人為設定的先驗概率,而是需要估計的P(y=Ck)
self.p_condition = {} # 模型的條件概率
def fit(self, X_data, y_data):
N = y_data.shape[0]
# 後驗期望估計P(y=Ck)的後驗概率,設定先驗概率為均勻分佈
c_y = Counter(y_data)
K = len(c_y)
for key, val in c_y.items():
self.p_prior[key] = (val + self.lambda_) / (N + K * self.lambda_)
# 後驗期望估計P(Xd=a|y=Ck)的後驗概率,同樣先驗概率為均勻分佈
for d in range(X_data.shape[1]): # 對各個維度分別進行處理
Xd_y = defaultdict(int)
vector = X_data[:, d]
Sd = len(np.unique(vector))
for xd, y in zip(vector, y_data): # 這裡Xd僅考慮出現在資料集D中的情況,故即使用極大似然估計葉沒有概率為0的情況
Xd_y[(xd, y)] += 1
for key, val in Xd_y.items():
self.p_condition[(d, key[0], key[1])] = (val + self.lambda_) / (c_y[key[1]] + Sd * self.lambda_)
return
def predict(self, X):
p_post = defaultdict()
for y, py in self.p_prior.items():
p_joint = py # 聯合概率分佈
for d, Xd in enumerate(X):
p_joint *= self.p_condition[(d, Xd, y)] # 條件獨立性假設
p_post[y] = p_joint # 分母P(X)相同,故直接儲存聯合概率分佈即可
return max(p_post, key=p_post.get)
if __name__ == '__main__':
data = np.array([[1, 0, -1], [1, 1, -1], [1, 1, 1], [1, 0, 1],
[1, 0, -1], [2, 0, -1], [2, 1, -1], [2, 1, 1],
[2, 2, 1], [2, 2, 1], [3, 2, 1], [3, 1, 1],
[3, 1, 1], [3, 2, 1], [3, 2, -1]])
X_data = data[:, :-1]
y_data = data[:, -1]
clf = NBayes(lambda_=1)
clf.fit(X_data, y_data)
print(clf.p_prior, '\n', clf.p_condition)
print(clf.predict(np.array([2, 0])))
我的GitHub
注:如有不當之處,請指正。