机器学习2—K近邻算法学习笔记

       Python3.6.3下修改代码中def classify0(inX,dataSet,labels,k)函数的classCount.iteritems()为classCount.items(),另外print在Python新版本下是函数,print后面需加上一对括号,否则执行会报错。

classify0详解

import numpy as np
#用于分类的输入向量是inX,输入的训练样本集为dataSet,
#标签向量为 labels ,最后的参数 k 表示用于选择最近邻居的数目,其中标签向量的元素数目和矩
#阵 dataSet 的行数相同。
def classify0(inX,dataSet,labels,k):
    # 获取 数组 形状的 第一个 参数 a=[[1,2],[1,2],[1,2]]  a.shape = [3,2] a.shape[0] = 3
# 一、
    dataSetSize = dataSet.shape[0]
    # tile 代表了inX,复制为dataSetSize行,1列的数组
# 二、
    diffMat = np.tile(inX,(dataSetSize,1))-dataSet
    # 平方
    sqDiffMat = diffMat**2
    # axis 等于 1 是将 矩阵的每一行 相加
    sqDistances = sqDiffMat.sum(axis=1)
    # 开方
    distances = sqDistances**0.5
# 三、
    # 从小到大 排列,argsort : 将distacnces中的元素从小到大排列,提取其对应的index(索引),然后输出到sortedDistances 
    sortedDistances = distances.argsort()
    classCount = {}
# 四、求出来 最低距离 的 labels结果,存放在classCount 中
    for i in range(k):
        #取第i+1个邻近的样本对应的类别标签
        voteIlabel =labels[sortedDistances[i]]
        #以标签为key,标签出现的次数为value将统计到的标签及出现次数写进字典
        classCount[voteIlabel] = classCount.get(voteIlabel,0)+1
        #对字典按value从大到小排序
    sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
        #返回排序后字典中最大value对应的key
    return sortedClassCount[0][0]

 以下注解参考

#将文本记录转换为Numpy的解析程序  
def file2matrix(filename):  
        
      fr=open(filename)     #打开文件  
        
      arrayOLines=fr.readlines()   #获取文件所有行  
        
      numberOfLines=len(arrayOLines)     #得到文件行数  
        
      returnMat=zeros((numberOfLines,3))   #先用零元素创建需要返回的numpy矩阵,(行数,列数)  
        
      classLabelVector=[]    # 创建空的标签列表  
        
      index=0  
        
      for line in arrayOLines:  
              
            line=line.strip()   #截取掉尾部的回车字符  
              
            listFromLine=line.split('\t')  #用‘\t’作为分隔符将整行元素分割成元素列表,将一行数据按空进行分割,  
              
            returnMat[index,:]=listFromLine[0:3] #选取列表前三个元素到=矩阵中  
              
            classLabelVector.append(listFromLine[-1]) #将列表的最后一列存储到向量中  
              
            index += 1  
              
      return returnMat,classLabelVector  #返回数据集矩阵和对应的标签向量  

 

#归一化特征值      
def autoNorm(dataSet):  
        
    minVals = dataSet.min(0)  #找到数据集中的最小值(实际上应该是样本数据中的一列中的最小值,参数0就代表这个,下同),这样说的话minVals和maxVals都应该是一个行向量(1*n)  
      
    maxVals = dataSet.max(0)   #找到数据集中的最大值  
      
    ranges = maxVals - minVals    #得到数据的范围差值  
      
    normDataSet = zeros(shape(dataSet))     # 定义空的要返回的归一化后的矩阵,该矩阵和传入的数据集是一样的大小  
      
    m = dataSet.shape[0]       #得到矩阵第一行的数据个数,也就是维数  
      
    normDataSet = dataSet - tile(minVals, (m,1))  #数据集与最小值相减(title()函数将按照括号中的参数制作对应大小的矩阵,用给定的minVals内容来填充  
      
    normDataSet = normDataSet/tile(ranges, (m,1))   #除以范围值之后就是归一化的值了。(注意是矩阵除法)  
      
    return normDataSet, ranges, minVals  

 

