python机器学习实战之最近邻kNN分类器
K近邻法是有监督学习方法,原理很简单,假设我们有一堆分好类的样本数据,分好类表示每个样本都一个对应的已知类标签,当来一个测试样本要我们判断它的类别是, 就分别计算到每个样本的距离,然后选取离测试样本最近的前K个样本的标签累计投票, 得票数最多的那个标签就为测试样本的标签。
源代码详解:
#-*-coding:utf-8-*-
#!/usr/bin/python
#测试代码约会数据分类importKNNKNN.datingClassTest1()标签为字符串KNN.datingClassTest2()标签为整形
#测试代码手写字体分类importKNNKNN.handwritingClassTest()
fromnumpyimport*#科学计算包
importoperator#运算符模块
fromosimportlistdir#获得指定目录中的内容(手写字体文件夹下样本txt)类型命令行ls
importmatplotlib#画图可视化操作
importmatplotlib.pyplotasplot
#显示一个二维图
defmyPlot(x,y,labels):
fig=plot.figure()#创建一个窗口
ax=fig.add_subplot(111)#画一个图
#ax.scatter(x,y)
ax.scatter(x,y,15.0*array(labels),15.0*array(labels))#支持分类颜色显示
ax.axis([-2,25,-0.2,2.0])
plot.xlabel('PercentageofTimeSpentPlayingVideoGames')#坐标轴名称
plot.ylabel('LitersofIceCreamConsumedPerWeek')
plot.show()
#创建假的数据测试
defcreateDataSet():
groop=array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])#numpy的array数组格式
labels=['A','A','B','B']#标签list
returngroop,labels
#定义KNN分类函数
defknnClassify0(inX,dataSet,labels,k):
#inX待分类的点数据集和标签DataSet,label最近领域个数k
dataSetSize=dataSet.shape[0]#数据集大小(行数)
#tile(A,(行维度,列维度))A沿各个维度重复的次数
#点A重复每一行到数据集大小行
differeMat=tile(inX,(dataSetSize,1))-dataSet#求待分类点与个个数据集点的差值
sqDiffMat=differeMat**2#求平方
sqDistances=sqDiffMat.sum(axis=1)#求和(各行求和)
distances=sqDistances**0.5#开方得到点A与数据集个点的欧式距离
sortedDistIndicies=distances.argsort()#返回递增排序后的原位置序列(不是值)
#取得最近的k个点统计标签类出现的频率
classCount={}#字典
foriinrange(k):
voteIlabel=labels[sortedDistIndicies[i]]#从小到大对应距离数据点的标签
classCount[voteIlabel]=classCount.get(voteIlabel,0)+1#对于类标签字典单词的值+1
#对类标签频率(字典的第二列(operator.itemgetter(1)))排序从大到小排序reverse=True
sortedClassCount=sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True)
returnsortedClassCount[0][0]#返回最近的对应的标签
#真实数据的处理输入TXT文本文件返回数据集和标签(已转化成数字)列表list
deffile2matrix(filename):
fr=open(filename)#打开文件
numberOfLines=len(fr.readlines())#得到文件所有的行数
returnMat=zeros((numberOfLines,3))
#创建一个用于存储返回数据的矩阵数据集每个数据的大小根据实际情况!!即是3列数应根据数据维度确定
classLabelVector=[]#对应标签
fr=open(filename)
index=0
forlineinfr.readlines():#每一行
line=line.strip()#默认删除空白符(包括'\n','\r','\t','')
listFromLine=line.split('\t')#按制表符(\t)分割字符串成元素列表
returnMat[index,:]=listFromLine[0:3]#前三个为数据集数据
classLabelVector.append(int(listFromLine[-1]))#最后一个为标签整形
index+=1
returnreturnMat,classLabelVector
#真实数据的处理输入TXT文本文件返回数据集和标签(为字符串)列表list
deffile2matrix2(filename):
fr=open(filename)#打开文件
numberOfLines=len(fr.readlines())#得到文件所有的行数
returnMat=zeros((numberOfLines,3))
#创建一个用于存储返回数据的矩阵数据集每个数据的大小根据实际情况!!即是3列数应根据数据维度确定
classLabelVector=[]#对应标签
fr=open(filename)
index=0
forlineinfr.readlines():#每一行
line=line.strip()#默认删除空白符(包括'\n','\r','\t','')
listFromLine=line.split('\t')#按制表符(\t)分割字符串成元素列表
returnMat[index,:]=listFromLine[0:3]#前三个为数据集数据
classLabelVector.append(str(listFromLine[-1]))#最后一个为标签字符串型
index+=1
returnreturnMat,classLabelVector
#数据集各个类型数据归一化平等化影响权值
defdataAutoNorm(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))#扩展minVals成样本总数行m行1列(属性值个数)
normDataSet=normDataSet/tile(ranges,(m,1))#矩阵除法每种属性值归一化numpy库为(linalg.solve(matA,matB))
returnnormDataSet,ranges,minVals#返回归一化后的数组和个属性范围以及最小值
#约会数据KNN分类测试
#标签为字符串型
defdatingClassTest1(test_ret=0.1):
hoRatio=test_ret#测试的样本比例剩下的作为训练集
datingDataMat,datingLabels=file2matrix2('datingTestSet.txt')#载入数据集
normMat,ranges,minVals=dataAutoNorm(datingDataMat)
m=normMat.shape[0]#总样本数量
numTestVecs=int(m*hoRatio)#总测试样本数
errorCount=0.0#错误次数记录
foriinrange(numTestVecs):#对每个测试样本
#KNN分类测试样本剩下的作为数据集数据集对应的标签最近的三个
classifierResult=knnClassify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
print"分类结果:%s,\t真实标签:%s"%(classifierResult,datingLabels[i])
if(classifierResult!=datingLabels[i]):errorCount+=1.0
print"总错误次数:%d"%errorCount
print"测试总数:%d"%numTestVecs
print"总错误率:%f"%(errorCount/float(numTestVecs))
#标签为整形int
defdatingClassTest2(test_ret=0.1):
hoRatio=test_ret#测试的样本比例剩下的作为训练集
datingDataMat,datingLabels=file2matrix('datingTestSet2.txt')#载入数据集
normMat,ranges,minVals=dataAutoNorm(datingDataMat)
m=normMat.shape[0]#总样本数量
numTestVecs=int(m*hoRatio)#总测试样本数
errorCount=0.0#错误次数记录
foriinrange(numTestVecs):#对每个测试样本
#KNN分类测试样本剩下的作为数据集数据集对应的标签最近的三个
classifierResult=knnClassify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
print"分类结果:%d,真实标签:%d"%(classifierResult,datingLabels[i])
if(classifierResult!=datingLabels[i]):errorCount+=1.0
print"总错误次数:%d"%errorCount
print"测试总数:%d"%numTestVecs
print"总错误率:%f"%(errorCount/float(numTestVecs))
#根据用户输入的样本的属性值判断用户所倾向的类型(有点问题??)
defclassifyPerson():
resultList=['讨厌','一般化','非常喜欢']
percent=float(raw_input("打游戏所花时间比例:"))
mile=float(raw_input("每年飞行的里程数量:"))
ice=float(raw_input("每周消费的冰淇淋量:"))
datingDataMat,datingLabels=file2matrix('datingTestSet2.txt')#载入数据集
normMat,ranges,minVals=dataAutoNorm(datingDataMat)
#新测试样本归一化
printranges,minVals
testSampArry=array([mile,percent,ice])#用户输入的测试样例
testSampArryNorm=(testSampArry-minVals)/ranges#样例归一化
printtestSampArry,testSampArryNorm
#分类
classifierResult=knnClassify0(testSampArryNorm,normMat,datingLabels,3)
printclassifierResult
print"他是不是你的菜:",resultList[classifierResult-1]
#手写字体图像32*32像素转化成1*1024的向量
defimg2vector(filename):
returnVect=zeros((1,1024))#创建空的返回向量
fr=open(filename)#打开文件
foriinrange(32):#对每一行
lineStr=fr.readline()#每一行元素
forjinrange(32):#每一行的每个值
returnVect[0,32*i+j]=int(lineStr[j])
returnreturnVect
#手写字体的KNN识别每个数字图片被转换成32*32的01矩阵
defhandwritingClassTest(k=3):
#得到训练数据集
hwLabels=[]#识别的标签
trainingFileList=listdir('trainingDigits')#加载手写字体训练数据集(所有txt文件列表)
m=len(trainingFileList)#总训练样本数
trainingMat=zeros((m,1024))#训练数据集
foriinrange(m):
fileNameStr=trainingFileList[i]#每个训练数据样本文件0_0.txt0_1.txt0_2.txt
fileStr=fileNameStr.split('.')[0]#以.分割第一个[0]为文件名第二个[1]为类型名txt文件
classNumStr=int(fileStr.split('_')[0])#以_分割,第一个[0]为该数据表示的数字标签
hwLabels.append(classNumStr)#训练样本标签
trainingMat[i,:]=img2vector('trainingDigits/%s'%fileNameStr)#训练样本数据
#得到测试数据集
testFileList=listdir('testDigits')#测试数据集
errorCount=0.0#错误次数计数
mTest=len(testFileList)#总测试数据样本个数
foriinrange(mTest):
fileNameStr=testFileList[i]#每个测试样本文件
fileStr=fileNameStr.split('.')[0]#得到文件名
classNumStr=int(fileStr.split('_')[0])#得到对应的真实标签
vectorUnderTest=img2vector('testDigits/%s'%fileNameStr)#测试样本数据
classifierResult=knnClassify0(vectorUnderTest,trainingMat,hwLabels,k)#分类
print"KNN分类标签:%d,真实标签:%d"%(classifierResult,classNumStr)
if(classifierResult!=classNumStr):errorCount+=1.0
print"\n总的错误次数:%d"%errorCount
print"\n总的错误比例:%f"%(errorCount/float(mTest))
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。