回顾
前面,我们介绍了 k k k-近邻算法,其工作机制就是给定测试样本,基于某种距离度量找出训练集中与其最靠近的k个训练样本,然后基于这k个“邻居”的信息来进行预测。
k k k近邻法会涉及到三个问题(三要素):距离度量、 k k k值的选择、分类决策规则,下面我们分别介绍。
距离度量
特征空间的两个实例点的距离度量是两个实例点相似程度的反映。距离小,那么相似度大;距离大,那么相似度小。 k k k-近邻模型的特征空间一般是 n n n维实数向量空间 R n R^n Rn。使用的距离是欧式距离,但也可以是其他距离,如更一般的 L p L_p Lp距离( L p L_p Lpdistance)或 M i n k o w s k i Minkowski Minkowski距离。
问题定义:设特征空间 X \mathcal{X} X是 n n n维实数向量空间 R n R^n Rn, x i , x j ∈ X , x i = ( x i ( 1 ) , x i ( 2 ) , . . . , x i ( n ) ) T , x j = ( x j ( 1 ) , x j ( 2 ) , . . . , x j ( n ) ) T , x i , x j 的 L p 距 离 定 义 为 : x_i,x_j \in \mathcal{X},x_i = (x_i^{(1)},x_i^{(2)},...,x_i^{(n)})^T,x_j= (x_j^{(1)},x_j^{(2)},...,x_j^{(n)})^T,x_i,x_j的L_p距离定义为: xi,xj∈X,xi=(xi(1),xi(2),...,xi(n))T,xj=(xj(1),xj(2),...,xj(n))T,xi,xj的Lp距离定义为:
L p ( x i , x j ) = ( ∑ l = 1 n ∣ x i ( l ) − x j ( l ) ∣ p ) 1 p L_p(x_i,x_j) = (\sum_{l=1}^{n}|x_i^{(l)}-x_j^{(l)}|^p)^{\frac{1}{p}} Lp(xi,xj)=(l=1∑n∣xi(l)−xj(l)∣p)p1
这里 p ⩾ 1 p \geqslant 1 p⩾1;
1、欧几里得距离(欧式距离 Eucledian Distance)
欧氏距离是最常用的距离计算公式,衡量的是多维空间中各个点之间的绝对距离,当数据很稠密并且连续时,这是一种很好的计算方式。
当 p = 2 p = 2 p=2时,就是欧式距离,即:
L 2 ( x i , x j ) = ( ∑ l = 1 n ∣ x i ( l ) − x j ( l ) ∣ p ) 1 2 L_2(x_i,x_j) = (\sum_{l=1}^{n}|x_i^{(l)}-x_j^{(l)}|^p)^{\frac{1}{2}} L2(xi,xj)=(l=1∑n∣xi(l)−xj(l)∣p)21
代码:
from math import *
# python3
# 欧式距离
def eculidean_dis(x, y):
return sqrt(sum(pow(a - b, 2) for a, b in zip(x, y)))
x = [1, 3, 2, 4]
y = [2, 5, 3, 1]
print(eculidean_dis(x, y)) # 结果为3.872983346207417
2、曼哈顿距离(Manhattan Distance)
当 p = 1 p=1 p=1时,称为曼哈顿距离,即:
L 1 ( x i , x j ) = ∑ l = 1 n ∣ x i ( l ) − x j ( l ) ∣ L_1(x_i,x_j) = \sum_{l=1}^{n}|x_i^{(l)}-x_j^{(l)}| L1(xi,xj)=l=1∑n∣xi(l)−xj(l)∣
代码:
# 曼哈顿距离
def manhattan_dis(x, y):
return sum(abs(a - b) for a, b in zip(x, y))
print(manhattan_dis(x, y)) # 结果为7
3、明可夫斯基距离(Minkowski distance)
明氏距离是欧氏距离的推广,是对多个距离度量公式的概括性的表述:
d i s t ( x i , x j ) = ( ∑ l = 1 n ∣ x i ( l ) − x j ( l ) ∣ p ) 1 p dist(x_i,x_j) = (\sum_{l=1}^{n}|x_i^{(l)}-x_j^{(l)}|^p)^{\frac{1}{p}} dist(xi,xj)=(l=1∑n∣xi(l)−xj(l)∣p)p1
从公式我们可以看出,
- 当p=1,“明可夫斯基距离”变成“曼哈顿距离”
- 当p=2,“明可夫斯基距离”变成“欧几里得距离”
- 当p=∞,“明可夫斯基距离”变成“切比雪夫距离”
代码:
# 明可夫斯基距离
def minkowski_dis(x, y, p):
sumval = sum(pow(abs(a - b), p) for a, b in zip(x, y))
mi = 1 / float(p)
return round(sumval ** mi, 3)
print(minkowski_dis(x, y, 3)) # 结果为3.332
k k k值的选择
k k k值的选择会对 k k k近邻法的结果产生重大影响。
如果 k k k值选择较小,就相当于用较小的领域中的训练实例进行预测,“学习”的近似误差会减小,只有与输入实例较近的训练实例才会对预测起作用,但确定是估计误差回增大。预测结果会对近邻的实例点非常敏感,如果近邻的实例点恰巧是噪声,预测就会出错。
相反如果 k k k值选择较大,就相当于用较大的领域中的训练实例进行预测,近似误差会增大,但估计误差会减小。
特例,如果 k = N k=N k=N,那么无论输入什么实例,都会简单的预测为训练实例中做多的类,这是的模型就没有意义了,丢失了训练实例中的大量有用信息。
在应用中,我们一般取一个较小的 k k k值,通常采用交叉验证法来选取最优的 k k k值。
分类决策规则
k k k近邻法中的分类决策规则往往是多数表决,即由输入实例的 k k k个近邻的训练实例中的多数类决定输入实例的类别。
补充拓展
余弦相似度(Cosine Similarity)
余弦相似度用向量空间中两个向量夹角的余弦值作为衡量两个个体间差异的大小。相比距离度量,余弦相似度更加注重两个向量在方向上的差异,而非距离或长度上。
代码:
# 余弦相似度
def cosine_dis(x, y):
num = sum(map(float, x * y))
denom = np.linalg.norm(x) * np.linalg.norm(y)
return round(num / float(denom), 3)
x = np.array([3, 4, 1, 5])
y = np.array([3, 4, 1, 5])
print(cosine_dis(x, y)) # 结果为1,这边是相同的两个向量
注:
余弦值的范围在[-1,1]之间,值越趋近于1,代表两个向量的方向越接近;越趋近于-1,他们的方向越相反;接近于0,表示两个向量近乎于正交。