【问题标题】:Calculate Tf-Idf Scores in pandas?计算熊猫的 Tf-Idf 分数?
【发布时间】:2019-01-10 03:01:52
【问题描述】:

我想从下面的文档中分别计算 tf 和 idf。我正在使用 python 和 pandas。

import pandas as pd
df = pd.DataFrame({'docId': [1,2,3], 
               'sent': ['This is the first sentence','This is the second sentence', 'This is the third sentence']})

我想使用不使用 Sklearn 库的 Tf-Idf 公式计算。

标记化后,我已将其用于 TF 计算:

tf = df.sent.apply(pd.value_counts).fillna(0) 

但这给了我一个计数,但我想要(count/total number of words)的比率。

对于 IDF: df[df['sent'] > 0] / (1 + len(df['sent'])

但它似乎不起作用。 我希望 Tf 和 Idf 都为 pandas 系列格式。

编辑

对于标记化,我使用了df['sent'] = df['sent'].apply(word_tokenize) 我的 idf 分数为:

tfidf = TfidfVectorizer()
feature_array = tfidf.fit_transform(df['sent'])
d=(dict(zip(tfidf.get_feature_names(), tfidf.idf_)))

如何分别获得 tf 分数?

【问题讨论】:

  • 请解释您是如何标记化的。另外,您是否认为每个句子都有自己的文档?
  • @T.Ray 检查我编辑的问题。我计算了 idf 分数。我只想要每个标记化单词的 tf 分数。
  • 我很困惑。我以为你不想使用sklearn

标签: python python-3.x pandas tf-idf tfidfvectorizer


【解决方案1】:

这是我的解决方案:

首先标记化,为方便起见单独列:

df['tokens'] = [x.lower().split() for x in df.sent.values] 

然后像你一样使用 TF,但使用 normalize 参数(出于技术原因,你需要一个 lambda func):

tf = df.tokens.apply(lambda x: pd.Series(x).value_counts(normalize=True)).fillna(0)

然后是 IDF(词汇表中每个单词一个):

idf = pd.Series([np.log10(float(df.shape[0])/len([x for x in df.tokens.values if token in x])) for token in tf.columns])
idf.index = tf.columns

如果你想要 TFIDF:

tfidf = tf.copy()
for col in tfidf.columns:
    tfidf[col] = tfidf[col]*idf[col]

【讨论】:

    【解决方案2】:

    您需要做更多的工作来计算它。

    import numpy as np
    
    df = pd.DataFrame({'docId': [1,2,3], 
                   'sent': ['This is the first sentence', 
                            'This is the second sentence',
                            'This is the third sentence']})
    
    # Tokenize and generate count vectors
    word_vec = df.sent.apply(str.split).apply(pd.value_counts).fillna(0)
    
    # Compute term frequencies
    tf = word_vec.divide(np.sum(word_vec, axis=1), axis=0)
    
    # Compute inverse document frequencies
    idf = np.log10(len(tf) / word_vec[word_vec > 0].count()) 
    
    # Compute TF-IDF vectors
    tfidf = np.multiply(tf, idf.to_frame().T)
    
    print(tfidf)
    
        is  the     first  This  sentence    second     third
    0  0.0  0.0  0.095424   0.0       0.0  0.000000  0.000000
    1  0.0  0.0  0.000000   0.0       0.0  0.095424  0.000000
    2  0.0  0.0  0.000000   0.0       0.0  0.000000  0.095424
    

    根据您的情况,您可能需要标准化:

    # L2 (Euclidean) normalization
    l2_norm = np.sum(np.sqrt(tfidf), axis=1)
    
    # Normalized TF-IDF vectors
    tfidf_norm = (tfidf.T / l2_norm).T
    
    print(tfidf_norm)
    
        is  the     first  This  sentence    second     third
    0  0.0  0.0  0.308908   0.0       0.0  0.000000  0.000000
    1  0.0  0.0  0.000000   0.0       0.0  0.308908  0.000000
    2  0.0  0.0  0.000000   0.0       0.0  0.000000  0.308908
    

    【讨论】:

    • 很好的答案,但我认为我们真的不需要对这个分数进行标准化。 TF-IDF 本身有两个标准化的步骤(1)TF:取相对频率而不是原始计数,因此文档的长度无关紧要,(2)IDF:跨文档出现的相对频率而不是原始文档计数,所以文档数量无关紧要。
    【解决方案3】:

    我想我和你有同样的问题。

    我想使用 TfIdfVectorizer,但它们的默认 tf-idf 定义不标准(tf-idf = tf + tf*idf 而不是普通的tf-idf = tf*idf

    TF = 术语“频率”通常用于表示计数。为此,您可以使用 sklearn 中的 CountVectorizer()。 如果需要,需要记录转换和规范化。

    使用 numpy 的选项在处理时间上要长得多(> 慢 50 倍)。

    【讨论】:

      猜你喜欢
      • 2018-11-09
      • 2017-03-07
      • 1970-01-01
      • 2021-06-17
      • 2012-04-23
      • 2015-04-17
      • 2017-11-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多