scikit-learn中的k-means向量是内部归一化的吗,还是TfidfVectorizer归一化失效?
在scikit-learn的Kmeans
中,向量是内部标准化到单位L2范数吗?还是说TfidfVectorizer
有问题?我在处理文本数据时进行聚类,使用TF-IDF向量化数据。代码太长,不能在这里复制,但简单来说,我是对20个新闻组的数据进行向量化和聚类。我初始化向量化器时可以选择(未标准化):
VectorizerUn = TfidfVectorizer(min_df=10,
max_df=0.5,
stop_words='english',
decode_error='ignore')
或者选择(L2标准化):
VectorizerL2 = TfidfVectorizer(min_df=10,
max_df=0.5,
stop_words='english',
decode_error='ignore',
norm=u'l2')
然后我使用以下方式初始化k均值:
km = KMeans(n_clusters=num_clusters, init='random', n_init=1, verbose=0)
接着,我开始进行交叉验证,分割数据,向量化并拟合训练数据集(下面的X在向量化器中代表'Un'或'L2')
Vectorized = VectorizerX.fit_transform(TrainData.data)
km.fit(Vectorized)
并为训练集中的消息分配数据到不同的聚类中
new_msg_vec = VectorizerX.transform([new_msg])
predicted_clust = km_clust.predict(new_msg_vec)[0]
其中new_msg
会遍历训练数据中的消息。然后,我根据20个新闻组中消息的已知组标签,将聚类分配给组(每个聚类属于其内容大多数的组),并使用测试数据来评估聚类/分类方案的性能。下面是分类错误率与聚类数量的关系图,分别针对未标准化和L2标准化的数据向量化:
误差条表示在进行10次独立运行km.fit(Vectorized)
步骤后分类错误的标准差。这两个结果基本相同。聚类的其他指标(ARI分数、AMI分数、NMI分数)也给出了基本相同的结果。
那么,Kmeans内部是否将向量标准化到L2范数为1,还是TfidfVectorizer
的norm
参数没有按预期工作?(我使用的是scikit-learn 0.14.1)
补充:我发现问题可能不在Kmeans上。如果我使用L1标准化约束进行向量化(在TfidfVectorizer
中设置norm=u'l1'
),聚类错误率从45%增加到大约80%。我改了标题以反映这一点。
1 个回答
Kmeans内部是否会把向量归一化到L2范数为1,还是说TfidfVectorizer的norm参数没有按预期工作?
都不是。正如@YS-L在评论中提到的,TfidfVectorizer
的默认行为是对它生成的向量进行L2归一化:
norm : 'l1', 'l2' or None, optional
Norm used to normalize term vectors. None for no normalization.
而且默认值是'l2'
,所以如果不想进行归一化,可以明确设置norm=None
。