1.概述
k邻近算法非常简单直观,没有显式的模型训练过程,只是采用测量不同特征值之间距离的方法分类。训练的过程相当于用训练集中的样本对特征向量空间进行划分,作为分类的依据。在分类的时候,对于一个新的样本,找到与它最接近的k个训练样本(通常k是不大于20的整数),选择k个最相似数据中出现次数最多的分类,作为新数据的分类。
k近邻的极端情况为k=1的时候,此时称为最近邻算法,对于一个未知的样本在训练样本中找到与它最接近的点的类别作为未知样本的类别。
k邻近算法的三个要素是k值的选择,距离度量及分类决策规则。接下来分别讨论细节。
2.训练
训练数据集为
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
n
x_i\in\chi\subseteq x^n
xi∈χ⊆xn为实例的特征向量,
y
i
∈
Y
=
{
c
1
,
c
2
,
.
.
.
,
c
k
}
y_i\in Y=\{ c_1,c_2,...,c_k\}
yi∈Y={c1,c2,...,ck}为实例的类别。
所有的训练实例将特征空间划分为若干个单元(cell),在
x
i
x_i
xi的单元中所有点距离
x
i
x_i
xi比距离其他其他训练样本都小。下面的图是一个二维特征空间的例子。
3.分类规则
分类的时候输入一个样本
x
x
x,输出它所属的类别
y
y
y。
首先在训练集
T
T
T中找到与
x
x
x最近邻的
k
k
k个点,涵盖这
k
k
k个点的邻域记作
N
k
(
x
)
N_k(x)
Nk(x)。在
N
k
(
x
)
N_k(x)
Nk(x)中根据分类决策规则确定
x
x
x所属的类别。例如将多数表决作为规则时:
y
=
a
r
g
m
a
x
c
j
Σ
I
(
y
i
=
=
c
j
)
y=argmax_{c_j} \Sigma I(y_i==c_j)
y=argmaxcjΣI(yi==cj)其中I为指示函数,当括号中条件成立时值为1,反之值为0。
4.k值的确定
k值作为该方法中唯一的一个参数对分类的准确度会产生很大的影响。在具体应用的时候通常先取一个比较小的数值,然后用交叉验证法选取最优k值。
如果选择较小的k值,相当于用较小邻域中的样本预测,只有与输入样本较近的训练样本才会对预测结果起作用。此时预测结果会对近邻的样本点非常敏感,分类容易受到噪声的干扰。
如果选择较大的k值,相当于用较大邻域中的样本预测,与输入样本距离较远的训练样本也会对预测产生影响。此时很可能忽略了训练样本中大量的有用信息。
##5.相似性测度的选取
两个点之间广义的距离成为
L
p
L_p
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)=(\Sigma_{l=1}^{n} \vert x_i^{(l)}-x_j^{(l)}\vert ^p )^{\frac{1}{p}}
Lp(xi,xj)=(Σl=1n∣xi(l)−xj(l)∣p)p1当
p
=
1
p=1
p=1时
L
p
L_p
Lp为Manhattan距离。
当
p
=
2
p=2
p=2时
L
p
L_p
Lp为欧氏距离。
当
p
=
∞
p=\infty
p=∞时
L
p
L_p
Lp为Manhattan距离。
##6.python实现
在实现kNN算法的时候可以遵循以下的步骤:
1.计算已知类别数据集中的点与待分类样本之间的距离;
2.按照距离递增次序排序;
3.选取与当前点距离最小的k个点;
4.确定前k个点所在类别的出现频率;
5.返回前k个点出现频率最高的类别作为当前点的预测分类。
以下为python代码。
# !/usr/bin/python
# -*- coding: utf-8 -*-
from numpy import *
import operator
def createDataSet():
group = array([ [1.0,1.1], [1.0,1.0], [0,0], [0,0.1]])
labels = ['A','A','B','B']
return group,labels
def classify0(inX, dataSet, labels, k):
#inX为待测样本,dataSet为训练集,
#labels为训练样本的标签集,k为用于选择的最近邻数目
dataSetSize = dataSet.shape[0]
# 计算距离
rep0 = tile( inX,(dataSetSize,1))
diffMat = rep0 - dataSet
sqDiffMat = diffMat**2
sqDistance = sqDiffMat.sum(axis=1)
distance = sqDistance**0.5
sortedDistIndicies = distance.argsort()
classCount={}
# 选择距离最小的k个点
for i in range(k):
voteIlabel = labels[ sortedDistIndicies[i] ]
#将classCount字典分解为元组列表
classCount[voteIlabel] = classCount.get(voteIlabel,0)+1
#运算符模块中的方法,按照第二个元素的次序对元组进行排序
sortedClassCount = sorted(classCount.iteritems(),key = operator.itemgetter(1),reverse=True)
return sortedClassCount[0][0]
# 主程序
[group,labels] = createDataSet()
print(classify0([0,0],group, labels,3))