python使用欧氏距离knn_机器学习经典算法具体解释及Python实现--K近邻(KNN)算法

训练样本是多维特征空间向量,当中每一个训练样本带有一个类别标签(喜欢或者不喜欢、保留或者删除)。分类算法常採用“多数表决”决定,即k个邻居中出现次数最多的那个类作为预測类。“多数表决”分类的一个缺点是出现频率较多的样本将会主导測试点的预測结果。那是由于他们比較大可能出如今測试点的K邻域而測试点的属性又是通过K领域内的样本计算出来的。解决这个缺点的方法之中的一个是在进行分类时将K个邻居到測试点的距离考虑进去。比如,若样本到測试点距离为d,则选1/d为该邻居的权重(也就是得到了该邻居所属类的权重),接下来统计统计k个邻居全部类标签的权重和,值最大的那个就是新数据点的预測类标签。

举例,K=5,计算出新数据点到近期的五个邻居的举例是(1,3,3,4,5),五个邻居的类标签是(yes,no,no。yes,no)

若是依照多数表决法,则新数据点类别为no(3个no,2个yes);若考虑距离权重类别则为yes(no:2/3+1/5,yes:1+1/4)。

以下的Python程序是採用KNN算法的实例(计算欧氏距离。多数表决法决断):一个是採用KNN算法改进约会站点配对效果。还有一个是採用KNN算法进行手写识别。

约会站点配对效果改进的样例是依据男子的每年的飞行里程、视频游戏时间比和每周冰激凌耗量三个特征来推断其是否是海伦姑娘喜欢的类型(类别为非常喜欢、一般和讨厌),决策採用多数表决法。

因为三个特征的取值范围不同,这里採用的scale策略为归一化。

使用KNN分类器的手写识别系统 仅仅能识别数字0到9。

须要识别的数字使用图形处理软件,处理成具有同样的色 彩和大小 :宽髙是32像素X32像素的黑白图像。虽然採用文本格式存储图像不能有效地利用内存空间,为了方便理解,这里已经将将图像转换为文本格式。训练数据中每一个数字大概有200个样本。程序中将图像样本格式化处理为向量,即一个把一个32x32的二进制图像矩阵转换为一个1x1024的向量。from numpy import *

import operator

from os import listdir

import matplotlib

import matplotlib.pyplot as plt

import pdb

def classify0(inX, dataSet, labels, k=3):

#pdb.set_trace()

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() #ascend sorted,

#return the index of unsorted, that is to choose the least 3 item

classCount={}

for i in range(k):

voteIlabel = labels[sortedDistIndicies[i]]

classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1# a dict with label as key and occurrence number as value

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

'''descend sorted according to value, '''

return sortedClassCount[0][0]

def file2matrix(filename):

fr = open(filename)

#pdb.set_trace()

L = fr.readlines()

numberOfLines = len(L) #get the number of lines in the file

returnMat = zeros((numberOfLines,3)) #prepare matrix to return

classLabelVector = [] #prepare labels return

index = 0

for line in L:

line = line.strip()

listFromLine = line.split('\t')

returnMat[index,:] = listFromLine[0:3]

classLabelVector.append(int(listFromLine[-1]))

#classLabelVector.append((listFromLine[-1]))

index += 1

fr.close()

return returnMat,classLabelVector

def plotscattter():

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

fig = plt.figure()

ax1 = fig.add_subplot(111)

ax2 = fig.add_subplot(111)

ax3 = fig.add_subplot(111)

ax1.scatter(datingDataMat[:,0],datingDataMat[:,1],15.0*array(datingLabels),15.0*array(datingLabels))

#ax2.scatter(datingDataMat[:,0],datingDataMat[:,2],15.0*array(datingLabels),15.0*array(datingLabels))

#ax2.scatter(datingDataMat[:,1],datingDataMat[:,2],15.0*array(datingLabels),15.0*array(datingLabels))

plt.show()

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

def datingClassTest(hoRatio = 0.20):

#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: %.2f%%" % (100*errorCount/float(numTestVecs))

print 'testcount is %s, errorCount is %s' %(numTestVecs,errorCount)

def classifyPerson():

'''

input a person , decide like or not, then update the DB

'''

resultlist = ['not at all','little doses','large doses']

percentTats = float(raw_input('input the person\' percentage of time playing video games:'))

ffMiles = float(raw_input('flier miles in a year:'))

iceCream = float(raw_input('amount of iceCream consumed per year:'))

datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')

normMat, ranges, minVals = autoNorm(datingDataMat)

normPerson = (array([ffMiles,percentTats,iceCream])-minVals)/ranges

result = classify0(normPerson, normMat, datingLabels, 3)

print 'you will probably like this guy in:', resultlist[result -1]

#update the datingTestSet

print 'update dating DB'

tmp = '\t'.join([repr(ffMiles),repr(percentTats),repr(iceCream),repr(result)])+'\n'

with open('datingTestSet2.txt','a') as fr:

fr.write(tmp)

def img2file(filename):

#vector = zeros(1,1024)

with open(filename) as fr:

L=fr.readlines()

vector =[int(L[i][j]) for i in range(32) for j in range(32)]

return array(vector,dtype = float)

def handwritingClassTest():

hwLabels = []

trainingFileList = listdir('trainingDigits') #load the training set

m = len(trainingFileList)

trainingMat = zeros((m,1024))

for i in range(m):

fileNameStr = trainingFileList[i]

fileStr = fileNameStr.split('.')[0] #take off .txt

classNumStr = int(fileStr.split('_')[0])

hwLabels.append(classNumStr)

trainingMat[i,:] = img2vector('trainingDigits/%s' % fileNameStr)

testFileList = listdir('testDigits') #iterate through the test set

errorCount = 0.0

mTest = len(testFileList)

for i in range(mTest):

fileNameStr = testFileList[i]

fileStr = fileNameStr.split('.')[0] #take off .txt

classNumStr = int(fileStr.split('_')[0])

vectorUnderTest = img2vector('testDigits/%s' % fileNameStr)

classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3)

print "the classifier came back with: %d, the real answer is: %d" % (classifierResult, classNumStr)

if (classifierResult != classNumStr): errorCount += 1.0

print "\nthe total number of errors is: %d" % errorCount

print "\nthe total error rate is: %f" % (errorCount/float(mTest))

if __name__ == '__main__':

datingClassTest()

#handwritingClassTest()

KNN算法学习包下载地址为:

(四)KNN回归

数据点的类别标签是连续值时应用KNN算法就是回归。与KNN分类算法过程同样。差别在于对K个邻居的处理上。KNN回归是取K个邻居类标签值得加权作为新数据点的预測值。加权方法有:K个近邻的属性值的平均值(最差)、1/d为权重(有效的衡量邻居的权重。使较近邻居的权重比較远邻居的权重大)、高斯函数(或者其它适当的减函数)计算权重= gaussian(distance) (距离越远得到的值就越小,加权得到更为准确的预计。

(五)总结

K-近邻算法是分类数据最简单最有效的算法,其学习基于实例,使用算法时我们必须有接近实际数据的训练样本数据。K-近邻算法必须保存所有数据集,假设训练数据集的非常大,必须使用大量的存储空间。此外,因为必须对数据集中的每一个数据计算距离值,实际使用时可能非常耗时。

k-近邻算法的还有一个缺陷是它无法给出不论什么数据的基础结构信息,因此我们也无法知晓平均实例样本和典型实例样本具有什么特征。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值