Jaccard相似系数(Jaccard similarity coefficient)用于比较有限样本集之间的相似性与差异性。Jaccard系数值越大,样本相似度越高。
定义
给定两个集合A
,B
,Jaccard 系数
定义为A
与B
交集的大小与A
与B
并集的大小的比值,定义如下:
当集合A
,B
都为空时,J(A,B)
定义为1
。
与Jaccard 系数
相关的指标叫做Jaccard 距离
,用于描述集合之间的不相似度。Jaccard 距离
越大,样本相似度越低。公式定义如下:
其中对称差(symmetric difference)
实例
由于编辑距离
关注在于字符间的不同之处,而最长公共子序列(LCS)
侧重点在于相同的部分,因此都无法衡量差异具体值的大小,只能获得“是否相同”这个结果,所以Jaccard系数
用来关心个体间共同具有的特征是否一致这个问题。
如集合A={1,2,3,4};B={3,4,5,6};
那么他们的J(X,Y)=l{3,4}/l{1,2,3,4,5,6}=1/3;
在数据挖掘领域,常常需要比较两个具有布尔值属性的对象之间的距离,Jaccard距离就是常用的一种方法。给定两个比较对象A,B。A, B 均有n个二元属性,即
每个属性取值为{0,1}。定义如下4个统计量:
- M00:A,B属性值同时为0的属性个数;
- M01:A属性值为0且B属性值为1的属性个数;
- M10:A属性值为1且B属性值为0的属性个数;
- M11:A,B属性值同时为1的属性个数;
代码实现
// 结果是去重的jaccard系数
// A ⋂ B
int _intersection(const wstring &str1, const wstring &str2) {
wstring::const_iterator first1 = str1.begin(), last1 = str1.end(), first2 = str2.begin(), last2 = str2.end();
int counter = 0;
wchar_t final = '\0';
while (first1 != last1 && first2 != last2) {
if (*first1 < *first2)
++first1;
else if (*first2 < *first1)
++first2;
else {
if (*first1 != final) {
++counter;
final = *first1;
}
++first1;
++first2;
}
}
return counter;
}
// A ⋃ B
int _union(const wstring &str1, const wstring &str2) {
wstring::const_iterator first1 = str1.begin(), last1 = str1.end(), first2 = str2.begin(), last2 = str2.end();
int counter = 0;
wchar_t final = '\0';
while (first1 != last1 && first2 != last2) {
if (*first1 <= *first2) {
if (final != *first1) {
++counter;
final = *first1;
}
++first1;
} else if (*first2 < *first1) {
if (final != *first2) {
++counter;
final = *first2;
}
++first2;
}
}
while (first1 != last1) {
if (final != *first1) {
++counter;
final = *first1;
}
++first1;
}
while (first2 != last2) {
if (final != *first2) {
++counter;
final = *first2;
}
++first2;
}
return counter;
}
// |A ⋂ B| / |A ⋃ B|
double jaccard_index(wstring str1, wstring str2) {
if (str1.size() == 0 || str2.size() == 0)
return 0;
sort(str1.begin(), str1.end());
sort(str2.begin(), str2.end());
return 1.0 * _intersection(str1, str2) / _union(str1, str2);
}