我希望能够以这种方式一个接一个地获取句子的POS标签:
def __remove_stop_words(self, tokenized_text, stop_words): sentences_pos = nltk.pos_tag(tokenized_text) filtered_words = [word for (word, pos) in sentences_pos if pos not in stop_words and word not in stop_words] return filtered_words
但是问题是pos_tag()每个句子大约需要一秒钟。还有另一种选择可用于pos_tag_sents()批量执行此操作并加快处理速度。但是,如果我能逐句地做这件事,我的生活会更轻松。
pos_tag()
pos_tag_sents()
有没有办法更快地做到这一点?
对于NLTK 3.1版,里面nltk/tag/__init__.py,pos_tag是这样定义的:
nltk/tag/__init__.py
pos_tag
from nltk.tag.perceptron import PerceptronTagger def pos_tag(tokens, tagset=None): tagger = PerceptronTagger() return _pos_tag(tokens, tagset, tagger)
因此,每次对pos_tagfirst的调用实例化PerceptronTagger都会花费一些时间,因为它涉及加载pickle文件。_pos_tag 只需调用tagger.tagwhentagset是None。因此,您可以通过 一次 加载文件并调用tagger.tag自己而不是调用来节省一些时间pos_tag:
PerceptronTagger
_pos_tag
tagger.tag
tagset
None
from nltk.tag.perceptron import PerceptronTagger tagger = PerceptronTagger() def __remove_stop_words(self, tokenized_text, stop_words, tagger=tagger): sentences_pos = tagger.tag(tokenized_text) filtered_words = [word for (word, pos) in sentences_pos if pos not in stop_words and word not in stop_words] return filtered_words
pos_tag_sents使用与上述相同的技巧-实例化PerceptronTagger一次,然后调用_pos_tag多次。因此,使用上述代码,您将获得与重构和调用相当的性能提升pos_tag_sents。
pos_tag_sents
另外,如果stop_words列表很长,则可以通过stop_words设置以下设置节省一些时间:
stop_words
stop_words = set(stop_words)
因为检查集合中的成员资格(例如pos not in stop_words)是一项O(1)(恒定时间)操作,而检查列表中的成员资格是一项O(n)操作(即,它需要的时间与列表的长度成比例地增加)。
pos not in stop_words
O(1)
O(n)