Python-NLTK中的Trigram概率分布平滑技术(Kneser Ney)返回零

时间:2019-07-13 07:26:52

标签: python python-3.x nltk probability smoothing

我掌握了我的卦的频率分布,然后训练了Kneser-Ney。 当我检查不在kneser_ney.prob中的三字母组合的list_of_trigrams时,我得到零!我在做什么错了?

freq_dist = nltk.FreqDist(list_of_trigrams)
kneser_ney = nltk.KneserNeyProbDist(freq_dist)

它甚至在列表中有n-1-gram,这就是我想要的:

print(kneser_ney.prob(('ئامادەكاری', 'بۆ', 'تاقیكردنەوە')))

这就是列表中的

('ئامادەكاری', 'بۆ', 'كارە')

我已经在网上搜寻了所有与我有相同问题的人,但是我没有发现任何问题...

1 个答案:

答案 0 :(得分:1)

我认为您所观察到的完全正常。

Kneser-Ney smoothing的Wikipedia页面(方法部分):

  

请注意,p_KN是一个适当的分布,因为以上述方式定义的值是非负的,并且总和为1。

0不在语料库中出现的概率为ngram

引用answer you cite

  

这是平滑的全部要点,用于将语料库中出现的ngram的一些概率质量重新分配给那些没有出现的ngram,以便最终不会得到一堆0的概率ngram。

上面的句子并不意味着通过 Kneser-Ney平滑,您选择的任何ngram的概率都将为非零,这意味着给定语料库,它将为现有ngram的方式,使您在以后的分析中有一定的 spare 概率可用于其他ngram。 这是您必须为非出现的ngram指定的空闲概率,而不是 Kneser-Ney平滑所固有的东西。


编辑

仅出于完整性考虑,我报告代码以观察行为(主要取自here,并适用于Python 3):

import nltk
nltk.download('gutenberg')
nltk.download('punkt')
from nltk.util import ngrams
from nltk.corpus import gutenberg

gut_ngrams = tuple(
    ngram for sent in gutenberg.sents()
    for ngram in ngrams(
        sent, 3, pad_left=True, pad_right=True,
        right_pad_symbol='EOS', left_pad_symbol="BOS"))
freq_dist = nltk.FreqDist(gut_ngrams)
kneser_ney = nltk.KneserNeyProbDist(freq_dist)

prob_sum = 0
for i in kneser_ney.samples():
    if i[0] == "I" and i[1] == "confess":
        prob_sum += kneser_ney.prob(i)
        print("{0}:{1}".format(i, kneser_ney.prob(i)))
print(prob_sum)
# ('I', 'confess', ','):0.26973684210526316
# ('I', 'confess', 'that'):0.16447368421052633
# ('I', 'confess', '.--'):0.006578947368421052
# ('I', 'confess', 'it'):0.03289473684210526
# ('I', 'confess', 'I'):0.16447368421052633
# ('I', 'confess', ',"'):0.03289473684210526
# ('I', 'confess', ';'):0.006578947368421052
# ('I', 'confess', 'myself'):0.006578947368421052
# ('I', 'confess', 'is'):0.006578947368421052
# ('I', 'confess', 'also'):0.006578947368421052
# ('I', 'confess', 'unto'):0.006578947368421052
# ('I', 'confess', '"--'):0.006578947368421052
# ('I', 'confess', 'what'):0.006578947368421052
# ('I', 'confess', 'there'):0.006578947368421052
# 0.7236842105263156

# trigram not appearing in corpus
print(kneser_ney.prob(('I', 'confess', 'nothing')))
# 0.0