机器学习源码学习笔记(一)-KNN邻近算法

1 、k-n 邻近算法

#coding=utf-8
from numpy import *
import  operator
def classify0(inX, dataSet, labels, k):
    dataSetSize = dataSet.shape[0]
    print("dataSetSize",dataSetSize )
    diffMat = tile(inX, (dataSetSize,1)) - dataSet
    print("title",tile(inX, (dataSetSize,1)))
    print("diffMat",diffMat)
    sqDiffMat = diffMat**2
    print("sqDiffMat",sqDiffMat)
     # 在行的方向上求和
    sqDistances = sqDiffMat.sum(axis=1)
    print ("sqDistances",sqDistances)
    distances = sqDistances**0.5
    print("distances",distances)
    # 进行排序,返回数组中,由小到大的索引值
    sortedDistIndicies = distances.argsort()
    print ("sortedDistIndicies",sortedDistIndicies)
    #  这是一个dict 字典,用于存储不同标签出现的次数,(key,value) 的存储结构;
    classCount={}
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        print('iiiii ',i)
        print('voteIlabel=',voteIlabel)
        # 这里是选择距离最小的k个点, sortedDistIndicies已经排好序,
        # 只需迭代的取前k个样本点的labels(即标签),并计算该标签出现的次数,
        # 这里还用到了dict.get(key, default=None)函数,key就是dict中的键voteIlabel,如果不存在则返回一个0并存入dict,如果存在则读取当前值并+1;
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
        print("classCount.get(voteIlabel,0)",classCount.get(voteIlabel,0))
        print("classCount[voteIlabel]", classCount[voteIlabel])
        # 这里使用了sorted()函数sorted(iterable, cmp=None, key=None, reverse=False),iteritems()将dict分解为元组列表,
        # operator.itemgetter(1)表示按照第二个元素的次序对元组进行排序,注意sort()的区别,可参考numpy.sort;
        sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
        print("sortedClassCount",sortedClassCount)
    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
group,labels = createDataSet()


classify0([0,0],group,labels,3)

2、将文本记录解析为Numpy 的解析程序

def file2matrix(filename):
    fr = open(filename)
    numberOfLines = len(fr.readlines())  # get the number of lines in the file
    returnMat = zeros((numberOfLines, 3))  # 生成一个numberoflinesx3 的 矩阵,并初始化为0
    classLabelVector = []  # prepare labels return
    fr = open(filename)
    index = 0
    for line in fr.readlines():
        line = line.strip()
        listFromLine = line.split('\t')
        print('第一维中的数据第0列数据listFromLine=', listFromLine)
        #将listFromLine 前三个值  赋值给 returnMat  的index 行的值
        returnMat[index, :] = listFromLine[0:3]
        print('listFromLine[0:3]', listFromLine[0:3])
        print('returnMat[index,:]', returnMat[index, :])
        #list 追加元素  (-1)listFromLine 最后一个元素
        classLabelVector.append(int(listFromLine[-1]))
        index += 1
    return returnMat, classLabelVector

3、归一化特征值函数

def autoNorm(dataSet):
   #选择第0列 最小值所在的那一行数据
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    normDataSet = zeros(shape(dataSet))
    # 取第第一维的大小
    m = dataSet.shape[0]
    #tile 重复一个数组在 行的维度上重复m次,列的方向不重复
    normDataSet = dataSet - tile(minVals, (m, 1))
     # element wise divide 矩阵相除
    normDataSet = normDataSet / tile(ranges, (m, 1)) 
    return normDataSet, ranges, minVals

4、作为完整程序验证分类器

def datingClassTest():
    hoRatio = 0.50      #hold out 10%
    datingDataMat,datingLabels = file2matrix('D:\\yls\\learn\\machinelearninginaction\\Ch02\\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):
        # k = normMat[numTestVecs:m,:]
        # z = datingLabels[numTestVecs:m]
        # 第一个参数是normMat矩阵的第i个行向量,
        # 第二个参数是此normMat矩阵[numTestVecs, m]左闭右开区间的的所有行组成的矩阵
        # 第三个参数是标签行向量datingLabels的[numTestVecs, m]左闭右开区间的的所有元素组成的新的行向量
        classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
        #classifierResult  是特征分类器得出的矩阵中中距离 normMat[i,:] 最近的特征值
        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

2-6 手写数字识别系统的测试代码

def handwritingClassTest():
    hwLabels = []
    # load the training set,trainingDigits目录中的文件内容存储在列表中
    trainingFileList = listdir('D:\\yls\\learn\\machinelearninginaction\\Ch02\\digits\\trainingDigits')
    #返回序列或集合的项数1934 。
    m = len(trainingFileList)
    trainingMat = zeros((m,1024))
    for i in range(m):
        fileNameStr = trainingFileList[i]
        # take off .txt  从文件名解析出 文件内的数字
        fileStr = fileNameStr.split('.')[0]
        classNumStr = int(fileStr.split('_')[0])
        # 把每个文件名对应的图件数字做为特征值
        hwLabels.append(classNumStr)
        #我们将把一个32×32的二进制图像矩阵转换为1×1024的向量,  由m个[1,1024]向量(即图像) 组成一个 训练 矩阵
        trainingMat[i,:] = img2vector('D:\\yls\\learn\\machinelearninginaction\\Ch02\\digits\\trainingDigits\\%s' % fileNameStr)
    # 读取待测试目录下的文件,并存储在列表中testFileList
    testFileList = listdir('D:\\yls\\learn\\machinelearninginaction\\Ch02\\digits\\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('D:\\yls\\learn\\machinelearninginaction\\Ch02\\digits\\testDigits\\%s' % fileNameStr)
        # 使用classify0测试每个文件,,
        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)))

猜你喜欢

转载自blog.csdn.net/ylscook/article/details/80253325