k-邻近算法理论及代码笔记

K近邻算法笔记

(主要参照李航-统计学习方法)

K近邻学习摘要

K近邻计算

代码实例

K近邻学习摘要

K近邻(k-Nearest Neighbor,简称 kNN)学习是一种常用的监督学习方法,是一种基本分类与回归方法。其工作机制非常简单:给定测试样本,基于某种距离度量找出训练集中与其最靠近的k个训练样本,然后基于这k个"邻居"的信息来进行预测。通常,在分类任务中可使用“投票法”,即选择这k个样本中出现最多的类别标记作为预测结果:在回归任务中使用“平均法”,即将这k个样本的实值输出标记的平均值作为预测结果:还可基于距离远近进行加权或加权投票,距离越近的样本权重越大。k近邻法是在1968年由Cover和Hart提出的。
算法1.1(引自李航统计学习方法)
训练数据集 T = { ( x 1 , y 1 ) , ( x 2 . y 2 ) , . . . , ( x N , y N ) } T=\{(x_{1},y_{1}),(x_{2}.y_{2}),...,(x_{N},y_{N})\} T={(x1,y1),(x2.y2),...,(xN,yN)}
其中 x i ∈ X ⊆ R n 为 实 例 的 特 征 向 量 , y i ∈ Y = { c 1 , c 2 , . . . , c k } x_{i}\in \mathcal X \subseteq R^{n} 为实例的特征向量,y_{i} \in\mathcal Y=\{c_1,c_2,...,c_k\} xiXRnyiY={c1,c2,...,ck} 为实例的类别, i =,1,2,…,N;实例特征向量x;
输出:实例x所属的类y。
(1)根据给定的距离度量,在训练集T中找出与x最邻近的k个点,涵盖这个k个点的邻域记作 N K ( x ) N_K(x) NK(x);
(2) 在 N K ( x ) N_K(x) NK(x)中根据分类决策规则(如多数表决)决定x的类别y;
y = a r g max ⁡ c j ∑ X i ⊆ N K ( x ) n I ( y i = c i ) , i = 1 , 2 , . . . , N ; j = 1 , 2 , . . , K y=arg \max\limits_{c_j} \sum\limits_{X_i \subseteq N_K(x)}^n I(y_i=c_i), i=1,2,...,N;j=1,2,..,K y=argcjmaxXiNK(x)nI(yi=ci),i=1,2,...,N;j=1,2,..,K
I I I为指示函数,即当 y i = c i y_i=c_i yi=ci I I I为1,否则 I I I为0.
当k=1时称为最近邻算法,最近邻法将训练数据集中与x最邻近点作为x的类。k近邻法没有显示的学习过程,k近邻算法没有模型。
上述描述简而言之:就是将需要分类的输入实例x,在训练集中计算出k个与其最相近的点,然后计算出这些点对应类别最多的那个类。将输入实例划分归为计算出的最多的那一类。

K近邻计算

k近邻算法有三个基本要素,距离度量、k值的选择、分类决策规则。
优点:精度高、对异常值不敏感、无数据输入假定。
缺点:计算复杂度高、空间复杂度高。
适用范围:数值型和标称型。

1.距离度量

两个实例点的距离用来计算两个实例点的相似度。这里可以使用的距离计算方法主要是三种,1、欧氏距离,2、 L p L_p Lp距离( L 1 , L 2 L_1,L_2 L1,L2等),3、Minkowski距离。以下为 L p L_p Lp距离计算方法:
X 是 n 维 实 数 向 量 空 间 R ( n ) , x i , x j ∈ X , \mathcal X是n维实数向量空间R^{(n)},x_i,x_j\in\mathcal X, XnR(n)xi,xjX,
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_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=(xi(1),xi(2),...xi(n))T,xj=(xj(1),xj(2),...xj(n))T,xi,xjLp
L p ( x i , x j ) = ( ∑ i = 1 n ∣ x i ( l ) − x j ( j ) ∣ p ) 1 p L_p(x_i,x_j)=\big(\sum\limits_{i=1}^n |x_i^{(l)}-x_j^{(j)}|^p \big)^{\dfrac{1}{p}} Lp(xi,xj)=(i=1nxi(l)xj(j)p)p1
当p=2时称为欧氏距离即:
L 2 ( x i , x j ) = ( ∑ i = 1 n ∣ x i ( l ) − x j ( j ) ∣ 2 ) 1 2 L_2(x_i,x_j)=\big(\sum\limits_{i=1}^n |x_i^{(l)}-x_j^{(j)}|^2 \big)^{\dfrac{1}{2}} L2(xi,xj)=(i=1nxi(l)xj(j)2)21
当p=1时称为曼哈顿距离即:
L 1 ( x i , x j ) = ( ∑ i = 1 n ∣ x i ( l ) − x j ( j ) ∣ ) L_1(x_i,x_j)=\big(\sum\limits_{i=1}^n |x_i^{(l)}-x_j^{(j)}|\big) L1(xi,xj)=(i=1nxi(l)xj(j))
p = ∞ p=\infty p=时,他是各个坐标距离的最大值,即
L ∞ ( x i , x j ) = ( max ⁡ l ∣ x i ( l ) − x j ( j ) ∣ ) L_\infty(x_i,x_j)=\big(\max\limits_l |x_i^{(l)}-x_j^{(j)}| \big) L(xi,xj)=(lmaxxi(l)xj(j))

