我试图使用Python NLTK使用Kneser-Ney平滑来平滑一组n-gram概率。 不幸的是,整个文档非常稀少。
我要做的是:把一个文本解析成一个三元组的列表。从这个列表中,我创建了一个FreqDist,然后使用这个FreqDist来计算KN平滑分布。
我很确定,结果是完全错误的。当我把个体的概率加起来,我得到的结果远远超过了1。以下面的代码为例:
import nltk
ngrams = nltk.trigrams("What a piece of work is man! how noble in reason! how infinite in faculty! in \
form and moving how express and admirable! in action how like an angel! in apprehension how like a god! \
the beauty of the world, the paragon of animals!")
freq_dist = nltk.FreqDist(ngrams)
kneser_ney = nltk.KneserNeyProbDist(freq_dist)
prob_sum = 0
for i in kneser_ney.samples():
prob_sum += kneser_ney.prob(i)
print(prob_sum)
输出为“41.5169642857428”。根据语料库的大小,这个值会无限大。这使得prob()只返回概率分布。
看看NLTK代码,我会说实现是有问题的。也许我只是不明白该如何使用代码。那样的话,你能给我个提示吗?在任何其他情况下:您知道任何正在工作的Python实现吗?我真的不想自己实现它。
Kneser-Ney(也可以查看一下Goodman and Chen,了解不同的平滑技术)是一个相当复杂的平滑,只有少数几个包我知道它是正确的。不知道任何python实现,但如果您只需要概率等,您绝对可以尝试SRILM
回答你的另一个问题:
我刚刚用Python完成了Kneser-Ney的实现。代码是here;自述文件中也有报告。如果有任何疑问请写信给我。
我认为你误解了奈伊在计算什么。
来自Wikipedia:
当然,我们在这里讨论的是大论,但对于高阶模型,同样的原理也是正确的。基本上,这句话的意思是,对于一个固定的上下文wi-1(或者更高阶模型的上下文),所有wi的概率必须加在一起。当你把所有样本的概率加起来时,你所做的就是包含多个上下文,这就是为什么你最终得到的“概率”大于1。如果保持上下文不变,如下面的代码示例中所示,则最终会得到一个数字<;=1。
基于NLTK-Gutenberg语料子集的输出如下。
这个和(.72)小于1的原因是,概率只计算出现在第一个单词是“I”而第二个单词是“忏悔”的语料库中的三元组。剩余的.28概率保留给在语料库中不跟在“I”和“忏悔”后面的wIs。这就是平滑的全部要点,从出现在语料库中的ngram到那些不出现的ngram重新分配一些概率质量,这样你就不会得到一堆0概率的ngram。
也不是这样
计算字符三联图?我认为这需要被标记化来计算单词三元组。
相关问题 更多 >
编程相关推荐