在c#中实现jaccard相似性

时间:2015-05-06 13:48:49

标签: c# similarity

我试图理解两个类型为double的数组之间的“Jaccard相似性”,其值大于零且小于一。

到目前为止,我已经搜索了很多网站,但我发现这两个数组的大小应该相同(数组1中的元素数应该等于数组2中的元素数)。但是我在两个数组中都有不同数量的元素。有没有办法实现“jaccard相似度”?

3 个答案:

答案 0 :(得分:4)

使用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())));

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

答案 1 :(得分:2)

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

答案 2 :(得分:0)

很抱歉,您的尸体投寄遗忘了,但以上答案被标记为正确答案。如果集合完全相同,则@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