因此,我正在将旧的数据可视化转换为新的平台,而我对他们的社区排序功能有些犹豫。在原始代码中,看起来作者使用了余弦相似度计算器的聚集聚类。我认为用Javascript处理此问题的最佳方法是使用我的自定义余弦相似度函数作为度量标准,用clusterfck制作一棵树。对于我传递的每组数据,树都会正确地对ALMOST进行排序。 (但是由于项目规范,“几乎”还不够好)。我检查了算法,一切看起来都不错,但是当我使用余弦相似度和欧几里得距离比较结果时,得到的排序结果相同。
是什么原因造成的?我想我可能传递的是错误的内容,而clusterfck默认传递的是欧几里得。下面是我的代码块。有人可以验证吗? (此外,还有一种更简便的方法来计算余弦相似度吗?我认为JS没有内置的点积)。
clusters = clusterfck.hcluster(relationArray, clusterfck.cosSim2, clusterfck.SINGLE_LINKAGE);
postOrder(clusters);
function postOrder(t) {
i++;
if (t == null) {
return;
} else {
postOrder(t.left);
postOrder(t.right);
if (t.left == null && t.right == null) {
communityArr.push(t.canonical[0]);
} else {
return;
}
}
}
function cosSim2(arr1, arr2) {
var d1 = 0,
d2 = 0,
cos = 0;
for(var i = 0; i < arr1.length; i++) {
d1 += Math.pow(arr1[i], 2);
}
for(var j = 0; j < arr2.length; j++) {
d2 += Math.pow(arr2[j], 2);
}
d1 = Math.sqrt(d1);
d2 = Math.sqrt(d2);
for(var j = 0; j < arr2.length; j++) {
if (arr1[j] == null) {
cos += 0;
} else {
cos += arr1[j] * arr2[j];
}
}
var cosSimilarity = cos / (d1 * d2);
return cosSimilarity;
}
最佳答案
我想这个回复对您来说太迟了。
但是如果有人偶然发现:
问题是您使用参数clusterfck.hcluster
调用clusterfck.cosSim2
作为距离度量。但是,由于您的真实距离函数只是cosSim2
,因此您可以有效地使用未定义的距离函数调用clusterfck.hcluster
,clusterfck会采用默认的距离函数“欧几里得” ...
另外请注意,您的函数确实测量的是向量之间的相似性,而不是其距离。即:余弦相似度越大,向量越相似(即,它们之间的角度越小)。
但是clusterfck.hcluster
期望真正的距离测量。也就是说,相反的假设是正确的:距离度量的值越大,向量越远(即向量越不相似)。
用您的函数调用clusterfck.hcluster
的效果是,最少相似的项被聚集在一起。
您可以轻松地从余弦相似度函数得出距离函数,如下所示:
function cosDist(arr1, arr2) {
return 1 - cosSim2(arr1, arr2);
}
此新函数
cosDist
的值范围为0到2,相同矢量的距离为0(如预期),而最远矢量(即相异)的距离为2。还有一个注意事项:
Wikipedia文章http://en.wikipedia.org/wiki/Cosine_similarity指出,从数学意义上说,此cosDist不是合适的距离度量(此处一般不包含三角形不等式),但是根据我的经验,使用此函数进行层次聚类时,这实际上不是问题。而且经常使用这种方式。
但是,有一种方法可以从余弦中得出真实的距离度量,这在同一维基百科文章中也提到过:https://en.wikipedia.org/wiki/Cosine_similarity#Angular_distance_and_similarity
关于javascript - Javascript Clusterfck指标,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11655021/