🔴参考书籍:《动手学推荐系统》
Cos相似度与皮尔逊相似度及其关联
Cos相似度
Cos相似度即两个向量在空间里的夹角余弦值。取值范围为[-1,1],0代表正交,-1和1代表方向完全相反和相同。
2个向量间的Cos相似度
公式
S X Y = X ⋅ Y ∣ ∣ X ∣ ∣ ∣ ∣ Y ∣ ∣ S_{XY}=\frac{\bold{X} \cdot \bold{Y}}{||X|| \quad ||Y||} SXY=∣∣X∣∣∣∣Y∣∣X⋅Y
代码
# 两个向量间的cos相似度
def cos4vector( v1, v2 ):
return (np.dot(v1,v2))/(np.linalg.norm(v1)*np.linalg.norm(v2))
其中,np.linalg.norm()
用于计算范数。参考链接:https://blog.csdn.net/m0_51816252/article/details/126199555
实例
以向量[1,2,3]和[2,3,4]为例:
S = 1 ∗ 2 + 2 ∗ 3 + 3 ∗ 4 1 2 + 2 2 + 3 2 + 2 2 + 3 2 + 4 2 = 0.9925 S = \frac{1*2+2*3+3*4}{\sqrt{1^2+2^2+3^2} + \sqrt{2^2+3^2+4^2}} = 0.9925 S=12+22+32+22+32+421∗2+2∗3+3∗4=0.9925
代码
x = np.array([1,2,3])
y = np.array([2,3,4])
print(cos4vector(x,y))
# 输出:0.9925833339709303
2个集合间的cos相似度
公式
S x y = N ( x ) ∩ N ( y ) ∣ N ( x ) ∣ × ∣ N ( y ) ∣ S_{xy}=\frac{N(\bold{x}) \cap N(\bold{y})}{\sqrt{|N(\bold{x})| \times |N(\bold{y})|}} Sxy=∣N(x)∣×∣N(y)∣N(x)∩N(y)
代码
# 两个集合间的cos相似度
def cos4set( set1, set2 ):
return len(set1&set2)/(len(set1)*len(set2))**0.5
集合是需要转化为0/1表示的向量,例如 N ( x ) = { 1 , 2 , 3 , 5 } , N ( y ) = { 1 , 4 , 5 , 6 } N(\bold{x})=\{1,2,3,5\}, N(\bold{y})=\{1,4,5,6\} N(x)={1,2,3,5},N(y)={1,4,5,6}的向量表示为 [ 1 , 1 , 1 , 0 , 1 , 0 ] , [ 1 , 0 , 0 , 1 , 1 , 1 ] [1,1,1,0,1,0], [1,0,0,1,1,1] [1,1,1,0,1,0],[1,0,0,1,1,1]。它们的点乘是元素值同时为1的对应位置的和,也就是2个集合的并集,而向量的模长,也是向量中为1的数量开根号,而为1的数量是本身集合的长度。
实例
S = 2 4 ∗ 4 = 0.5 S = \frac{2}{\sqrt{4*4}} = 0.5 S=4∗42=0.5
set1 = set([1,2,3,5])
set2 = set([1,4,5,6])
print(len(set1&set2)) # 2
print(len(set1),len(set2)) # 4 4
print(cos4set(set1,set2)) # 0.5
Pearson相似度
理论
皮尔逊相似度又称皮尔逊相关系数,用于衡量两个变量的相关程度。取值范围为[-1,1]。0代表毫无关系,-1和1代表完全负相关和完全相关。
基准公式为
S X Y = c o v ( X , Y ) σ X σ Y = ∑ i = 1 n ( X i − X ‾ ) ( Y i − Y ‾ ) ∑ i = 1 n ( X i − X ‾ ) 2 ∑ i = 1 n ( Y i − Y ‾ ) 2 S_{XY}=\frac{cov(\bold{X},\bold{Y})}{\sigma \bold{X} \sigma \bold{Y}} = \frac{\sum^n_{i=1} (X_i - \overline{X})(Y_i - \overline{Y})}{\sqrt{\sum^n_{i=1} (X_i - \overline{X})^2} \sqrt{\sum^n_{i=1} (Y_i - \overline{Y})^2}} SXY=σXσYcov(X,Y)=∑i=1n(Xi−X)2∑i=1n(Yi−Y)2∑i=1n(Xi−X)(Yi−Y)
其中, c o v ( X , Y ) cov(\bold{X},\bold{Y}) cov(X,Y)代表协方差矩阵,公式如下:
c o v ( X , Y ) = ∑ i = 1 n ( X i − X ‾ ) ( Y i − Y ‾ ) cov(\bold{X},\bold{Y}) = \sum^n_{i=1} (X_i - \overline{X})(Y_i - \overline{Y}) cov(X,Y)=i=1∑n(Xi−X)(Yi−Y)
σ X \sigma \bold{X} σX代表 X \bold{X} X的标准差:
σ X = ∑ i = 1 n ( X i − X ‾ ) 2 \sigma \bold{X} = \sqrt{\sum^n_{i=1} (X_i - \overline{X})^2} σX=i=1∑n(Xi−X)2
X ‾ \overline{X} X是 X \bold{X} X的期望也是平均值。
代码
# 两个向量间的pearson相似度
def pearson( v1, v2 ):
v1_mean = np.mean( v1 )
v2_mean = np.mean( v2 )
return ( np.dot( v1 - v1_mean, v2 - v2_mean) )/\
( np.linalg.norm( v1 - v1_mean ) *
np.linalg.norm( v2 - v2_mean ) )
实例
有2个向量:
v
1
=
[
1
,
0
,
1
,
1
]
,
v
2
=
[
0
,
1
,
1
,
0
]
v1 = [1,0,1,1],v2=[0,1,1,0]
v1=[1,0,1,1],v2=[0,1,1,0],v1的期望(平均值)为
(
1
+
0
+
1
+
1
)
/
4
=
3
4
(1+0+1+1)/4= \frac{3}{4}
(1+0+1+1)/4=43;v2的期望为1/2。皮尔逊相似度的分子在代码中的实现为,先进行向量相减(v1 - v1_mean
),然后使用np.dot()
点积操作进行元素相乘再求和。
S = [ 0.25 , − 0.75 , 0.25 , 0.25 ] ⋅ [ − 0.5 , 0.5 , 0.5 , − 0.5 ] 0.2 5 2 + ( − 0.75 ) 2 + 0.2 5 2 + 0.2 5 2 ⋅ ( − 0.5 ) 2 + 0. 5 2 + 0. 5 2 ( − 0.5 ) 2 = − 0.5 12 4 = − 0.577 S = \frac{[0.25,-0.75,0.25,0.25] \cdot [-0.5,0.5,0.5,-0.5]}{\sqrt{0.25^2+(-0.75)^2+0.25^2+0.25^2} \cdot \sqrt{(-0.5)^2+0.5^2+0.5^2(-0.5)^2}} \\ = \frac{-0.5}{\frac{\sqrt{12}}{4}} \\ = - 0.577 S=0.252+(−0.75)2+0.252+0.252⋅(−0.5)2+0.52+0.52(−0.5)2[0.25,−0.75,0.25,0.25]⋅[−0.5,0.5,0.5,−0.5]=412−0.5=−0.577
v1 = np.array([1,0,1,1])
v2 = np.array([0,1,1,0])
v1_mean = np.mean( v1 )
print(v1 - v1_mean) # [ 0.25 -0.75 0.25 0.25]
v2_mean = np.mean( v2 )
print(v2 - v2_mean) # [-0.5 0.5 0.5 -0.5]
print(pearson(v1,v2)) # -0.5773502691896258
cos相似度与皮尔逊相似度的关联
cos相似度的公式可以展开为:
S X Y = X ⋅ Y ∣ ∣ X ∣ ∣ ∣ ∣ Y ∣ ∣ = ∑ i = 1 n X i Y i ∑ i = 1 n X i 2 ∑ i = 1 n Y i 2 S_{XY}=\frac{\bold{X} \cdot \bold{Y}}{||X|| \quad ||Y||} = \frac{\sum^n_{i=1} X_i Y_i}{\sqrt{\sum^n_{i=1} X_i^2} \sqrt{\sum^n_{i=1} Y_i^2}} SXY=∣∣X∣∣∣∣Y∣∣X⋅Y=∑i=1nXi2∑i=1nYi2∑i=1nXiYi
再看看皮尔逊相似度:
S X Y = c o v ( X , Y ) σ X σ Y = ∑ i = 1 n ( X i − X ‾ ) ( Y i − Y ‾ ) ∑ i = 1 n ( X i − X ‾ ) 2 ∑ i = 1 n ( Y i − Y ‾ ) 2 S_{XY}=\frac{cov(\bold{X},\bold{Y})}{\sigma \bold{X} \sigma \bold{Y}} = \frac{\sum^n_{i=1} (X_i - \overline{X})(Y_i - \overline{Y})}{\sqrt{\sum^n_{i=1} (X_i - \overline{X})^2} \sqrt{\sum^n_{i=1} (Y_i - \overline{Y})^2}} SXY=σXσYcov(X,Y)=∑i=1n(Xi−X)2∑i=1n(Yi−Y)2∑i=1n(Xi−X)(Yi−Y)
- 对于cos相似度来说,皮尔逊相似度在求 X i − X ‾ X_i - \overline{X} Xi−X和 Y i − Y ‾ Y_i - \overline{Y} Yi−Y的余弦夹角值
- 因此,皮尔逊相似度是想让每个向量的值都减去该向量所有值的平均值,然后求夹角余弦值。这个操作等价于先对数据做标准化处理,然后求余弦相似度。
# 两个向量间的pearson相似度
def pearsonSimple( v1, v2 ):
v1 -= np.mean( v1 )
v2 -= np.mean( v2 )
return cos4vector( v1, v2 ) #调用余弦相似度函数
为什么要用皮尔逊相似度?由于每个人的评分体系不同,甲可能偏向宽容打分,平均分为8;而乙偏向严肃打分,平均分只有3。先减去用户自己对所有物品的平均打分,再求余弦值,显然更合理。