Английский не мой родной язык. Приносим извинения за грамматические ошибки.
Я видел много документов для добавления одного сглаживания в языковую модель, и меня все еще очень смущает переменная V в формуле:
P (wi |w_i-1 ) = c(w_i-1 ,wi )+1 / c(w_i-1 )+V
что касается корпуса этого примера, и я использую биграмму
<s> John read Moby Dick </s>
<s> Mary read a different book </s>
<s> She read a book by Cher </s>
если я хочу вычислить любое P (wi | w_i-1). V будет 11 потому что количество комбинаций [w_i-1, w] равно 11 . Но я обнаружил, что он не включает регистр [w_i-1, "<" / s ">"] (или V будет 12) Почему нам не нужно включать этот случай? Разве w_i-1 не стоит в конце статьи или предложения?
Здесь есть хороший учебник: 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
С дополнительным сглаживанием, также известным как Сглаживание Лапласа,
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>
?
А: Одна из возможных причин состоит в том, что мы никогда не рассматриваем пустые предложения в языковых моделях, поэтому <s>
и </s>
не могут работать сами по себе, а словарь |V|
исключает их.
Можно ли добавить их в |V|
?
А: На самом деле, если |V|
- это достаточно большой, наличие +2 для <s>
и </s>
не имеет большого значения. Пока |V|
согласован и фиксирован согласован во всех вычислениях и имеет значение достаточно большой, вероятности языковой модели любого предложения относительно другого предложения с той же языковой моделью не должны сильно отличаться.
Спасибо за подробный ответ. Но хочу спросить, например, в п.8 туториала. Когда мы хотим вычислить p (READ | CHER), мы также принимаем во внимание [CHER, </S>], поэтому знаменатель равен 1. Но почему мы не принимаем его во внимание, когда рассматриваем добавление сглаживания?