《机器学习实战》2.1.2kNN注释

from numpy import * #导入科学计算包
import operator #导入运算符模块,KNN执行排序算法时,会用到这个模块提供的函数
import matplotlib.pyplot as plt #matplotlib.pyplot是一个有命令风格的函数集合,每一个pyplot函数都使一副图像做出些许改变,例如创建一幅图,在图中创建一个绘图区域,在绘图区域中添加一条线等等。
from os import listdir

#定义了一个函数,创建数据集和标签
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

#定义了一个函数,用于分类,inX用于分类的输入向量,dataSet是训练样本集,k选择最近邻居的数目
def classify0(inX,dataSet,labels,k):
    dataSetSize=dataSet.shape[0]    #表明有几个数据集
    diffMat=tile(inX,(dataSetSize,1))-dataSet   #tile(A,n),功能是将数组inX重复n次,比如输入【0,0】变成【【0,0】【0,0】【0,0】【0,0】】
    sqDiffMat=diffMat**2    #数组的每一个值进行平方
    sqDistances=sqDiffMat.sum(axis=1)   #axis=1就是将一个矩阵的每一行向量相加
    distances=sqDistances**0.5  #将求的和进行开根号
    sortedDistIndicies=distances.argsort()  #argsort函数返回的是数组值从小到大的索引值
    classCount={ }   #大括号{ }花括号:代表dict字典数据类型,字典是由键对值组组成。冒号':'分开键和值,逗号','隔开组.这里用于存储不同标签出现的次数
    for i in range(k):
        voteIlabel=labels[sortedDistIndicies[i]]    #按照距离先后顺序,通过第i个索引值找到对应的标签
        classCount[voteIlabel]=classCount.get(voteIlabel,0)+1   #计算标签在字典中出现的次数,如果还没有在classCount中出现就默认为0,如果之前出现过,就+1
    sortedClassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True) #按照第二个元素的顺序对元祖进行排序,发生频率最高就是结果
    return sortedClassCount[0][0]   #频率最高e的元素标签就是所分类的结果

#测试分类器
# group,labels=createDataSet()
# print(classify0([0,0],group,labels,3))#结果为B

#处理输入格式的问题,函数输入为文件名字符串,输入为训练样本矩阵和类标签向量
def file2matrix(filename):
    fr=open("datingTestSet2.txt")#返回的是一个叫做“file object”的东西,通过它,可以得到文件的内容,但是这并不表示它就是文件的内容,例如输出为<_io.TextIOWrapper name='datingTestSet2.txt' mode='r' encoding='cp936'>
    arrayOLines=fr.readlines()#输出:['40920\t8.326976\t0.953952\t3\n', '14488\t7.153469\t1.673904\t2\n',...]
    numberOfLines=len(arrayOLines)#获取文件行数
    returnMat=zeros((numberOfLines,3))#创建一个numberOfLines行,3列的0矩阵
    classLabelVector=[] #[ ]代表list列表数据类型
    index=0
    for line in arrayOLines:
        line=line.strip()   #strip() 方法用于移除字符串头尾指定的字符(默认为空格),截取掉所有的回车字符
        listFromLine=line.split('\t') #得到的整行数据分割成一个元素列表
        returnMat[index,:]=listFromLine[0:3]     #选取前三个元素存到特征矩阵中去,取从0开始到3之前的,即取第0  1  2 个
        classLabelVector.append(int(listFromLine[-1])) #append() 方法用于在列表末尾添加新的对象。索引值-1表示列表中的最后一列元素。需注意的是,要告诉解释器,列表中存储的元素值为整形,否则python会将这些元素当做字符串处理。
        index+=1
    return returnMat,classLabelVector
#测试读取文件的结果
datingDataMat,datingLabels=file2matrix("datingTestSet2.txt")
# print(datingDataMat)
# print(datingLabels)

# fig=plt.figure()#创建一幅图,可以没有参数,也可以有参数
# ax=fig.add_subplot(111)#将画布分割成1行41列,图像画在从左到右从上到下的第1块,参考http://blog.csdn.net/s201402023/article/details/51536687
# ax.scatter(datingDataMat[:,0],datingDataMat[:,1],15.0*array(datingLabels),15.0*array(datingLabels)) #第一个代表列,第二个代表行,例如这个就代表了取所有行,第1  2列,详情https://www.cnblogs.com/shanlizi/p/6850318.html
# plt.show()

