nltk语言模型(ngram)根据上下文计算单词的概率
nlp
nltk
python
5
0

我正在使用Python和NLTK构建语言模型,如下所示:

from nltk.corpus import brown
from nltk.probability import LidstoneProbDist, WittenBellProbDist
estimator = lambda fdist, bins: LidstoneProbDist(fdist, 0.2)
lm = NgramModel(3, brown.words(categories='news'), estimator)
# Thanks to miku, I fixed this problem
print lm.prob("word", ["This is a context which generates a word"])
>> 0.00493261081006
# But I got another program like this one...
print lm.prob("b", ["This is a context which generates a word"]) 

但这似乎不起作用。结果如下:

>>> print lm.prob("word", "This is a context which generates a word")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.6/dist-packages/nltk/model/ngram.py", line 79, in prob
    return self._alpha(context) * self._backoff.prob(word, context[1:])
  File "/usr/local/lib/python2.6/dist-packages/nltk/model/ngram.py", line 79, in prob
    return self._alpha(context) * self._backoff.prob(word, context[1:])
  File "/usr/local/lib/python2.6/dist-packages/nltk/model/ngram.py", line 82, in prob
    "context %s" % (word, ' '.join(context)))
TypeError: not all arguments converted during string formatting

谁能帮我吗?谢谢!

参考资料:
Stack Overflow
收藏
评论
共 4 个回答
高赞 时间 活跃

关于您的第二个问题:发生这种情况是因为在布朗语料库类别news中没有出现"b" ,您可以使用以下方法进行验证:

>>> 'b' in brown.words(categories='news')
False

>>> 'word' in brown.words(categories='news')
True

我承认该错误消息非常含糊,因此您可能要向NLTK作者提交错误报告。

收藏
评论

我知道这个问题很旧,但是每次我在Google nltk的NgramModel类上弹出该问题。 NgramModel的概率实现有点不直观。询问者感到困惑。据我所知,答案不是很好。由于我不经常使用NgramModel,这意味着我感到困惑。不再。

源代码位于此处: https : //github.com/nltk/nltk/blob/master/nltk/model/ngram.py 。这是NgramModel的prob方法的定义:

def prob(self, word, context):
    """
    Evaluate the probability of this word in this context using Katz Backoff.

    :param word: the word to get the probability of
    :type word: str
    :param context: the context the word is in
    :type context: list(str)
    """

    context = tuple(context)
    if (context + (word,) in self._ngrams) or (self._n == 1):
        return self[context].prob(word)
    else:
        return self._alpha(context) * self._backoff.prob(word, context[1:])

注意 :'self [context] .prob(word)等同于'self._model [context] .prob(word)')

好的。现在至少我们知道要寻找什么。背景需要是什么?让我们看一下构造函数的摘录:

for sent in train:
    for ngram in ingrams(chain(self._lpad, sent, self._rpad), n):
        self._ngrams.add(ngram)
        context = tuple(ngram[:-1])
        token = ngram[-1]
        cfd[context].inc(token)

if not estimator_args and not estimator_kwargs:
    self._model = ConditionalProbDist(cfd, estimator, len(cfd))
else:
    self._model = ConditionalProbDist(cfd, estimator, *estimator_args, **estimator_kwargs)

好的。构造函数从其“上下文”是字母组合的元组的条件频率分布中创建条件概率分布(self._model)。这告诉我们,“语境” 应该是一个字符串或一个多词串名单。 “上下文” 必须是包含字母组合的可迭代对象。实际上,该要求更为严格。这些元组或列表的大小必须为n-1。这样想吧。您告诉它是一个Trigram模型。您最好为其提供适当的三字母组合上下文。

让我们通过一个更简单的示例来了解这一点:

>>> import nltk
>>> obs = 'the rain in spain falls mainly in the plains'.split()
>>> lm = nltk.NgramModel(2, obs, estimator=nltk.MLEProbDist)
>>> lm.prob('rain', 'the') #wrong
0.0
>>> lm.prob('rain', ['the']) #right
0.5
>>> lm.prob('spain', 'rain in') #wrong
0.0
>>> lm.prob('spain', ['rain in']) #wrong
'''long exception'''
>>> lm.prob('spain', ['rain', 'in']) #right
1.0

(作为一个附带说明,实际上尝试使用MLE作为NgramModel中的估计量来做任何事情都是一个坏主意。事情将会崩溃。我保证。)

至于最初的问题,我想我对OP想要的最好的猜测是:

print lm.prob("word", "generates a".split())
print lm.prob("b", "generates a".split())

...但是这里发生了太多误解,我无法说出他实际上在试图做什么。

收藏
评论

快速解决:

print lm.prob("word", ["This is a context which generates a word"])
# => 0.00493261081006
收藏
评论

我暂时不会使用NLTK的NgramModel。当前存在一个平滑错误,当n> 1时,该错误会导致模型大大高估可能性。如果您确实使用了NgramModel,则绝对应该在此处应用git问题跟踪器中提到的修复程序: https : //github.com/nltk/nltk/issues/367

收藏
评论
新手导航
  • 社区规范
  • 提出问题
  • 进行投票
  • 个人资料
  • 优化问题
  • 回答问题

关于我们

常见问题

内容许可

联系我们

@2020 AskGo
京ICP备20001863号