• 机器学习与数据挖掘—K邻近算法(KNN)


    KNN:分类算法

    目标:

    对未知类别的样本进行分类预测

    步骤:

    1.对于某个未知类别样本,根据距离度量计算每个已知类别样本与其距离。
    2.选出K个与该未知类别样本距离最小的已知类别的样本。
    3.在K个已知类别样本里得到频数最多的类别,该类别就是未知类别样本的预测。

    KNN算法:

    
    # 寻找K值 1~60 打印误差最小的K值和对应的误差个数及误差率
    from numpy import *
    
    import operator  # 引入运算符模块,K邻近算法会使用到其中的函数
    
    
    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 classifyO(inX, dataSet, labels, k):  # KNN算法
        # 用于分类的输入向量是inX,
        # 输入的训练样本集为dataSet,标签向量为labe1s,最后的参数k表示用于选择最近邻居的数目,
        # 其中标签向量的元素数目和矩阵dataset的行数相同。
    
        dataSetSize = dataSet.shape[0]  # shape[0]就是读取矩阵第一维度的长度。
        diffMat = tile(inX, (dataSetSize, 1)) - dataSet
        #根据公式可推测出计算差值
        # 把inx行列重复copy(dataSetSize,1)次。
        # inX是个向量,而dataset是个矩阵,两者之间要进行相减的运算,需要把这个向量也补成一个和dataset有相同行数列数的矩阵,
        # tile()的第二个参数,也就是(datasetsize,1),这个参数的意思就是把inX补成有datasetsize行数的矩阵。
        # 然后和dataset相减就是根据矩阵的减法进行的。因此diffMat是一个差值矩阵。
        sqDiffMat = diffMat ** 2  # 欧氏距离计算公式
        sqDistances = sqDiffMat.sum(axis=1)  # axis这个参数,它决定对矩阵求和时候的顺序,axis=0是按照行求和,axis=1是按照列进行求和。
        distances = sqDistances ** 0.5  # 0.5次方即开根号
        sortedDisIndicies = distances.argsort()  # 就是把向量中每个元素进行排序,而它的结果是元素的索引(原来的下标)形成的向量。
        classCount = {}  # 生成字典,对classCount元素赋值,其实是个计数器
        # 选择距离待分类点最小的k个点
        for i in range(k):  # 遍历k,寻找该样本标签的类型
            voteIlabel = labels[sortedDisIndicies[i]]
            classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
        # python3字典的 items() 方法,以列表的形式返回可遍历的(键,值)元组数组。
        sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
        # 内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作与sort方法不一样。
        # reverse -- 排序规则,reverse = True 降序 , reverse = False 升序(默认)。
        # sorted函数返回类型为list
        return sortedClassCount[0][0]  # 返回前k个点出现频率最高的类别作为当前点的预测分类。即最符合的标签
    
    # 文件导入
    
    def file2matrix(filename):
        fr = open(filename)
        # 得到文件行数
        arrayOLines = fr.readlines()
        # 创建返回的NumPy矩阵
        numberOfLines = len(arrayOLines)
        returnMat = zeros((numberOfLines, 3))
        # 解析文件数据到列表
        classLabelVector = []
        index = 0
        for line in arrayOLines:
            line = line.strip()
            listFromLine = line.split('	')
            returnMat[index, :] = listFromLine[0:3]
            classLabelVector.append(int(listFromLine[-1]))
            index += 1
        return returnMat, classLabelVector
    
    #散点图代码块 (已注释需要运行出图片解注释即可)
    
    #from numpy import array
    #import matplotlib
    #import matplotlib.pyplot as plt
    #fig = plt.figure()
    #ax = fig.add_subplot(111)
    #datingDataMat,datingLabels = file2matrix('F:python项目KNNdatingTestSet2.txt')
    #ax.scatter(datingDataMat[:,1],datingDataMat[:,2],15.0*array(datingLabels),15.0*array(datingLabels))
    #plt.show()
    
    #归一化特征值
    def autoNorm(dataSet):
        minVals = dataSet.min(0)
        maxVals = dataSet.max(0)
        ranges = maxVals - minVals
        #将每列的最小值放在变量minvals中,将最大值放在变量maxVals中,
        # 其中dataset.min(0)中的参数0使得函数可以从列中选取最小值,而不是选取当前行的最小值。
        # 然后,函数计算可能的取值范围,并创建新的返回矩阵。
        normDataSet = zeros(shape(dataSet))
        m = dataSet.shape[0]
        normDataSet = dataSet - tile(minVals, (m,1))#特征在短阵有1000×3个值,而minvals与raange的值都为1×3。因此利用tile()
        #函数将变量内容复制成输入矩阵同样大小的矩阵
        normDataSet = normDataSet/tile(ranges, (m,1)) #矩阵除法
        return normDataSet, ranges, minVals
    
    
    
    #自动化调试模块代码
    
    
    def Autodebug(k):
        minCount = 20 #假如其中有20个误差,结果当然没有这么多,设置这么大也没关系,反正minCount会被覆盖掉
        for k in range(1,60):
            datingClassTest(k)
            #print("the total error rate is : ", datingClassTest(k)[1]) #该条注释用来验证结果
           #print("the total error count is : ", datingClassTest(k)[0]) #该条注释用来验证结果
            if(datingClassTest(k)[0]<minCount):
                                                 #误差最小一定误差数最少,误差数最少,误差率一定最小
                minCount=datingClassTest(k)[0]
    
        print("The minErroK's minErroCount= ",minCount)
        print("The minErroK's minErroRate=",minCount/100)
        for k in range(1,60):
            datingClassTest(k)
            if datingClassTest(k)[0]==minCount:
                print("The nice K= ",datingClassTest(k)[2])
    
    
    
    
    #分类器
    def datingClassTest(k):
        hoRatio=0.1
        datingDataMat,datingLabels=file2matrix('F:python项目KNNdatingTestSet2.txt')
        normMat,minVals,ranges=autoNorm(datingDataMat)
        m=normMat.shape[0]
        errorCount=0.0
        numTestVecs=int(m*hoRatio)
        for i in range(numTestVecs):
            classifierResult=classifyO(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],k) #//K取3时
            if (classifierResult!=datingLabels[i]):
                errorCount+=1.0
                x=errorCount/float(numTestVecs)
        return (errorCount,x,k) #稍作修改,方便Autodebug()函数调用,自动化测试,返回误差个数和误差率即可
    
    
    
    
    
    
    Autodebug(1) #直接Run即可
    
    
    #如果k值选择较大的话,距离较远的训练样本也能够对实例预测结果产生影响。
    # 这时候,模型相对比较鲁棒,不会因为个别噪声点对最终预测结果产生影响。
    # 但是缺点也十分明显:算法的近邻误差会偏大,距离较远的点(与预测实例不相似)也会同样对预测结果产生影响,
    # 使得预测结果产生较大偏差,此时模型容易发生欠拟合。
    #因此,在实际工程实践中,我们一般采用交叉验证的方式选取k值。
    # 通过以上分析可知,一般k值选得比较小,我们会在较小范围内选取k值。
    # 同时把测试集上准确率最高的那个确定为最终的算法超参数k。
    
    #虽然K值4与7都满足最小误差率,但k值4作为超参数更好
    
  • 相关阅读:
    JMeter中的HTTPS套接字错误
    使用JMETER进行REST API测试(分步指南)
    JMeter BeanShell示例
    未能载入软件包“WebDriverAgentRunner”,因为它已损坏或丢失必要的资源。
    ERROR: Could not connect to lockdownd, error code -19 -20
    (转)Selenium-11: Execute JavaScript with JavascriptExecutor
    在服务器上使用 gradle 打包 android 源码
    poi+properties文件实现多环境测试数据一键切换
    cocos2D-X 常用功能封装
    MD5 AND JSON AND XML
  • 原文地址:https://www.cnblogs.com/AmosAlbert/p/12832189.html
Copyright © 2020-2023  润新知