朴素贝叶斯算法python sklearn实现_朴素贝叶斯算法优化与 sklearn 实现

进行拉普拉斯平滑运算后,我们运行程序,仍然得出了两个测试样本均属于非侮辱类的结果,这是为什么呢?

我们查看最终计算出的 p0 和 p1 会发现,他们的结果都是 0,这又是为什么呢?

这是因为出现了另一个问题 -- 下溢出

我们的概率运算中,所有参与运算的概率都太小了,小数相乘会使运算的积进一步减小,最终结果向下溢出超出了计算机浮点数的精度,就都会变成 0

解决办法很自然的可以想到 -- 将乘法运算转换为加法运算,但如何在保证算法正确性的前提下进行转换呢?

在代数中,ln(a * b) = ln(a) + ln(b),同时,自然对数可以保证运算趋势的正确性:

因此我们通过对数运算优化训练函数 trainNB0 与测试函数 classifyNB:

def trainNB0(trainMap, results):

"""

朴素贝叶斯分类器训练函数

:param trainMap: 训练文档矩阵

:param results: 训练类别标签向量

:return:

p0Vect - 侮辱类的条件概率数组

p1Vect - 非侮辱类的条件概率数组

pAbusive - 文档属于侮辱类的概率

"""

dataListNum = len(trainMap)

vocabularysNum = len(trainMap[0])

""" 计算文档属于侮辱词概率 """

pAbusive = sum(results) / float(dataListNum)

p0Num = np.ones(vocabularysNum)

p1Num = np.ones(vocabularysNum)

p0Denom = 2.0

p1Denom = 2.0

""" 将所有行按是否是侮辱类分别叠加,统计各个词出现的次数 """

for i in range(dataListNum):

if results[i] == 1:

p1Num += trainMap[i]

p1Denom += sum(trainMap[i])

else:

p0Num += trainMap[i]

p0Denom += sum(trainMap[i])

""" 计算概率 """

p1Vect = np.log(p1Num / p1Denom)

p0Vect = np.log(p0Num / p0Denom)

return p0Vect, p1Vect, pAbusive

def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):

"""

朴素贝叶斯分类器分类函数

:param vec2Classify: 待分类的词条数组

:param p0Vec: 侮辱类的条件概率数组

:param p1Vec: 非侮辱类的条件概率数组

:param pClass1: 文档属于侮辱类的概率

:return: 是否属于侮辱类,0. 不属于,1. 属于

"""

p0 = sum(vec2Classify * p0Vec) + np.log(1.0 - pClass1)

print("p0: ", p0)

p1 = sum(vec2Classify * p1Vec) + np.log(pClass1)

print("p1: ", p1)

if p1 > p0:

return 1

else:

return 0

最终我们得到了正确的结果:

p0: -7.694848072384611

p1: -9.826714493730215

['love', 'my', 'dalmation'] 属于非侮辱类

p0: -7.20934025660291

p1: -4.702750514326955

['stupid', 'garbage'] 属于侮辱类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值