Я знаю, что этот вопрос старый, но он появляется каждый раз, когда я использую класс ngramModel от Google nltk.Пробная реализация NgramModel немного неинтуитивна.Аскер в замешательстве.Насколько я могу судить, ответы не велики.Поскольку я не часто использую NgramModel, это означает, что я запутался.Не более.
Здесь находится исходный код: https://github.com/nltk/nltk/blob/master/nltk/model/ngram.py. Вот определение метода проб NgramModel:
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:])
( note : '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) из условного частотного распределения, «контекст» которого - кортежи униграмм.Это говорит нам, что «контекст» должен , а не быть строкой или списком с одной строкой из нескольких слов.'context' ДОЛЖЕН быть чем-то повторяемым, содержащим символы.На самом деле, требование немного более строгое.Эти кортежи или списки должны иметь размер n-1.Думайте об этом так.Вы сказали, что это модель триграмм.Вам лучше дать ему соответствующий контекст для триграмм.
Давайте посмотрим на это в действии на более простом примере:
>>> 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 - плохая идея. Все развалится. Я гарантирую это.)
Что касается исходного вопроса, я полагаю, что мое лучшее предположение о том, чего хочет ОП, таково:
print lm.prob("word", "generates a".split())
print lm.prob("b", "generates a".split())
... но здесь так много недоразумений, что я не могу сказать, что он на самом деле пытался сделать.