继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

测试markdown文章中的p标签

慕仔4209126
关注TA
已关注
手记 304
粉丝 69
获赞 305

引言:

    k近邻法(k-nearest neighbor, kNN)是一种基本分类与回归方法,其基本做法是:给定测试实例,基于某种距离度量找出训练集中与其最靠近的k个实例点,然后基于这k个最近邻的信息来进行预测。
    通常,在分类任务中可使用“投票法”,即选择这k个实例中出现最多的标记类别作为预测结果;在回归任务中可使用“平均法”,即将这k个实例的实值输出标记的平均值作为预测结果;还可基于距离远近进行加权平均或加权投票,距离越近的实例权重越大。
    k近邻法不具有显式的学习过程,事实上,它是懒惰学习(lazy learning)的著名代表,此类学习技术在训练阶段仅仅是把样本保存起来,训练时间开销为零,待收到测试样本后再进行处理。
    本文只讨论分类问题中的k近邻法。

一、k近邻法的三要素

    距离度量、k值的选择及分类决策规则是k近邻法的三个基本要素。根据选择的距离度量(如曼哈顿距离或欧氏距离),可计算测试实例与训练集中的每个实例点的距离,根据k值选择k个最近邻点,最后根据分类决策规则将测试实例分类。
    如图1,根据欧氏距离,选择k=4个离测试实例最近的训练实例(红圈处),再根据多数表决的分类决策规则,即这4个实例多数属于“-类”,可推断测试实例为“-类”。
    k近邻法1968年由Cover和Hart提出。
欧氏距离的kNN

图1


1.距离度量

    特征空间中的两个实例点的距离是两个实例点相似程度的反映。K近邻法的特征空间一般是n维实数向量空间Rn。使用的距离是欧氏距离,但也可以是其他距离,如更一般的Lp距离或Minkowski距离。
    设特征空间X是n维实数向量空间RnRnxi,xj∈Xxi,xjXxi=(x(1)i,x(2)i,⋯,x(n)i)Txi=(xi(1),xi(2),,xi(n))Txj=(x(1)j,x(2)j,⋯,x(n)j)Txj=(xj(1),xj(2),,xj(n))Txi,xjxi,xjLpLp距离定义为

Lp(xi,xj)=(∑l=1n|xi(l)−xj(l)|p)1pLp(xi,xj)=(l=1n|xi(l)xj(l)|p)1p


这里p≥1。
当p=1时,称为曼哈顿距离(Euclidean distance),即

L1(xi,xj)=∑l=1n|xi(l)−xj(l)|L1(xi,xj)=l=1n|xi(l)xj(l)|


当p=2时,称为欧氏距离(Euclidean distance),即

L2(xi,xj)=(∑l=1n|xi(l)−xj(l)|2)12L2(xi,xj)=(l=1n|xi(l)xj(l)|2)12


当p=∞时,它是各个坐标距离的最大值,即

L∞(xi,xj)=maxl |xi(l)−xj(l)|L(xi,xj)=maxl |xi(l)xj(l)|


证明:

以二维实数向量空间(n=2)为例说明曼哈顿距离和欧氏距离的物理意义。
① 曼哈顿距离

L1(xi,xj)=∑l=12|xi(l)−xj(l)|=|xi(1)−xj(1)|+|xi(2)−xj(2)|L1(xi,xj)=l=12|xi(l)xj(l)|=|xi(1)xj(1)|+|xi(2)xj(2)|


图2绿色线即曼哈顿距离物理意义,其中横向线条表示|x1i−x1j||x1ix1j|,竖向线条表示|x2i−x2j||x2ix2j|

② 欧氏距离

L2(xi,xj)=(∑l=12|xi(l)−xj(l)|2)12=|xi(1)−xj(1)|2+|xi(2)−xj(2)|2−−−−−−−−−−−−−−−−−−−−−−−−√2L2(xi,xj)=(l=12|xi(l)xj(l)|2)12=|xi(1)xj(1)|2+|xi(2)xj(2)|22


图2红色线即欧氏距离物理意义,根据勾股定理可得。

欧氏距离与曼哈顿距离

图2


2.k值的选择

    k值的选择会对k近邻法的结果产生重大影响。在应用中,k值一般取一个比较小的数值,通常采用交叉验证法来选取最优的k值。

3.分类决策规则

    k近邻法中的分类决策规则往往是多数表决,即由输入实例的k个邻近的训练实例中的多数类,决定输入实例的类。



二、k近邻算法及代码实现(python)

1.算法

算法1(k近邻法)
输入:训练集

D={(x1,y1),(x2,y2),⋯,(xN,yN)}D={(x1,y1),(x2,y2),,(xN,yN)}

其中,xi∈X⊆RnxiXRn为实例的特征向量,yi∈Y={c1,c2,⋯,ck}yiY={c1,c2,,ck}为实例的类别,i=1,2,…,N。
输出:实例x所属的类别y
① 根据给定的距离度量,在训练集D中找出与x最近邻的k个点,涵盖这k个点的x的领域记作Nk(x)Nk(x)
② 在Nk(x)Nk(x)中根据分类决策规则(如多数表决)决定x的类别y

y=arg maxcj∑xi∈Nk(x)I(yj=cj),     i=1,2,⋯,N;j=1,2,⋯,Ky=arg maxcjxiNk(x)I(yj=cj),     i=1,2,,N;j=1,2,,K

