如何解决朴素贝叶斯分类中的数值下溢问题?

2024-09-30 01:25:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一些函数来实现朴素贝叶斯分类器(对于我的数据集),而不使用任何ML库。 我想知道如何在这段代码中解决数值下溢问题。我知道我需要使用log来计算分类器中的概率,但我无法让它工作。当我打印p1和p0时,我当前得到0作为两者的输出。如何更改函数以使用log计算概率p0和p1

# build a naive bayes classifier
def classifyNB0(vec2Classify, p0Vec, p1Vec, pAbusive):
    p1 = np.prod(np.power(p1Vec, vec2Classify)) * pAbusive
    print('p1 =',p1)
    # element-wise power computation
    p0 = np.prod(np.power(p0Vec, vec2Classify)) * (1.0 - pAbusive)
    print('p0 =',p0)
    if p1 > p0:
        return 1
    else:
        return 0
    

p1Vec中的值:

p1Vec = [0.05263158 0.15789474 0.05263158 0.         0.         0.05263158
 0.         0.05263158 0.         0.10526316 0.         0.
 0.         0.         0.05263158 0.05263158 0.05263158 0.05263158
 0.10526316 0.05263158 0.         0.         0.05263158 0.
 0.05263158 0.05263158 0.         0.         0.         0.
 0.         0.        ]

vec2Classify中的值:

vec2Classify = [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0]

Tags: 函数logreturn分类器npprod概率power
1条回答
网友
1楼 · 发布于 2024-09-30 01:25:16

我认为这实际上是一个数学问题,你的帖子可能更适合Math Exchange

我同意@simon的观点,最好用一些“对数”来解决这个问题,但首先我建议用纸和笔来简化代码:

我对“朴素贝叶斯分类”一无所知,但就我从您的代码中所见,您基本上需要计算不等式p1 > p0。让我们做一些数学题

显然,我们可以等价地计算log (p_1) > log (p_0)。让我们试着重写p1p0的两个表达式

The Math displayed is by compiled by LaTeX, then screenshotted and pasted here ..

在代码中,我们希望您需要迭代列表/向量以获得总和

log_p1 = log(p1) = V[0]*log(U[0]) + ... + V[n]*log(U[n]) + log(pA)

根据您的数值,我希望这些计算不会受到下溢的影响,因此可以进行评估:log_p1 > log_p0

就python代码而言,总和为

import numpy as np

log_p1 = np.log(pAbusive)
log_p0 = np.log(1-pAbusive)
for i in range(len(p1Vec)):
  log_p1 += vec2Classify[i] * np.log(p1Vec[i])
  log_p0 += vec2Classify[i] * np.log(p0Vec[i])

然后评估一下

log_p1 > log_p0

编辑: 当我查看您在稍后的编辑中添加到文章中的数据时,您的数学变得微不足道。您不需要powerlog。你可以一起避免它们。请注意

power(x,0) = 1

power(x,1) = x

log(1) = 0

<永远

你可以简单地写

p1 = pAbusive
for x,y in zip(p1Vec, vec2Classify):
  if y: # == 1
    p1 *= x

或者,作为一行列表

p1 = pA * np.prod([x if y else 1 for x,y in zip(p1Vec,vec2Classify)])

如果出现下溢,请使用log重试

log_p1 = np.log(pA) + sum([np.log(x) if y else 0 for x,y in zip(p1Vec,vec2Classify)])
# ...
# and evaluate,
log_p1 > log_p0

EDIT2: 您实际上没有下溢问题。我尝试输入您的数据,坦率地说,p1的计算结果正确到0.0。如果你仔细看一下vec2Classify,你会发现它只在三个不同的索引中保存1,而p1Vec在完全相同的索引中保存0

如果p1Vec至少其中一个vec2Classify1的索引处p1Vec为零,那么整个p1 = prod( ... ) 始终为零,因为您将与power(0,1) = 0相乘

可能您的输入数据(p1Vec, vec2Classify)键入错误

相关问题 更多 >

    热门问题