机器学习笔记(3)——K近邻法

来源:互联网 时间:1970-01-01

K-nearest neighbor(KNN)

k近邻法一种基本的分类与回归方法,原理和实现都比较直观。其输入为样本的特征向量,输出为样本的类别,可以进行多类别分类。k近邻法是通过统计与未知样本最近点的训练样本的类别来投票决定未知样本的类别,不具有显式的学习过程k近邻法主要包含有k值选择距离度量以及分类决策规则三部分。

1.k近邻模型

距离度量

特征空间中两个样本的距离是两个样本的相似程度的反映。在k 近邻法中常用的距离度量包括:
(1)Minkowski Distacne(闵可夫斯基距离)
定义两个变量xi,xj∈χ,xi=(x1i,x2i,…,xni),xj=(x1j,x2j,…,xnj),则他们之间的闵可夫斯基距离为:
Lp(xi,xj)=(∑l=1n(xli−xlj))1p
p=1时,称为曼哈顿距离(Manhattan distance)
L1(xi,xj)=∑l=1n|xli−xlj|
p=2时,是常用的欧式距离(Euclidean distance)
L2(xi,xj)=∑l=1n|xli−xlj|2−−−−−−−−−−−√
p=∞ 时,是常用的切比雪夫距离(chebyshev distance)
L∞(xi,xj)=maxl|xni−xnj|
上述距离在不同特征中存在一定的缺点,比如特征维度中不同的单位,如果用绝对值会导致比重不一,因此不同的特征都需要归一化,即统一为相对值。
(2)马氏距离(Mahalanobis distance)
定义两个变量xi,xj∈χ,xi=(x1i,x2i,…,xni),xj=(x1j,x2j,…,xnj),则他们之间的马氏距离为:
D(xi,xj)=(xi−yj)TS−1(xi,xj)−−−−−−−−−−−−−−−−−√
其中S 是协方差矩阵。马氏距离与量纲无关,排除了变量之间相关性的干扰。在图像处理领域中常用作特征测量的标尺。
(3)夹角余弦(Cosine)
夹角余弦可以用来衡量两个特征向量方向的差异,机器学习中常用这一概念来衡量样本的差异,对于给定变量,其定义为:
cos(θ)=∑nl=1xlixlj∑nl=1xni2−−−−−−−√∑nl=1xnj2−−−−−−−√
夹角余弦越大表示两个向量夹角越小,向量相似度越高。夹角余弦度量的特征距离常用在自然语言处理中,是很常用的机器学习特征向量度量手段。
其余衡量样本相似度的手段还有汉明距离,杰卡德相似系数,相关系数和信息熵等。不同距离标准的选择对于KNN最终的分类结果是可能不同的。

k值选择

k 值选择会对KNN的结果产生重大影响。
如果选择较小的k 值,相当于在较小的邻域中进行预测,使“学习”的近似误差减小,估计误差增大,预测结果会对近邻的样本点非常敏感。这意味着,k 值越小整体模型会变得越复杂,模型容易过拟合。如果k 值较大,相当于在较大的邻域中进行预测,可以减少“学习”的估计误差,但是近似误差增大。这意味着k 值越大,模型越简单,适应性越强。
通常选取交叉验证法来选取 k 值。

分类决策规则

在KNN中常用的分类决策规则往往是多数表决,即由距离测试样本最近的k个训练样本的类别决定分类结果。
分类函数:
f:Rn←{c1,c2,…,ck}
那么误分类的概率:
P(Y≠f(X))=1−P(Y=f(x))
给定样本x∈χ,其最近邻的k 个训练样本构成的集合Nk(x). 如果最终的决策类别是cj, 那么误分类率为:
1k∑xi∈Nk(x)I(yi≠cj)=1−1k∑xi∈Nk(x)I(yi=cj)
要使误分类率最小,即经验风险最小,就要使∑xi∈Nk(x)I(yi=cj) 最大,所以多数表决规则等效于经验风险最小化。

2.k近邻算法

kNN 算法简单、直观:给定一个训练样本集,对新的输入样本,在训练样本中找k 个与该测试样本最近邻的k 个样本,这k 个样本多数属于哪一类,则该测试样本就属于哪一类:

  • Algorithm 3.1
  • Input: traning_data T={(x1,y1),(x2,y2),…,(xN,yN)}, testing_data (xi,yi)
  • Output: the label of yi
  • calculate all distances between testing_data and training_data
  • select the nearest k sample Nk(x)
  • voting rule: yi=argmax∑xi∈Nk(x)I(yi=cj)

    KNN算法的简单实现

# Project: Machine Learning-KNN# Author:Lyndon# Date: 2015/10/18from numpy import *import operator# Creating training datadef createdata(): group = array([[1,1],[1,1.1],[0.9,1],[0,0.1],[0.1,0],[0.1,0.1],[0,1],[0.1,0.9],[0,0.8]]) labels = ['A','A','A','B','B','B','C','C','C'] return group,labels# testing processdef knnclassify(testing_data,group,labels,k): datasize = group.shape[0] #the rows of array # calculate the distance diffMat = tile (testing_data,(datasize,1))-group sqdiffMat = diffMat**2 sqdiffMatsum=sqdiffMat.sum(axis=1) distances = sqdiffMatsum**2 # majority voting rule classcount={} sortdistances = distances.argsort() for i in range(k): votelabel = labels[sortdistances[i]] classcount[votelabel] = classcount.get(votelabel,0)+1 sortclass=sorted(classcount.iteritems(),key=operator.itemgetter(1),reverse=True) return sortclass[0][0]# mainif __name__ == "__main__": string=raw_input("please enter two numbers, split by comma:") input_data= string.split(",") testing_data= [] for i in range(len(input_data)): testing_data.append(float(input_data[i])) string1=raw_input("please enter the k:") k=int(string1) group,labels = createdata() label=knnclassify(testing_data,group, labels, k) print "the label of input data is:" + str(label)

kNN 没有显式的学习过程,直接通过给定的训练来预测未知样本的结果,测试结果:

kNN 是经典的数据分类算法,在邮件分类,文字识别,推荐系统等领域都有相应的应用,但其整体计算量大,特别对于高维数据会消耗很多资源,虽然KD树能够优化搜索的计算量,但计算大部分的数据还是消耗很大资源。
PS:本文为机器学习(3)总结笔记,通过python实现了简单分类,原理主要参考李航《统计学习理论》第三章。

相关阅读:
Top