python 余数定义 a=k*b+r_《统计学习方法》第三章:k-近邻算法(K-Nearest Neighbors)...

监督学习,多分类、回归

计算输入点与数据集点距离,升序排序,选取数据集里前k个点,计算这k个点对应类别(也就是label)出现的概率,最大概率的分类就是输入点的分类。

目录

一、分类问题

812740f90dd249638291a54db5fff17b.png             

8e94bdef7e7ec12c648481805acd1b74.png

二、监督学习

316b560e0d7df7295972b0edea7a1277.png                        

90088ee9f3ef94e40e3f2b05a00e08a7.png

三、KNN算法原理和流程

56c0d74139b480d0f50c2bd00c810caf.png                

ee47217947ed1d032b9a247b4eac7b26.png

1、工作原理

存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每个数据与所属分类的对应关系。

输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。

一般来说,只选择样本数据集中前N个最相似的数据。分类数K一般不大于20,最后,选择k个中出现次数最多的分类,作为新数据的分类。

2、一般流程

收集数据:可以使用任何方法

准备数据:距离计算所需要的数值,最后是结构化的数据格式。

分析数据:可以使用任何方法

训练算法:(此步骤kNN)中不适用

测试算法:计算错误率

使用算法:首先需要输入样本数据和结构化的输出结果,然后运行k-近邻算法判定输入数据分别属于哪个分类,最后应用对计算出的分类执行后续的处理。

3、距离计算

441bacefde709df9ad25d8791f8b650e.png

f2218e0c4cbd8d7f72c1f1adc057665b.png              

0a4b43453d6a09de71b75c979f2265dd.png

c14b01c975c22f6c2941f9c8ba3acc0d.png         

251851f7061701ca52a3e88cbfb7b899.png

250c86887dee743f09cbcdf357274c85.pngp=1对应最里面的棱形;p=2对应中间的圆;p=∞对应外面的矩形

4、k值的选择

1)如果选择较小的K值

“学习”的近似误差(approximation error)会减小,但 “学习”的估计误差(estimation error) 会增大

噪声敏感

K值的减小就意味着整体模型变得复杂,容易发生过拟合

2)如果选择较大的K值

减少学习的估计误差,但缺点是学习的近似误差会增大

K值的增大,就意味着整体的模型变得简单

三、Python代码

1、数据导入

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,lables

group,labels=kNN.createDataSet()

Python 数组和numpy矩阵的关系:

>>> a=[[1,2,3,4],[5,6,7,8],[9,10,11,12]]

>>> c=zeros((3,4))

>>> c

array([[ 0., 0., 0., 0.],

[ 0., 0., 0., 0.],

[ 0., 0., 0., 0.]])

>>> c[0,:]=a[0]

>>> c

array([[ 1., 2., 3., 4.],

[ 0., 0., 0., 0.],

[ 0., 0., 0., 0.]])

2、算法和关键函数

1)分类算法流程和关键函数

Shapegroup,labels=kNN.createDataSet()

group.shape

group.shape[0]

Tiletile([1.0,1.2],(4,1))

# 输出

array([[ 1. , 1.2],

[ 1. , 1.2],

[ 1. , 1.2],

[ 1. , 1.2]])

tile([1.0,1.2],(4,1))-group

#输出

array([[ 0. , 0.1],

[ 0. , 0.2],

[ 1. , 1.2],

[ 1. , 1.1]])

a=(tile([1.0,1.2],(4,1))-group)**2

#输出

array([[ 0. , 0.01],

[ 0. , 0.04],

[ 1. , 1.44],

[ 1. , 1.21]])

Argsortb=a.sum(axis=1)

c=b**0.5

d=c.argsort()

>>> d

array([0, 1, 3, 2])

字典的使用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.classify0([0,0.2],group,labels,3)

>>'B'

2)文本中解析数据

文件读取相关函数:Open()、Readlines、Zeros()

3)用matplotlib绘制散点图

import matplotlib

>>> import matplotlib.pyplot as plt

>>> fig=plt.figure()

>>> ax=fig.add_subplot(111)

>>> ax.scatter(datingDataMat[:,1],datingDataMat[:,2])

>>> plt.show()

>>> fig=plt.figure()

>>> ax=fig.add_subplot(111)

>>>ax.scatter(datingDataMat[:,1],datingDataMat[:,2],15.0*array(datingLabels),15.0*array(datingLabels))

>>> plt.show()

4)数据归一化

def autoNorm(dataSet):

minVals = dataSet.min(0)

maxVals = dataSet.max(0)

ranges = maxVals - minVals

