まず、(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 文法に追加し、重みを再正規化して、不明な単語に非常に小さな重みを与えます (よりスマートな平滑化/補間手法を試すこともできます)。
これは宿題の質問なので、完全なコードで答えることはしません。しかし、上記のヒントは問題を解決するのに十分なはずです.