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

先看看二者定义,给定两个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)

  1. 余弦相似度:
    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(θ)=ABAB=i=1nai2 ×i=1nbi2 i=1nai×bi

  2. 皮尔逊相关系数:
    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(aiaˉ)2 ×i=1n(bibˉ)2 i=1n(aiaˉ)×(bibˉ)

其中:
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ˉ=n1i=1nai,bˉ=n1i=1nbi

两式对比,可见皮尔逊相关系数的计算是先对向量每一分量减去分量均值,再求余弦相似度。这一操作称为中心化(将特征向量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

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

  • 12
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值