余弦相似度

6

我计算了两个文档的tf/idf值。以下是tf/idf值:

1.txt
0.0
0.5
2.txt
0.0
0.5

文件类似于:
1.txt = > dog cat
2.txt = > cat elephant

我如何使用这些值来计算余弦相似性?

我知道应该计算点积,然后找到距离并将点积除以它。如何使用我的值计算这个?

还有一个问题:两个文档是否应该具有相同数量的单词很重要吗?


1
这不更适合发布在http://mathoverflow.net/吗? - Nicolás
5
这是一个信息检索任务,对于纯数学专业的人来说并不重要。 - Aditya Mukherji
13
请不要推荐mathoverflow.net网站,该网站用于解答严肃的数学问题。 - Jason S
3个回答

16
            a * b
sim(a,b) =--------
           |a|*|b|

a*b是点积

一些细节:

def dot(a,b):
  n = length(a)
  sum = 0
  for i in xrange(n):
    sum += a[i] * b[i];
  return sum

def norm(a):
  n = length(a)
  for i in xrange(n):
    sum += a[i] * a[i]
  return math.sqrt(sum)

def cossim(a,b):
  return dot(a,b) / (norm(a) * norm(b))

是的。在某种程度上,a和b必须具有相同的长度。但是,a和b通常具有稀疏表示形式,您只需要存储非零条目,就可以更快地计算范数和点积。


谢谢,但我还有一个问题不太清楚。我在网上看到人们谈论这个问题,但我不理解。我应该在tf/idf值上计算余弦相似度,还是只计算idf值或只计算tf值??? 我知道PHP并开始学习Java。但很抱歉我不知道你在这里使用了哪种编程语言?您能告诉我吗?我会查看该语言的基本语法。或者,如果您可以使用我的tf/idf值来计算余弦相似度,那么它将向我展示如何编写该函数... 再次感谢您的回复! - user238384
@agazerboy 这个示例是用 Python 给出的,应该很容易读懂。for i in xrange(n) 的意思是 for (i=0; i<n; i++)。你应该根据 tf-idf 值进行计算,有时候也可以使用 tf。 - Yin Zhu

9

简单的Java代码实现:

  static double cosine_similarity(Map<String, Double> v1, Map<String, Double> v2) {
            Set<String> both = Sets.newHashSet(v1.keySet());
            both.retainAll(v2.keySet());
            double sclar = 0, norm1 = 0, norm2 = 0;
            for (String k : both) sclar += v1.get(k) * v2.get(k);
            for (String k : v1.keySet()) norm1 += v1.get(k) * v1.get(k);
            for (String k : v2.keySet()) norm2 += v2.get(k) * v2.get(k);
            return sclar / Math.sqrt(norm1 * norm2);
    }

2
一个匿名用户的评论指出,应该使用 both.retainAll() 而不是 removeAll 来获取交集。 - Rup

1

1)计算tf-idf(通常比仅使用tf更好,但完全取决于您的数据集和要求)

来自维基百科(关于idf)

一个反向文档频率因子被纳入其中,它减少了在文档集中非常频繁出现的术语的权重,并增加了很少出现的术语的权重。

2)不,两个文档具有相同数量的单词并不重要。

3)您可以通过调用一些机器学习库函数在任何语言中找到tf-idfcosine-similarity。我更喜欢使用Python。

使用 scikit-learn 0.18.2 的 Python 代码来计算tf-idfcosine-similarity

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
# example dataset
from sklearn.datasets import fetch_20newsgroups

# replace with your method to get data
example_data = fetch_20newsgroups(subset='all').data

max_features_for_tfidf = 10000
is_idf = True 

vectorizer = TfidfVectorizer(max_df=0.5, max_features=max_features_for_tf_idf,
                             min_df=2, stop_words='english',
                             use_idf=is_idf)


X_Mat = vectorizer.fit_transform(example_data)

# calculate cosine similarity between samples in X with samples in Y
cosine_sim = cosine_similarity(X=X_Mat, Y=X_Mat)

4) 你可能会对截断奇异值分解(SVD)感兴趣


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接