如何比较相似
在数据科学中,经常需要知道个体间差异的大小,进而评价个体的相似性和类别
首先这里的个体是一个泛化的概念,个体的相似既可以指两个人的相似、两个物品的相似,也可以是人和物的相似、两个分布的相似、两个数据集的相似等
1.欧式距离
用距离衡量个体之间的差异时,距离越大,说明个体差异越大,个体之间越不相似。
欧式距离的计算公式
d
i
s
t
(
x
,
y
)
=
∑
i
=
1
k
(
x
i
−
y
i
)
2
dist(x, y) = \sqrt{\sum_{i=1}^{k}{(x_i-y_i)^2}}
dist(x,y)=i=1∑k(xi−yi)2
公式说明:
x,y代表两个个体,对应着两个多维的向量
xi,yi是两个向量在维度i上的值
import numpy as np
users = ['u1', 'u2', 'u3', 'u4', 'u5', 'u6']
#用户-行为评分矩阵
rating_matrix = np.array([[4, 3, 0, 0, 5, 0],
[5, 0, 4, 0, 4, 0],
[4, 0, 5, 3, 4, 0],
[0, 3, 0, 0, 0, 5],
[0, 4, 0, 0, 0, 4],
[0, 0, 2, 4, 0, 5]
])
#根据公式计算用户u1和u2的距离
d1 = np.sqrt(np.sum(np.square(rating_matrix[0, :] - rating_matrix[1, :])))
print(d1)
d 1 = 5.196152422706632 d1 = 5.196152422706632 d1=5.196152422706632
如果我们想得到所有样本两两之间距离的方法,这个方法在scikit-learn已经存在
import pandas as pd
from sklearn.metrics.pairwise import euclidean_distances
import numpy as np
users = ['u1', 'u2', 'u3', 'u4', 'u5', 'u6']
rating_matrix = np.array([[4, 3, 0, 0, 5, 0],
[5, 0, 4, 0, 4, 0],
[4, 0, 5, 3, 4, 0],
[0, 3, 0, 0, 0, 5],
[0, 4, 0, 0, 0, 4],
[0, 0, 2, 4, 0, 5]
])
eucl_dists = euclidean_distances(rating_matrix)
dist_df = pd.DataFrame(eucl_dists, columns=users, index=users)
print(dist_df)
结果如图所示:
u1 | u2 | u3 | u4 | u5 | u6 | |
---|---|---|---|---|---|---|
u1 | 0.000000 | 5.196152 | 6.633250 | 8.124038 | 7.615773 | 9.746794 |
u2 | 5.196152 | 0.000000 | 3.316625 | 9.539392 | 9.433981 | 9.273618 |
u3 | 6.633250 | 3.316625 | 0.000000 | 10.000000 | 9.899495 | 8.185353 |
u4 | 8.124038 | 9.539392 | 10.000000 | 0.000000 | 1.414214 | 5.385165 |
u5 | 7.615773 | 9.433981 | 9.899495 | 1.414214 | 0.000000 | 6.082763 |
u6 | 9.746794 | 9.273618 | 8.185353 | 5.385165 | 6.082763 | 0.000000 |
用户距离矩阵是一个方阵,对角线元素全为0,也就是自己和自己的距离为0;
用户距离矩阵是一个对称矩阵,比如u1与u2的距离等于u2与u1的距离
2.夹角余弦相似度
除了使用距离我们还可以使用相似度来很很衡量用户的相似性,常用的相似度为余弦相似度
c
o
s
(
θ
)
=
a
⃗
⋅
b
⃗
÷
(
∣
∣
a
⃗
∣
∣
∣
b
⃗
∣
∣
)
cos(\theta) =\vec{a}\cdot\vec{b}\div(||\vec{a}|||\vec{b}||)
cos(θ)=a⋅b÷(∣∣a∣∣∣b∣∣)
import numpy as np
users = ['u1', 'u2', 'u3', 'u4', 'u5', 'u6']
rating_matrix = np.array([[4, 3, 0, 0, 5, 0],
[5, 0, 4, 0, 4, 0],
[4, 0, 5, 3, 4, 0],
[0, 3, 0, 0, 0, 5],
[0, 4, 0, 0, 0, 4],
[0, 0, 2, 4, 0, 5]
])
#用于计算一个向量的模长
def mod(vec):
x = np.sum(vec**2)
return x**0.5
#用于计算两个向量的夹角的余弦值
def sim(vec1, vec2):
s = np.dot(vec1, vec2) / (mod(vec1) * mod(vec2))
return s
#计算两个用户的相似度
cos_sim = sim(rating_matrix[0], rating_matrix[1])
print(cos_sim)
scikit-learn也提供了计算所有样本两两之间的相似度并且得到矩阵相似度的方法:
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.metrics.pairwise import cosine_similarity
users = ['u1', 'u2', 'u3', 'u4', 'u5', 'u6']
rating_matrix = np.array([[4, 3, 0, 0, 5, 0],
[5, 0, 4, 0, 4, 0],
[4, 0, 5, 3, 4, 0],
[0, 3, 0, 0, 0, 5],
[0, 4, 0, 0, 0, 4],
[0, 0, 2, 4, 0, 5]
])
cos_sims = cosine_similarity(rating_matrix)
sims_df = pd.DataFrame(cos_sims, columns=users, index=users)
print(sims_df)
sns.heatmap(sims_df, cmap='Blues', annot=True, fmt='.2f')
plt.show()
相似度矩阵的特点:
矩阵是一个方阵,对角元素都是1,即自己和自己的相似度最大,为1.
矩阵时是对称矩阵,u1和u2的相似度等于u2和u1的相似度。
上面代码还使用了热力图,用可视化的方法来观察相似度矩阵。
颜色越高代表相似度越高。