机器学习-14:MachineLN之kNN源码

你要的答案或许都在这里小鹏的博客目录

我想说:

其实你坚持的东西都是有意义的,就好比给代码加注释,你真去做了就知道了;另外建议大家建立一个自己的工具箱,就像我建立一个MachineLP_tools,里面放可以复用的代码,然后支持大家开源,你手上现有的代码可能很快就会过时,希望能够在有效期内发挥最大的功效;最后建议自己搭建一个自己的机器学习训练框架,用着顺手、用着舒服、用着放心,比起相信别人,相信大家更相信自己。


下面是kNN代码和详细注释, 又是截图,哈哈,虽然好代码都是敲出来的但是需要文本的可以私聊我;kNN原理参考:MachineLN之kNN


# 下面就是kNN的核心公式,每次给代码加注释都能想起李皓宇老师
def classify0(inX, dataSet, labels, k):
    # 在矩阵中我们一般说行和列,而在图像中我们说的是宽和高,但是宽对应的是列,高对应的是行;
    # 首先获取有样本集的数量,为什么? 这下一句就能看出来,为了给新的输入样本做广播,进行向量与矩阵的减法;
    dataSetSize = dataSet.shape[0]
    # dataSetSize行,1列; 进行矩阵减法;
    diffMat = tile(inX, (dataSetSize,1)) - dataSet
    # 下面三行就是平方求和取根号, 计算欧式距离; 也就是计算样本间的相似度;
    sqDiffMat = diffMat**2
    # 求和
    sqDistances = sqDiffMat.sum(axis=1)
    # 取根a号
    distances = sqDistances**0.5
    # 对新样本与各类别样本计算距离后排序,然后返回排序后的索引; (默认的是升序排列)
    sortedDistIndicies = distances.argsort()
    # 定义一个字典, 排序后的前k个值中含有类别的个数;
    classCount={}
    # 下面就是kNN中的k;          
    for i in range(k):
        # 下面就是根据排序后的索引值,取出对应样本的标签值;
        voteIlabel = labels[sortedDistIndicies[i]]
        # 统计前排序后k个中个类别的数量; 这里的get用的很妙,前几天刚听同事提过,学习了;
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
    # 对字典按照value进行排序; python2中可以用下面的方式,貌似python3貌似用不了;
    # 如果没有好的方法; 那么可以用我这种比较笨拙的方法:但是返回的是列表;
    '''
    def dict2list(dic:dict):  
        #将字典转化为列表 
        keys = dic.keys()  
        vals = dic.values()  
        lst = [(key, val) for key, val in zip(keys, vals)]  
        return lst  
    # lambda生成一个临时函数  
    # d表示字典的每一对键值对,d[0]为key,d[1]为value  
    # reverse为True表示降序排序  
    stat = sorted(dict2list(stat), key=lambda d:d[1], reverse=True) '''
    # 降序排列; 
    sortedClassCount = sorted(classCount.iteritems(), 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
    # 定义返回样本的集二维数组; 只取了3个数据所以定义为3列;
    returnMat = zeros((numberOfLines,3))        #prepare matrix to return
    # 存放对应的标签;
    classLabelVector = []                       #prepare labels return   
    fr = open(filenamea)
    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))
    # 获取样本的集的数量; 用于对最小值 和 ranges进行广播; 用于后面矩阵的减法 和 除法;
    m = dataSet.shape[0]
    # 归一化的操作; 此处有问题; 可以查看 MachineLN之样本归一化;
    normDataSet = dataSet - tile(minVals, (m,1))
    normDataSet = normDataSet/tile(ranges, (m,1))   #element wise divide
    return normDataSet, ranges, minVals


# kNN 分类 
def datingClassTest():
    # 设置一个比率,在0到1之间,用于将样本集设置多少训练集和多少为测试集; 
    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):
        # 取第i个测试样本,通过训练集计算新样本的类别;
        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):
    # 用来存储每个图片拉成向量后的结果,这里的图片是32*32所以是1024;
    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


# 下面是手写体数字通过kNN进行识别;
def handwritingClassTest():
    # 用于存放样本类别
    hwLabels = [a]
    # 由于每张手写体的图是放在一个文件中;要将所有文件生成样本集;
    # 获取文件夹中的所有文件;
    trainingFileList = listdir('trainingDigits')           #load the training set
    # 获取文件数量;
    m = len(trainingFileList)
    # 定义一个数组, m行(手写体数量),1024像素数;
    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)
        # 取第i个测试样本,通过训练集计算新样本的类别; k值仍为3
        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))



推荐阅读:

1. 机器学习-1:MachineLN之三要素

2. 机器学习-2:MachineLN之模型评估

3. 机器学习-3:MachineLN之dl

4. 机器学习-4:DeepLN之CNN解析

5. 机器学习-5:DeepLN之CNN权重更新(笔记)

6. 机器学习-6:DeepLN之CNN源码

7. 机器学习-7:MachineLN之激活函数

8. 机器学习-8:DeepLN之BN

9. 机器学习-9:MachineLN之数据归一化

10. 机器学习-10:MachineLN之样本不均衡

11. 机器学习-11:MachineLN之过拟合

12. 机器学习-12:MachineLN之优化算法

13. 机器学习-13:MachineLN之kNN

14. 机器学习-14:MachineLN之kNN源码

15. 机器学习-15:MachineLN之感知机

16. 机器学习-16:MachineLN之感知机源码

17. 机器学习-17:MachineLN之逻辑回归

18. 机器学习-18:MachineLN之逻辑回归源码




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MachineLP

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值