zoukankan      html  css  js  c++  java
  • 机器学习实战学习笔记(二)-KNN算法(2)-KNN算法改进约会网站的配对效果

    机器学习实战学习笔记(二)-KNN算法(2)-KNN算法改进约会网站的配对效果

    情景概要

    某个妹子交往过三种类型的人:

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

    这个妹子想要知道自己到底喜欢哪一类男人,于是提供了她收集的约会数据(1000行,吐槽一波,手动狗头),并希望能创建一种分类机制来帮她完成这件事情。

    数据表格如下:

    实际数据集是这样的:

    datingTestSet.txt

    datingTestSet2.txt

    导入数据

    # 判断分类
    def isWhichClass(className):
        if className=='didntLike':
            return 1
        elif className=='smallDoses':
            return 2
        elif className=='largeDoses':
            return 3
    
    #加载数据
    
    def file2matrix(filename):
        fr=open(filename)
        arrayOLines=fr.readlines()
        numbersOfLines=len(arrayOLines)#获取一共有多少行
        returnMat=np.zeros((numbersOfLines,3))#创建n行3列的全零矩阵
        classLabelVector=[]#标签向量
        index=0
        for line in arrayOLines:
            line=line.strip()
            listFormLine=line.split('	')
            returnMat[index,:]=listFormLine[0:3]
            classLabelVector.append(isWhichClass(listFormLine[-1]))
            index+=1
        return returnMat,classLabelVector
    

    数据可视化

    #绘图
    def makeGraph():
        returnMat,classLabelVector=file2matrix('KNNdatingTestSet.txt')
        fig=plt.figure()
        ax=fig.add_subplot(111)
        x1=[x[1] for i,x in enumerate(returnMat) if classLabelVector[i]==1]
        y1=[x[2] for i,x in enumerate(returnMat) if classLabelVector[i]==1]
        x2=[x[1] for i,x in enumerate(returnMat) if classLabelVector[i]==2]
        y2=[x[2] for i,x in enumerate(returnMat) if classLabelVector[i]==2]
        x3=[x[1] for i,x in enumerate(returnMat) if classLabelVector[i]==3]
        y3=[x[2] for i,x in enumerate(returnMat) if classLabelVector[i]==3]
        type1=plt.scatter(x1,y1,c="red",cmap='brg',alpha=0.2, marker='8', linewidth=0)
        type2=plt.scatter(x2,y2,c="green",cmap='brg',alpha=0.2, marker='8', linewidth=0)
        type3=plt.scatter(x3,y3,c="blue",cmap='brg', alpha=0.2, marker='8', linewidth=0)
        ax.legend([type1, type2, type3], ["Did Not Like", "Liked in Small Doses", "Liked in Large Doses"], loc=2)
        mpl.rcParams['font.sans-serif']=['SimHei'] #指定默认字体 SimHei为黑体
        mpl.rcParams['axes.unicode_minus']=False #用来正常显示负号
        plt.xlabel('玩游戏时间所占百分比', fontsize=14)
        plt.ylabel('每周消耗的冰激凌的公斤数', fontsize=14)
        plt.show()
    

    归一化数据

    原理:

    为什么要归一化?

    数字差值最大的属性对计算结果的影响最大,也就是说,但这三种特征是同等重要的,因此要归一化

    归一化方法

    在处理这种不同取值范围的特征值时,我们通常采用的方法是将数值归一化,如将取值范围
    处理为0到1或者-1到1之间。下面的公式可以将任意取值范围的特征值转化为0到1区间内的值:

    newvalue=(o1dValue -min) / (max- min)
    

    其中min和max分别是数据集中的最小特征值和最大特征值。

    # 自动归一化
    def autoNorm(dataSet):
        minVal=dataSet.min(0)
        maxVal=dataSet.max(0)
        ranges=maxVal-minVal
        normDataSet=np.zeros(np.shape(dataSet))
        m=dataSet.shape[0]
        normDataSet=dataSet-np.tile(minVal,(m,1))
        normDataSet=normDataSet/np.tile(ranges,(m,1))
        return normDataSet,ranges,minVal
    

    测试分类效果

    #测试数据
    def datingAllClassTest():
        hoRatio = 0.10      #测试集数量比例
        datingDataMat,datingLabels = file2matrix("KNNdatingTestSet.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=knnClassify(normMat[i,:],normMat[numTestVecs:m,:],datingLabels,3)
            print("预测的结果是%d 真正的答案是%d"%(classifierResult,datingLabels[i]))
            if classifierResult!=datingLabels[i]:
                errorCount+=1
        print("总的正确率是 %f"%(errorCount/float(numTestVecs)))
        print("错误数量是 %d"%errorCount)
    

    实际应用作为分类器

    #使用数据判断妹子是否喜欢你
    def datingClassTest():
        resultList = ['妹子不喜欢你', '妹子有点喜欢你', '妹子特别喜欢你']
        ffMiles=float(input("你一年坐的飞机飞多少里:"))
        iceCream=float(input("你一年吃多少冰激凌?"))
        gameTime=float(input("你一年打多少小时的游戏?"))
        inArr=np.array([ffMiles,gameTime,iceCream])
        resDataMatrix,labels=file2matrix("KNNdatingTestSet.txt")
        normData,ranges,minVal=autoNorm(resDataMatrix)
        classResult=knnClassify((inArr-minVal)/ranges,normData,labels,3)
        print("估计是%s"%(resultList[classResult-1]))
    

    源代码

    import numpy as np 
    import matplotlib.pyplot as plt 
    import matplotlib as mpl
    import operator as op
    # 判断分类
    def isWhichClass(className):
        if className=='didntLike':
            return 1
        elif className=='smallDoses':
            return 2
        elif className=='largeDoses':
            return 3
    
    #加载数据
    
    def file2matrix(filename):
        fr=open(filename)
        arrayOLines=fr.readlines()
        numbersOfLines=len(arrayOLines)#获取一共有多少行
        returnMat=np.zeros((numbersOfLines,3))#创建n行3列的全零矩阵
        classLabelVector=[]#标签向量
        index=0
        for line in arrayOLines:
            line=line.strip()
            listFormLine=line.split('	')
            returnMat[index,:]=listFormLine[0:3]
            classLabelVector.append(isWhichClass(listFormLine[-1]))
            index+=1
        return returnMat,classLabelVector
    
    
    def file3matrix(filename):
        fr=open(filename)
        arrayOLines=fr.readlines()
        numbersOfLines=len(arrayOLines)#获取一共有多少行
        returnMat=np.zeros((numbersOfLines,3))#创建n行3列的全零矩阵
        classLabelVector=[]#标签向量
        index=0
        for line in arrayOLines:
            line=line.strip()
            listFormLine=line.split('	')
            returnMat[index,:]=listFormLine[0:3]
            classLabelVector.append(int(listFormLine[-1]))
            index+=1
        return returnMat,classLabelVector
    
    #绘图
    def makeGraph():
        returnMat,classLabelVector=file2matrix('KNNdatingTestSet.txt')
        fig=plt.figure()
        ax=fig.add_subplot(111)
        x1=[x[1] for i,x in enumerate(returnMat) if classLabelVector[i]==1]
        y1=[x[2] for i,x in enumerate(returnMat) if classLabelVector[i]==1]
        x2=[x[1] for i,x in enumerate(returnMat) if classLabelVector[i]==2]
        y2=[x[2] for i,x in enumerate(returnMat) if classLabelVector[i]==2]
        x3=[x[1] for i,x in enumerate(returnMat) if classLabelVector[i]==3]
        y3=[x[2] for i,x in enumerate(returnMat) if classLabelVector[i]==3]
        type1=plt.scatter(x1,y1,c="red",cmap='brg',alpha=0.2, marker='8', linewidth=0)
        type2=plt.scatter(x2,y2,c="green",cmap='brg',alpha=0.2, marker='8', linewidth=0)
        type3=plt.scatter(x3,y3,c="blue",cmap='brg', alpha=0.2, marker='8', linewidth=0)
        ax.legend([type1, type2, type3], ["Did Not Like", "Liked in Small Doses", "Liked in Large Doses"], loc=2)
        mpl.rcParams['font.sans-serif']=['SimHei'] #指定默认字体 SimHei为黑体
        mpl.rcParams['axes.unicode_minus']=False #用来正常显示负号
        plt.xlabel('玩游戏时间所占百分比', fontsize=14)
        plt.ylabel('每周消耗的冰激凌的公斤数', fontsize=14)
        plt.show()
    
    #K近邻算法
    #inX是输入的数据
    #dataSet是训练的数据
    #labels是标签,类别
    #k是周围邻居的数量
    #返回预测的类别
    def knnClassify(inX,dataSet,labels,k):
        #计算欧式距离
        dataSetSize=dataSet.shape[0]#shape是(4,2),要获取点的数量显然是shape[0]
        diffMat=np.tile(inX,(dataSetSize,1))-dataSet
        '''
        np.tile(inX,(dataSetSize,1))=[[0,0],[0,0],[0,0],[0,0]]
        dataSet=[[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]]
        np.tile-dataSet=[[-1.0,-1.1],[-1.0,-1.0],[0,0],[0,-0.1]]
        即([x1-x0,y1-y0],[x2-x0,y2-x0],[x3-x0,y3-y0],[x4-x0,y4-y0])
        '''
        sqdiffMat=diffMat**2
        #([(x1-x0)**2,(y1-y0)**2],[(x2-x0)**2,(y2-x0)**2],[(x3-x0)**2,(y3-y0)**2],[(x4-x0)**2,(y4-y0)**2])
        sqDistances=sqdiffMat.sum(axis=1)
        #([(x1-x0)**2+y1-y0)**2],[(x2-x0)**2+(y2-x0)**2],[(x3-x0)**2+(y3-y0)**2],[(x4-x0)**2+(y4-y0)**2])
        # print(sqDistances)
        distances=sqDistances**0.5
        #([(x1-x0)**2+(y1-y0)**2]**(0.5),[(x2-x0)**2+(y2-x0)**2]**(0.5),[(x3-x0)**2+(y3-y0)**2]**(0.5),[(x4-x0)**2+(y4-y0)**2])**(0.5)
        sortedDistIndicies=distances.argsort()#按照数值大小对下标排序,[2 3 1 0]
        classCount={}
        #选择距离最小的k个点
        for i in range(k):
            votIlabel=labels[sortedDistIndicies[i]]#获取最近的K个邻居的距离,对应的目标值
            # print(votIlabel)
            classCount[votIlabel]=classCount.get(votIlabel,0)+1#get(key,default)当key不存在时候默认值是default
        sortedClassCount = sorted(classCount.items(), key=op.itemgetter(1), reverse=True)
        # [('B', 2), ('A', 1)]
        return sortedClassCount[0][0]#返回与其最近的k个邻居中,出现最多的次数
    
    # 自动归一化
    def autoNorm(dataSet):
        minVal=dataSet.min(0)
        maxVal=dataSet.max(0)
        ranges=maxVal-minVal
        normDataSet=np.zeros(np.shape(dataSet))
        m=dataSet.shape[0]
        normDataSet=dataSet-np.tile(minVal,(m,1))
        normDataSet=normDataSet/np.tile(ranges,(m,1))
        return normDataSet,ranges,minVal
    
    
    #测试数据
    def datingAllClassTest():
        hoRatio = 0.10      #hold out 10%
        datingDataMat,datingLabels = file2matrix("KNNdatingTestSet.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=knnClassify(normMat[i,:],normMat[numTestVecs:m,:],datingLabels,3)
            print("预测的结果是%d 真正的答案是%d"%(classifierResult,datingLabels[i]))
            if classifierResult!=datingLabels[i]:
                errorCount+=1
        print("总的正确率是 %f"%(errorCount/float(numTestVecs)))
        print("错误数量是 %d"%errorCount)
    
    #使用数据判断妹子是否喜欢你
    def datingClassTest():
        resultList = ['妹子不喜欢你', '妹子有点喜欢你', '妹子特别喜欢你']
        ffMiles=float(input("你一年坐的飞机飞多少里:"))
        iceCream=float(input("你一年吃多少冰激凌?"))
        gameTime=float(input("你一年打多少小时的游戏?"))
        inArr=np.array([ffMiles,gameTime,iceCream])
        resDataMatrix,labels=file2matrix("KNNdatingTestSet.txt")
        normData,ranges,minVal=autoNorm(resDataMatrix)
        classResult=knnClassify((inArr-minVal)/ranges,normData,labels,3)
        print("估计是%s"%(resultList[classResult-1]))
       
    
    if __name__ == "__main__":
        datingClassTest()
        
    
    

    目录结构

    数据集

    https://github.com/pbharrin/machinelearninginaction

    参考书籍

    《机器学习实战》-彼得·哈灵顿

  • 相关阅读:
    MySQL 存储过程实例
    [MySQL优化] -- 如何了解SQL的执行频率
    [MySQL优化] -- 如何定位效率较低的SQL
    [MySQL优化] -- 如何查找SQL效率地下的原因
    [MySQL优化] -- 如何使用SQL Profiler 性能分析器
    2020.10.09软件更新公告
    2020.04.12软件更新公告
    2020.04.11软件更新公告
    2020.02.21软件更新公告
    程序员调用MODI的正确姿势
  • 原文地址:https://www.cnblogs.com/mengxiaoleng/p/12229899.html
Copyright © 2011-2022 走看看