normDataSet = zeros(shape(dataSet))

m = dataSet.shape[0]

normDataSet = dataSet - tile(minVals, (m,1))

normDataSet = normDataSet/tile(ranges, (m,1)) #element wise divide

return normDataSet, ranges, minVals

>>> n,r,m=kNN.autoNorm(datingDataMat)

>>> n

array([[ 0.44832535, 0.39805139, 0.56233353],

[ 0.15873259, 0.34195467, 0.98724416],

[ 0.28542943, 0.06892523, 0.47449629],

...,

[ 0.29115949, 0.50910294, 0.51079493],

[ 0.52711097, 0.43665451, 0.4290048 ],

[ 0.47940793, 0.3768091 , 0.78571804]])

>>> r

array([ 9.12730000e+04, 2.09193490e+01, 1.69436100e+00])

>>> m

array([ 0. , 0. , 0.001156])

5)使用k-近邻算法的手写识别系统

def datingClassTest():

hoRatio = 0.50 #hold out 10%

datingDataMat,datingLabels = file2matrix('datingTestSet2.txt') #load data setfrom file

normMat, ranges, minVals = autoNorm(datingDataMat)

m = normMat.shape[0]

numTestVecs = int(m*hoRatio)

errorCount = 0.0

for i in range(numTestVecs):

classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)

print "the classifier came back with: %d, the real answer is: %d" % (classifierResult, datingLabels[i])

if (classifierResult != datingLabels[i]): errorCount += 1.0

print "the total error rate is: %f" % (errorCount/float(numTestVecs))

print errorCount

6)测试算法

def datingClassTest():

hoRatio = 0.50 #hold out 10%

datingDataMat,datingLabels = file2matrix('datingTestSet2.txt') #load data setfrom file

normMat, ranges, minVals = autoNorm(datingDataMat)

m = normMat.shape[0]

numTestVecs = int(m*hoRatio)

errorCount = 0.0

for i in range(numTestVecs):

classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)

print "the classifier came back with: %d, the real answer is: %d" % (classifierResult, datingLabels[i])

if (classifierResult != datingLabels[i]): errorCount += 1.0

print "the total error rate is: %f" % (errorCount/float(numTestVecs))

print errorCount

>>> testVector=kNN.img2vector('testDigits/0_13.txt')

>>> tesVector[0,0:31]

3、分类算法

1)分类算法流程

对未知类别的数据集中的每个点依次执行以下操作:

计算已知类别数据集众多点与当前点之间的距离

按照距离递增次序排序

选取与当前点距离最小的k个点

群定前k个点所在类别的出现频率

2)kNN中分类算法

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()

classCount={}

for item in range(k):

voteIlabel = labels[sortedDistIndicies[item]]

classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1

sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)

return sortedClassCount[0][0]

四、kNN算法改进

1、KNN面临的挑战

a1b6acf700da0c196715b211127676ab.png

2、算法改进

1)距离度量

马氏距离(MahalanobisDistance):

eaacac24b86923b53c4800d5a0399779.png           

f46ebe474d02be0b807d1624fe1f49d1.png       

39187d0f2868d0948584d1a099f3f97b.png

f9c9e2479e1b39bda2dac6e6d41bea35.png

4c4ba4dc707ada3a4f411577239919e8.png

马氏距离NUMPY示例:

import numpy

x = numpy.array([[3,4],[5,6],[2,2],[8,4]])

xT = x.T

D = numpy.cov(xT)

invD = numpy.linalg.inv(D)

tp = x[0] – x[1]

print numpy.sqrt(dot(dot(tp, invD), tp.T))

Ø由P.C.Mahalanobis提出

Ø基于样本分布的一种距离测量

Ø考虑到各种特性之间的联系(例如身高和体重),可以消除样本间的相关性

Ø广泛用于分类和聚类分析

f37c864a2c5ff5e03f3ba031bd8284df.png

7682dcc099d113cd0e40b2bc62661121.png

eca9a9f9f46b536fb7be09acd2b5d673.png

2)KD树

KD树是一种对K维空间中的实例点进行存储以便对其进行快速检索的树形数据结构。

KD树是二叉树,表示对K维空间的一个划分(partition),构造KD树相当于不断地用垂直于坐标轴的超平面将k维空间切分,构成一系列的k维超矩形区域,KD树的每个结点对应于一个k维超矩形区域。

构造KD树

3f4c371b492bc609e59ebd3487a985ab.png

cb037d44eafd0154d29a67331c3015da.png

KD树搜索

e9fd6bb9990578a3669d831f3b9dc9f1.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值