【Python】欧氏距离和余弦距离

一、欧几里得距离(Euclidean Distance)

   欧氏距离是最常见的距离度量,衡量的是多维空间中各个点之间的绝对距离。公式如下:

Euclidean Distance

  因为计算是基于各维度特征的绝对数值,所以欧氏度量需要保证各维度指标在相同的刻度级别,比如对身高(cm)和体重(kg)两个单位不同的指标使用欧式距离可能使结果失效。

        Python实现如下:

import numpy as np

x=np.random.random(10)
y=np.random.random(10)

# solution1
dist1 = np.linalg.norm( x - y )

# solution2
dist2 = np.sqrt(np.sum(np.square(x - y)))  

print('x',x)
print('y',y)
print('dist1',dist1)
print('dist2',dist2)
          运行结果:



二、余弦距离

         余弦相似度用向量空间中两个向量夹角的余弦值作为衡量两个个体间差异的大小。相比距离度量,余弦相似度更加注重两个向量在方向上的差异,而非距离或长度上。公式如下:

Cosine Similarity

              Python实现如下:

import numpy as np
from scipy.spatial.distance import pdist

x=np.random.random(10)
y=np.random.random(10)

# solution1
dist1 = 1 - np.dot(x,y)/(np.linalg.norm(x)*np.linalg.norm(y))

# solution2
dist2 = pdist(np.vstack([x,y]),'cosine')

print('x',x)
print('y',y)
print('dist1',dist1)
print('dist2',dist2)
            运行结果:



三、欧氏距离和余弦距离的区别

           

        余弦距离使用两个向量夹角的余弦值作为衡量两个个体间差异的大小。相比欧氏距离,余弦距离更加注重两个向量在方向上的差异。

        借助三维坐标系来看下欧氏距离和余弦距离的区别:

clip_image009

           从上图可以看出,欧氏距离衡量的是空间各点的绝对距离,跟各个点所在的位置坐标直接相关;而余弦距离衡量的是空间向量的夹角,更加体现在方向上的差异,而不是位置。如果保持A点位置不变,B点朝原方向远离坐标轴原点,那么这个时候余弦距离 clip_image011 是保持不变的(因为夹角没有发生变化),而A、B两点的距离显然在发生改变,这就是欧氏距离和余弦距离之间的不同之处。

           欧氏距离和余弦距离各自有不同的计算方式和衡量特征,因此它们适用于不同的数据分析模型:

欧氏距离能够体现个体数值特征的绝对差异,所以更多的用于需要从维度的数值大小中体现差异的分析,如使用用户行为指标分析用户价值的相似度或差异。

余弦距离更多的是从方向上区分差异,而对绝对的数值不敏感,更多的用于使用用户对内容评分来区分兴趣的相似度和差异,同时修正了用户间可能存在的度量标准不统一的问题(因为余弦距离对绝对数值不敏感)。


  • 11
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
以下是使用Python实现k-means算法,其中包括欧氏距离、曼哈顿距离和夹角余弦距离的实现: ```python import numpy as np import math # 欧氏距离 def euclidean_distance(x1, x2): return np.sqrt(np.sum((x1 - x2)**2)) # 曼哈顿距离 def manhattan_distance(x1, x2): return np.sum(np.abs(x1 - x2)) # 夹角余弦距离 def cosine_distance(x1, x2): dot_product = np.dot(x1, x2) norm_x1 = np.linalg.norm(x1) norm_x2 = np.linalg.norm(x2) return 1 - dot_product / (norm_x1 * norm_x2) class KMeans: def __init__(self, k=3, max_iters=100, distance="euclidean"): self.k = k self.max_iters = max_iters self.distance = distance def initialize_centroids(self, X): n_samples, n_features = X.shape centroids = np.zeros((self.k, n_features)) for i in range(self.k): centroid = X[np.random.choice(range(n_samples))] centroids[i] = centroid return centroids def closest_centroid(self, sample, centroids): distances = np.zeros(self.k) for i, centroid in enumerate(centroids): if self.distance == "euclidean": distances[i] = euclidean_distance(sample, centroid) elif self.distance == "manhattan": distances[i] = manhattan_distance(sample, centroid) else: distances[i] = cosine_distance(sample, centroid) closest_index = np.argmin(distances) return closest_index def create_clusters(self, X, centroids): clusters = [[] for _ in range(self.k)] for sample_i, sample in enumerate(X): centroid_i = self.closest_centroid(sample, centroids) clusters[centroid_i].append(sample_i) return clusters def calculate_centroids(self, X, clusters): n_features = X.shape[1] centroids = np.zeros((self.k, n_features)) for i, cluster in enumerate(clusters): centroid = np.mean(X[cluster], axis=0) centroids[i] = centroid return centroids def get_cluster_labels(self, clusters, X): y_pred = np.zeros(X.shape[0]) for cluster_i, cluster in enumerate(clusters): for sample_i in cluster: y_pred[sample_i] = cluster_i return y_pred def predict(self, X): centroids = self.initialize_centroids(X) for _ in range(self.max_iters): clusters = self.create_clusters(X, centroids) prev_centroids = centroids centroids = self.calculate_centroids(X, clusters) if np.all(centroids == prev_centroids): break return self.get_cluster_labels(clusters, X) ``` 使用示例: ```python from sklearn.datasets import make_blobs import matplotlib.pyplot as plt X, y = make_blobs(centers=3, n_samples=500, random_state=1) kmeans = KMeans(k=3, max_iters=100, distance="euclidean") y_pred = kmeans.predict(X) plt.scatter(X[:, 0], X[:, 1], c=y_pred) plt.title("K-Means Clustering") plt.show() ``` 其中,distance参数可以设置为"euclidean"、"manhattan"或者"cosine",表示使用欧氏距离、曼哈顿距离或夹角余弦距离

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值