我希望能够以这种方式逐个获得句子的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()
来批量执行此操作并加快速度。但如果我可以逐句判刑,我的生活会更容易。
有没有办法更快地完成这项工作?
答案 0 :(得分:16)
对于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
的每次调用都会首先实例化PerceptronTagger
,这需要一些时间,因为它涉及loading a pickle file。 _pos_tag
为tagset
时None
simply calls tagger.tag
。
因此,您可以通过加载文件一次来节省一些时间,并自行致电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
使用与上述相同的技巧 - it instantiates PerceptronTagger
once,然后多次调用_pos_tag
。因此,您可以使用上述代码获得相似的性能提升,就像重构和调用pos_tag_sents
一样。
此外,如果stop_words
是一个长列表,您可以通过设置stop_words
来节省一些时间:
stop_words = set(stop_words)
因为检查集合中的成员资格(例如pos not in stop_words
)是O(1)
(常量时间)操作,而检查列表中的成员资格是O(n)
操作(即它需要时间增长与列表长度成比例。)