【问题标题】:sklearn's TfidfVectorizer word frequency?sklearn的TfidfVectorizer词频?
【发布时间】:2016-03-02 20:36:41
【问题描述】:

我对 sklearn 的 TfidfVectorizer 在处理每个文档中单词的频率时有疑问。

我看到的示例代码是:

>>> from sklearn.feature_extraction.text import TfidfVectorizer

>>> corpus = [

>>>     'The dog ate a sandwich and I ate a sandwich',
>>>     'The wizard transfigured a sandwich'
>>> ]

>>> vectorizer = TfidfVectorizer(stop_words='english')

>>> print vectorizer.fit_transform(corpus).todense()

[[ 0.75458397  0.37729199  0.53689271  0.          0.        ]
[ 0.          0.          0.44943642  0.6316672   0.6316672 ]]

我的问题是:如何解释矩阵中的数字?我知道 0 意味着这个词,即向导在第一个文档中出现 0 次,因此它是 0,但是我如何解释数字 0.75458397?是“吃”这个词在第一个文件中出现的频率吗?还是“吃”这个词在整个语料库中出现的频率?

【问题讨论】:

    标签: python scikit-learn tf-idf


    【解决方案1】:

    TF-IDF(意思是“词频 - 逆文档频率”)在其表示中为您提供词的频率。

    TF-IDF 对仅出现在极少数文档中的术语给予高分,而对出现在许多文档中的术语给予低分,因此它粗略地衡量一个术语在给定文档中的区分度。查看this 资源以找到对 TF-IDF 的出色描述并更好地了解它的作用。

    如果您只想要计数,则需要使用CountVectorizer

    【讨论】:

    • examine_row=tv_df.iloc[0] print(examine_row.sort_values(ascending=False)) 数字越大,在文档中的使用频率越高
    • 如何单独获得词频? CountVectorizer 返回计数,而不是频率...
    • 你能详细说明你所说的频率是什么意思吗? IE。 “词频”中的频率表示“计数”。
    【解决方案2】:

    我想你忘记了 TF-IDF 向量通常是标准化的,所以它们的大小(长度或 2 范数)总是 1。

    因此,TFIDF 值0.75 是“ate”的频率乘以“ate”的逆文档频率,然后除以该 TF-IDF 向量的幅度

    这里是所有肮脏的细节(跳到tfidf0 =的妙语):

    from sklearn.feature_extraction.text import TfidfVectorizer
    corpus = ["The dog ate a sandwich and I ate a sandwich",
              "The wizard transfigured a sandwich"]
    vectorizer = TfidfVectorizer(stop_words='english')
    tfidfs = vectorizer.fit_transform(corpus)
    
    
    from collections import Counter
    import pandas as pd
    
    columns = [k for (v, k) in sorted((v, k)
               for k, v in vectorizer.vocabulary_.items())]
    tfidfs = pd.DataFrame(tfidfs.todense(),
                          columns=columns)
    #     ate   dog  sandwich  transfigured  wizard 
    #0   0.75  0.38      0.54          0.00    0.00
    #1   0.00  0.00      0.45          0.63    0.63
    
    df = (1 / pd.DataFrame([vectorizer.idf_], columns=columns))
    #     ate   dog  sandwich  transfigured  wizard
    #0   0.71  0.71       1.0          0.71    0.71
    corp = [txt.lower().split() for txt in corpus]
    corp = [[w for w in d if w in vectorizer.vocabulary_] for d in corp]
    tfs = pd.DataFrame([Counter(d) for d in corp]).fillna(0).astype(int)
    #    ate  dog  sandwich  transfigured  wizard
    #0    2    1         2             0       0
    #1    0    0         1             1       1
    
    # The first document's TFIDF vector:
    tfidf0 = tfs.iloc[0] * (1. / df)
    tfidf0 = tfidf0 / pd.np.linalg.norm(tfidf0)
    #        ate       dog  sandwich  transfigured  wizard
    #0  0.754584  0.377292  0.536893           0.0     0.0
    
    tfidf1 = tfs.iloc[1] * (1. / df)
    tfidf1 = tfidf1 / pd.np.linalg.norm(tfidf1)
    #    ate  dog  sandwich  transfigured    wizard
    #0   0.0  0.0  0.449436      0.631667  0.631667
    

    【讨论】:

      【解决方案3】:

      只需在代码下方打印,您就会看到类似的输出

      #(0, 1)        0.448320873199    Document 1, term = Dog
      #(0, 3)        0.630099344518    Document 1, term = Sandwitch
      
          print(vectorizer.fit_transform(corpus))  
      # if python 3 other wise remove () in print
      

      【讨论】:

        【解决方案4】:

        注意:如果您只有 unigrams,请使用此选项

        sklearn 的 tfidfvectorizer 不会直接给你计数。 要获得计数,您可以使用TfidfVectorizer 类方法inverse_transformbuild_tokenizer

        from sklearn.feature_extraction.text import TfidfVectorizer
        corpus = [
            'The dog ate a sandwich and I ate a sandwich',
            'The wizard transfigured a sandwich'
        ]
        
        vectorizer = TfidfVectorizer(stop_words='english')
        
        X = vectorizer.fit_transform(corpus)
        X_words = tfidf.inverse_transform(X) ## this will give you words instead of tfidf where tfidf > 0
        
        tokenizer = vectorizer.build_tokenizer() ## return tokenizer function used in tfidfvectorizer
        
        for idx,words in enumerate(X_words):
            for word in words:
                count = tokenizer(corpus[idx]).count(word)
                print(idx,word,count)
        

        输出

        0 dog 1
        0 ate 2
        0 sandwich 2
        1 sandwich 1
        1 wizard 1
        1 transfigured 1
        #0 means first sentence in corpus 
        

        这是一个解决方法,希望对某人有所帮助:)

        【讨论】:

          【解决方案5】:

          应该是vectorizer 在该行 X_words = tfidf.inverse_transform(X) 而不是 tfidf。

          【讨论】:

            猜你喜欢
            • 2021-03-09
            • 1970-01-01
            • 2013-11-14
            • 2015-01-05
            • 2019-07-29
            • 2017-07-15
            • 2013-12-06
            • 2018-08-07
            • 2021-02-13
            相关资源
            最近更新 更多