皮尔逊相关性与余弦相似度

皮尔逊相关性是什么 皮尔逊是一种相关性度量方法,主要依靠计算得出的皮尔逊相关系数度量。
皮尔逊相关系数输出范围为-1到+1,0代表无相关性,负值为负相关,正值为正相关。
几何上来讲,皮尔逊相关系数是余弦相似度在维度值缺失情况下的一种改进。
皮尔逊系数就是在使用cos计算两个向量(cos = a ? b / |a|?|b|)时进行中心化。
余弦相似度(余弦距离) 计算的是两个向量在空间中的夹角大小, 值域为[-1, 1]: 1代表夹角为0°, 完全重叠/完全相似; -1代表夹角为180°, 完全相反方向/毫不相似.
余弦相似度的问题是: 其计算严格要求"两个向量必须所有维度上都有数值", 比如:v1 = (1, 2, 4), v2=(3, -1, null), 那么这两个向量由于v2中第三个维度有null, 无法进行计算.然而, 实际我们做数据挖掘的过程中, 向量在某个维度的值常常是缺失的, 比如v2=(3, -1, null), v2数据采集或者保存中缺少一个维度的信息, 只有两个维度. 那么, 我们一个很朴素的想法就是, 我们在这个地方填充一个值, 不就满足了"两个向量必须所有维度上都有数值"的严格要求了吗? 填充值的时候, 我们一般这个向量已有数据的平均值, 所以v2填充后变成v2=(3, -1, 1), 接下来我们就可以计算cos了.
中心化是什么 而皮尔逊相关系数的思路是, 我把这些null的维度都填上0, 然后让所有其他维度减去这个向量各维度的平均值, 这样的操作叫作中心化.
中心化的意思是说, 对每个向量, 我先计算所有元素的平均值avg, 然后向量中每个维度的值都减去这个avg, 得到的这个向量叫做被中心化的向量.
机器学习, 数据挖掘要计算向量余弦相似度的时候, 由于向量经常在某个维度上有数据的缺失, 预处理阶段都要对所有维度的数值进行中心化处理.
皮尔逊系数公式 皮尔逊相关性与余弦相似度
文章图片

观察以上皮尔逊系数的公式:
分子部分: 每个向量的每个数字要先减掉向量各个数字的平均值, 这就是在中心化.
分母部分: 两个根号式子就是在做取模运算, 里面的所有的 r 也要减掉平均值, 其实也就是在做中心化.
结论 皮尔逊相关系数是余弦相似度在维度值缺失情况下的一种改进.
一些其它定义 欧氏距离 欧式距离,即欧几里得距离,是最常见的两点之间的距离表示法,它定义在欧几里得空间中,例如x = (x1,x2,…,xn)和y = (y1,y2,…,yn)的欧式距离可表示为:
皮尔逊相关性与余弦相似度
文章图片

协方差 协方差是一个反映两个随机变量相关程度的指标,如果一个变量跟随着另一个变量同时变大或者变小,那么这两个变量的协方差就是正值,反之相反。
皮尔逊相关性与余弦相似度
文章图片

虽然协方差能反映两个随机变量的相关程度(协方差大于0的时候表示两者正相关,小于0的时候表示两者负相关),但是协方差值的大小并不能很好地度量两个随机变量的关联程度,例如,现在二维空间中分布着一些数据,我们想知道数据点坐标X轴和Y轴的相关程度,如果X与Y的相关程度较小但是数据分布的比较离散,这样会导致求出的协方差值较大,用这个值来度量相关程度是不合理的。
皮尔逊相关性与余弦相似度
文章图片

Pearson相关系数是用协方差除以两个变量的标准差得到的。为了更好的度量两个随机变量的相关程度,引入了Pearson相关系数,其在协方差的基础上除以了两个随机变量的标准差,容易得出,pearson是一个介于-1和1之间的值,当两个变量的线性关系增强时,相关系数趋于1或-1;当一个变量增大,另一个变量也增大时,表明它们之间是正相关的,相关系数大于0;如果一个变量增大,另一个变量却减小,表明它们之间是负相关的,相关系数小于0;如果相关系数等于0,表明它们之间不存在线性相关关系
皮尔逊代码实现

#手动实现pearsonimport math import numpy as np#获取两个向量平均值 def calcMean(x,y): sum_x=0 sum_y=0for i in x.flat: sum_x+=i for i in y.flat: sum_y+=in=len(x)x_mean = float(sum_x+0.0)/n y_mean = float(sum_y+0.0)/nreturnx_mean,y_mean#求两个向量的pearson系数 def calcPearson9(x,y): x_mean,y_mean = calcMean(x,y) n = len(x) sumTop = 0.0 sumBottom = 0.0 x_pow = 0.0 y_pow = 0.0for i in range(n): sumTop +=(x[i]-x_mean)*(y[i]-y_mean) for i in range(n): x_pow += pow(x[i]-x_mean,2) for i in range(n): y_pow += pow(y[i]-y_mean,2) sumBottom = math.sqrt(x_pow *y_pow) p = sumTop / sumBottom return pif __name__ == '__main__': x1 = np.random.random_integers(0, 10, (100, 1)) x2 = np.random.random_integers(0, 10, (100, 1))p=calcPearson9(x1,x2) print(p)

【皮尔逊相关性与余弦相似度】pearsonr(x,y):
1)输入:x为特征,y为目标变量.
2)输出:r: 相关系数 [-1,1]之间,p-value: p值。
注: p值越小,表示相关系数越显著,一般p值在500个样本以上时有较高的可靠性。
import numpy as np from scipy.stats import pearsonr#设定向量长度 l=100 #生成闭区间[0,10]上离散均匀分布的整数值,(a,b)为a行b列 #生成三个向量 x1=np.random.random_integers(0,10,l) x2=np.random.random_integers(0,10,l)p12 = pearsonr(x1,x2) print(p12)

余弦相似度代码实现
importjieba importnumpy as np import redef get_word(s1,s2): #s1为句子1 s2为句子2 返回余弦相似度 #分词 cut1 = jieba.cut(s1) cut2 = jieba.cut(s2)#split可以把字符串转为列表 list_word1 = (','.join(cut1)).split(',') list_word2 = (','.join(cut2)).split(',')#set构造一个集合,且不重复,可以据此找出两句中重合的词汇 key_word = list(set(list_word1+list_word2))#构造两个词频矩阵 word_vector1 = np.zeros(len(key_word)) word_vector2 = np.zeros(len(key_word))#计算词频 for i in range(len(key_word)): for j in range(len(list_word1)): if key_word[i] == list_word1[j]: word_vector1[i]+=1 for k in range(len(list_word2)): if key_word[i] == list_word2[k]: word_vector2[i]+=1 #输出分别的词频向量 return word_vector1,word_vector2def cos(vec1,vec2): #dot为矩阵乘法 #linalg.norm()为求范数 dist = float(np.dot(vec1,vec2)/(np.linalg.norm(vec1) * np.linalg.norm(vec2))) return distif __name__ == '__main__': s1 = "很高兴见到你" s2 = '我也很高兴见到你'vec1,vec2 = get_word(s1,s2)dist = cos(vec1,vec2) print(dist)

    推荐阅读