首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NLTK包估计(unigram)困惑

NLTK包估计(unigram)困惑
EN

Stack Overflow用户
提问于 2015-10-22 02:48:31
回答 2查看 14.5K关注 0票数 10

我正在尝试计算我所拥有的数据的困惑程度。我使用的代码是:

代码语言:javascript
复制
 import sys
 sys.path.append("/usr/local/anaconda/lib/python2.7/site-packages/nltk")

from nltk.corpus import brown
from nltk.model import NgramModel
from nltk.probability import LidstoneProbDist, WittenBellProbDist
estimator = lambda fdist, bins: LidstoneProbDist(fdist, 0.2)
lm = NgramModel(3, brown.words(categories='news'), True, False, estimator)
print lm

但我收到了错误,

代码语言:javascript
复制
File "/usr/local/anaconda/lib/python2.7/site-packages/nltk/model/ngram.py", line 107, in __init__
cfd[context][token] += 1
TypeError: 'int' object has no attribute '__getitem__'

我已经为我拥有的数据执行了潜在的Dirichlet分配,并且我已经生成了unigram及其各自的概率(它们被归一化为数据的总概率之和为1)。

我的unigram和它们的概率如下:

代码语言:javascript
复制
Negroponte 1.22948976891e-05
Andreas 7.11290670484e-07
Rheinberg 7.08255885794e-07
Joji 4.48481435106e-07
Helguson 1.89936727391e-07
CAPTION_spot 2.37395965468e-06
Mortimer 1.48540253778e-07
yellow 1.26582575863e-05
Sugar 1.49563800878e-06
four 0.000207196011781

这只是我拥有的unigram文件的一小部分。对于大约1000行,遵循相同的格式。总概率(第二列)总和为1。

我是一名初露头角的程序员。这个ngram.py属于nltk包,我不知道如何纠正这个问题。我这里的示例代码来自nltk文档,我不知道现在该怎么做。请帮我做点什么。提前感谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-10-22 05:16:34

困惑是测试集的反向概率,通过字数进行归一化。在单字的情况下:

现在你说你已经构建了单字模型,这意味着,对于每个单词,你都有相关的概率。然后你只需要应用这个公式。我假设您有一个很大的字典unigram[word],它可以提供语料库中每个单词的概率。您还需要有一个测试集。如果您的unigram模型不是字典形式的,请告诉我您使用了什么数据结构,以便我可以相应地调整它以适应我的解决方案。

代码语言:javascript
复制
perplexity = 1
N = 0

for word in testset:
    if word in unigram:
        N += 1
        perplexity = perplexity * (1/unigram[word])
perplexity = pow(perplexity, 1/float(N))

更新:

正如您所要求的一个完整的工作示例,这里有一个非常简单的示例。

假设这是我们的语料库:

代码语言:javascript
复制
corpus ="""
Monty Python (sometimes known as The Pythons) were a British surreal comedy group who created the sketch comedy show Monty Python's Flying Circus,
that first aired on the BBC on October 5, 1969. Forty-five episodes were made over four series. The Python phenomenon developed from the television series
into something larger in scope and impact, spawning touring stage shows, films, numerous albums, several books, and a stage musical.
The group's influence on comedy has been compared to The Beatles' influence on music."""

下面是我们如何首先构建unigram模型:

代码语言:javascript
复制
import collections, nltk
# we first tokenize the text corpus
tokens = nltk.word_tokenize(corpus)

#here you construct the unigram language model 
def unigram(tokens):    
    model = collections.defaultdict(lambda: 0.01)
    for f in tokens:
        try:
            model[f] += 1
        except KeyError:
            model [f] = 1
            continue
    N = float(sum(model.values()))
    for word in model:
        model[word] = model[word]/N
    return model

我们这里的模型是平滑的。对于其知识范围之外的单词,它分配0.01的概率较低。我已经告诉过你如何计算困惑:

代码语言:javascript
复制
#computes perplexity of the unigram model on a testset  
def perplexity(testset, model):
    testset = testset.split()
    perplexity = 1
    N = 0
    for word in testset:
        N += 1
        perplexity = perplexity * (1/model[word])
    perplexity = pow(perplexity, 1/float(N)) 
    return perplexity

现在我们可以在两个不同的测试集上进行测试:

代码语言:javascript
复制
testset1 = "Monty"
testset2 = "abracadabra gobbledygook rubbish"

model = unigram(tokens)
print perplexity(testset1, model)
print perplexity(testset2, model)

您将获得以下结果:

代码语言:javascript
复制
>>> 
49.09452736318415
99.99999999999997

请注意,在处理困惑时,我们会尝试减少它。对于某个测试集,具有较少困惑的语言模型比具有较大困惑的语言模型更可取。在第一个测试集中,单词Monty被包括在单字模型中,因此困惑的相应数字也较小。

票数 21
EN

Stack Overflow用户

发布于 2018-01-18 00:10:49

谢谢你的代码片段!不应该:

代码语言:javascript
复制
for word in model:
        model[word] = model[word]/float(sum(model.values()))

更确切地说:

代码语言:javascript
复制
v = float(sum(model.values()))
for word in model:
        model[word] = model[word]/v

哦..。我看我已经回答了..。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33266956

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档