2012-12-03 56 views
1

我想根据使用python的tf-idf矩阵对一些文档进行聚类。Scipy,tf-idf和余弦相似性

首先,我使用规范化的tf遵循公式的维基百科定义。 http://en.wikipedia.org/wiki/Tf-idf

Feat_vectors以二维numpy数组开头,行代表文档,列代表术语,每个单元格中的值为每个文档中每个术语的出现次数。

import numpy as np 

feat_vectors /= np.max(feat_vectors,axis=1)[:,np.newaxis] 
idf = len(feat_vectors)/(feat_vectors != 0).sum(0) 
idf = np.log(idf) 
feat_vectors *= idf 

我然后使用SciPy的聚类这些载体:

from scipy.cluster import hierarchy 

clusters = hierarchy.linkage(feat_vectors,method='complete',metric='cosine') 
flat_clusters = hierarchy.fcluster(clusters, 0.8,'inconsistent') 

然而,在最后一行它抛出一个错误:

ValueError: Linkage 'Z' contains negative distances. 

余弦相似性从-1到1。然而,余弦相似性状态的维基百科页面http://en.wikipedia.org/wiki/Cosine_similarity

In the case of information retrieval, the cosine similarity of two documents will range >from 0 to 1, since the term frequencies (tf-idf weights) cannot be negative.

所以如果我得到一个消极的相似性,似乎我在计算tf-idf时出错。任何想法我的错误是什么?

+0

看起来像你的'feat_vectors'具有负值。在乘以'idf'之前,或者在采用'np.log'之前,idf的值小于1。 – tiago

+0

矩阵中的最小值为零。只是余弦相似度的结果<0。 – Fergusmac

回答

1

我怀疑的错误是在下面一行:

idf = len(feat_vectors)/(feat_vectors != 0).sum(0) 

,因为你的逻辑载体将被转换成在和一个int len是一个int,你失去精度。替换为:

idf = float(len(feat_vectors))/(feat_vectors != 0).sum(0) 

为我工作(即生产出我期待的虚拟数据)。其他一切看起来都正确

0

我知道这是一个旧帖子,但似乎最近自己偶然发现了这个问题。事实上,我甚至使用TfidfVectorizer(来自sklearn.feature_extraction.text)来生成TFIDF矩阵,一旦我自己的函数发出这个错误。这也没有帮助。

似乎用于相似性的余弦度量值会导致负值。我尝试了欧几里得,并立即工作。 这里是一个更详细的答案,我发现相同的链接 - https://stackoverflow.com/a/2590194/3228300

希望这会有所帮助。