【问题标题】:How to filter out words with low tf-idf in a corpus with gensim?如何用gensim过滤掉语料库中tf-idf低的单词?
【发布时间】:2014-09-01 12:16:39
【问题描述】:

我正在使用gensim 执行一些 NLP 任务。我从dictionary.doc2bow 创建了一个语料库,其中dictionarycorpora.Dictionary 的对象。现在我想在运行 LDA 模型之前过滤掉具有低 tf-idf 值的项。我查看了语料库类的documentation,但找不到访问这些术语的方法。有任何想法吗?谢谢。

【问题讨论】:

标签: python nlp gensim


【解决方案1】:

假设您有一个由 gensim 的 TfidfModel() 生成的文档 tfidf_doc 和相应的词袋文档 bow_doc,并且您想要过滤 tfidf 值低于该文档中 cut_percent% 单词的单词,你可以调用tfidf_filter(tfidf_doc, cut_percent),然后它会返回tfidf_doc的剪切版本:

def tfidf_filter(tfidf_doc, cut_percent):

    sorted_by_tfidf = sorted(tfidf_doc, key=lambda tup: tup[1])
    cut_value = sorted_by_tfidf[int(len(sorted_by_tfidf)*cut_percent)][1]

    #print('before cut:',len(tfidf_doc))

    #print('cut value:', cut_value)
    for i in range(len(tfidf_doc)-1, -1, -1):
        if tfidf_doc[i][1] < cut_value:
            tfidf_doc.pop(i)

    #print('after cut:',len(tfidf_doc))

    return tfidf_doc

然后你想通过生成的tfidf_doc过滤文档bow_doc,只需调用filter_bow_by_tfidf(bow_doc, tfidf_doc),它将返回bow_doc的剪切版本:

def filter_bow_by_tfidf(bow_doc, tfidf_doc):
    bow_idx = len(bow_doc)-1
    tfidf_idx = len(tfidf_doc)-1

    #print('before :', len(bow_doc))

    while True:
        if bow_idx < 0: break

        if tfidf_idx < 0:
            #print('pop2 :', bow_doc.pop(bow_idx))
            bow_doc.pop(bow_idx)
            bow_idx -= 1
        if bow_doc[bow_idx][0] > tfidf_doc[tfidf_idx][0]:
            #print('pop1 :', bow_doc.pop(bow_idx))
            bow_doc.pop(bow_idx)
            bow_idx -= 1
        if bow_doc[bow_idx][0] == tfidf_doc[tfidf_idx][0]:
            #print('keep :', bow_doc[bow_idx])
            bow_idx -= 1
            tfidf_idx -= 1

    #print('after :', len(bow_doc))

    return bow_doc

【讨论】:

    【解决方案2】:

    这与之前的答案基本相同,但额外处理了 tf-idf 表示中由于 0 分而缺失的单词(所有文档中都存在术语)。以前的答案没有过滤这些术语,它们仍然出现在最终的语料库中。

    #Same as before
    
    dictionary = corpora.Dictionary(doc_list)
    corpus = [dictionary.doc2bow(doc) for doc in doc_list]
    tfidf = models.TfidfModel(corpus, id2word = dictionary)
    
    
    #Filter low value words and also words missing in tfidf models.
    
    low_value = 0.025
    
    for i in range(0, len(corpus)):
        bow = corpus[i]
        low_value_words = [] #reinitialize to be safe. You can skip this.
        tfidf_ids = [id for id, value in tfidf[bow]]
        bow_ids = [id for id, value in bow]
        low_value_words = [id for id, value in tfidf[bow] if value < low_value]
        words_missing_in_tfidf = [id for id in bow_ids if id not in tfidf_ids] # The words with tf-idf socre 0 will be missing
    
        new_bow = [b for b in bow if b[0] not in low_value_words and b[0] not in words_missing_in_tfidf]  
    
    #reassign        
    corpus[i] = new_bow
    

    【讨论】:

      【解决方案3】:

      这是旧的,但如果您想查看每个文档级别的内容,请执行以下操作:

      #same as before
      dictionary = corpora.Dictionary(doc_list)
      corpus = [dictionary.doc2bow(doc) for doc in doc_list]
      tfidf = models.TfidfModel(corpus, id2word = dictionary)
      
      #filter low value words
      low_value = 0.025
      
      for i in range(0, len(corpus)):
          bow = corpus[i]
          low_value_words = [] #reinitialize to be safe. You can skip this.
          low_value_words = [id for id, value in tfidf[bow] if value < low_value]
          new_bow = [b for b in bow if b[0] not in low_value_words]
      
          #reassign        
          corpus[i] = new_bow
      

      【讨论】:

        【解决方案4】:

        假设你的语料库如下:

        corpus = [dictionary.doc2bow(doc) for doc in documents]
        

        运行 TFIDF 后,您可以检索低值单词列表:

        tfidf = TfidfModel(corpus, id2word=dictionary)
        
        low_value = 0.2
        low_value_words = []
        for bow in corpus:
            low_value_words += [id for id, value in tfidf[bow] if value < low_value]
        

        然后在运行 LDA 之前将它们从字典中过滤掉:

        dictionary.filter_tokens(bad_ids=low_value_words)
        

        现在重新计算语料库,过滤掉低价值的词:

        new_corpus = [dictionary.doc2bow(doc) for doc in documents]
        

        【讨论】:

        • 但是,如果一个词在所有文档中的 tf-idf 高于阈值,而仅在一个文档中的 tf-idf 低于阈值,则会从所有文档中删除。
        • 如果我们使用 tf-idf 过滤令牌,这与 dictionary.filter_extremes() 有何不同?
        猜你喜欢
        • 1970-01-01
        • 2020-03-16
        • 2020-01-06
        • 2014-04-21
        • 2013-05-31
        • 2016-08-07
        • 1970-01-01
        • 2019-04-14
        • 2017-05-30
        相关资源
        最近更新 更多