为什么pos_tag()如此缓慢,却可以避免?

发布于 2021-01-29 14:11:19

我希望能够以这种方式一个接一个地获取句子的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
被浏览
158
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    对于NLTK
    3.1版,里面nltk/tag/__init__.pypos_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.tagwhentagsetNone。因此,您可以通过
    一次 加载文件并调用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)操作(即,它需要的时间与列表的长度成比例地增加)。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看