使用对数概率的复杂化 - 朴素贝叶斯文本分类器

Posted

技术标签:

【中文标题】使用对数概率的复杂化 - 朴素贝叶斯文本分类器【英文标题】:Complication using log-probabilities - Naive Bayes text classifier 【发布时间】:2016-09-17 15:18:29 【问题描述】:

我正在用 Python 从头开始​​构建一个朴素贝叶斯文本分类器,我知道,在遇到概率非常小的乘积时,使用概率上的对数是一个不错的选择。

现在的问题是,我使用的数学函数对这些极小概率的乘积求和。

具体来说,我正在尝试计算给定所有类的混合组件(类)的总单词概率。

简单地将这些总概率的对数相加是不正确的,因为总和的对数不等于对数的总和。

举个例子,假设我有 3 个类,2000 个单词和 50 个文档。 然后我有一个名为 wordprob 的单词概率矩阵,它有 2000 行和 3 列。

本例中的总单词概率算法如下所示:

sum = 0
for j in range(0,3):
    prob_product = 1
    for i in words:  #just the index of words from my vocabulary in this document
        prob_product = prob_product*wordprob[i,j]
    sum = sum + prob_product

最终发生的情况是,由于许多小概率彼此相乘,prob_product 在多次迭代中变为 0。

由于我不能用日志轻松解决这个问题(因为前面的总和),我完全一无所知。

任何帮助将不胜感激。

【问题讨论】:

NumPy 有一个 logaddexp function 就是为了这个目的。 scipy.misc.logsumexp 也可能感兴趣。) 【参考方案1】:

我认为最好将所有内容都记录在日志中。计算产品对数的第一部分只是将术语的对数相加。第二位,计算对数指数之和的对数有点棘手。

一种方法是将产品的每个日志存储在一个数组中,然后你需要一个函数,给定一个包含 n 个元素的数组 L,将计算

S = log( sum  i=1..n | exp( L[i]))

一种方法是找到 L 的最大值,例如 M;一点代数展示

S = M + log( sum  i=1..n | exp( L[i]-M))

每个项 L[i]-M 都是非正数,因此不会发生溢出。下溢不是问题,因为它们 exp 将返回 0。其中至少一个(L[i] 为 M 的那个)将为零,因此它的 exp 将为 1,我们最终会得到可以传递给的东西日志。换句话说,公式的评估将毫无问题。

如果你有函数 log1p (log1p(x) = log(1+x)) 那么你可以通过从总和中省略(只有一个!) i 其中 L[i] == M 来获得一些准确性,并且将总和传递给 log1p 而不是 log。

【讨论】:

【参考方案2】:

High school algebra 告诉你这个:

log(A*B*....*Z) = log(A) + log(B) + ... + log(Z) != log(A + B + .... + Z)

【讨论】:

【参考方案3】:

您的问题似乎是在数学方面,而不是在编码方面。 我还没有完全弄清楚你的问题是什么,但是日志的总和等于产品的日志。不知道有没有帮助。。 此外,您正在为每个 j 计算一个 prob_product 但您只使用最后一个(并且您正在重新初始化它)。你打算做两件事之一:要么在 j 循环之前初始化它,要么在你增加 j 之前使用它。最后,我认为您不需要初始化 sum,除非这是您未在此处显示的另一个循环的一部分。

这就是我现在所拥有的。 抱歉,帖子很长,没有代码。

【讨论】:

感谢您的反馈。一旦我将该 prob_product 添加到我的总和中,我需要重新初始化它,以便开始新列 j 的新产品。 @C.Steyn 没错。现在更多关于外观方面的内容,顺便提一下,range(0,3) 与 range(3) 完全相同,递增变量可以这样完成:prob_product *= wordprob[i,j] sum += prob_product

以上是关于使用对数概率的复杂化 - 朴素贝叶斯文本分类器的主要内容,如果未能解决你的问题,请参考以下文章

朴素贝叶斯文本分类错误结果

朴素贝叶斯文本分类器 - 确定何时应将文档标记为“未分类”

基于R语言的文本挖掘——朴素贝叶斯分类器

数据挖掘十大经典算法之朴素贝叶斯

朴素贝叶斯分类器原理

机器学习系列-朴素贝叶斯分类器