# -*- coding: cp936 -*-
'''
Created on Nov 27, 2016
KNN Code for Machine Learning in Action Ch. 2
@author: Miaotong Jiang
'''
from numpy import *
from os import listdir
import operator
mydict={'largeDoses':3, 'smallDoses':2, 'didntLike':1}
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]
diffs=tile(inx,(datasetsize,1))-dataset
sq=diffs**2
ss=sq.sum(axis=1)#( >>> sum([[1,5],[0,3]],axis=1) array([6, 3]) >>> sum([[1,5],[0,3]],axis=0) array([1, 8]) )
s=ss**0.5
sortedsindices=s.argsort()#返回数组值从小到大的索引值
classCount={}
for i in range(k):
votellabel=labels[sortedsindices[i]]
classCount[votellabel]=classCount.get(votellabel,0)+1
sortedclasscount=sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True)#sorted(可迭代 类型,cmp(用于比较的函数,由key决定,有默认值,), key(此处根据第二个域排序),reverse反转)
print classCount#输出是列表['B','2','A','1']
return sortedclasscount[0][0]
def file2matrix(filename):#解析训练数据文件,将其转化成训练数据输入矩阵和输出矩阵
fr=open(filename)
arrayolines=fr.readlines()
numberoflines=len(arrayolines)#得到文件行数
returnmat=zeros((numberoflines,3))#创建零填充的矩阵
classlabelvector=[]
index=0
for line in arrayolines:
line=line.strip()#截取掉所有回车符
listfromline=line.split('\t')#利用\t将数据分割成一个元素列表
returnmat[index,:]=listfromline[0:3]#选取前三个元素储存到矩阵中
classlabelvector.append(int(mydict[listfromline[-1]]))#把最后一列存到classlabelvector里
index+=1
return returnmat,classlabelvector
def autonorm(dataset):#将矩阵具体的特征值(即测试数据矩阵的每个元素归一化)
minvals=dataset.min(0)
maxvals=dataset.max(0)
ranges=maxvals-minvals
normdataset=zeros(shape(dataset))#shape() 输入参数:类似数组(比如列表,元组)等,或是数组返回:一 个整型数字的元组,元组中的每个元素表示相应的数组每一维的长度
m=dataset.shape[0]#行数
normdataset=dataset-tile(minvals,(m,1))
normdataset=normdataset/tile(ranges,(m,1))
return normdataset,ranges,minvals
def datingclasstest():#错误率测试函数
horatio=0.05#测试数据的比例
datingdatamat,datinglabels=file2matrix('datingtestset.txt')
normmat,ranges,minvals=autonorm(datingdatamat)
m=normmat.shape[0]
numtestvecs=int(m*horatio)
errorcount=0.0
for i in range(numtestvecs):#%还用在python的格式化输出,比如:a = 'test' ;print 'it is a %s' %(a) ;打印的 结果就是 it is a test
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))
def classifyperson():#海伦约会网站预测函数
resultlist=['not at all','in small doses','in large doses']
percenttats=float(raw_input("percentage of time spent playing video games?"))
ffmiles=float(raw_input("frequent flier miles earned per year?"))
icecream=float(raw_input("liters of ice cream consumed per year"))
datingdatamat,datinglabels=file2matrix('datingtestset.txt')
normmat,ranges,minvals=autonorm(datingdatamat)
inarr=array([ffmiles,percenttats,icecream])
classifierresult=classify0((inarr-minvals)/ranges,normmat,datinglabels,3)
print"You will probably like this person,"
return resultlist[classifierresult-1]#需要给出返回值
def img2vector(filename):#图像转换为向量
returnvector=zeros((1,1024))
fr=open(filename)
for i in range(32):
linestr=fr.readline()
for j in range(32):
returnvector[0,32*i+j]=int(linestr[j])
return returnvector
def handwritingclasstest():#手写数字识别系统测试
hwlabels=[]
trainingfilelist=listdir('trainingdigits')#获取目录内容
m=len(trainingfilelist)
trainingmat=zeros((m,1024))#每行是一个图像
for i in range(m):
filenamestr=trainingfilelist[i]
filestr=filenamestr.split('.')[0]#去掉.txt
classnumstr=int(filestr.split('_')[0])#去掉_及之后的内容
hwlabels.append(classnumstr)#从文件名解析分类数字
trainingmat[i,:]=img2vector('trainingdigits/%s'%filenamestr)
testfilelist=listdir('testdigits')
errorcount=0.0
mtest=len(testfilelist)
for i in range(mtest):
filenamestr=testfilelist[i]
filestr=filenamestr.split('.')[0]
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"the total number of errors is:%d"%errorcount
print"the total error rate is:%f"%(errorcount/mtest)
def handwritingclasspredict():#手写识别系统预测
vectorundertest=img2vector('testSet.txt')
hwlabels=[]
trainingfilelist=listdir('trainingdigits')#获取目录内容
m=len(trainingfilelist)
trainingmat=zeros((m,1024))#每行是一个图像
for i in range(m):
filenamestr=trainingfilelist[i]
filestr=filenamestr.split('.')[0]#去掉.txt
classnumstr=int(filestr.split('_')[0])#去掉_及之后的内容
hwlabels.append(classnumstr)#从文件名解析分类数字
trainingmat[i,:]=img2vector('trainingdigits/%s'%filenamestr)
classifierresult=classify0(vectorundertest,trainingmat,hwlabels,3)
return classifierresult