Здесь есть хороший учебник: https://nlp.stanford.edu/~wcmac/papers/20050421-smoothing-tutorial.pdf
Рассмотрим модель языка ngram (без сглаживания):
p (w_i | w_i-1) = c (w_i-1 w_i) / c (w_i-1)
p (w_1, w_2 ... w_n) = product_i = 1_to_n (p (w_i | w_i-1))
В коде:
from collections import Counter
from functools import reduce, partial
from operator import mul
from nltk import ngrams
def prob_product(prob_list):
return reduce(mul, prob_list, 1)
text = [['<s>', 'John', 'read', 'Moby', 'Dick', '</s>'],
['<s>', 'Mary', 'read', 'a', 'different', 'book', '</s>'],
['<s>', 'She', 'read', 'a', 'book', 'by', 'Cher', '</s>']]
bigram_counts = sum([Counter(ngrams(t, 2)) for t in text], Counter())
unigram_counts = sum([Counter(ngrams(t, 1)) for t in text], Counter())
count_S_John = bigram_counts[('<s>', 'John')]
count_S = unigram_counts[('<s>',)]
sentence = '<s> John read a book </s>'.split()
prob_S_John_read_a_book = prob_product([bigram_counts[bg]/unigram_counts[bg[:-1]]
for bg in ngrams(sentence, 2)])
print(prob_S_John_read_a_book) # 0.555555
for bg in ngrams(sentence, 2):
print(bg, bigram_counts[bg], unigram_counts[bg[:-1]])
[выход]:
0.55555
('<s>', 'John') 1 3
('John', 'read') 1 1
('read', 'a') 2 3
('a', 'book') 1 2
('book', '</s>') 1 2
С добавлением сглаживания, aka Сглаживание по Лапласу ,
p (w_i | w_i-1) = (1 + c (w_i-1 w_i)) / (| V | + c (w_i-1))
где |V|
- количество токенов (обычно без <s>
и </s>
).
Так в коде:
laplace_prob_S_John_read_a_book = prob_product([(1+bigram_counts[bg]) / (len(unigram_counts)-2 + unigram_counts[bg[:-1]])
for bg in ngrams(sentence, 2)])
print(laplace_prob_S_John_read_a_book)
for bg in ngrams(sentence, 2):
print(bg, 1+bigram_counts[bg], len(unigram_counts)-2 + unigram_counts[bg[:-1]])
[выход]:
0.00012075836251660427
('<s>', 'John') 2 14
('John', 'read') 2 12
('read', 'a') 3 14
('a', 'book') 2 13
('book', '</s>') 2 13
Примечание: len(unigram_counts)-2
отвечает за удаление <s>
и </s>
из номера. слов в словаре.
Выше это как.
В: Почему |V|
не учитывает <s>
и </s>
?
A: Одна из возможных причин заключается в том, что мы никогда не рассматриваем пустые предложения в языковых моделях, поэтому <s>
и </s>
не могут стоять самостоятельно, а словарь |V|
исключает их.
Можно ли добавить их в |V|
?
A: На самом деле, если |V|
достаточно достаточно большой , то наличие +2 для <s>
и </s>
не будет иметь большого значения. До тех пор, пока |V|
непротиворечиво и фиксировано непротиворечиво во всех вычислениях и достаточно велико , вероятности языковой модели любого предложения относительно другого предложения с той же языковой моделью не должны быть слишком разными.