#分类器针对约会网站的测试代码  
def datingClassTest():  
        
    hoRatio = 0.10      #测试所占的比例  
      
    datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')       #将文件中的数据转换为矩阵形式和提取出标签矩阵  
      
    normMat, ranges, minVals = autoNorm(datingDataMat)    #对提取出的矩阵数据归一化处理  
      
    m = normMat.shape[0]   #获得数据总的条数  
      
    numTestVecs = int(m*hoRatio)    #得出作为测试的数据个数  
      
    errorCount = 0.0      #初始化错误个数为0  
      
    for i in range(numTestVecs):  #对测试的数据进行遍历  
            
        classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)    # 对数据进行分类  
          
        print("the classifier came back with: %s, the real answer is: %s" % (classifierResult, datingLabels[i]))   #输出分类结果和实际的类别(之前的代码有问题啊,要将%d,改为%s)  
          
        if (int(classifierResult) != int(datingLabels[i])): errorCount += 1.0    # 如果分类结果与实际结果不一致 ,错误数加1  
          
    print("the total error rate is: %f" % (errorCount/float(numTestVecs)))   # 输出错误率  
      
    print(errorCount)    #输出错误总数

 

#约会网站预测函数  
def classiyPerson():  
      
    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('datingTestSet2.txt')         # 从文件中读取已有数据  
     
    normMat,ranges,minVals = autoNorm(datingDataMat)                     # 对数据进行归一化  
     
    inArr =array([ffMiles,percentTats,iceCream])                         # 将单个输入数据定义成一条数据  
      
    classifierResult = classify0(inArr,datingDataMat,datingLabels,3)      # 对输入数据进行分类  
     
    print('You will probably like this person: %s' % (resultList[int(classifierResult) - 1]))       # 输出预测的分类类别
# 将单个手写字符文件变成向量   
def img2vector(filename):  
        
    returnVect = zeros((1,1024))   #创建要返回的1*1024的矩阵并初始化为0  
      
    fr = open(filename)    # 打开文件  
      
    for i in range(32):    #从0到31行遍历  
            
        lineStr = fr.readline()   #读取一行(自动成为一个列表)  
          
        for j in range(32):  #从0到31列  
                
            returnVect[0,32*i+j] = int(lineStr[j])   #将一行中的每个元素复制到要返回的矩阵中  
              
    return returnVect   #返回该1*1024的矩阵 
# 手写字符识别测试  
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]     # 对文件名进行分割  
          
        classNumStr = int(fileStr.split('_')[0])   # 获得文件名中的类标签  
          
        hwLabels.append(classNumStr)    # 把类标签放到hwLabels中  
          
        trainingMat[i,:] = img2vector('trainingDigits/%s' % fileNameStr)     # 把文件变成向量并赋值到trainingMat这个矩阵中    
          
    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" % (int(classifierResult), int(classNumStr)))       # 输出预测类别和实际类别  
          
        if (int(classifierResult) != int(classNumStr)): errorCount += 1.0      # 如果二者不一致,累加错误数量   
          
    print("\nthe total number of errors is: %d" % errorCount)       # 输出分类错误的数目  
      
    print("\nthe total error rate is: %f" % (errorCount/float(mTest)))          # 输出分类的错误率  

 

第二章代码修改如下:

from numpy import *
import operator
from os import listdir

def classify0(inX, dataSet, labels, k):
    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()     
    classCount={}          
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]

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 file2matrix(filename):
    fr = open(filename)
    numberOfLines = len(fr.readlines())         #get the number of lines in the file
    returnMat = zeros((numberOfLines,3))        #prepare matrix to return
    classLabelVector = []                       #prepare labels return   
    fr = open(filename)
    index = 0
    for line in fr.readlines():
        line = line.strip()
        listFromLine = line.split('\t')
        returnMat[index,:] = listFromLine[0:3]
        classLabelVector.append(int(listFromLine[-1]))
        index += 1
    return returnMat,classLabelVector
    
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.50      #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: %f" % (errorCount/float(numTestVecs)))
    print(errorCount)
    
def img2vector(filename):
    returnVect = zeros((1,1024))
    fr = open(filename)
    for i in range(32):
        lineStr = fr.readline()
        for j in range(32):
            returnVect[0,32*i+j] = int(lineStr[j])
    return returnVect

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)))
View Code

 

posted @ 2017-12-25 11:24  Vae永Silence  阅读(856)  评论(0编辑  收藏  举报