Итак, я перевожу старую визуализацию данных на новую платформу, и я немного застрял в их функции сортировки сообщества. В исходном коде похоже, что автор использует агломеративную кластеризацию с калькулятором косинусного сходства. Я решил, что лучший способ приблизиться к этому в Javascript — создать дерево с clusterfck, используя мою пользовательскую функцию подобия косинуса в качестве метрики. Дерево сортирует ПОЧТИ правильно для каждого набора данных, которые я передаю. (Но из-за спецификаций проекта «почти» недостаточно). Я проверил свой алгоритм, и все выглядит правильно, но когда я сравниваю свои результаты, используя косинусное сходство и евклидово расстояние, я получаю тот же результат сортировки.
Что может быть причиной этого? Я думаю, что могу передать что-то неправильно, и 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;
}