美文网首页机器学习实战
2-6节 k-近邻算法|优化约会网站的配对效果项目汇总|机器学习

2-6节 k-近邻算法|优化约会网站的配对效果项目汇总|机器学习

作者: 努力奋斗的durian | 来源:发表于2018-08-10 16:09 被阅读44次

文章原创,最近更新:2018-08-10

本章节的主要内容是:
重点介绍项目案例1: 优化约会网站的配对效果中的完整代码

1.KNN项目案例介绍:

项目案例1:

优化约会网站的配对效果

项目概述:

1)海伦使用约会网站寻找约会对象。经过一段时间之后,她发现曾交往过三种类型的人: 不喜欢的人、魅力一般的人、 极具魅力的人。
2)她希望: 1. 工作日与魅力一般的人约会 2. 周末与极具魅力的人约会 3. 不喜欢的人则直接排除掉。现在她收集到了一些约会网站未曾记录的数据信息,这更有助于匹配对象的归类。

开发流程:
  • 收集数据:提供文本文件
  • 准备数据:使用 Python 解析文本文件
  • 分析数据:使用 Matplotlib 画二维散点图
  • 训练算法:此步骤不适用于 k-近邻算法
  • 测试算法:使用海伦提供的部分数据作为测试样本。
    测试样本和非测试样本的区别在于:测试样本是已经完成分类的数据,如果预测分类与实际类别不同,则标记为一个错误。
  • 使用算法:产生简单的命令行程序,然后海伦可以输入一些特征数据以判断对方是否为自己喜欢的类型。
数据集介绍

海伦把这些约会对象的数据存放在文本文件 datingTestSet2.txt (数据来源于《机器学习实战》第二章 k邻近算法)中,总共有 1000 行。

本文使用的数据主要包含以下三种特征:每年获得的飞行常客里程数,玩视频游戏所耗时间百分比,每周消费的冰淇淋公升数。其中分类结果作为文件的第四列,并且只有3、2、1三种分类值。datingTestSet2.csv文件格式如下所示:

飞行里程数 游戏耗时百分比 冰淇淋公升数 分类结果
40920 8.326976 0.953952 3
14488 7.153469 1.673904 2
26052 1.441871 0.805124 1

数据在datingTestSet2.txt文件中的格式如下所示:


2.优化约会网站的配对效果项目

第二章是描述K近邻算法的,算法本质就是寻找距离最近的点,这个距离可以是欧式距离,也可以是其他,这本书采用的就是欧式距离了。K近邻算法主要是用来分类的,比如我新输入一个数据,要判断他属于哪个类别,用这个算法就很合适了,简单实用。

2.1准备工作

这里第一步,其实就是为了检验我们后续编写的的K近邻算法有没有效果。

首先我们创建一个名为kNN.py的文件,然后我们就创建一个函数,这个函数返回一个矩阵和标签列表,以方便我们后续对K近邻算法进行检验。

具体内容,可参见:2-1节 k-近邻算法-KNN算法|优化约会网站的配对效果项目|机器学习实战-学习笔记

import numpy as np
import operator

def createDataSet():
    """
    创建数据集和标签

     调用方式
     import kNN
     group, labels = kNN.createDataSet()
    """
    group = np.array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
    labels=["A","A","B","B"]
    return group,labels

2.2kNN算法

目的就是为了找最近的距离,采用的是欧氏距离.
具体内容,可参见:2-1节 k-近邻算法-KNN算法|优化约会网站的配对效果项目|机器学习实战-学习笔记