#归一化特征值
def autoNorm(dataSet):
    minVals=dataSet.min(0)#将每一列的最小值放在minVals中,0代表使得函数可以从列中选取最小值,而不是选取当前行的最小值
    maxVals=dataSet.max(0)
    ranges=maxVals-minVals
    normDataSet=zeros(shape(dataSet))
    m=dataSet.shape[0]#]#得到数组的行数。即知道有几个训练数据
    normDataSet=dataSet-tile(minVals,(m,1))#将矩阵中每个值减去当前列的最小值。注:因为最小值矩阵是(1,3),要复制成(m,3列的)
    normDataSet=normDataSet/tile(ranges,(m,1))#将矩阵中每个值除以取值范围(最大值-最小值)
    return normDataSet,ranges,minVals#分别为归一化后的矩阵,每一列的取值范围,每一列的最小值
#测试归一化
# normMat,ranges,minVals=autoNorm(datingDataMat)
# print(normMat)
# print(ranges)
# print(minVals)

#针对约会网站的测试精确率的代码
def datingClassTest():
    hoRatio=0.10
    datingDataMat,datingLabels=file2matrix('datingTestSet.txt')#获取datingTestSet文本的数据和标签
    normMat,ranges,minVals=autoNorm(datingDataMat)#将datingTestSet数据归一化
    m=normMat.shape[0]#计算datingTestSet的总行数
    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(datingClassTest())

#该函数是为了使用户能够自己输入三个特征,然后输出结果
def classifyPerson():
    resultList=['not at all','in small doses','in large doses']
    percentTats=float(input("percentage of time spent playing video games?"))#??????????要加float
    ffMiles=float(input("frequent flier miles earned per year?"))
    iceCream=float(input("liters of ice cream earned per year?"))
    datingDataMat,datingLabels=file2matrix('datingTestSet2.txt')
    normat,ranges,minVals=autoNorm(datingDataMat)
    inArr=array([ffMiles,percentTats,iceCream])
    classfierResult=classify0((inArr-minVals)/ranges,normat,datingLabels,3)
    print(classfierResult)
    print("you will probably like this person:",resultList[classfierResult-1])
# classifyPerson()#执行代码

#手写识别系统
#将图片转换成向量,图片为32*32大小,向量为1*1024的向量。打开给定文件,循环读出前32行,将每行的前32个字符值放在numpy数组中
def img2vector(filename):
    returnVect=zeros((1,1024))
    fr=open(filename)#<_io.TextIOWrapper name='testDigits/0_13.txt' mode='r' encoding='cp936'>
    # print(fr)
    # lineStr1 = fr.readlines()
    # print(lineStr1)
    for i in range (32):
        lineStr=fr.readline()#输出整个文件
        # print(lineStr)
        for j in range(32):
            returnVect[0,32*i+j]=int(lineStr[j])
    return returnVect
#测试上面函数
# testVector=img2vector('testDigits/0_13.txt')
# print(testVector[0,0:31])#输出结果的1-31列,总共31个

#手写数字识别系统的测试代码
def handwritingClassTest():
    hwLabels=[]#存储每个文件的类别。是1 还是2  3  4  。。。
    trainingFileList=listdir('trainingDigits')#返回指定路径下的文件和文件夹列表。
    m=len(trainingFileList)#输出目录中的文件个数
    trainingMat=zeros((m,1024))#将所有的训练文件整合成一个矩阵,每一行是一个文件
    for i in range(m):#将所有的训练文件整理成一个矩阵,每一行为一个文件
        fileNameStr=trainingFileList[i]#获取每一行数据的文件名(包括后缀名)
        fileStr=fileNameStr.split('.')[0]#获取每一行数据的文件名(不包括后缀名)
        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("\n the total number of errors is:%d"%errorCount)
    print("\n the total error rate is:%f"%(errorCount/float(mTest)))
#测试代码:
handwritingClassTest()
注:直接将代码复制运行出错,将 classCount.iteritems()换成classCount.items()即可

猜你喜欢

转载自blog.csdn.net/wanwanwei/article/details/78965194