zoukankan      html  css  js  c++  java
  • 我的机器学习之旅(五):K近邻算法(KNN)

    原理:

    存在一个样本数据集合,也称作为训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一个数据与所属分类的对应关系。输入没有标签的新数据后,将新的数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本最相似数据(最近邻)的分类标签。一般来说,我们只选择样本数据集中前k个最相似的数据,这就是k-近邻算法中k的出处,通常k是不大于20的整数。最后,选择k个最相似数据中出现次数最多的分类,作为新数据的分类。

    KNN的一般流程:

    (1)收集数据集,特征和类别标签

    (2)准备数据,数据的归一化,去除坏数据等

    (3)构造输入数据集,运用KNN判定数据的分类类别

    (4)计算错误率,获得比较合适的K值

    (5)输入需要预测分类的数据集

    乳腺癌判断实例:

    (1)获取数据:

    import pandas as pd
    import numpy as np
    
    name_c=['sample code number','clump thickness', 'uniformity of cell size', 'uniformity of cell shape','marginal adhesion','single epithelial cell',
           'bare nuclei','bland chromatin','normal nucleoli','mitoses','class'
           ]
    data=pd.read_csv('http://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data',names=name_c)
    data=data.replace(to_replace='?',value=np.nan)
    data=data.dropna(how='any')
    
    l=[] 
    ###第7列数据是字符形式,这里为了简便就不要那一列了
    for i in name_c[1:10]: 
        l.append(data[i ].values) if i!=name_c[6] else 0

    (2)数据处理:

    #数据归一化函数
    def
    autoNorm(dataSet): #获得数据的最大最小值 print ("**********************") minVals = dataSet.min(0) maxVals = dataSet.max(0) print ("minValues:",minVals) print ("maxValuse:",maxVals) #计算最大最小值的差 ranges = maxVals - minVals #shape(dataSet)返回dataSet的矩阵行列数 normDataSet=np.zeros(np.shape(dataSet)) #返回dataSet的行数 m = dataSet.shape[0] #原始值减去最小值 normDataSet=dataSet-np.tile(minVals,(m,1)) #除以最大值和最小值的差,得到的归一化的数据 normDataSet = normDataSet/np.tile(ranges,(m,1)) print (normDataSet) return normDataSet,ranges,minVals


    (3)kNN算法,计算欧式距离,选择距离最小的前k个点,并返回分类结果。

    def classify(intX,dataSet,labels,k):
        '''
        KNN算法
        '''
        #numpy中shape[0]返回数组的行数,shape[1]返回列数
        dataSetSize = dataSet.shape[0]
        #将intX在横向重复dataSetSize次,纵向重复1次
        #例如intX=([1,2])--->([[1,2],[1,2],[1,2],[1,2]])便于后面计算
        diffMat = np.tile(intX,(dataSetSize,1))-dataSet
        #二维特征相减后乘方
        sqdifMax = diffMat**2
        #计算距离
        seqDistances = sqdifMax.sum(axis=1)
        distances = seqDistances**0.5
        #print ("distances:",distances)
        #返回distance中元素从小到大排序后的索引
        sortDistance = distances.argsort()
        #print ("sortDistance:",sortDistance)
        classCount = {}
        for i in range(k):
            #取出前k个元素的类别
            voteLabel = labels[sortDistance[i]]
            classCount[voteLabel] = classCount.get(voteLabel,0)+1
        #dict.get(key,default=None),字典的get()方法,返回指定键的值,如果值不在字典中返回默认值。
        #计算类别次数
    
        #key=operator.itemgetter(1)根据字典的值进行排序
        #key=operator.itemgetter(0)根据字典的键进行排序
        #reverse降序排序字典
        sortedClassCount = sorted(classCount.items(),key = operator.itemgetter(1),reverse = True)
        #print(intX)
        print ("sortedClassCount:",sortedClassCount)
        return sortedClassCount[0][0]

    (4)数据的分类测试  

    def datingClassTest(datingDataMat,datingLabels,k=10):
        #取所有数据的10%
        hoRatio = 0.1
        #数据归一化,返回归一化后的矩阵,数据范围,数据最小值
        normMat,ranges,minVals = autoNorm(datingDataMat)
        #获得nornMat的行数
        m = normMat.shape[0]
        #百分之十的测试数据的个数
        numTestVecs = int(m*hoRatio)
        #分类错误计数
        errorCount = 0.0
    
        for i in range(numTestVecs):
            #前numTestVecs个数据作为测试集,后m-numTestVecs个数据作为训练集
            classifierResult = classify(normMat[i,:],normMat[numTestVecs:m,:],
                datingLabels[numTestVecs:m],k)
            print ("分类结果:%d 	真实类别:%d"%(classifierResult,datingLabels[i]))
            if classifierResult != datingLabels[i]:
                errorCount += 1.0
        print ("错误率:%f"%(errorCount/float(numTestVecs)*100))
    datingClassTest(np.array(l).T,data[name_c[10]].values,10)

     缺点:如果数据大,需要耗费大量内存和运算时间。无法给出分类的典型特征。

  • 相关阅读:
    Go
    Go
    Go
    Go
    Go
    Go
    爬虫常用相关库
    Go
    python基础第7天(day19)
    python基础第五天(day17)元组,集合,字符串操作 字符编码:
  • 原文地址:https://www.cnblogs.com/allenren/p/8657379.html
Copyright © 2011-2022 走看看