Yuv*_*hen 7 nlp tf-idf scikit-learn tfidfvectorizer
在 scikit-learn 中TfidfVectorizer
,我们可以拟合训练数据,然后使用相同的向量化器来转换我们的测试数据。对训练数据进行转换的输出是一个矩阵,表示给定文档中每个单词的 tf-idf 分数。
但是,拟合向量化器如何计算新输入的分数?我已经猜到了:
我曾尝试从 scikit-learn 的源代码中推断出该操作,但无法完全弄清楚。它是我之前提到的选项之一还是完全其他选项?请协助。
绝对是前者:每个单词的idf
(逆文档频率)仅根据训练文档计算。这是有道理的,因为这些值正是您调用fit
矢量化器时计算出的值。如果您描述的第二个选项是正确的,我们基本上每次都会重新安装向量化器,并且我们还会导致information leak
在模型评估期间使用测试集中的 idf。
除了这些纯粹的概念性解释之外,您还可以运行以下代码来说服自己:
from sklearn.feature_extraction.text import TfidfVectorizer
vect = TfidfVectorizer()
x_train = ["We love apples", "We really love bananas"]
vect.fit(x_train)
print(vect.get_feature_names())
>>> ['apples', 'bananas', 'love', 'really', 'we']
x_test = ["We really love pears"]
vectorized = vect.transform(x_test)
print(vectorized.toarray())
>>> array([[0. , 0. , 0.50154891, 0.70490949, 0.50154891]])
Run Code Online (Sandbox Code Playgroud)
遵循拟合方法如何工作的推理,您可以自己重新计算这些 tfidf 值:
“apples”和“bananas”的 tfidf 得分显然为 0,因为它们没有出现在x_test
. 另一方面,“梨”不存在x_train
,因此甚至不会出现在矢量化中。因此,只有“爱”、“真的”和“我们”才会有 tfidf 分数。
Scikit-learn 将 tfidf 实现为 log((1+n)/(1+df) + 1) * f 其中 n 是训练集中的文档数(我们为 2),df 是单词所在的文档数只出现在训练集中,f 是单词在测试集中的频率计数。因此:
tfidf_love = (np.log((1+2)/(1+2))+1)*1
tfidf_really = (np.log((1+2)/(1+1))+1)*1
tfidf_we = (np.log((1+2)/(1+2))+1)*1
Run Code Online (Sandbox Code Playgroud)
然后,您需要通过文档的 L2 距离来缩放这些 tfidf 分数:
tfidf_non_scaled = np.array([tfidf_love,tfidf_really,tfidf_we])
tfidf_list = tfidf_non_scaled/sum(tfidf_non_scaled**2)**0.5
print(tfidf_list)
>>> [0.50154891 0.70490949 0.50154891]
Run Code Online (Sandbox Code Playgroud)
您确实可以看到,我们得到了相同的值,这证实了scikit-learn
实施此方法的方式。
归档时间: |
|
查看次数: |
1767 次 |
最近记录: |