皮尔逊相关系数和余弦相似度

您所在的位置:网站首页 两个向量夹角的余弦值是负值吗对吗 皮尔逊相关系数和余弦相似度

皮尔逊相关系数和余弦相似度

2024-07-16 08:19| 来源: 网络整理| 查看: 265

先看看二者定义,给定两个n维向量A,B:

A = ( a 1 , a 2 , … , a n ) A = (a_1, a_2, \ldots ,a_n) A=(a1​,a2​,…,an​) B = ( b 1 , b 2 , … , b n ) B = (b_1, b_2, \ldots ,b_n) B=(b1​,b2​,…,bn​)

余弦相似度: c o s ( θ ) = A ⋅ B ∥ A ∥ ⋅ ∥ B ∥ = ∑ i = 1 n a i × b i ∑ i = 1 n a i 2 × ∑ i = 1 n b i 2 cos(\theta) = {A \cdot B \over \Vert A \Vert \cdot \Vert B \Vert } = \frac{ \sum_{i=1}^n a_i \times b_i }{ \sqrt {\sum_{i=1}^n a_i^2} \times \sqrt {\sum_{i=1}^n b_i^2}} cos(θ)=∥A∥⋅∥B∥A⋅B​=∑i=1n​ai2​ ​×∑i=1n​bi2​ ​∑i=1n​ai​×bi​​

皮尔逊相关系数: p e a r s o n _ r = ∑ i = 1 n ( a i − a ˉ ) × ( b i − b ˉ ) ∑ i = 1 n ( a i − a ˉ ) 2 × ∑ i = 1 n ( b i − b ˉ ) 2 pearson\_r = \frac{ \sum_{i=1}^n (a_i - \bar a ) \times (b_i - \bar b) }{ \sqrt {\sum_{i=1}^n (a_i - \bar a )^2} \times \sqrt {\sum_{i=1}^n (b_i - \bar b)^2}} pearson_r=∑i=1n​(ai​−aˉ)2 ​×∑i=1n​(bi​−bˉ)2 ​∑i=1n​(ai​−aˉ)×(bi​−bˉ)​

其中: a ˉ = 1 n ∑ i = 1 n a i , b ˉ = 1 n ∑ i = 1 n b i \bar a = {1 \over n} \sum_{i=1}^n a_i, \bar b = {1 \over n} \sum_{i=1}^n b_i aˉ=n1​i=1∑n​ai​,bˉ=n1​i=1∑n​bi​

两式对比,可见皮尔逊相关系数的计算是先对向量每一分量减去分量均值,再求余弦相似度。这一操作称为中心化(将特征向量X根据 x ˉ \bar x xˉ 移动)。

这么做有什么好处呢?比如小明和小刚爱看电影,他们都看过《夏洛特烦恼》、《羞羞的铁拳》和《西虹市首富》,两个人也都在豆瓣上给这几部电影打了分,分值如下表:

夏洛特烦恼羞羞的铁拳西虹市首富小明9.67.55.8小刚8.35.62.4

如果豆瓣的程序员小哥哥想评判小明和小刚的兴趣是否相似(以此来给他们推荐类似的电影或投放相同广告),先初始化两个特征向量:

import numpy as np a_scores = np.array([9.6, 7.5, 5.8]) b_scores = np.array([8.3, 5.6, 2.4])

试下余弦相似度:

from sklearn.metrics.pairwise import cosine_similarity cosine_similarity([a_scores], [b_scores]) output: array([[0.9760924]])

两个人的余弦相似度是0.9760924,还不错,再试试皮尔逊相关系数:

from scipy.stats import pearsonr pearsonr(a_scores, b_scores)[0] output: 0.9940012359465

效果更好!

余弦相似度除了可以比较样本间相似度,也可用于判断特征的重要性,网上比较多的例子即是评判sklearn库的iris(鸢尾花)数据集特征,在此一起总结下。

加载数据集:

from scipy.stats import pearsonr from sklearn.datasets import load_iris # 加载数据集 iris = load_iris()

看数据前10行,每行包含鸢尾花的4个特征(花萼、花瓣的长宽):

iris.data[:10] output: array([[5.1, 3.5, 1.4, 0.2], [4.9, 3. , 1.4, 0.2], [4.7, 3.2, 1.3, 0.2], [4.6, 3.1, 1.5, 0.2], [5. , 3.6, 1.4, 0.2], [5.4, 3.9, 1.7, 0.4], [4.6, 3.4, 1.4, 0.3], [5. , 3.4, 1.5, 0.2], [4.4, 2.9, 1.4, 0.2], [4.9, 3.1, 1.5, 0.1]])

看看label前10行,都是1个品种:

iris.target[:10] output: array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

每个样本有4维特征,通过计算各特征与label的皮尔逊相关系数,即可得到各特征的重要性,所以需要依次取出iris.data的每一列特征,怎么取呢?sklearn.datasets中的数据集已经帮我们处理好了。iris是sklearn.utils.Bunch类的实例,其中iris.data.T就是iris.data的转置,看看其前10行(由于样本过多,这里只显示10个):

iris.data.T[:, :10] output: array([[5.1, 4.9, 4.7, 4.6, 5. , 5.4, 4.6, 5. , 4.4, 4.9], [3.5, 3. , 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9, 3.1], [1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5, 1.4, 1.5], [0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1]])

下面就可以计算特征重要性了:

from scipy.stats import pearsonr for feature in iris.data.T: # 计算皮尔逊相关系数 print(pearsonr(feature, iris.target)[0]) output: 0.7825612318100814 -0.4194462002600275 0.9490425448523336 0.9564638238016173

不过要注意的是,皮尔逊相关系数只对线性相关有效,并不是所有衡量特征重要性都可以这么用,需要因地制宜。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3