Как выполнить сглаживание Кнезера-Нея в NLTK на уровне слов для триграммовой языковой модели? - PullRequest
0 голосов
/ 10 января 2020

Я пытаюсь обучить языковой модели на трех граммах текстового корпуса и хочу выполнить сглаживание KN. По-видимому, 'nltk.trigrams' делает это на уровне персонажа. Мне было интересно, как я смогу сделать это на уровне слов, а также выполнить сглаживание KN. Вот фрагмент кода, который я написал и не работает:

    with open('file.txt',"r",encoding = "ISO-8859-1") as ff:
        text = ff.read()

    word_tok = tknzr.tokenize(text)
    ngrams = nltk.trigrams(word_tok)
    freq_dist = nltk.FreqDist(ngrams)
    kneser_ney = nltk.KneserNeyProbDist(freq_dist)
    print(kneser_ney.prob('you go to'))

Я получаю ошибку:

    Expected an iterable with 3 members.

1 Ответ

0 голосов
/ 12 января 2020

Заменить строку:

print(kneser_ney.prob('you go to'))

на:

print(kneser_ney.prob('you go to'.split()))

Тогда все работает нормально. Я получаю значение 0,05217391304347826 при использовании в качестве учебного файла текста из романа «Моби Дик», загруженного из Project Gutenberg

С этой модификацией ваш код становится аналогом полному крылу:

with open('./txts/mobyDick.txt') as ff:
    text = ff.read()


from nltk import word_tokenize,trigrams
from nltk import FreqDist, KneserNeyProbDist


word_tok = word_tokenize(text)
ngrams = trigrams(word_tok)
freq_dist = FreqDist(ngrams)
kneser_ney = KneserNeyProbDist(freq_dist)
print(kneser_ney.prob('you go to'.split()))

Также все здесь делается на уровне слов, а не на уровне символов:

ngrams = trigrams(word_tok)
for _ in range(0,10):
    print(next(ngrams))

#('\ufeff', 'The', 'Project')
#('The', 'Project', 'Gutenberg')
#('Project', 'Gutenberg', 'EBook')
#('Gutenberg', 'EBook', 'of')
#('EBook', 'of', 'Moby')
#('of', 'Moby', 'Dick')
#('Moby', 'Dick', ';')
#('Dick', ';', 'or')
#(';', 'or', 'The')
#('or', 'The', 'Whale')

Распределение частот также на уровне слов:

freq_dist.freq(tuple('on the ocean'.split()))
#7.710783916846906e-06
freq_dist.freq(tuple('new Intel CPU'.split()))
#0.0


...