2016-01-30 19 views
12
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 

Когда я запускаю приведенный выше код, он производит следующий вывод для предложения «выключить свет» -NLTK ViterbiParser терпит неудачу в разборе слова, которые не в правиле PCFG

(S (VP (VB turn) (PRT (RP off)) (NP (DT the) (NNS lights)))) (p=2.53851e-14)

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

ValueError: Grammar does not cover some of the input words: u"'please'"

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

+0

Нет ли способа сгладить ваши вероятности? – L3viathan

ответ

7

Во-первых, попробуйте использовать (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 грамматики, а затем перенормировать веса, дают либо очень небольшой вес до искомых слов (вы также можете попробовать умнее методов сглаживания/интерполяции)

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

+0

Кроме того, соответствующий вопрос, задающий вопрос, будет либо непосредственно в Stackoverflow, либо в списке https://groups.google.com/forum/?hl=ru#!forum/nltk-users. – alvas