上式中,I为指示函数,即当yi=ci时I为1,否则I为0。


2.代码实现(python)

以下代码来自Peter Harrington《Machine Learing in Action》
距离度量为欧氏距离,分类决策规则为多数表决。classify0()函数有4个输入参数:用于分类的输入向量是inX,输入的训练集为dataSet,类别为labels,k表示用于选择最近邻的数目。
代码如下(保存为kNN.py):

# -- coding: utf-8 --
form 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):
    dataSetSize = dataSet.shape[0]
    # 根据欧式距离计算训练集中每个样本到测试点的距离
    diffMat = tile(inX, (dataSetSize,1)) - dataSet
    sqDiffMat = diffMat**2
    sqDistances = sqDiffMat.sum(axis=1)
    distances = sqDistances**0.5
    # 计算完所有点的距离后,对数据按照从小到大的次序排序
    sortedDistIndicies = distances.argsort()
    # 确定前k个距离最小的元素所在的主要分类,最后返回发生频率最高的元素类别
    classCount={}
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
    sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]

运行命令如下:
kNN.py运行命令
group和labels为训练集,其中group为特征向量,labels为类别。输入测试实例[0,0],选取与测试实例距离最近的3个元素,最后返回这3个元素中发生频率最高的元素类别,即为kNN近邻法的预测值。



三、k近邻法的实现:kd树

    实现k近邻法时,主要考虑的问题是如何对训练数据进行快速k近邻搜索,这点在特征空间的维数大及训练数据容量大时尤其必要。
    k近邻法最简单的实现方法是线性扫描(linear scan),这时要计算输入实例与每一个训练实例的距离,当训练集很大时,计算非常耗时。为了提高k近邻法搜索的效率,可以考虑使用特殊的结构存储训练数据,以减少计算距离的次数。具体方法很多,下面介绍其中的kd树方法(kd树是存储k维空间数据的树结构,这里的k与k近邻法的k意义不同)。

1.构造kd树

    kd树是二叉树,是一种对k维空间中实例点进行存储以便对其进行快速检索的树形数据结构。kd树表示对k维空间的一个划分(partition),构造kd树相当于不断地用垂直于坐标轴的超平面将k维空间切分,构成一系列的k维超矩形区域。kd树的每个结点对应于一个k维超矩形区域。
    通常,依次选择坐标轴对空间切分,选择训练实例点在选定坐标轴上的中位数(一组数据按大小顺序排列起来,处于中间的一个数或最中间两个数的平均值。本文在最中间有两个数时选择最大值作中位数)为切分点,这样得到的kd树是平衡的。注意,平衡的kd树搜索时未必是最优的。

2.算法

算法2(构造平衡kd树)
输入:k维空间数据集

D={x1,x2,⋯,xn}D={x1,x2,,xn}

其中xi=(x(1)i,x(2)i,⋯,x(n)i)T,i=1,2,⋯,Nxi=(xi(1),xi(2),,xi(n))Ti=1,2,,N
输出:kd树
①  开始:构造根结点,根结点对应于包含D的k维空间的超矩形区域。
    选择x1为坐标轴,以D中所有实例的x1坐标的中位数为切分点,将根结点对应的超矩形区域切分为两个子区域。切分由通过切分点并与坐标轴x1垂直的超平面实现。
    由根结点生成深度为1的左、右子结点:左子结点对应坐标x1小于切分点的子区域,右子结点对应坐标x1大于切分点的子区域。将落在切分超平面上的实例点保存在根结点。
②  重复:对深度为j的结点,选择xl为切分的坐标轴,l=j(mod k)+1,以该结点的区域中所有实例点的xl坐标的中位数为切分点,将该结点对应的超矩形区域切分为两个子区域。切分由通过切分点并与坐标轴xl垂直的超平面实现。
    由该结点生成深度为j+1的左、右子结点:左子结点对应坐标xl小于切分点的子区域,右子结点对应坐标xl大于切分点的子区域。将落在切分超平面上的实例点保存在该结点。
③  直到两个子区域没有实例存在时停止,从而形成kd树的区域划分。
例1 给定一个二维空间的数据集:

D={(2,3)T,(5,4)T,(9,6)T,(4,7)T,(8,1)T,(7,2)T}D={(2,3)T,(5,4)T,(9,6)T,(4,7)T,(8,1)T,(7,2)T}

构造一个平衡kd树。
解:D为二维空间,则k=2。
① D中6个实例的x1坐标的中位数为7,则以(7 , 2)为切分点,由通过切分点并与坐标轴x1垂直的平面将超矩形区域切分为两个子区域。根结点为(7 , 2),左区域包括:(2 , 3) , (5 , 4) ,  (4 , 7),右区域包括:(8 , 1) , (9 , 6),深度为1
② 对深度为j=1的结点,选择l=j(mod k)+1=1(mod 2)+1=2即x2为切分的坐标轴。则左区域的切分点为(5 , 4) ,左子区域为(2 , 3),右子区域为(4 , 7);右区域的切分点为(9 , 6) ,左子区域为(8 , 1)。
如此递归,最后得到的平衡kd树如下所示:
例1


3.搜索kd树(未完,待续)










以上全部内容参考书籍如下:
李航《统计学习方法》
周志华《机器学习》
Peter Harrington《Machine Learing in Action》

原文出处

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP