为何我的TF-IDF值不符合预期?词频翻倍但权重未翻倍
TF-IDF计算结果不符合预期的原因解析
问题场景
我将三条推文转换为词元后,用scikit-learn的TfidfVectorizer计算TF-IDF:
- 推文1(13个词元):
geraldkutney happen realize happen conveniently rename catch yet emergency post fact come government(happen出现2次) - 推文2(13个词元):
michaelemann burn happen chickenshittily change get make stupid argument good deed go unpunished(happen出现1次) - 推文3(3个词元):
rickcaughell thomas_6278 coderedearth jrockstrom jordanbpeterson fact exxon predict good accuracy would happen temperature today back 1970s 80 prof model accurate(happen出现1次)
计算代码如下:
vectoriser = sk_text.TfidfVectorizer() vectoriser.fit(twit_api['text_clean']) twit_vec = vectoriser.transform(twit_api['text_clean']) twit_vec.columns = vectoriser.get_feature_names_out() tokens_enc = twit_vec.toarray()
查询happen的TF-IDF值得到:
- 推文1:0.41124561276932653
- 推文2:0.18906439908376366
- 推文3:0.1523571031416618
原本以为推文1的happen值应该是推文2的两倍(因为TF刚好翻倍),但实际结果不符,问题出在哪?
核心原因:默认的L2归一化影响
scikit-learn的TfidfVectorizer默认启用了L2归一化(norm='l2'),这会让每个文档的TF-IDF向量的模长(所有元素的平方和的平方根)为1。单个词的最终TF-IDF值,不仅取决于自身的TF×IDF,还会被文档中其他所有词的TF×IDF值共同影响。
具体计算逻辑拆解
IDF的计算:
happen在3条推文中都出现了,根据默认的smooth_idf=True规则:
IDF = log((总文档数+1)/(包含该词的文档数+1)) + 1 = log((3+1)/(3+1)) +1 = 1
所以happen的IDF对所有文档都是1。未归一化的原始TF-IDF:
- 推文1:TF=2/13,原始值= (2/13)*1 ≈0.1538
- 推文2:TF=1/13,原始值= (1/13)*1≈0.0769
到这里两者确实是两倍关系,但后续的归一化打破了这个比例。
- L2归一化的影响:
归一化后的数值 = 原始值 / 该文档所有词元原始TF-IDF值的平方和的平方根。
推文1和推文2的其他词元的IDF和TF都不同:比如推文1中的geraldkutney只在这条推文出现,它的IDF是log((3+1)/(1+1))+1≈1.693,而推文2中的michaelemann同样只在自身出现,IDF也是≈1.693,但两条推文的词元数量、每个词的TF都不一样,导致两条文档的归一化分母完全不同,最终happen的归一化值就不再是两倍关系。
验证方法
如果想得到单纯的TF×IDF结果,去掉归一化即可:
vectoriser = sk_text.TfidfVectorizer(norm=None)
此时推文1的happen值会是推文2的两倍,因为没有归一化,结果直接是TF与IDF的乘积,而happen的IDF在两条文档中一致。
内容的提问来源于stack exchange,提问作者Daniel V
相关产品推荐
相关产品推荐