def classify0(inX,dataSet,labels,k):
    """
    inX:用于分类的输入向量
    dataSet:输入的训练样本集
    lables:标签向量
    k:表示用于选择最近邻居的数目
    
    预测数据所在分类可在输入下列命令
    kNN.classify0([0,0], group, labels, 3)
    """
    # array的shape函数返回指定维度的大小,如dataset为n*m的矩阵,
    # 则dataset.shape[0]返回n,dataset.shape[1]返回m,dataset.shape返回n,m
    dataSetSize = dataSet.shape[0]
    # tile函数简单的理解,它的功能是重复某个数组。比如tile(A,n),功能是将数组A重复n次,构成一个新的数组
    # 所以此处tile(inX,(dataSetSize,1))的作用是将inX重复复制dataSetSize次,以便与训练样本集的样本个数一致
    # 减去dataSet就是求出其差值,所以diffMat为一个差值矩阵
    diffmat=np.tile(inX,(dataSetSize,1))-dataSet
    #距离度量,度量公式为欧氏距离
    sqdiffmat=diffmat**2
    # 将矩阵的每一行相加,axis用于控制是行相加还是列相加
    sqdistances=sqdiffmat.sum(axis=1)
    #开方
    distances=sqdistances**0.5
    # 根据距离排序从小到大的排序,返回对应的索引位置
    sortedDistIndicies=distances.argsort()
    # 选择距离最小的k个点
    classcount={}
   
    for i in range(k):
        # 找到该样本标签的类型
        voteIlabel=labels[sortedDistIndicies[i]]
        # 字典的get方法,list.get(k,d) 其中 get相当于一条if...else...语句,参数k在字典中,字典将返回list[k];如果参数k不在字典中则返回参数d
        classcount[voteIlabel]=classcount.get(voteIlabel,0)+1
        # 字典的 items() 方法,以列表返回可遍历的(键,值)元组数组。
        # sorted 中的第2个参数 key=operator.itemgetter(1) 这个参数的意思是先比较第几个元素
        sortedClasscount = sorted(classcount.items(),key=operator.itemgetter(1),reverse=True)
        # 返回最符合的标签
        return sortedClasscount[0][0]

2.3准备数据。我们将数据转化为numpy解析程序

具体内容,可参见:2-2节 k-近邻算法-使用 Python 解析文本文件|优化约会网站的配对效果项目|机器学习实战-学习笔记

def file2matrix(filename):
    """
    导入训练数据
    filename: 数据文件路径
    return: 数据矩阵returnMat和对应的类别classLabelVector
    """
    # 打开文件
    fr=open(filename)
    # 读取每一行的信息
    array0Lines=fr.readlines()
    # 获得文件中的数据行的行数
    numberofLines=len(array0Lines)
    # 生成numberofLines行3列的零矩阵,这3列都是用来存放特征信息
    returnMat=np.zeros((numberofLines,3))
    # 存放类别是列表
    classLabelVector=[]
    index=0
    for line in array0Lines:
        # 去掉回车制表符,生成新的字符串
        line=line.strip()
        # 通过split以\t切割字符串,返回元素列表
        listFromLine=line.split('\t')
        # 选取前三个数据的特征值放进矩阵
        returnMat[index,:]=listFromLine[0:3]
        # 将listFromLine列表中的最后一列元素存储到classLabelVector
        # 这列的数据是类别数据
        classLabelVector.append(int(listFromLine[-1]))
        # 更新index
        index +=1
    #返回特征矩阵returnMat和类别矩阵classLabelVector
    return returnMat,classLabelVector

2.4使用Matplotlib创建散点图

具体内容,可参见:2-3节 k-近邻算法-使用 Matplotlib 画二维散点图|优化约会网站的配对效果项目|机器学习实战-学习笔记

简单版本

import numpy as np
import matplotlib
import matplotlib.pyplot as plt

fig=plt.figure()
ax=fig.add_subplot(1,1,1)
datingDataMat,datingLabels=file2matrix('datingTestSet2.txt')
ax.scatter(datingDataMat[:,1],datingDataMat[:,2],15.0*np.array(datingLabels),15.0*np.array(datingLabels))
plt.show()

详细版本
为了得到更好的效果,采用datingDataMat矩阵的属性列1和2展示数据,并以红色的'*'表示类标签1、蓝色的'o'表示表示类标签2、绿色的'+'表示类标签3

