问题我试图回答这个问题:考虑两个文档A和B,它们的欧几里得距离为d,余弦相似性为c(除了原始项频率之外,不使用任何归一化(。如果我们通过将a附加到自身来创建新文档a',并通过将B附加到自身创建另一个文档B',则:
a.a'和B'之间的欧几里得距离是多少(使用原始项频率(?
我的解决方案
doc1 = "the quicker brown dogs easily jumps over the lazy dogs"
doc2 = "the quicker dogs pose a serious problem for lazy dogs"
def calc_term_frequency(doc : list):
dic = {}
for word in doc.split():
if word in dic:
dic[word] = dic[word] + 1
else:
dic[word]= 1
for word, frequency in dic.items():
dic[word]= frequency / len(doc.split())
return dic
tfs_doc1 = calc_term_frequency(doc1)
tfs_doc2 = calc_term_frequency(doc2)
print(tfs_doc1)
将tfs_doc1输出为:{":0.2,"更快":0.1,"棕色":0.1这似乎起到了应有的作用。然后,我继续计算欧几里得距离,首先是在doc1和doc1之间,然后是doc1和doc2之间,如下所示。
import math
math.sqrt(sum((tfs_doc1.get(k, 0) - tfs_doc1.get(k, 0))**2 for k in set(tfs_doc1.keys()).union(set(tfs_doc1.keys())))) # output: 0
math.sqrt(sum((tfs_doc1.get(k, 0) - tfs_doc2.get(k, 0))**2 for k in set(tfs_doc1.keys()).union(set(tfs_doc2.keys())))) # output: 0.316227766016838
这给了我0.316227766016838的分数。当我尝试使用sklearn验证这是正确的时,如下所示:
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.metrics.pairwise import euclidean_distances
corpus_vect = CountVectorizer().fit_transform(corpus).todense()
print(euclidean_distances(corpus_vect[0], corpus_vect[0])) # output: 0
print(euclidean_distances(corpus_vect[0], corpus_vect[1] )) # output: 3.
我得到的输出为[[0.]][[3.]],这转换为我的"手动"结果的四舍五入(,1(。
问题:当我试图回答最初的问题并"加倍"字符串时,例如
doc1 = "the quicker brown dogs easily jumps over the lazy dogs the quicker brown dogs easily jumps over the lazy dogs"
doc2 = "the quicker dogs pose a serious problem for lazy dogs the quicker dogs pose a serious problem for lazy dogs"
使用"sklearn方法"/矢量器时,我得到了与手动技术相同的输出(0.316227766016838(,但[[0.]][[6.]]。因此,使用一种方法ED保持不变,使用另一种方法则加倍!
什么是正确的解决方案,是什么导致了差异?真的被困在这里了。提前谢谢。
当您将字符串加倍时,所有术语(包括原始术语(的频率都将重复。因此,如果在复制之前,文档a和B分别有一个(a1, a2, ..., ad)
和(b1, b2, ..., bd)
频率矢量,则欧氏距离将为sqrt((a1-b1)^2 + (a2-b2)^2 + ... + (ad - bd)^2)
。现在,经过复制,我们有了(2 * a1, 2 * a2, ..., 2 * ad)
和(2 * b1,2 * b2, ...,2 * bd)
,距离是:
dist(A', B') = sqrt((2 * a1- 2 * b1)^2 + (2 * a2 - 2 *b2)^2 + ... + (2 * ad - 2 * bd)^2) =
2 * sqrt((a1-b1)^2 + (a2-b2)^2 + ... + (ad - bd)^2) = 2 * dist(A,B)
注意,在手动解决方案中,您将频率除以文档的长度,这样可以防止重复术语频率。