2.k值选择

k值的选择会直接对k近邻的结果产生重大影响。如果k值过小,就相当于使用较小邻域中的训练实例进行预测,获得的"近似误差"会减小,只有与输入实例较近的训练实例才会对预测结果起作用。缺点是估计误差会增大预测结果对近邻的实例点非常敏感,如果近邻点恰好是噪声就会出错。就意味着发生过拟合。相反k值较大就会发生欠拟合。
以此k值一般是一个较小的数,通常采用交叉验证老获取最优的k值。

3.分类决策规则

k近邻中的分类决策规则往往是多数表决,即由输入实例的k个近邻的训练实例中的多数类决定输入实例的类。
多数表决的=规则有如下解释:如果分类的损失函数为0-1损失函数。分类函数为:
f : R n − > { c 1 , c 2 , . . c K } f:R^n->\{c_1,c_2,..c_K\} f:Rn>{c1,c2,..cK}
那个误分类的概率是
P ( Y ≠ f ( X ) ) = 1 − P ( Y = f ( X ) ) P(Y\neq f(X))=1-P(Y=f(X)) P(Y=f(X))=1P(Y=f(X))
对给定的实例 x ∈ X x\in \mathcal X xX,其中最近邻的k个训练实例点构成集合 N k ( x ) N_k(x) Nk(x),如果涵盖 N k ( x ) N_k(x) Nk(x)的区域类别是 c j c_j cj,那么误分类率是:
1 k ∑ x i ∈ N k ( x ) I ( y i ≠ c j ) = 1 − 1 k ∑ x i ∈ N k ( x ) I ( y i = c j ) \dfrac{1}{k}\sum\limits_{x_i\in N_k(x)} I(y_i \neq c_j)=1- \dfrac{1}{k}\sum\limits_{x_i\in N_k(x)} I(y_i=c_j) k1xiNk(x)I(yi=cj)=1k1xiNk(x)I(yi=cj)
要使误差分类率最小即风险最小,就要使 ∑ x i ∈ N k ( x ) I ( y i = c j ) \sum\limits_{x_i\in N_k(x)} I(y_i=c_j) xiNk(x)I(yi=cj)最大,所以多数表决规则等价于经验风险最小化。

代码实例

代码改自机器学习实战,将py2改为py3可运行,修改处为classCount.items(),py2为classCount.iteritems()

import numpy as np
import operator

#创建虚拟数据集
def createDataSet():
    trainSet = np.array([[1.0, 1.1], [1.0, 1.0], [0.0, 0.0], [0.0, 0.1]])
    labels = ["A", "A", "B", "B"]
    return trainSet, labels

#构建分类器
def classify0(inputX, trainSet, labels, k):
    trainSetLen = len(trainSet)
    inputXMat = np.tile(inputX, (trainSetLen, 1))
    diffMat = inputXMat - trainSet
    sqDiffMat = diffMat**2
    sqDistances = sqDiffMat.sum(axis=1)
    distances = sqDistances**0.5
    sortedDistIndicies = distances.argsort()
    classCount = {}
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]

trainSet, labels = createDataSet()
print(classify0([0.1, 0], trainSet, labels, 3))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凉寒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值