zoukankan      html  css  js  c++  java
  • 机器学习 k-近邻算法

    1、使用python导入数据

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

    kNN分类算法:

    from numpy import *
    import operator
    def classify0(inX,dataSet,labels,k):
        dataSetSize=dataSet.shape[0]    #shape[0]表示dataSet的行数
        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]
    distances是1*4的矩阵,分别表示待分类的点与所有已知点的距离;
    sortedDistIndicies是distances从小到大的索引值;
    voteIlabel相当于临时变量,用来取得标签值;
    classCount[voteIlabel]=classCount.get(voteIlabel,0)+1    如果在字典classCount中找到key=voteIlabel的value,就加1,找不到的话classCount.get(voteIlabel,0)返回0然后加1
    sortedClassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)  先把字典classCount变成列表,再按照第二维降序排列,返回的仍是列表

    执行算法:

    import kNN
    from classify_kNN import *
    g,l=kNN.createDataSet()
    result=classify0([0,0],g,l,3)
    print(result)

    输出:

    B


    items():将字典中的项按照列表返回,无序:

    get():返回字典对应key的value值,不存在key时返回第二个参数:

    dic={'a':1,'b':2,'c':3}
    print(dic.items())
    print(dic.get('c','no'))
    输出:
    dict_items([('b', 2), ('c', 3), ('a', 1)])
    3
    

    shape:返回矩阵的维数;

    from numpy import *
    c=array([[1,1],[2,3,],[5,6]])
    print(c)
    print(c.shape)
    print(c.shape[0])
    print(c.shape[1])
    输出:
    [[1 1]
     [2 3]
     [5 6]]
    (3, 2)
    3
    2
    

     operator.itemgetter():返回对象特定维的数据,结合sorted()方法使用:

    import operator
    students=[['刚田武',20,'gangtw'],['朱二娃',25,'zhuerw'],['咪咪two',30,'miomitwo']]
    print(sorted(students,key=operator.itemgetter(1),reverse=True))
    输出:
    [['咪咪two', 30, 'miomitwo'], ['朱二娃', 25, 'zhuerw'], ['刚田武', 20, 'gangtw']]
    

    argsort():返回数组值从小到大的索引值


    归一化数值:在计算欧氏距离的过程中,数值较大的属性对结果的贡献大,如果认为不同属性权重应该相同的话,就需要将数值归一化处理。

    from numpy import *
    def autoNorm(dataset):
        minVals=dataset.min(0)  #取每列的最小值,返回数组
        print(minVals)
        maxVals=dataset.max(0)
        print(maxVals)
        ranges=maxVals-minVals  #ranges是每列的最大值与最小值之差组成的数组
        print(ranges)
        normDataset=zeros(shape(dataset))
        print(normDataset)
        m=dataset.shape[0]  #取dataset的行数
        normDataset=dataset-tile(minVals,(m,1))
        print(normDataset)
        normDataset=normDataset/tile(ranges,(m,1))
        print(ranges)
        return normDataset
    

     minVals=dataset.min(0)    #取数据集每列的最小值,返回数组

    from numpy import *
    dataset=array(([6,5],
                 [3,1000],
                 [10,300]))
    print(dataset.min())    #返回所有元素中的最小值
    print(dataset.min(0))   #返回每列的最小值组成的数组
    print(dataset.min(1))   #返回每行的最小值组成的数组
    输出:
    3
    [3 5]
    [ 5  3 10]
    

     m=dataset.shape[0] #取dataset的行数

    from numpy import *
    dataset=array(([6,5],
                 [3,1000],
                 [10,300]))
    print(dataset.shape)    #返回数据集的“形状”,行数和列数
    print(dataset.shape[0])     #返回行数
    print(dataset.shape[1])     #返回列数
    输出:
    (3, 2)
    3
    2
    

    测试分类器

    def datingClassTest():
        hoRatio=0.1
        datingDataMat,datingLabels=file2matrix('datingTestSet2.txt')
        normMat,ranges,minVals=autoNorm(datingDataMat)
        m=normMat.shape[0]
        numTestVecs=int(m*hoRatio)
        errorCount=0
        for i in range(numTestVecs):
            classifyerResult=classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
            print('classify result is %s ,the real answer is %s'%(classifyerResult,datingLabels[i]))
            if classifyerResult!=datingLabels[i]:
                errorCount+=1
        print('the total error rate is %f'%(errorCount/float(numTestVecs)))
    

    hoRatio=0.1  测试数据占数据集的10%


    使用:输入各参数,输出分类结果:

    def classifyPerson():
        resultList=['not at all','in small doses','in largr doses']
        timeOnGames=float(input('请输入游戏时间百分比:'))
        flyMiles=float(input('请输入每年飞行里程数:'))
        iceCream=float(input('请输入每周消耗的冰淇淋升数:'))
        datingDataMat,datingLabels=file2matrix('datingTestSet2.txt')
        normMat,ranges,minVals=autoNorm(datingDataMat)
        person2test=array([flyMiles,timeOnGames,iceCream])
        classifierResult=classify0((person2test-minVals)/ranges,normMat,datingLabels,5)
        print('you may like thie one:',resultList[classifierResult-1])
    

     通过调节k值可以调整分类器的正确率。


    使用k近邻算法识别手写数字

    def handwritingClassTest():
        hwLabels=[]
        trainingFileList=listdir('digits/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('digits/trainingDigits/%s'%fileNameStr)
        testFileList=listdir('digits/testDigits')
        errorCount=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('分类结果:%s,实际结果:%s'%(classifierResult,classNumStr))
            if(classifierResult!=classNumStr):
                errorCount+=1
        print('分类错误总计:',errorCount)
        print('分类错误率:',errorCount/float(mTest))
    

    注释:

    trainingMat用来存储数据集,每个待测记录都要计算与此数据集之间的距离

    hwLabels用来存储trainingMat对应的标签

    fileNameStr存储文件名

    fileStr存储不含后缀的文件名

    classNumStr存储每条记录实际标签

    vectorUnderTest表示待分类记录

    计算分类错误率时,使用float()将int型数据变成浮点型

  • 相关阅读:
    POJ 2411 状态压缩递,覆盖方案数
    POJ 2774 最长公共子串
    POJ 1743 不可重叠的最长重复子串
    POJ 3294 出现在至少K个字符串中的子串
    POJ 3261 出现至少K次的可重叠最长子串
    POJ 1741/1987 树的点分治
    HDU1556 Color the ball
    解决linux系统时间不对的问题
    CentOS 6.9使用Setup配置网络(解决dhcp模式插入网线不自动获取IP的问题)
    Linux网络配置(setup)
  • 原文地址:https://www.cnblogs.com/zhhy236400/p/9826347.html
Copyright © 2011-2022 走看看