我正在尝试在NLTK中实现一个基于标记器的分块器。我编写的代码如下,
>>> import nltk,pprint,re,nltk.tree,string,codecs>>> import nltk.corpus, nltk.tag>>> import datetime>>> from nltk.corpus import conll2000>>> train_sents = conll2000.chunked_sents('train.txt', chunk_types=['NP'])>>> test_sents = conll2000.chunked_sents('test.txt', chunk_types=['NP'])>>> def conll_tag_chunks(chunk_sents): tag_sents = [nltk.chunk.tree2conlltags(tree) for tree in chunk_sents] return [[(t, c) for (w, t, c) in chunk_tags] for chunk_tags in tag_sents]>>> tr_chunk = conll_tag_chunks(train_sents)>>> te_chunk = conll_tag_chunks(test_sents)>>> u_chunker = nltk.UnigramTagger(tr_chunk)>>> accuracy=u_chunker.evaluate(te_chunk)>>> print accuracy0.832112628491
整体看起来不错,但我无法为新应用句子进行分类。这可能是一个非常简单的问题,但我无法解决。
如果有人可以友善地提出建议
回答:
训练数据始终是一对对的列表(<输入>, <期望输出>)
。你训练的标记器接受相同类型的<输入>
。所以看看你的训练输入:
>>> print(tr_chunk[0][:5], "...")[('NN', 'B-NP'), ('IN', 'O'), ('DT', 'B-NP'), ('NN', 'I-NP'), ('VBZ', 'O')] ...
你训练了一个基于仅它们的词性标记(丢弃原始单词)来寻找命名实体的分块器,所以要使用它,你也必须只传递一个词性标记列表。
>>> words = "I sure love New York .".split()>>> tags = [ t for (w, t) in nltk.pos_tag(words) ]>>> u_chunker.tag(tags)
如果效果不好,那就训练一个更好的分块器。