• KNN算法实践,加两个有趣的例子-----约会对象例子和数字识别例子 本人在百度上下了一些图片又做了识别测试,效果好的惊人哦!!! 不知道汉王ORC什么的是不是用的KNN

    前段时间在京东上购买了这本很多人都推荐的书---机器学习实战。刚刚看完第一章,感觉本书很适合   初学者,特别是对急于应用机器学习但又不想深究理论的小白(像我这样的)。不过在这里还是推荐一下李航老师的那本《统计学习方法》,该书注重理论推导及挖掘算法背后的数学本质,和《机器学习实战》配合起来学习,可以达到事半功倍的效果。有这两本书基本可以让我们这些小白开始起飞了。

                                                                       

           看完《统计学习方法》的KNN算法推导,虽然知道了该算法的理论基础,但是对KNN算法还是没有一个宏观的把握,这样估计几天就会忘得一干二净。这几天抽空将《机器学习实战》中的KNN代码动手自己写了一遍,实践以后确实对它有了更深的理解,也知道了它的适用范围。本书是用python语言写的,确实是个正确的选择,感觉用起来很像matlab,特别方便。不过听实验室某位大神说搞大数据R语言用的也不少,现在真心感觉要学语言实在太多了。在大数据领域,两大王牌软件spark和hadoop分别是用scala和java写的,统计处理又推荐使用R,平时仿真又是python。对于我们这种一直用C/C++的,平时没写过什么软件应用,一下子要学这么多高级语言,实在有点招架不住啊!尴尬

    废话不多说,谁让我铁了心要进军大数据的奋斗。兄弟们,拿起python来。开干。。。

           KNN算法概况起来一句话:在样本数据中,距离测试样本点的一定范围内,寻找最多的一种样本类型,作为测试点的类型。距离可以是欧式距离,也可以非欧式距离,看具体的情况而定。至于范围大小的选取至关重要,目前貌似学术界也没什么办法可以算出哪个范围最好,所以工程上一般都是穷举测试。然后就是样本点和测试点的构建了,其实也就是特征提取,这部分是最最重要的,这直接决定了机器学习算法的准确性。如果特征不好,即使你的机器学习算法再好也没用。如果特征很棒,即使用的不是最优的机器学习算法效果也不错。这是实验室大牛说的。他说在各种大数据竞赛里,后面起决定性作用的是特征选择与提取,而不是算法(目前是这样的)。当然,非监督学习除外,因为它根本就不用特征提取。至于怎样选择特征最有效,这就要结合具体数据,具体问题而言了。本菜也不在这里YY了。

          书中用了两个实例来测试KNN算法, 一个是约会对象判断,一个是数字识别。本人觉得还是数字识别比较有趣,因为可以自己动手测试一下,特别有成就感吐舌头。废话不多说,上代码:

    #!/usr/bin/env python
    #-*- coding: utf-8 -*-
    
    """
    Created on Aug 29, 2015
    
    @author: freestyle4568
    this module is kNN method, classifying something.
    """
    import numpy as np
    import operator
    
    def createdataset():
        """该函数用于产生kNN实验用列,返回样本数据集(numpy数组)和样本类型集(列表)
        
        Keyword arguments:
        None
        """
        group = np.array([[1.0, 1.1], 
                          [1.0, 1.0],
                          [0, 0], 
                          [0, 0.1]
                          ])
        labels = ['A', 'A', 'B', 'B']
        return group, labels
    
    def classify(testData, dataSet, labels, k):
        """应用KNN方法对测试点进行分类,返回一个结果类型
        
        Keyword argument:
        testData: 待测试点,格式为数组
        dataSet: 训练样本集合,格式为矩阵
        labels: 训练样本类型集合,格式为数组
        k: 近邻点数
        """
        dataSetSize = dataSet.shape[0]
        multitestData = np.tile(testData, (dataSetSize, 1))
        diffMat = multitestData - dataSet
        sqdiffMat = diffMat**2
        sqdistance = sqdiffMat.sum(axis=1)
        #print(sqdistance)
        distance = sqdistance**0.5
        sortedDistIndex = distance.argsort()
        classCount = {}
        for i in range(k):
            voteIlabel = labels[sortedDistIndex[i]]
            classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
        sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
        #print(sortedClassCount)
        return sortedClassCount[0][0]
    
    
    if __name__ == '__main__':
        import matplotlib.pyplot as plt
        group, labels = createdataset()
        print('group is:')
        print(group)
        print('labels is:')
        print(labels)
        plt.plot(group[:, 0], group[:, 1], 'o')
        plt.xlim(-0.1, 1.2)
        plt.ylim(-0.1, 1.2)
        plt.show()
        test = [0, 0]
        print('test is:')
        print(test)
        print('classify result is:')
        print(classify(test, group, labels, 3))
        
    
    运行结果:

    1.绘制出了测试点在特征空间中的坐标


    2.测试点为main函数中写的,(0,0),分类结果为B,KNN算法函数编写正确。

           KNN算法构建好了,来进行第一个有趣的实验,约会对象分类实验。实验说明:本人特别喜欢约会,并且会给各个约会对象打分,分为三个档次:非常喜欢,一般喜欢,不喜欢。每个对象特征现成的,已经提取好了,如:鼻子多少分,嘴巴多少分,喜欢运动否,每天跑多少步等。再进行KNN的时候有个坑,就是各个特征范围不一样,有的大有的小,在计算欧式距离时小范围的特征当然不占优势,为了避免这种情况需要将特征进行归一化处理。然后再进行KNN分类,作者给出了测试用例和样本数据,所以可以借此来看看KNN算法的可靠性。

           约会实例构建:(里面用到前面我们写的KNN算法,所以记得import kNN哦)

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    '''
    Created on Aug 29, 2015
    
    @author: freestyle4568
    '''
    import numpy as np
    import kNN
    
    
    
    def file2matrix(filename):
        """该函数将约会文件内容转换成数据处理格式,返回一个测试特征集(格式二维数组),和测试集类别集(格式列表)
        
        Keyword argument:
        filename -- 约会数据所在的路径,最好是绝对路径
        """
        fr = open(filename)
        arrayOnLines = fr.readlines()
        numberOfLines = len(arrayOnLines)
        returnMat = np.zeros((numberOfLines, 3))
        classLabel = []
        for i in range(numberOfLines):
            line = arrayOnLines[i]
            line = line.strip()
            listFromLine = line.split('\t')
            returnMat[i, :] = listFromLine[0:3]
            classLabel.append(int(listFromLine[-1]))
        return returnMat, classLabel
    
    def autoNorm(dataSet):
        """该函数将数据集的所以特征归一化,返回归一化后的特征集(格式为数组),特征集最小值(格式为一维数组),特征集范围(格式为一维数组)
        
        Keyword argument:
        dataSet -- 特征数据集
        """
        minVals = dataSet.min(axis=0)
        maxVals = dataSet.max(axis=0)
        ranges = maxVals - minVals
        dataSize = dataSet.shape[0]
        normDataSet = dataSet - np.tile(minVals, (dataSize, 1))
        normDataSet = normDataSet / np.tile(ranges, (dataSize, 1))
        return normDataSet, minVals, ranges
        
    def dateClassTest(filename, k):
        """测试KNN算法对于约会数据的错误率
        
        Keyword argument:
        None
        """
        ratio = 0.10
        dataSet, labels = file2matrix(filename)
        normDateSet, minVals, ranges = autoNorm(dataSet)
        dataSize = dataSet.shape[0]
        numTestVecs = int(dataSize*ratio)
        errorcount = 0.0
        print("m : %d" % dataSize)
        for i in range(numTestVecs):
            classifyResult = kNN.classify(normDateSet[i, :], normDateSet[numTestVecs:dataSize, :],\
                                          labels[numTestVecs:dataSize], k)
            if classifyResult != labels[i]:
                errorcount += 1
            print("the real answer is: %d, the classify answer is: %d" % (labels[i], classifyResult))
        print("the total error ratio is %f" % (errorcount/float(numTestVecs)))
                
        
        
            
    if __name__ == '__main__':
        filename = '/home/freestyle4568/lesson/machineLearning/machinelearninginaction/Ch02/datingTestSet2.txt'
        dateClassTest(filename, 3)
    
    测试结果如下:


    可以到在本例中KNN的错误率为5%。还是相当不错的。(不过书上测试的书2.4%,难道数据更新过了,还是我KNN写错了,应该不会吧疑问

    这里选取K值为3。感兴趣的同学可以试试改改K值看看,通过改变范围大小,KNN的准确率怎么变化。

    当K值取所以样本数量时,会发现KNN准确率会怎么样?当K取1时会怎么样?微笑

    留给各位思考啦!!!

           再看下面一个更有趣的例子----数字识别。这个很好理解,就是给一个0-9的数字图片,然后通过KNN看分类结果是多少。

    看具体代码:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    '''
    Created on Aug 31, 2015
    
    @author: freestyle4568
    '''
    
    import numpy as np
    import os
    import kNN
    
    def img2vector(filename): 
        """函数将以文本格式出现的32*32的0-1图片,转变成一维特征数组,返回一维数组
        
        Keyword argument:
        filename -- 文本格式的图片文件
        """
        
        imgvect = np.zeros((1, 1024))
        fr = open(filename)
        for i in range(32):
            linestr = fr.readline()
            for j in range(32):
                imgvect[0, 32*i + j] = int(linestr[j])
        return imgvect
    
    def handwriteClassfiy(testfile, trainfile, k):
        """函数将trainfile中的文本图片转换成样本特征集和样本类型集,用testfile中的测试样本测试,无返回值
        
        Keyword argument:
        testfile -- 测试图片目录
        trainfile -- 样本图片目录
        """
        
        trainFileList = os.listdir(trainfile)
        trainFileSize = len(trainFileList)
        labels = []
        trainDataSet = np.zeros((trainFileSize, 1024))
        for i in range(trainFileSize):
            filenameStr = trainFileList[i]
            digitnameStr = filenameStr.split('.')[0]
            digitLabels = digitnameStr.split('_')[0]
            labels.append(digitLabels)
            trainDataSet[i, :] = img2vector(trainfile + '/' + filenameStr)
        testFileList = os.listdir(testfile)
        testNumber = len(testFileList)
        errorcount = 0.0
        for testname in testFileList:
            testdigit = img2vector(testfile + '/' + testname)
            classifyresult = kNN.classify(testdigit, trainDataSet, labels, k)
            testStr = testname.split('.')[0]
            testDigitLabel = testStr.split('_')[0]
            if classifyresult != testDigitLabel:
                errorcount += 1.0
            #print('this test real digit is:%s, and the result is: %s' % (testDigitLabel, classifyresult))
        print('k = %d, errorRatio is: %f' % (k, errorcount/float(testNumber)))
        return
    
    if __name__ == '__main__':
        filename = '/home/freestyle4568/lesson/machineLearning/machinelearninginaction/Ch02/digits/trainingDigits/0_0.txt'
        traindir= '/home/freestyle4568/lesson/machineLearning/machinelearninginaction/Ch02/digits/trainingDigits'
        testdir = '/home/freestyle4568/lesson/machineLearning/machinelearninginaction/Ch02/digits/testDigits'
        handwriteClassfiy(testdir, traindir, 3)
    


               正如代码中写的,我们先读入图片所在目录,然后将目录中的文本格式的二值图片文件转变为一维特征矩阵。然后代入我们的KNN算法,得出分类结果,还是一样的,让我们看看这次数字识别的效果。


    运行了很长的时间,电脑风扇狂转有没有,最后结果准确率高达1.3%。大笑

    被KNN的准确率震惊到了。不过细细一想,也可能是由于作者准备的数字测试图片恰好比较规范,和测试样例比较接近,导致了这么高的准确率。抱着这种想法,我就打算自己在网上搜点手写数字图片下来,用python将图片二值化一下,大小转换成统一的32*32。然后按照作者的命名方式放在mydigit目录下面。

    这些是我在百度图片里面下的手写图片:





    为了节约时间,这里就不把所有图片贴出来了,感兴趣的同学可以自己下一些测试一下。

    我先将下来的图片放在一个imgfile目录里面,然后将处理过的文本图片放在一个mydigit目录下面。

    贴一个我处理过的图片4:

    00000000000000000000000000000000
    00000000000000000000000000000000
    00000000000000000000000000000000
    00000000000000001111000000000000
    00000000000000001111000000000000
    00000000000000011111000000000000
    00000000000000111111100000000000
    00000000000001111111100000000000
    00000000000011111111100000000000
    00000000000011110111000000000000
    00000000000111100111000000000000
    00000000011111000111000000000000
    00000000011110000111000000000000
    00000000111100000111000000000000
    00000000111100000111000000000000
    00000001111000001111000000000000
    00000011111111100111110000000000
    00000011111111111111111111111000
    00000001111111111111111111111000
    00000000000000011111001111110000
    00000000000000001111000000000000
    00000000000000001111000000000000
    00000000000000001111000000000000
    00000000000000001110000000000000
    00000000000000001110000000000000
    00000000000000001110000000000000
    00000000000000011110000000000000
    00000000000000011110000000000000
    00000000000000001110000000000000
    00000000000000001110000000000000
    00000000000000000110000000000000
    00000000000000000000000000000000

    是不是很带感,再来一个8吧:

    00000000000000000000000000000000
    00000000000000000000000000000000
    00000000000011111110000000000000
    00000000000010000110000000000000
    00000000001100000010000000000000
    00000000001100000011000000000000
    00000000001100000011000000000000
    00000000001100000001000000000000
    00000000000100000001000000000000
    00000000001110000011000000000000
    00000000000110000011000000000000
    00000000000011000011000000000000
    00000000000001111110000000000000
    00000000000000011110000000000000
    00000000000000111110000000000000
    00000000000001110110000000000000
    00000000000001110011000000000000
    00000000000011000011000000000000
    00000000000011000011100000000000
    00000000000110000000100000000000
    00000000000110000001101000000000
    00000000000110000000111000000000
    00000000000100000000110000000000
    00000000001100000000111000000000
    00000000001100000000011000000000
    00000000001000000000010000000000
    00000000001100000000110000000000
    00000000000110000000010000000000
    00000000000101000000100000000000
    00000000000111000001100000000000
    00000000000011111111000000000000
    00000000000000000000000000000000
    我的处理代码:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    '''
    Created on Sep 1, 2015
    
    @author: freestyle4568
    '''
    
    import numpy as np
    import os
    import Image
    
    def changeImgFile(imgDir):
        """该函数将图片格式的文件转换成32*32的文本格式图片,并删除原来的图片格式文件,无返回值
        
        Keyword argument:
        imgDir -- 保存图片的目录
        """
        
        imgFileList = os.listdir(imgDir)
        print imgFileList
        imgNumber = len(imgFileList)
        for i in range(imgNumber):
            imgName = imgFileList[i]
            print imgName
            imgBig = Image.open(imgDir + '/' + imgName)
            imgNormal = imgBig.resize((32, 32))
            digitImg = imgNormal.convert('L')
            digit_mat = digitImg.load()
            fr = open(imgDir+'/../mydigit/'+str(i), 'w')
            for i in range(32):
                for j in range(32):
                    if digit_mat[j, i] != 255:
                        fr.write('1')
                    else:
                        fr.write('0')
                fr.write('\n')
            fr.close()
        
    if __name__ == '__main__':
        imgDir = '/home/freestyle4568/lesson/machineLearning/kNNinAction/imgfile'
        changeImgFile(imgDir)
    

    测试图片处理好了,下面直接调用我们之前的代码,只需要将目录路径改一下就可以了。

    快来看看测试结果:


    尖叫吧,欢呼吧,居然只有一个错了,可喜可贺,这里终于可以看到KNN的真正威力了。

    可是为什么我这里K取16呢?

    答对了,我是先扫描,再取错误率最小的k值的。想不想看看我的扫描结果(电脑可是嗡嗡直叫啊),可是我怎么一点也不心疼。。。。


    好啦,今天的KNN实践就见到这里啦,具体的理论看有时间在补上。(这可是我在教研室偷偷码的)

    展开全文
  • 机器学习实战——kNN

    2018-05-21 22:13:14
    最近在学习机器学习算法,感觉有本书写得很不错——《机器学习实战》,如果有一点基础去看这本书,然后在结合书中实例进行实践,还是很有收获的。 之后,可能会不定时的更新此书的相关内容,主要内容参考此书,...

    最近在学习机器学习算法,感觉有本书写得很不错——《机器学习实战》,如果有一点基础去看这本书,然后在结合书中实例进行实践,还是很有收获的。


    之后,可能会不定时的更新此书的相关内容,主要内容参考此书,夹杂一些我自己实践中的经验。

    KNN算法

    本书介绍的第一个机器学习算法是kNN算法,这个算法比较基础,简单易懂。

    实现的主要步骤:
    (1)收集数据。

    (2)准备数据:使用python解析文本文件

    (3)分析数据:主要是可视化数据

    (4)训练算法:kNN不用训练

    (5)测试算法:计算错误率,或者准确率

    (6)使用算法:

    A. 输入训练样本向量或者特征向量;

    B. 计算待分类样本(或特征向量)到这些训练样本的距离,一般是欧式距离

    C. 选取最小的k个距离,统计对应的类别,哪个类别多,待分类的样本就属于哪一类

    kNN的简单实现

    注:代码主要参考自书本,有一些改动。

    kNN的简单实现
    #-*- coding:utf-8 -*-
    import numpy as np
    import matplotlib.pyplot as plt
    import os
    import cv2 as cv
    
    # kNN算法的流程
    # 收集、整理数据->计算数据到分类点的距离
    # 选取k个距离最近的数据,看这几个数据属于哪一类,
    # 所属类别多的,待分类的点就属于此类
    # kNN算法不需要训练!!
    
    def createDataSet():
        # 构造简单的数据集
        group = np.array([[1.0, 1.1],[1.0,1.0],[0,0.2],[0,0.1]])
        # 这里对数据集进行修改,感觉书上的有点不合理 [0,0]->[0,0.2]
        labels = ['A','A','B','B']
        return group, labels
    数据的可视化
    def visualData(group,labels):
        # 数据可视化
        x1 = group[:2,0]
        y1 = group[:2,1]
        x2 = group[2:,0]
        y2 = group[2:,1]
        p1= plt.scatter(x1,y1)
        p2= plt.scatter(x2,y2)
        plt.legend([p1,p2],["A","B"])
        plt.show()
    def classify0(inX, dataSet, labels, k):
        """
        :param inX: 待分类的向量 - [x0,y0]
        :param dataSet: 数据集 - [[x1,y1],[x2,y2],...] - numpy类型
        :param labels: 标签数据 - 'A'或者'B'
        :param k: 设置的k值,选取前k个结果 - int
        :return:分类的结果,'A'或者'B'
        """
        d = inX-dataSet
        sqMat = d**2
        sqDis = sqMat.sum(axis=1)
        distances = sqDis**0.5
        sortedDis = distances.argsort()  # 将距离排序,并提取其对应的序号
        assert len(sortedDis)>=k  # 检查k的设置是否有问题
        classCount = {}
        for i in range(k):
            votelabel = labels[sortedDis[i]]
            classCount[votelabel] = classCount.get(votelabel, 0)+1
        keylist = list(classCount.keys())
        s = 0
        for l in keylist:
            if classCount[l] > s:
                s = classCount[l]
                res = l
        return res

    运行结果:

    可视化的结果:

    最终分类结果:
    

    kNN的手写数字识别

    思路:将手写数字图像转为向量,然后计算测试图像向量和训练图像向量的距离,然后选k个所属类别最多的作为最终类别。
    
    # 以下为手写数字识别的内容
    def img2vector(filename):
        # 将二进制图转换为向量,方便进行距离的计算
        resVec = np.zeros((1, 1024))
        fr = open(filename)
        for i in range(32):
            lineStr = fr.readline()
            for j in range(32):
                resVec[0, 32*i+j] = int(lineStr[j])
        return resVec
    def visualImg(filename):
        # 可视化手写数字图像
        resimg = np.zeros((32, 32))
        fr = open(filename)
        for i in range(32):
            lineStr = fr.readline()
            for j in range(32):
                resimg[i][j] = int(lineStr[j])
        cv.imshow("numberImg", resimg)
        cv.waitKey(0)
        return resimg
    def handwritingClassTest():
        hwLabels = []
        trainingFileList = os.listdir('./digits/trainingDigits/')
        m = len(trainingFileList)
        trainingMat = np.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('./digits/trainingDigits/%s' % fileNameStr)
        testFileList = os.listdir('./digits/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('./digits/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)))
    手写数字图像的可视化:
    

    最终的分类结果:
    




    单看这个结果,好像比用CNN的结果还要好,https://blog.csdn.net/louishao/article/details/60867339

    但是,kNN分类的这个数据集是比较小的,而且算法较为简单,比较复杂的情况分类的效果就会变得差一些,而且kNN无法表示图像/数据的特征。

    完整代码

    #-*- coding:utf-8 -*-
    import numpy as np
    import matplotlib.pyplot as plt
    import os
    import cv2 as cv
    
    # kNN算法的流程
    # 收集、整理数据->计算数据到分类点的距离
    # 选取k个距离最近的数据,看这几个数据属于哪一类,
    # 所属类别多的,待分类的点就属于此类
    # kNN算法不需要训练!!
    
    def createDataSet():
        # 构造简单的数据集
        group = np.array([[1.0, 1.1],[1.0,1.0],[0,0.2],[0,0.1]])
        # 这里对数据集进行修改,感觉书上的有点不合理 [0,0]->[0,0.2]
        labels = ['A','A','B','B']
        return group, labels
    def visualData(group,labels):
        # 数据可视化
        x1 = group[:2,0]
        y1 = group[:2,1]
        x2 = group[2:,0]
        y2 = group[2:,1]
        p1= plt.scatter(x1,y1)
        p2= plt.scatter(x2,y2)
        plt.legend([p1,p2],["A","B"])
        plt.show()
    
    def classify0(inX, dataSet, labels, k):
        """
        :param inX: 待分类的向量 - [x0,y0]
        :param dataSet: 数据集 - [[x1,y1],[x2,y2],...] - numpy类型
        :param labels: 标签数据 - 'A'或者'B'
        :param k: 设置的k值,选取前k个结果 - int
        :return:分类的结果,'A'或者'B'
        """
        d = inX-dataSet
        sqMat = d**2
        sqDis = sqMat.sum(axis=1)
        distances = sqDis**0.5
        sortedDis = distances.argsort()  # 将距离排序,并提取其对应的序号
        assert len(sortedDis)>=k  # 检查k的设置是否有问题
        classCount = {}
        for i in range(k):
            votelabel = labels[sortedDis[i]]
            classCount[votelabel] = classCount.get(votelabel, 0)+1
        keylist = list(classCount.keys())
        s = 0
        for l in keylist:
            if classCount[l] > s:
                s = classCount[l]
                res = l
        return res
    
    # 以下为手写数字识别的内容
    def img2vector(filename):
        # 将二进制图转换为向量,方便进行距离的计算
        resVec = np.zeros((1, 1024))
        fr = open(filename)
        for i in range(32):
            lineStr = fr.readline()
            for j in range(32):
                resVec[0, 32*i+j] = int(lineStr[j])
        return resVec
    
    def visualImg(filename):
        # 可视化手写数字图像
        resimg = np.zeros((32, 32))
        fr = open(filename)
        for i in range(32):
            lineStr = fr.readline()
            for j in range(32):
                resimg[i][j] = int(lineStr[j])
        cv.imshow("numberImg", resimg)
        cv.waitKey(0)
        return resimg
    
    def handwritingClassTest():
        hwLabels = []
        trainingFileList = os.listdir('./digits/trainingDigits/')
        m = len(trainingFileList)
        trainingMat = np.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('./digits/trainingDigits/%s' % fileNameStr)
        testFileList = os.listdir('./digits/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('./digits/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)))
    
    if __name__ == '__main__':
        '''
        group, labels = createDataSet()
        visualData(group, labels)
        inX = [0, 0]
        classres = classify0(inX, group, labels, 3)
        print(classres)
        '''
        '''
        handWriteTrainDir = "./digits/trainingDigits/"
        handWriteTestDir = "./digits/testDigits/"
        trainlist = os.listdir(handWriteTestDir)
        visualImg(handWriteTrainDir+trainlist[500])
        vec = img2vector(handWriteTrainDir+trainlist[0])
        '''
        handwritingClassTest()
    展开全文
  • 最近入坑了机器学习,为了快速提高自己的机器学习的代码能力,入坑了《机器学习实战》,目前只学习了第一个重要算法:k近邻算法(kNN),在学习过程中发现许多相关的学习资料要么代码是python2的,要么代码的解释不够...

    更新:代码在这里:https://github.com/lwpyh/machinelearning-in-action

    最近入坑了机器学习,为了快速提高自己的机器学习的代码能力,入坑了《机器学习实战》,目前只学习了第一个重要算法:k近邻算法(kNN),在学习过程中发现许多相关的学习资料要么代码是python2的,要么代码的解释不够详细,对于像我这样的菜鸡而言苦不堪言,为了后来者不踩我踩过的大坑,现在將这一章的学习笔记做一个小结,全文有些长,请根据自己的需要查看。

    一.什么是kNN

    首先上一段李航《统计学习方法》里kNN的算法总结

    用人话来说就是,对于某一个群体里的某个个体,其某一特性取决于其周围最近的k个人的该特性的多数值。

    举个例子,有一个100人的球迷群体,他们的主队分别是巴萨和皇马,现对于某一球迷(x),我们不知道他是皇马球迷还是巴萨死忠,我们依据k近邻算法可以对其主队(类)进行预测,假如取其周围最近的9个球迷(与x最邻近的k个点,这里k=9)来统计他们的主队(类别),发现其中5人为巴萨球迷,剩余4人为皇马球迷,我们就认为该球迷为巴萨球迷(多数表决)。

    这个就是k近邻算法的基本原理,下面结合机器学习实战,將这一算法进行实践。

    注:编程语言:python3.5,数据库来源:点击打开链接  打开后右侧随书下载——《机器学习实战》源代码.zip

    二.第一个kNN算法实践

    任务目标:自己创建一个基本数据集,并建立一个基本分类器,基于创建的基本数据集对某一数据进行分类

    任务实施:

    1.创建数据集

    在kNNdemo3.py 文件输入下列代码:

    这样就建立了一个数据集,在这个数据集里,group代表了其具体坐标位置,labels代表了其标签(属性),下面基于该数据集建立了一个基本分类器,该分类器將通过坐标,对其可能的属性是‘A’还是‘B’进行预测。下面是分类器部分的代码:

    注意:书里为python2.7的代码,所以倒数第三行书里用的是iteritems(),但在python3里已经被item()代替

    下面在terminal里运行这个分类器:

    这里首先载入python,载入数据集后对[0,0]和[3,3]通过分类器分别判断其标签是‘A’还是‘B’

    三.使用k-近邻算法选择约会对象

    任务目标:通过每年飞行里程数,玩视频游戏所耗时间,冰淇淋消耗数来确定约会对象是否是意中人

    任务实施:

    因为我们的数据是以文本形式存储的,所以需要將文本转换为numpy矩阵,以便于將其带入现有函数来分类。代码如下:

    现在这一文本文件已经转换为了所需要的数组形式,现在这个问题就已经转换为之前的分类问题了,但是在分类前还需要对其进行归一化处理,代码如下:

    现在,我们再將现有数据带入具体问题,以分类器的形式来实现这个问题,并集成为一个函数,代码如下:

    现在在terminal上再对文本数据处理一下,看看该算法,对于这个数据集效果如何:

    不难发现,其错误率只有5%,所以算法效果不错,故我们以此算法为基础,来实现对于约会对象满意度的预测模型,代码如下:

    现在我们在terminal上对数据进行处理,对应的交互代码如下:

    这一段代码首先重载了kNNdemo3这个模块,每一次更新代码后都需要重载模块,值得注意的是,原来书上写的reload(kNNdemo3),但是在python3里不能这么写,必须现载入imp模块,再reload。后面执行的就是预测模型,以预测是否合适。

    四.手写识别算法

    任务目标:通过训练模型,希望模型能准确识别0-9的数字图像

    任务实施:

    首先要对图像进行预处理,前面我们获取的均是向量,虽然图像本质上也是种向量,但这种向量并不是我们之前分类器所使用的向量,为了方便处理,这里我们將图像均依次转化为一维向量,代码如下:

    下面就是带入一个分类器,来实现手写图像识别,,在这里使用了listdir方法和skelearn库,以便于后面运算,这里需在文件里加上这两行代码:

    再写入手写图像识别函数:

    最后在terminal上运行这个函数,得到的结果如下:

    错误率只有1.34%,令人满意,所以我们可以认为这个算法满足我们的需要。

    注:本文参考资料:李航《统计学习方法》,Peter Harrington《机器学习实战》,手写识别系统sklearn代码源自Jack Cui,其主页:点击打开链接

    展开全文
  • 目录机器学习实战KNN算法(代码)详解KNN算法一般流程算法的一般操作创建数据集KNN算法代码详解代码测试运行实现: 机器学习实战KNN算法(代码)详解 KNN算法一般流程       &...

    机器学习实战之KNN算法(代码)详解

    KNN算法一般流程

           (1)收集数据:可以使用任何方法
           (2)准备数据:距离计算所需要的数值,最好是结构化数据格式
           (3)分析数据:可以使用任何方法
           (4)训练算法:此步骤不适合KNN
           (5)测试算法:计算错误率
           (6)使用算法:首先需要输入样本数据和结构化的输出结果,然后运行KNN判定输入数据分别属于哪个分类,最后应用对计算出的分类执行后续的处理。

    算法的一般操作

    对未知类别属性的数据集中的每个点一次执行以下操作:
           (1)计算已知类别数据集中的点与当前点之间的距离;
           (2)按照距离递增次序排序;
           (3)选取与当前点距离最小的k个点
           (4)确定前K个点所在的类别的出现频率
           (5)返回前K个点出现频率最高的类别作为当前点的预测分类

    创建数据集

    from numpy import *
    import operator
    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
    

    在这里插入图片描述
                                       带有四个数据点的简单例子.

    KNN算法

    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           
        sortedDisiIndicies = distances.argsort()
        
        #选择k个距离最小的点
        classCount = {}
        for i in range(k):
            voteIlabel = labels[sortedDisiIndicies[i]]
            classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
            
        #排序:将classCount字典分分解为元组列表,使用运算符模块的itemgetter方法,按照第二个元素的次序对元组进行排序
        sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse = True)
        
        return sortedClassCount[0][0]
    

    代码详解

     1、 diffMat = tile(inX,(dataSetSize,1))-dataSet 
    

    构造出元素为[inXx - Ax ,inXy - Ay]的数组
           tile(A, reps)函数:
           构造一个把A重复reps遍的数组

        Examples
        -------------------------------------------------------------
        >>> a = np.array([0, 1, 2])
        >>> np.tile(a, 2)
        array([0, 1, 2, 0, 1, 2])
        
        >>> np.tile(a, (2, 2))
        array([[0, 1, 2, 0, 1, 2],
               [0, 1, 2, 0, 1, 2]])
               
        >>> np.tile(a, (2, 1, 2))
        array([[[0, 1, 2, 0, 1, 2]],
               [[0, 1, 2, 0, 1, 2]]])
    
        >>> b = np.array([[1, 2], [3, 4]])
        >>> np.tile(b, 2)
        array([[1, 2, 1, 2],
               [3, 4, 3, 4]])
               
        >>> np.tile(b, (2, 1))
        array([[1, 2],
               [3, 4],
               [1, 2],
               [3, 4]])
    
        >>> c = np.array([1,2,3,4])
        >>> np.tile(c,(4,1))
        array([[1, 2, 3, 4],
               [1, 2, 3, 4],
               [1, 2, 3, 4],
               [1, 2, 3, 4]])
        -----------------------------------------------------------
    

     2、 sqDistances = sqDiffMat.sum(axis = 1) #计算每行的和
    

           sum函数:
           当axis=0,按列计算和;当axis=1,按行计算和

     3、 sortedDisiIndicies = distances.argsort()
    

           argsort函数:
           Returns the indices that would sort this array.(排好序后返回其索引,不改变原数组元素排列顺序)

     4、 classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1 #统计k个数据里每个标签的频率
    

           get函数:
           dict.get(key, default=None)
           参数
           key – 字典中要查找的键。
           default – 如果指定键的值不存在时,返回该默认值值。
           返回值
           返回指定键的值,如果值不在字典中返回默认值None


     5、 sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse = True)
    

           sorted函数:
           sorted()函数对所有可迭代的对象进行排序操作。
           sorted(iterable[,cmp[,key[,reverse]]])
           iterable是可迭代对象;
           cmp是比较函数。
           key为一个函数或者lambda函数。所以itemgetter可以用来当key的参数
           reverse为排序方向,reverse=True降序,reverse=False升序。

           itemgetter函数:

    >>>itemgetter(1)([3,4,5,2,7,8])  
    > 4
    
    >>>itemgetter(4)([3,4,5,2,7,8]) 
    > 7
    
    >>>itemgetter(1,3,5)([3,4,5,2,7,8])  
    >(4,2,8)
    

           operator.itemgetter函数
           operator模块提供的itemgetter函数用于获取对象的哪些维的数据,参数为一些序号。看下面的例子

    a = [1,2,3]
     
    >>> b=operator.itemgetter(1)      #定义函数b,获取对象的第1个域的值
    >>> b(a) 
    2
    
    >>> b=operator.itemgetter(1,0)  #定义函数b,获取对象的第1个域和第0个的值
    >>> b(a) 
    (2, 1)
    

           要注意,operator.itemgetter函数获取的不是值,而是定义了一个函数,通过该函数作用到对象上才能获取值。


    代码测试

    if __name__ == "__main__":
        group, labels=createDataset()
        print(classify0([0,0], group, labels, 3))
    
    

    运行实现:

    在这里插入图片描述

    展开全文
  • 机器学习实战 KNN实战

    2018-10-16 23:06:52
    KNN实战1、KNN算法的一般流程1、搜集数据:可以使用任何方法2、准备数据:距离计算所需要的数值,最好是结构化的数据格式3、分析数据:可以使用任何方法4、训练算法:此...学习《机器学习实战》 1、KNN算法的一般...


    学习《机器学习实战》

    1、KNN算法的一般流程

    1、搜集数据:可以使用任何方法

    2、准备数据:距离计算所需要的数值,最好是结构化的数据格式

    建立一个KNN.py,里面放置数据和标签。

    # _*_ encoding=utf8 _*_
    
    from numpy import *
    import operator
    
    
    def createDataSet():
        group = array([1.1,1.0],[1.0,1.0],[0,0],[0,0.1])
        labels = ['A','A','B','B']
        return group,labels
    
    

    3、分析数据:可以使用任何方法

    四个点很明显可以看见,分为两类,A标签有两个点,B标签有两个点。

    4、训练算法:此步骤不适用于KNN算法

    KNN的伪代码思想:
    对未知类别属性的数据集中的每个点依次执行以下操作:
    (1)、计算已知类别数据集中的点与当前点之间的操作;
    (2)、按照距离递增次序排序
    (3)、选取与当前点距离最小的k个点
    (4)、确定前k个点所在类别出现的概率
    (5)、返回前k个点出现概率最高的类别作为当前点的预测分类
    KNN的python代码

    def classify(inX,dataSet,labels,k):
        dataSetSize = dataSet.shape[0]
        print(dataSetSize) # 获取第一维的维度  4*2  也就是4
        # tile 重复inX维度(4,1) inX = [0,0]  ==>先横向复制4次,纵向复制1次,也就是本身 最后的维度(4,2)
        # 这儿求欧式距离,都是求到0 0 的距离 以下几行都是求欧式距离
        diffMat = tile(inX, (dataSetSize, 1)) - dataSet
        sqDiffMat = diffMat ** 2
        # 按列求和,也可按行求和axis=1
        sqDistances = sqDiffMat.sum(axis=1)
        print(sqDistances)
        distances = sqDistances ** 0.5
    
        print(distances)
        # 返回从小到大的数值的索引
        sortedDistIndicies = distances.argsort()
        print(sortedDistIndicies)
        classCount = {}
        for i in range(k):
            voteIlabel = labels[sortedDistIndicies[i]]
            # 统计离0 0 最近的范围的标签是什么,
            classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
        sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
        print(sortedClassCount[0][0]) # 输出预测属于哪一类
    

    5、测试算法:计算错误率

    检测分类的结果

    if __name__ == '__main__':
        group,labels = createDataSet()
        classify([0,0],group,labels,3)
    

    6、使用算法:首先需求输入样本数据和结构化的输出结果,然后运行KNN算法判定输入数据分别属于哪一个分类,最后应用对计算出的分类执行后续的处理。

    2、约会问题

    在线约会想找一个适合自己的对象,她把每一个约会对象划分为三类人。

    • 不喜欢的人
    • 魅力一般的人
    • 极具魅力的人

    根据哪些特征可以把一个人划分到其中一类呢,她是根据三个特点的分值占比,将一个人划分到某一类,这三个特点是:

    • 每年获得飞行常客里程数
    • 玩视频游戏所占时间百分比
    • 每周消费的冰淇淋公升数
      数据特征如下:
    40920 8.326976 0.953952 3
    14488 7.153469 1.673904 2
    26052 1.441871 0.805124 1
    75136 13.147394 0.428964 1
    38344 1.669788 0.134296 1
    72993 10.141740 1.032955 1
    35948 6.830792 1.213192 3
    42666 13.276369 0.543880 3
    

    首先让文件数据读入内存,训练数据和标记数据分开存储

    def file2matrix(filename):
        fr = open(filename)
        numberOfLines = len(fr.readlines())
        returnMat = zeros((numberOfLines,3))
        classLabelVector = []
        fr = codecs.open(filename,'r','utf-8')
        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
    

    查看一下内存中的训练数据和标签数据
    代码:

    if __name__ == '__main__':
        # group,labels = createDataSet()
        # classify([0,0],group,labels,3)
        datingDataMat,datingLabels = file2matrix('../data/datingTestSet2.txt')
        print(datingDataMat[:3])
        print(datingLabels[0:20])
    

    结果:

    [[4.092000e+04 8.326976e+00 9.539520e-01]
     [1.448800e+04 7.153469e+00 1.673904e+00]
     [2.605200e+04 1.441871e+00 8.051240e-01]]
    [3, 2, 1, 1, 1, 1, 3, 3, 1, 3, 1, 1, 2, 1, 1, 1, 1, 1, 2, 3]
    

    有了数据,有了代码,有了结果标签,就可以从训练数据抽取出一条数据,看看结果预测的对不对
    选取最后一条数据,数据如下,把他从训练数据文件中删除:

    43757	7.882601	1.332446	3
    

    找前3个点出现的概率,测试代码如下:

    if __name__ == '__main__':
        # group,labels = createDataSet()
        # classify([0,0],group,labels,3)
        datingDataMat,datingLabels = file2matrix('../data/datingTestSet2.txt')
        print(datingDataMat[:3])
        print(datingLabels[0:20])
        classify([43757,7.882601,1.332446], datingDataMat, datingLabels, 3)
    

    。。。预测出来是1,看来是拿到的特征不够,改一行代码试试,找与前100个点的距离

    classify([43757,7.882601,1.332446], datingDataMat, datingLabels, 3)
    

    nice,预测出来是3了。

    3、使用Matplotlib创建散点图

    还是使用刚刚从文件读取出来的数据,查看玩视频游戏消耗时间占比和每周消费冰淇淋的公升数这两个数值,(第一个值太大,不压缩的话其他特征就看不见了,所以不选第一列的值)
    代码:

    if __name__ == '__main__':
        datingDataMat,datingLabels = file2matrix('../data/datingTestSet2.txt')
        fig = plt.figure()
        ax = fig.add_subplot(111)
        ax.scatter(datingDataMat[:,1],datingDataMat[:,2])
        plt.show()
    

    结果图
    在这里插入图片描述
    横轴是玩视频游戏消耗时间占比,纵轴是每周消费冰淇淋的公升数
    由于颜色一样,这样的数据显示没什么太大的意义,现在加上标签分类,区分颜色查看这个点属于那一类。下图就是查看第二列和第三列数据,显示的属于哪一类(不喜欢、一般魅力、极具魅力)
    修改的代码:

    ax.scatter(datingDataMat[:,1],datingDataMat[:,2],
                   15.0*array(datingLabels),15.0*array(datingLabels))
    

    结果图:
    在这里插入图片描述

    4、归一化数值

    刚刚所说,第一列的数据范围远远大于第二列和第三列的数值范围,所以第一列带来的影响也远远大于其他两列,
    归一化就是将数据利用一定的比例压缩在0-1之间,这儿使用的方法如下
    newValue = (oldValue-min)/(max-min)
    也就是,(当前数据-该列最小数据)/(该列的最大数据-该列的最小数据)
    代码:

    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))
        return normDataSet, ranges, minVals
    

    好像给了测试数据,测试方法如下:

    def datingClassTest():
        hoRatio = 0.50      #hold out 10%
        datingDataMat,datingLabels = file2matrix('../data/datingTestSet2.txt')       
        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)
    

    运行测试代码:

    if __name__ == '__main__':
        datingClassTest()
    

    查看结果:

    ...
    the classifier came back with: 2, the real answer is: 2
    500
    the classifier came back with: 1, the real answer is: 1
    500
    the classifier came back with: 1, the real answer is: 1
    the total error rate is: 0.064128
    

    可以看见约会问题的分类错误率是6.4128%
    全部代码

    # _*_ encoding=utf8 _*_
    
    from numpy import *
    import operator
    import codecs
    import matplotlib
    import matplotlib.pyplot as plt
    
    
    
    def createDataSet():
        group = array([[1.1,1.0],[1.0,1.0],[0.0,0.0],[0.0,0.1]])
        labels = ['A','A','B','B']
        return group,labels
    
    def classify(inX,dataSet,labels,k):
        dataSetSize = dataSet.shape[0]
        print(dataSetSize) # 获取第一维的维度  4*2  也就是4
        # tile 重复inX维度(4,1) inX = [0,0]  ==>先横向复制4次,纵向复制1次,也就是本身 最后的维度(4,2)
        # 这儿求欧式距离,都是求到0 0 的距离 以下几行都是求欧式距离
        diffMat = tile(inX, (dataSetSize, 1)) - dataSet
        sqDiffMat = diffMat ** 2
        # 按列求和,也可按行求和axis=1
        sqDistances = sqDiffMat.sum(axis=1)
        # print(sqDistances)
        distances = sqDistances ** 0.5
    
        # print(distances)
        # 返回从小到大的数值的索引
        sortedDistIndicies = distances.argsort()
        # print(sortedDistIndicies)
        classCount = {}
        for i in range(k):
            voteIlabel = labels[sortedDistIndicies[i]]
            # 统计离0 0 最近的范围的标签是什么,
            classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
        sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
        # print(sortedClassCount[0][0]) # 输出预测属于哪一类
        return sortedClassCount[0][0]
    
    def file2matrix(filename):
        fr = open(filename)
        numberOfLines = len(fr.readlines())
        returnMat = zeros((numberOfLines,3))
        classLabelVector = []
        fr = codecs.open(filename,'r','utf-8')
        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))
        return normDataSet, ranges, minVals
    
    def datingClassTest():
        hoRatio = 0.50      #hold out 10%
        datingDataMat,datingLabels = file2matrix('../data/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 = classify(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)
    
    if __name__ == '__main__':
        # group,labels = createDataSet()
        # classify([0,0],group,labels,3)
    
        # datingDataMat,datingLabels = file2matrix('../data/datingTestSet2.txt')
        # print(datingDataMat[:3])
        # print(datingLabels[0:20])
        # classify([43757,7.882601,1.332446], datingDataMat, datingLabels, 100)
    
        # fig = plt.figure()
        # ax = fig.add_subplot(111)
        # ax.scatter(datingDataMat[:,1],datingDataMat[:,2],
        #            15.0*array(datingLabels),15.0*array(datingLabels))
        # plt.show()
        datingClassTest()
    

    5、手写体识别数据分类

    类似之前的约会问题,构造输入和标签(10分类)就好。
    构造输入方法也就是读取文件的方法:
    查看手写体的文件,如下这样一个矩阵刻画出来的阿拉伯数字。

    00000000000001111000000000000000
    00000000000011111110000000000000
    00000000001111111111000000000000
    00000001111111111111100000000000
    00000001111111011111100000000000
    00000011111110000011110000000000
    00000011111110000000111000000000
    00000011111110000000111100000000
    00000011111110000000011100000000
    00000011111110000000011100000000
    00000011111100000000011110000000
    00000011111100000000001110000000
    00000011111100000000001110000000
    00000001111110000000000111000000
    00000001111110000000000111000000
    00000001111110000000000111000000
    00000001111110000000000111000000
    00000011111110000000001111000000
    00000011110110000000001111000000
    00000011110000000000011110000000
    00000001111000000000001111000000
    00000001111000000000011111000000
    00000001111000000000111110000000
    00000001111000000001111100000000
    00000000111000000111111000000000
    00000000111100011111110000000000
    00000000111111111111110000000000
    00000000011111111111110000000000
    00000000011111111111100000000000
    00000000001111111110000000000000
    00000000000111110000000000000000
    00000000000011000000000000000000
    
    # 手写体识别是32*32的
    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 = os.listdir('../data/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('../data/trainingDigits/%s' % fileNameStr)
        testFileList = os.listdir('../data/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('../data/testDigits/%s' % fileNameStr)
            classifierResult = classify(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)))
    

    结果:

    the total number of errors is: 11
    
    the total error rate is: 0.011628
    

    错误率很低,非常不错了

    展开全文
  • #-*-coding:utf-8-*- from numpy import * import operator 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'] ...
  • Python数据分析与机器学习实战教程,该课程精心挑选真实的数据集为案例,通过python数据科学库numpy,pandas,matplot结合机器学习库scikit-learn完成一些列的机器学习案例。课程以实战为基础,所有课时都结合代码...
  • 最近在学习机器学习,觉得机器学习特别有趣,现在将KNN算法做一个总结。 一、简介  KNN是一种有监督的分类算法,思想很简单,就是通过测量预测数据与训练数据之间的距离,选取前K个距离最短(或距离在K以内)的...
  • 一、KNN分类思想二、例子一1.情景如下图,这里共有四个点,两个B类,两个A类。[1,1.1]-A 、[1,1]-A 、[0,0]-B 、[0,0.1]-B。现在我们输入点[0,0],要求KNN分类器帮我们分类,判断点[0,0]是A类还是B类。算法中设置K=3...
  • 本文直接给出sklearn里面KNN 算法的用法。具体实现过程如下: import numpy as np from sklearn import datasets import operator from sklearn import neighbors import sklearn.model_selection as ms ...
  • 假设有一个样本数据集合,并且这个集合里边的的每个数据都存在分类用的标签(也就是监督学习)。输入没有标签的新数据,将新数据和原有数据进行对应的特征进行比较,然后算法提取样本集中特征最相似的数据的分类标签...
  • from numpy import * import operator def classify0(inX, dataSet, labels, k): dataSetSize = dataSet.shape[0] print tile(inX, (dataSetSize, 1)) # generate array([[0,0],[0,0],[0,0],[0,0]]) ...
  • 机器学习实战 KNN代码

    2017-10-11 12:00:28
    机器学习实战(一) KNN 本人,研一机器学习和数据挖掘的课比较少,加上对机器学习比较感兴趣,本科也接触了一些知识和项目,发现很多算法都是直接调用库,实现很少实操,特此把每个算法的步骤都复现一遍,算是加强...
  • 机器学习实战kNN

    2018-03-24 16:31:55
    概述k-近邻算法采用测量不同特征值之间的距离方法进行分类。优点:精度高、对异常值不敏感、无数据输入假定 缺点:计算复杂度高、空间复杂度高 适用数据范围:数值型和标称型工作原理存在一个一个数据集合,也称训练...
  • 使用python3.0版本修改了书本身使用的python2版本代码
  • 机器学习实战 from numpy import * import operator def createDatSet(): group=array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]]) labels=['A','A','B','B'] return group,labels def classfy0(inX...
  • 机器学习和python编程都刚开始学,从看代码开始,实践出真知 # -*- coding: utf-8 -*- from numpy import * import operator def classify0(inX, dataSet, labels, k):  dataSetSize = dataSet.shape[0] #object....
  • [机器学习实战]kNN

    2017-12-26 09:35:51
    加权kNN 高斯函数 交叉验证 原理kNN(k近邻算法)的基本思想就是选择距离待分类点最近的K个点,统计这K个点中出现的分类的概率, 出现概率最高的分类即为待分类点的分类源码from numpy import * import operatordef ...
  • 选择了《机器学习实战》这本书配合来实现。这本书使用 Python 实现,很适合我。真本书实现的第一个算法就是大名鼎鼎的 K-近邻算法。KNN 算法的基本原理就是在一堆样本中找出与测试样本距离(欧氏距离/非欧距离)最近...
  • ok,今天花了一天时间看了小人书(机器学习实战),并且撸到了KNN算法,并完成了一个KNN算法的应用 真的!!!小人书是本特别不错的适合入门ML的书!!!!! 没有繁杂的数学推导过程,先给出概念和实战应用,等对ML有个大致了解...
1 2 3 4 5 ... 20
收藏数 4,824
精华内容 1,929