我一直在使用SKLearn中的TF-IDF向量化器,但是我无法手动重现值(以了解发生了什么)。为了添加一些上下文,我有一个从文档中提取出来的命名实体列表(在我的实际数据中,这些可以增加到5个元组,但在此处我将其限制为二元组)。我只想知道这些值的TF-IDF分数,并认为通过参数传递这些术语可以做到这一点。以下是我正在处理的类似于虚拟数据:
这就是我需要帮助的地方。据我所了解,我们计算TF-IDF的方法如下: TF:词频:根据SKlearn指南,“文档中一个词出现的次数”。 IDF:逆文档频率:1+包含该词项的文档数与1+总文档数之比的自然对数。根据同样的链接中的指南,结果值加1是为了防止被零除。
然后我们将TF乘以IDF,给出特定文档中给定术语的整体TF-IDF。 示例 以第一列为例,它只有一个命名实体'Boston',根据上述代码,在第一个文档中具有1的TF-IDF。然而,当我手动计算时,得到以下结果:
from sklearn.feature_extraction.text import TfidfVectorizer
import pandas as pd
# list of named entities I want to generate TF-IDF scores for
named_ents = ['boston','america','france','paris','san francisco']
# my list of documents
docs = ['i have never been to boston',
'boston is in america',
'paris is the capitol city of france',
'this sentence has no named entities included',
'i have been to san francisco and paris']
# find the max nGram in the named entity vocabulary
ne_vocab_split = [len(word.split()) for word in named_ents]
max_ngram = max(ne_vocab_split)
tfidf = TfidfVectorizer(vocabulary = named_ents, stop_words = None, ngram_range=(1,max_ngram))
tfidf_vector = tfidf.fit_transform(docs)
output = pd.DataFrame(tfidf_vector.T.todense(), index=named_ents, columns=docs)
注意: 我知道停用词默认被移除,但是我的实际数据集中一些命名实体包括'国务院'等短语。因此它们已经保留在这里。这就是我需要帮助的地方。据我所了解,我们计算TF-IDF的方法如下: TF:词频:根据SKlearn指南,“文档中一个词出现的次数”。 IDF:逆文档频率:1+包含该词项的文档数与1+总文档数之比的自然对数。根据同样的链接中的指南,结果值加1是为了防止被零除。
然后我们将TF乘以IDF,给出特定文档中给定术语的整体TF-IDF。 示例 以第一列为例,它只有一个命名实体'Boston',根据上述代码,在第一个文档中具有1的TF-IDF。然而,当我手动计算时,得到以下结果:
TF = 1
IDF = log-e(1+total docs / 1+docs with 'boston') + 1
' ' = log-e(1+5 / 1+2) + 1
' ' = log-e(6 / 3) + 1
' ' = log-e(2) + 1
' ' = 0.69314 + 1
' ' = 1.69314
TF-IDF = 1 * 1.69314 = 1.69314 (not 1)
也许我在文档中漏掉了得分被限制为1的内容,但我无法找出我的错误所在。此外,根据以上计算,在第一列和第二列中,波士顿的得分应该没有任何区别,因为该术语在每个文档中只出现一次。
编辑
发帖后,我想到也许术语频率是与文档中的unigrams数量或命名实体数量之比计算的。例如,在第二个文档中,SKlearn生成了波士顿的得分为0.627914
。如果我将TF计算为标记='boston'(1):所有单元标记(4)的比率,则得到0.25
的TF。将其应用于TF-IDF后,返回刚刚超过0.147
的分数。
同样地,当我使用标记='boston'(1):所有NE标记(2)的比率,并应用TF-IDF时,我得到一个分数为0.846
。因此,显然我做错了什么。