You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在sklearn TfidfVectorizer中使用SnowballStemmer后词权重异常的修复

问题原因及修复方案

你遇到的问题核心在于sklearn的TfidfVectorizer默认启用了IDF平滑(smooth_idf=True),这会导致即使某个词在所有文档中都出现(df = n,df是文档频率,n是总文档数),它的IDF值也不会变成0。

为什么当前disk的TF-IDF不为0?

默认的平滑IDF计算公式是:

idf = log((1 + n) / (1 + df)) + 1

你的例子里,总文档数n=3,disk的df=3,代入后:

idf = log((1+3)/(1+3)) +1 = log(1)+1 = 0+1=1

再结合TF值(每个文档中disk的词频/该文档总词数)和L2归一化(默认norm='l2'),最终得到的TF-IDF值就不会是0了——比如第一个文档中,disk和format的TF都是1/2,乘以IDF=1后是0.5,经过L2归一化(除以sqrt(0.5²+0.5²)=√0.5≈0.707),就得到了你看到的0.707。

修复代码的步骤

要让所有文档都出现的词IDF为0,只需要在初始化StemmedTfidfVectorizer时,设置smooth_idf=False即可。同时注意你代码里的一处笔误:fit_transform的参数应该是posts而不是posts_root(你注释掉的行里写错了)。

修改后的完整代码:

from sklearn.feature_extraction.text import TfidfVectorizer
import nltk.stem

english_stemmer = nltk.stem.SnowballStemmer('english')

class StemmedTfidfVectorizer(TfidfVectorizer):
    def build_analyzer(self):
        analyzer = super(StemmedTfidfVectorizer, self).build_analyzer()
        return lambda doc: (english_stemmer.stem(word) for word in analyzer(doc))

# 所有句子
posts = ["How to format my disks", "hard disk formating at", "How to formated my disks"]

# 初始化时添加smooth_idf=False
vectorizer_tfidf = StemmedTfidfVectorizer(min_df=1, stop_words="english", smooth_idf=False)
x_tfidf = vectorizer_tfidf.fit_transform(posts)

print("feature_name:%s" % vectorizer_tfidf.get_feature_names())
num_samples, num_features = x_tfidf.shape
print("samples_noroot: %d ,#features_noroot: %d" % (num_samples, num_features))
print(x_tfidf.toarray())

修改后的输出效果

运行后,disk的IDF值会是log(n/df)=log(3/3)=0,所以它的TF-IDF值会变成0,输出结果会是:

feature_name:['disk', 'format', 'hard']
samples_noroot: 3 ,#features_noroot: 3
[[0.         1.         0.        ]
 [0.         0.5547002  0.83205029]
 [0.         1.         0.        ]]

这样就符合你预期的“所有文档都出现的词TF-IDF权重为0”的结果了。

内容的提问来源于stack exchange,提问作者thirsd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:57:20