实现过程中需要注意的几点:
- 得到P(Xi,Yi)时先要统计出Xi在Yi上出现的次数
cnt(Xi,Yi)
,以及Y的总次数cnt(Yi)
,p(Xi|Yi) = cnt(Xi|Yi) / cnt(Yi)
- 统计次数时多用
numpy.array
中的操作 - 拉普拉斯平滑的实现可以在初始化中将每个特征对应的值出现次数赋值为1而不是0
- 为了防止在预测时,连乘所用的条件概率的值过小造成下溢,可以将概率对数化再相加处理
二分类为例的代码
import numpy as np
def trainNB(X_train, y_train):
"""二分类朴素贝叶斯训练,得到概率值"""
doc_cnt = len(y_train)
word_cnt = len(X_train[0])
pAbusive = np.sum(y_train) / doc_cnt
word_p0_cnt, word_p1_cnt = np.ones(word_cnt), np.ones(word_cnt) #不用zeros,拉普拉斯平滑
word_p0_sum, word_p1_sum = 2, 2 #同上
for i in range(doc_cnt):
if y_train[i] == 1:
word_p1_cnt += X_train[i]
word_p1_sum += np.sum(X_train[i])
else:
word_p0_cnt += X_train[i]
word_p0_sum += np.sum(X_train[i])
p1_vec = word_p1_cnt / word_p1_sum
p0_vec = word_p0_cnt / word_p0_sum
return np.log(p1_vec), np.log(p0_vec), pAbusive #对数化
def classifyNB(X_test, p0_vec, p1_vec, pAbusive):
p1 = np.sum(X_test * p1_vec) + np.log(pAbusive) #防止下溢
p0 = np.sum(X_test * p0_vec) + np.log(1 - pAbusive)
return 1 if p1 > p0 else 0