在 C# 中实现 jaccard 相似度

Implementing jaccard similarity in c#

我试图理解 "Jaccard similarity" 两个双精度型数组的值大于零且小于一。

到目前为止,我已经在很多网站上搜索过这个,但我发现两个数组的大小应该相同(数组 1 中的元素数应该等于数组 2 中的元素数)。但是我在两个数组中有不同数量的元素。有什么办法可以实现 "jaccard similarity" ?

Jaccard 相似度是两个集合之间的交集大小除以并集大小的指标。在您的情况下,您必须编写代码来找出两个数组中出现了多少个元素,然后将其除以两个数组的大小之和。

使用 C# 的 LINQ ...

假设您有一个名为 A 的双精度数组和另一个名为 B 的双精度数组。这将为您提供 Jaccard 索引:

var CommonNumbers = from a in A.AsEnumerable<double>()
                    join b in B.AsEnumerable<double>() on a equals b
                    select a;
double JaccardIndex = (((double) CommonNumbers.Count()) /
                       ((double) (A.Count() + B.Count())));

第一个语句获取出现在两个数组中的数字列表。第二个计算索引 - 这只是交集的大小(两个数组中出现的数字数量)除以联合的大小(一个数组的大小,或者更确切地说,一个数组的计数加上另一个数组的计数)。

抱歉发了死帖,但上面的答案被标记为正确答案。如果集合完全相同,来自@AgapwIesu 答案的 Jaccard 相似系数最大为 0.5。至少,你需要乘以分子 x2 来归一化它,像这样:

var CommonNumbers = from a in A.AsEnumerable<double>()
                    join b in B.AsEnumerable<double>() on a equals b
                    select a;
double JaccardIndex = 2*(((double) CommonNumbers.Count()) /
                       ((double) (A.Count() + B.Count())));

请注意,此相似系数是 而非 交集,除以 Wikipedia 处定义的并集。如果你想得到交集,使用LINQ除以联合,你可以试试这个代码:

private static double JaccardIndex(IEnumerable<double> A, IEnumerable<double> B)
{
    return (double)A.Intersect(B).Count() / (double)A.Union(B).Count();
}

请注意,UnionIntersect 适用于唯一对象,因此您在处理非唯一集合时应小心:

List<int> A = new List<int>() { 1, 1, 1, 1 };
List<int> B = new List<int>() { 1, 1, 1, 1 };
Console.WriteLine(A.Union(B).Count()); // = 1, not 4
Console.WriteLine(A.Intersect(B).Count()); // = 1, not 4