为什么pos_tag()如此缓慢,却可以避免?
我希望能够以这种方式一个接一个地获取句子的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()
批量执行此操作并加快处理速度。但是,如果我能逐句地做这件事,我的生活会更轻松。
有没有办法更快地做到这一点?
-
对于NLTK
3.1版,里面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_tag
first的调用实例化PerceptronTagger
都会花费一些时间,因为它涉及加载pickle文件。_pos_tag
只需调用tagger.tag
whentagset
是None
。因此,您可以通过
一次 加载文件并调用tagger.tag
自己而不是调用来节省一些时间pos_tag
: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
。
另外,如果
stop_words
列表很长,则可以通过stop_words
设置以下设置节省一些时间:stop_words = set(stop_words)
因为检查集合中的成员资格(例如
pos not in stop_words
)是一项O(1)
(恒定时间)操作,而检查列表中的成员资格是一项O(n)
操作(即,它需要的时间与列表的长度成比例地增加)。