使用 sklearn 计算两个不同列的单独 tfidf 分数

Posted

技术标签:

【中文标题】使用 sklearn 计算两个不同列的单独 tfidf 分数【英文标题】:Computing separate tfidf scores for two different columns using sklearn 【发布时间】:2016-08-12 10:10:54 【问题描述】:

我正在尝试计算一组查询与每个查询的一组结果之间的相似性。我想使用 tfidf 分数和余弦相似度来做到这一点。我遇到的问题是我无法弄清楚如何使用两列(在熊猫数据框中)生成 tfidf 矩阵。我已经连接了两列,它工作正常,但使用起来很尴尬,因为它需要跟踪哪个查询属于哪个结果。我将如何一次计算两列的 tfidf 矩阵?我正在使用 pandas 和 sklearn。

以下是相关代码:

tf = TfidfVectorizer(analyzer='word', min_df = 0)
tfidf_matrix = tf.fit_transform(df_all['search_term'] + df_all['product_title']) # This line is the issue
feature_names = tf.get_feature_names() 

我正在尝试将 df_all['search_term'] 和 df_all['product_title'] 作为参数传递给 tf.fit_transform。这显然不起作用,因为它只是将字符串连接在一起,这不允许我将 search_term 与 product_title 进行比较。另外,有没有更好的方法来解决这个问题?

【问题讨论】:

您需要在df_all['search_term'] + " " + df_all['product_title'] 中添加一个空格,否则您可能会将产品的第一个单词与搜索的最后一个单词结合起来 你也不需要analyzer=word,因为这是默认值 代码中的那一行不是我想要的,我希望将术语和产品分开,以便计算搜索和产品之间的余弦相似度。 我知道,我只是说,如果你想将它们组合在一起,你需要添加空间,将来某个时候你会需要这个 【参考方案1】:

您只需将所有单词放在一起就取得了良好的开端;通常,像这样的简单管道就足以产生良好的结果。您可以使用pipelinepreprocessing 构建更复杂的特征处理管道。以下是它对您的数据的作用:

import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.preprocessing import FunctionTransformer
from sklearn.pipeline import FeatureUnion, Pipeline

df_all = pd.DataFrame('search_term':['hat','cat'], 
                       'product_title':['hat stand','cat in hat'])

transformer = FeatureUnion([
                ('search_term_tfidf', 
                  Pipeline([('extract_field',
                              FunctionTransformer(lambda x: x['search_term'], 
                                                  validate=False)),
                            ('tfidf', 
                              TfidfVectorizer())])),
                ('product_title_tfidf', 
                  Pipeline([('extract_field', 
                              FunctionTransformer(lambda x: x['product_title'], 
                                                  validate=False)),
                            ('tfidf', 
                              TfidfVectorizer())]))]) 

transformer.fit(df_all)

search_vocab = transformer.transformer_list[0][1].steps[1][1].get_feature_names() 
product_vocab = transformer.transformer_list[1][1].steps[1][1].get_feature_names()
vocab = search_vocab + product_vocab

print(vocab)
print(transformer.transform(df_all).toarray())

['cat', 'hat', 'cat', 'hat', 'in', 'stand']

[[ 0.          1.          0.          0.57973867  0.          0.81480247]
 [ 1.          0.          0.6316672   0.44943642  0.6316672   0.        ]]

【讨论】:

感谢您的帮助。我试图弄清楚这一点,但我似乎无法弄清楚它会返回什么。当我运行它时,我没有得到一个 tfidf 矩阵,它给了我别的东西吗?另外,它应该访问 df_all 吗?似乎根本没有被引用... 我添加了一个示例计算,希望能让事情更清楚。老实说,我无法准确确定正在使用的 tf-idf 变体,我认为它可能正在使用对数频率,即使在文档中说它没有) 这家伙整理了一些笔记,可能会澄清一些事情github.com/rasbt/pattern_classification/blob/master/… 我建议使用传统函数而不是 lambda,因为 lambda 会导致意外行为。见github.com/scikit-learn/scikit-learn/issues/9467 我建议也使用这样的变压器***.com/a/52703546/7927776

以上是关于使用 sklearn 计算两个不同列的单独 tfidf 分数的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 sklearn CountVectorizer and() 来获取包含任何标点符号作为单独标记的 ngram?

使用 numpy 和 sklearn 计算 R^2(确定系数)给出不同的结果

为啥tf模型训练时的二元交叉熵损失与sklearn计算的不同?

sklearn 分类器管道所需的“列的有效规范”是啥?

跨不同系统(机器)使用相同 random_state 的 Sklearn 不同结果

在管道/gridSearch 中使用 TFI/DF 和 CountVectorizer