Подтвердить что ты не робот

NLTK ViterbiParser не удается выполнить синтаксический анализ слов, которые не соответствуют правилу PCFG

import nltk
from nltk.parse import ViterbiParser

def pcfg_chartparser(grammarfile):
    f=open(grammarfile)
    grammar=f.read()
    f.close()
    return nltk.PCFG.fromstring(grammar)

grammarp = pcfg_chartparser("wsjp.cfg")

VP = ViterbiParser(grammarp)
print VP
for w in sent:
    for tree in VP.parse(nltk.word_tokenize(w)):
        print tree

Когда я запускаю вышеуказанный код, он производит следующий вывод для предложения: "выключите свет" -

(S   (VP (вращение VB)) (PRT (RP off)) (NP (DT) (подсветка NNS)))) (p = 2.53851e-14)

Однако, это вызывает следующую ошибку для предложения: "пожалуйста, выключите свет" -

ValueError: Грамматика не охватывает некоторые входные слова: u "'please'"

Я создаю ViterbiParser, предоставляя ему вероятностную контекстную свободную грамматику. Он хорошо работает при разборе предложений, содержащих слова, которые уже находятся в правилах грамматики. Он не разбирает предложения, в которых Парсер не видел слова в грамматических правилах. Как обойти это ограничение?
Я имею в виду это assignment.

4b9b3361

Ответ 1

Во-первых, попробуйте использовать (i) пространства имен и (ii) однозначные имена переменных, например:

>>> from nltk import PCFG
>>> from nltk.parse import ViterbiParser
>>> import urllib.request
>>> response = urllib.request.urlopen('https://raw.githubusercontent.com/salmanahmad/6.863/master/Labs/Assignment5/Code/wsjp.cfg')
>>> wsjp = response.read().decode('utf8')
>>> grammar = PCFG.fromstring(wsjp)
>>> parser = ViterbiParser(grammar)
>>> list(parser.parse('turn off the lights'.split()))
[ProbabilisticTree('S', [ProbabilisticTree('VP', [ProbabilisticTree('VB', ['turn']) (p=0.002082678), ProbabilisticTree('PRT', [ProbabilisticTree('RP', ['off']) (p=0.1089101771)]) (p=0.10768769667270556), ProbabilisticTree('NP', [ProbabilisticTree('DT', ['the']) (p=0.7396712852), ProbabilisticTree('NNS', ['lights']) (p=4.61672e-05)]) (p=4.4236397464693323e-07)]) (p=1.0999324002161311e-13)]) (p=2.5385077255727538e-14)]

Если мы посмотрим на грамматику:

>>> grammar.check_coverage('please turn off the lights'.split())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.4/dist-packages/nltk/grammar.py", line 631, in check_coverage
    "input words: %r." % missing)
ValueError: Grammar does not cover some of the input words: "'please'".

Чтобы устранить проблемы с неизвестным словом, существует несколько параметров:

  • Используйте wildcard нетерминальные узлы для замены неизвестных слов. Найдите способ заменить слова, которые грамматика не покрывает из check_coverage() с помощью wildcard, затем проанализируйте предложение с помощью подстановочного знака

    • это обычно уменьшает точность анализатора, если вы специально не тренируете PCFG с помощью грамматики, которая обрабатывает неизвестные слова, а подстановочный знак является надмножеством неизвестных слов.
  • Вернитесь к своему файлу создания грамматики, который у вас есть, прежде чем создавать обучение PCFG с learn_pcfg.py и добавить все возможные слова в терминальные производства.

  • Добавьте неизвестные слова в грамматику pcfg, а затем перенормируйте веса, учитывая либо очень малые веса для неизвестных слов (вы также можете попробовать более умные методы сглаживания/интерполяции)

Так как это вопрос домашней работы, я не буду давать ответ с полным кодом. Но намеков выше должно быть достаточно, чтобы решить проблему.