我想在一组句子上训练NgramModel,使用Witten-Bell平滑来估计看不见的ngrams,然后用它来获得由该分布生成的测试集的对数似然。我想做的几乎与在这里找到的文档示例中做同样的事情:http://nltk.org/_modules/nltk/model/ngram.html,但是使用Witten-Bell平滑。这里有一些玩具代码试图做我想做的事情:
from nltk.probability import WittenBellProbDist
from nltk import NgramModel
est = lambda fdist, bins: WittenBellProbDist(fdist)
fake_train = [str(t) for t in range(3000)]
fake_test = [str(t) for t in range(2900, 3010)]
lm = NgramModel(2, fake_train, estimator = est)
print lm.entropy(fake_test)
不幸的是,当我尝试运行它时,我收到以下错误:
Traceback (most recent call last):
File "ngram.py", line 8, in <module>
lm = NgramModel(2, fake_train, estimator = est)
File "/usr/lib/python2.7/dist-packages/nltk/model/ngram.py", line 63, in __init__
self._model = ConditionalProbDist(cfd, estimator, len(cfd))
File "/usr/lib/python2.7/dist-packages/nltk/probability.py", line 2016, in __init__
**factory_kw_args)
File "ngram.py", line 4, in <lambda>
est = lambda fdist, bins: WittenBellProbDist(fdist)
File "/usr/lib/python2.7/dist-packages/nltk/probability.py", line 1210, in __init__
self._P0 = self._T / float(self._Z * (self._N + self._T))
ZeroDivisionError: float division by zero
导致此错误的原因是什么?据我所知,我根据文档正确使用了所有内容,当我使用Lidstone而不是Witten-Bell时,这种方法正常。
作为第二个问题,我的数据形式是一系列不相交的句子。我怎样才能使用像字符串列表这样的句子,或者做一些能产生相同分布的东西呢? (当然,我当然可以使用一个列表,其中所有句子都带有分隔后续句子的虚拟标记,但这不会产生相同的分布。)一个地方的文档说允许列出字符串列表,但后来我发现了一个错误报告,其中据说编辑了文档以反映不允许的文件(当我只是尝试一个字符串列表时我得到一个错误)。
答案 0 :(得分:2)
almost 3 years显然是一个众所周知的问题。 ZeroDivisionError
的原因是由于__init__
中的以下行,
if bins == None:
bins = freqdist.B()
self._freqdist = freqdist
self._T = self._freqdist.B()
self._Z = bins - self._freqdist.B()
每当未指定bins
参数时,默认为None
,因此self._Z
实际上只是freqdist.B() - freqdist.B()
和
self._P0 = self._T / float(self._Z * (self._N + self._T))
减少到,
self._P0 = freqdist.B() / 0.0
此外,如果您将bins
指定为大于freqdist.B()
的任何值,则在执行此代码行时,
print lm.entropy(fake_test)
您将收到NotImplementedError
,因为在WittenBellProbDist
班级内
def discount(self):
raise NotImplementedError()
discount
方法显然也用于prob
类的logprob
和NgramModel
,因此您也无法调用它们。
在不更改NLTK
的情况下修复这些问题的一种方法是从WittenBellProbDist
继承并覆盖相关方法。
答案 1 :(得分:0)
暂时我会远离NLTK的NgramModel。当n> 1时,目前存在平滑错误导致模型极大地高估了可能性。这适用于所有估算器,包括WittenBellProbDist甚至LidstoneProbDist。我认为这个错误已经存在了几年,这表明这部分NLTK没有经过充分的测试。
答案 2 :(得分:0)
NLTK 3.4包含可导入为nltk.lm