Machine Learning in Action机器学习实战 第二章 KNN算法 (笔记)

导入一些常用的库

from numpy import *
import operator
from os import listdir
# 开始定义分类函数
# inx为需要分类的参数,dataSet为训练集,labels为dataSet的标签向量,也就是对应的分类结果。k为最近的几个邻近数目,k应为奇数。
def classify0(inX, dataSet, labels, k):                                
    dataSetSize = dataSet.shape[0]                  # shape是返回的为dataSet的维度,也就是有几行几列(如果是二维)。
                                                    # 取第一个维度就是有多少行,一般来说行为数据有多少条,列为数据特征值。    
    diffMat = tile(inX, (dataSetSize,1)) - dataSet  # tile函数是创建一个重复元素矩阵的函数,第一个参数inx为需要分类的参数,(dataSetSize,1)为重复的方式。
                                                    # 这里的行重复的次数与数据集的条数相同,列重复一次。因为输入参数的特征数(列数),和每条数据的列数一样,只要重复一次就可以了
                                                    # diffMat就是一个输入参数和每个数据的特征值之差矩阵
    sqDiffMat = diffMat**2                          # 将特征值之差的矩阵的每个元素都平方
    sqDistances = sqDiffMat.sum(axis=1)             # 将每行的元素按列加和,axis=1是指定加和方式为按列加和
    distances = sqDistances**0.5                    # 将加和后开方就得出了inx到每个数据的距离,这里的算法用的是欧式距离,还有一种曼哈顿距离也可以考虑
    sortedDistIndicies = distances.argsort()        # 按从小到大排列再提取其对应的index(索引),然后输出索引值,就是原来数据中排第几行。    
    classCount={}                                   # 创建分类统计字典          
    for i in range(k):                              # 取前K个数据
        voteIlabel = labels[sortedDistIndicies[i]]  # 先取第i个数据的index值,然后再根据index值取到标签
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1   # 根据取到的标签去字典中找对应的index,如果没有这个index便创建这个index,默认初始值为0
                                                                     # 找到这个index对应的值,然后加1,因为统计到了一次这个index        
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)   # 原书classCount.iteritems()在python3.5版本中改成了classCount.items(),来获取字典中的键-值
                                                                                              # 按照第二个域来排序也就是值来排序
                                                                                              #  reverse = True 就是反转,从大到小排序
    return sortedClassCount[0][0]                          #输出标签  
【1】由于tile这个函数创建矩阵比较陌生
    建议可以自己用打印一下tile(1,4); tile(1,(4,2)); tile((1,2),(4,2)) 来感受一下
    注意tile是numpy下的函数。需要先导入numpy
【2】argsort 函数是将dataSet中的数据先按从小到大排列,然后再给出排列好的数据在原来dataSet中是第几行的一个数组。
    如果对这个函数比较陌生也可以自己创建几个例子来print一下。

def file2matrix(filename):
    fr = open(filename)  # 打开这个输入文件
    arrayOLines = fr.readlines()            # 读取文件信息
    numberOfLines = len(arrayOLines)         # 读取文件行数N
    returnMat = zeros((numberOfLines,3))        # 创建一个N行3列元素全部是0的矩阵
    classLabelVector = []                       # 创建一个存放分类向量的空矩阵  
    index = 0                                   # 初始化index
    for line in arrayOLines:           # 对于文件中的每一行
        line = line.strip()               # 移除字符串头尾指定的字符(默认为空格)
        listFromLine = line.split('\t')   # 根据tab来分割每行的数据
        returnMat[index,:] = listFromLine[0:3] # 将读取出来的前三个值赋给那个零矩阵的第index行
        classLabelVector.append(int(listFromLine[-1])) # 将最后一个值赋给分类矩阵中
        index += 1  # index加1
    return returnMat,classLabelVector

首先要熟悉这个要读取的数据结构,这篇文章是已经熟悉了数据结构,才能这样创建矩阵。

def datingClassTest():
    hoRatio = 0.10      #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)#numTestVecs前为测试集,之后的数据都为训练集
        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)

记住python3 print要加括号了



猜你喜欢

转载自blog.csdn.net/aaronpaul/article/details/79645577