我尝试对文本进行一些处理。这是我的代码的一部分:
fp = open(train_file)
raw = fp.read()
sents = fp.readlines()
words = nltk.tokenize.word_tokenize(raw)
bigrams = ngrams(words,2, left_pad_symbol='<s>', right_pad_symbol=</s>)
fdist = nltk.FreqDist(words)
在旧版本的nltk
中,我在StackOverflow上找到了perplexity
的这段代码
estimator = lambda fdist, bins: LidstoneProbDist(fdist, 0.2)
lm = NgramModel(5, train, estimator=estimator)
print("len(corpus) = %s, len(vocabulary) = %s, len(train) = %s, len(test) = %s" % ( len(corpus), len(vocabulary), len(train), len(test) ))
print("perplexity(test) =", lm.perplexity(test))
但是,此代码不再有效,因此,在nltk
中没有找到任何其他包或函数。我应该实施吗?
答案 0 :(得分:1)
让我们假设我们有一个模型,该模型将一个英语句子作为输入,并给出一个概率分数,该分数对应于它是一个有效英语句子的可能性。我们想确定这个模型有多好。一个好的模型应该给有效的英语句子打高分,给无效的英语句子打低分。困惑度是一种常用的度量,用于量化这种模型的“良好”程度。如果句子 s 包含 n 个单词,那么就会感到困惑
因此,给定一些数据(称为火车数据),我们可以计算上述条件概率。但是,实际上是不可能的,因为这将需要大量的训练数据。然后,我们假设要计算
下一个单词仅取决于前一个单词
接下来的单词仅取决于前面的 n 个单词
最大似然估计(MLE)是一种估计个体概率的方法
count(w)是单词w在火车数据中出现的次数
count(vocab)是火车数据中唯一词(称为词汇)的数量。
count(w_ {i-1},w_i)是单词w_ {i-1},w_i在火车数据中以相同顺序(字母组合)一起出现的次数
count(w_ {i-1})是单词w_ {i-1}在列车数据中出现的次数。 w_ {i-1}称为上下文。
我们已经看到$ p(s)$以上是通过将许多小数字相乘来计算的,因此由于计算机上浮点数的精度有限,因此在数值上不稳定。让我们使用log的漂亮属性来简化它。我们知道
火车数据[“一个苹果”,“一个橙色”] 词汇:[一个,苹果,橘子,UNK]
MLE估计
对于测试句子“苹果”
l = (np.log2(0.5) + np.log2(0.25))/2 = -1.5
np.power(2, -l) = 2.8284271247461903
对于测试语句“一只蚂蚁”
l = (np.log2(0.5) + np.log2(0))/2 = inf
码
import nltk
from nltk.lm.preprocessing import padded_everygram_pipeline
from nltk.lm import MLE
train_sentences = ['an apple', 'an orange']
tokenized_text = [list(map(str.lower, nltk.tokenize.word_tokenize(sent)))
for sent in train_sentences]
n = 1
train_data, padded_vocab = padded_everygram_pipeline(n, tokenized_text)
model = MLE(n)
model.fit(train_data, padded_vocab)
test_sentences = ['an apple', 'an ant']
tokenized_text = [list(map(str.lower, nltk.tokenize.word_tokenize(sent)))
for sent in test_sentences]
test_data, _ = padded_everygram_pipeline(n, tokenized_text)
for test in test_data:
print ("MLE Estimates:", [((ngram[-1], ngram[:-1]),model.score(ngram[-1], ngram[:-1])) for ngram in test])
test_data, _ = padded_everygram_pipeline(n, tokenized_text)
for i, test in enumerate(test_data):
print("PP({0}):{1}".format(test_sentences[i], model.perplexity(test)))
火车数据:“一个苹果”,“一个橙色” 填充的火车数据:“(s)一个苹果(/ s)”,“(s)一个橙子(/ s)” 词汇:(s),(/ s)an,苹果,橙子,UNK
MLE估计
对于测试句子“一个苹果”,填充:“(s)一个苹果(s)”
l = (np.log2(p(an|<s> ) + np.log2(p(apple|an) + np.log2(p(</s>|apple))/3 =
(np.log2(1) + np.log2(0.5) + np.log2(1))/3 = -0.3333
np.power(2, -l) = 1.
对于测试语句“一只蚂蚁”,填充:“(s)只蚂蚁(s)”
l = (np.log2(p(an|<s> ) + np.log2(p(ant|an) + np.log2(p(</s>|ant))/3 = inf
码
import nltk
from nltk.lm.preprocessing import padded_everygram_pipeline
from nltk.lm import MLE
from nltk.lm import Vocabulary
train_sentences = ['an apple', 'an orange']
tokenized_text = [list(map(str.lower, nltk.tokenize.word_tokenize(sent))) for sent in train_sentences]
n = 2
train_data = [nltk.bigrams(t, pad_right=True, pad_left=True, left_pad_symbol="<s>", right_pad_symbol="</s>") for t in tokenized_text]
words = [word for sent in tokenized_text for word in sent]
words.extend(["<s>", "</s>"])
padded_vocab = Vocabulary(words)
model = MLE(n)
model.fit(train_data, padded_vocab)
test_sentences = ['an apple', 'an ant']
tokenized_text = [list(map(str.lower, nltk.tokenize.word_tokenize(sent))) for sent in test_sentences]
test_data = [nltk.bigrams(t, pad_right=True, pad_left=True, left_pad_symbol="<s>", right_pad_symbol="</s>") for t in tokenized_text]
for test in test_data:
print ("MLE Estimates:", [((ngram[-1], ngram[:-1]),model.score(ngram[-1], ngram[:-1])) for ngram in test])
test_data = [nltk.bigrams(t, pad_right=True, pad_left=True, left_pad_symbol="<s>", right_pad_symbol="</s>") for t in tokenized_text]
for i, test in enumerate(test_data):
print("PP({0}):{1}".format(test_sentences[i], model.perplexity(test)))