2016-01-30 40 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 

Quando eseguo il codice di cui sopra, si produce il seguente output per la frase, "spegnere le luci" -NLTK ViterbiParser fallisce nel parsing parole che non sono in regola PCFG

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

Tuttavia , solleva il seguente errore per la frase, "si prega di spegnere le luci" -

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

sto costruendo un ViterbiParser fornendo una grammatica libera dal contesto probabilistico. Funziona bene nell'analisi di frasi che hanno parole che sono già nelle regole della grammatica. Non riesce ad analizzare le frasi in cui Parser non ha visto la parola nelle regole grammaticali. Come aggirare questa limitazione?
Mi riferisco a questo assignment.

+0

Non c'è modo di attenuare le probabilità? – L3viathan

risposta

7

In primo luogo, cercare di utilizzare (i) spazi dei nomi e (ii) i nomi delle variabili inequivocabili, ad esempio:

>>> 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)] 

Se guardiamo la grammatica:

>>> 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'". 

Per risolvere la parola sconosciuta problemi, ci sono diverse opzioni:

  • Utilizzare i nodi non-terminali wildcard per sostituire le parole sconosciute. Trovare un modo per sostituire le parole che la grammatica non coprire dal check_coverage() con l'wildcard, quindi analizzare la frase con il carattere jolly

    • questo di solito diminuisce la precisione del parser meno che non abbia espressamente allenare il PCFG con una grammatica che gestisce le parole sconosciute e il carattere jolly è un superset delle parole sconosciute.
  • Torna al file produzione grammaticale che si ha prima di creare l'apprendimento della PCFG con learn_pcfg.py e aggiungere tutte le parole possibili nelle produzioni terminali.

  • Aggiungere le parole sconosciute nella tua grammatica PCFG e poi rinormalizzare i pesi, data o molto piccoli pesi alle parole sconosciute (si può provare anche più intelligenti tecniche di levigatura/interpolazione)

Dal momento che questo è una domanda sui compiti a casa. Non darò la risposta con il codice completo. Ma i suggerimenti sopra dovrebbero essere sufficienti per risolvere il problema.

+0

Inoltre, il canale appropriato per porre una domanda potrebbe essere direttamente in Stackoverflow o nell'elenco https://groups.google.com/forum/?hl=it#!forum/nltk-users. – alvas