要计算两个对象的相似性,有很多种方法可以做相关性分析。
简单的举例几个常用的样本相似性度量方法:
欧式距离(Euclidean Distance)
汉明距离(Hamming Distance)
曼哈顿距离(Manhattan Distance)
余弦相似度(Cosine)
修正余弦相似度(Adjusted Cosine)
皮尔逊相关系数(Pearson)
斯皮尔曼相关系数(Spearman)
1、 欧式距离(Euclidean Distance)
欧式距离全称是欧几里距离,是最易于理解的一种距离计算方式,这里不多介绍。
2、汉明距离(Hamming distance)
汉明距离表示的是两个字符串(相同长度)对应位不同的数量。比如有两个等长的字符串 str1 = “0001” 和 str2 = “0100” 那么它们之间的汉明距离就是2。汉明距离多用于图像像素的匹配(同图搜索)。
3.曼哈顿距离(Manhattan Distance)
想象你在曼哈顿要从一个十字路口开车到另外一个十字路口,那么驾驶的最近距离并不是直线距离,因为你不可能横穿房屋。所以,曼哈顿距离表示的就是你的实际驾驶距离,即两个点在标准坐标系上的绝对轴距总和。
4.余弦相似度(Cosine)
即,高维度上的“余弦夹角”。
夹角越小,余弦值越接近于1,则越正相关;反之趋于-1则负相关。趋于0则不相关。
欧式距离和夹角余弦的区别:
夹角余弦更能反映两者之间的变动趋势,对向量的方向更敏感,对绝对的数值不敏感,而欧式距离较则对数值敏感。
5.修正余弦相似度(Adjusted Cosine)
为什么需要在余弦相似度的基础上使用修正余弦相似度?请看下面这个例子:
有两用户对两个内容评分,按5分制,X和Y两个用户对这两个内容的评分分别为(1,2)和(4,5),使用余弦相似度得到的结果是0.98,两者极为相似。但从评分上看X似乎不喜欢第2个内容,而Y则比较喜欢,余弦相似度对数值的不敏感导致了结果的误差,需要修正这种不合理性就出现了调整余弦相似度,即所有维度上的数值都减去所有评分的均值,比如X和Y的评分均值是(1+2+4+5)/4=3,那么调整后为(-2,-1)和(1,2),再用余弦相似度计算,得到-0.8。
6、皮尔逊相关系数(Pearson Correlation Coefficient)
皮尔逊相关系数公式实际上就是在计算夹角余弦之前将两个向量减去各个样本的平均值,达到中心化的目的。皮尔逊相关函数是余弦相似度在维度缺失上面的一种改进方法。
7.斯皮尔曼相关系数(Spearman)
斯皮尔曼相关系数被定义成等级变量之间的皮尔逊相关系数。注意:当变量的两个值相同时,它们的排行是通过对它们位置进行平均而得到的。
例如:
有变量A =(10,8.9,4.5,4.5,2,0.6),其对应按降序的等级变量是xi=(6,5,3.5,3.5,2,1)。变量B =(4,28.1,8,7.5,2.9,5),其对应按降序的等级变量是yi=(5,1,2,3,6,4)。
它是衡量两个变量的依赖性的 非参数 指标。 它利用单调方程评价两个统计变量的相关性。 如果数据中没有重复值, 并且当两个变量完全单调相关时,斯皮尔曼相关系数则为+1或−1。
总结:
- 如果数据存在“分数膨胀”,可用皮尔逊相关系数。
- 如果数据之间比较“密集”,数据比较完整,变量之间基本存在公有值,且这些距离数据是非常重要的,那就使用欧几里得或曼哈顿距离。
- (空缺值处理:用0代替空缺值的方法可能会造成较大误差,“平均值”填充效果好于0值填充)
- 如果数据是稀疏的,则使用余弦相似度。
其他相关参考:
- 5种常用的相关分析方法:http://bluewhale.cc/2016-06-30/analysis-of-correlation.html
- Pearson相关系数和Spearman相关系数的区别:https://blog.csdn.net/Android_xue/article/details/100136612
对应C++代码:
bool Cosine(double* A, double* B, V3DLONG Length, double &similarity)
{
//余弦相似度
// similarity 相关性
// 0.8-1.0 极强相关
// 0.6-0.8 强相关
// 0.4-0.6 中等程度相关
// 0.2-0.4 弱相关
// 0.0-0.2 极弱相关或无相关
//计算相关系数
double R1(0), R2(0), R3(0);
for (long i = 0; i < Length; i++)
{
R1 += A[i] * B[i];
R2 += pow(A[i], 2);
R3 += pow(B[i], 2);
}
similarity = R1 / sqrt(R2*R3);
return true;
}
bool AdjustedCosine(double* A, double* B, V3DLONG Length, double &similarity)