import kNN
import operator
import matplotlib
import matplotlib.pyplot  as plt
import numpy as np
from matplotlib.font_manager import FontProperties
font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)
group,labels=kNN.createDataSet()
fig=plt.figure()
ax=fig.add_subplot(1,1,1)
datingDataMat,datingLabels=file2matrix('datingTestSet2.txt')
#ax.scatter(datingDataMat[:,1],datingDataMat[:,2],15.0*np.array(datingLabels),15.0*np.array(datingLabels))
datingLabels = np.array(datingLabels)
idx_1 = np.where(datingLabels==1)
p1 = ax.scatter(datingDataMat[idx_1,0],datingDataMat[idx_1,1],marker = '*',color = 'r',label='1',s=10)
idx_2 = np.where(datingLabels==2)
p2 = ax.scatter(datingDataMat[idx_2,0],datingDataMat[idx_2,1],marker = 'o',color ='g',label='2',s=20)
idx_3 = np.where(datingLabels==3)
p3 = ax.scatter(datingDataMat[idx_3,0],datingDataMat[idx_3,1],marker = '+',color ='b',label='3',s=30)
plt.xlabel("每年获取的飞行里程数",fontproperties=font)
plt.ylabel("玩视频游戏所消耗的事件百分比",fontproperties=font)
ax.legend((p1,p2,p3),("不喜欢","魅力一般","极具魅力"),loc=2,prop=font)
plt.show()

2.5归一化处理

归一化是为了让数据都处于[0,1]之间
具体内容,可参见:2-4节 k-近邻算法-归一化处理|优化约会网站的配对效果项目|机器学习实战-学习笔记

def autoNorm(dataSet):
    """
    归一化特征值,消除属性之间量级不同导致的影响
    dataSet: 数据集
    return: 归一化后的数据集normDataSet,ranges和minVals即归一化的数据集,最小值与极差
    归一化公式:
        Y = (X-Xmin)/(Xmax-Xmin)
        其中的 min 和 max 分别是数据集中的最小特征值和最大特征值。该函数可以自动将数字特征值转化为0到1的区间。
    """
    # 找出样本集中每列属性的最小值
    minVals= dataSet.min(0)
    # 找出样本集中每列属性的最大值
    maxVals= dataSet.max(0)
    # 每列最大最小值之间的极差
    ranges=maxVals-minVals
    # 创建与样本集一样大小的零矩阵
    normDataSet=np.zeros(np.shape(dataSet))
    # 获得样本集的行的维度
    m=dataSet.shape[0]
    # 样本集中的元素与最小值组成的矩阵
    normDataSet=dataSet-np.tile(minVals,(m,1))
    # 将最小值之差除以范围组成矩阵
    normDataSet=normDataSet/np.tile(ranges,(m,1))
    return normDataSet, ranges, minVals

2.6测试算法

具体内容,可参见:2-5节 k-近邻算法-测试算法&使用算法|优化约会网站的配对效果项目|机器学习实战-学习笔记

def datingClassTest():
    """
    对约会网站的测试方法
    return:错误数
    """
    # 设置测试数据的的一个比例(训练数据集比例=1-hoRatio)
    hoRatio= 0.1 # 测试范围,一部分测试一部分作为样本
    # 从文件中加载数据,获得特征和标签分开保存
    datingDataMat,datingLabels =file2matrix('datingTestSet2.txt')
    # 特征归一化,返回归一化特征,归一化范围集每个特征最小值
    normMat,ranges,minVals=autoNorm(datingDataMat)
    # m表示数据的行数,即矩阵的第一维
    m =normMat.shape[0]
    # 设置测试的样本数量,numTestVecs:m表示训练样本的数量
    numTestVecs=int(m*hoRatio)
    print("numTestVecs=",numTestVecs)
    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)

2.7使用算法:构建完整的约会网站预测函数

具体内容,可参见:2-5节 k-近邻算法-测试算法&使用算法|优化约会网站的配对效果项目|机器学习实战-学习笔记

def classifyPerson():
    resultList=['not at all', 'in small doses', 'in large doses']
    # 原文中用的raw_input,在python3中统统使用input
    percentTats = float(input("Percentage of time spent playing vedio game?"))
    ffMiles = float(input("frequent flier miles earned per years?"))
    iceCream = float(input("liters of ice cream consumed per years?"))
    datingDataMat,datingLabels=file2matrix("datingTestSet2.txt")
    normMat,ranges,minVals =autoNorm(datingDataMat)
    
    inArr=np.array([ffMiles, percentTats, iceCream])
    # classifyerResut-1是因为分类结果是123,而resultlist中排序是012
    classifierResult=classify0((inArr-minVals)/ranges,normMat,datingLabels,3)
    print("You will probably like this person: ",resultList[classifierResult-1])

相关文章

网友评论

    本文标题:2-6节 k-近邻算法|优化约会网站的配对效果项目汇总|机器学习

    本文链接:https://www.haomeiwen.com/subject/eqxlbftx.html