k-means 聚类中使用余弦距离 cos distance
本文在 知乎 发布
k-means 聚类算法中使用欧氏距离作为判别标准,本文讨论使用余弦距离作为判别的方法和理论基础。
先说结论:使用欧氏距离聚类结果等价于使用余弦距离聚类结果。
首先看余弦的计算 ,
可以看做两个归一化后的单位向量的内积,同时理解对样本向量进行归一化并不改变余弦距离的计算。
而在欧氏距离的计算中,
如果向量已经是单位向量,那么
也即使用余弦距离和使用欧氏距离进行判别的聚类结果是等价。
所以使用余弦距离进行聚类的方式是先将样本进行归一化,然后使用常规方法和工具(如 scikit-learn)进行计算。
余下的问题则是余弦聚类的中心和距离怎么计算?
对于维度为 m 的 n 个样本
求样本余弦中心 使得
其中
把问题等价重写为目标
和约束
则使用 Lagrange multiplier 方法有,
于是 , 令
推出
带回约束条件中,由
得到
于是
至此,就得到了余弦中心的计算方法。
注意到这个余弦中心向量的方向和模长并没有关系,这也和余弦距离的特性相符合。
当对样本进行归一化,同时假定余弦中心向量归一化后,
即余弦中心为欧氏中心归一化后的结果
附:使用 scikit-learn 进行计算的代码
# 归一化
nm = np.sqrt((X**2).sum(axis=1))[:,None]
X = X / nm
kmeans = KMeans(n_clusters=2, random_state=0).fit(X)
# 其实也是在计算归一化
mm = np.sqrt(np.square(kmeans.cluster_centers_).sum(axis=1)[:,None])
cos_centers = kmeans.cluster_centers_ / mm
distance = 1 - np.dot(cos_centers, X.T)