学习笔记——《机器学习实战》KNN算法实现 约会网站测试,手写数字识别,代码,注释,错误修改

# -*- 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
    

你可能感兴趣的:(机器学习,算法,python)