使用k-近邻算法改进约会网站的配对效果。

在上一文中:初识K-近邻算法。已经介绍了kNN(k-近邻算法)的工作原理和代码实现,这次将讲述《机器学习实战》中的一个案例,使用kNN算法来改进越会网站的配对效果。


案例的描述及kNN流程。

海伦一直使用在线约会网站寻找适合自己的约会对象。尽管约会网站会推荐不同的人选,但是她没有从中找到喜欢的人。经过一番总结,她发现曾交往过三中类型的人:

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

尽管发现了上述规律,但海伦依然无法将约会网站推荐的匹配对象归入恰当的分类。她觉得可以在周一到周五约会那些魅力一般的人,而周末更喜欢与那些极具魅力的人为伴。海伦希望我们的分类软件可以更好地帮助她将匹配对象划分到确切的分类中。此外海伦还收集了一些约会网站未曾记录的数据信息,她认为这些数据更有助于匹配对象的归类。

海伦的情况就是这样,想让我们利用她给的数据,然后帮助她分析一下对某人的感觉会是什么。虽然不明白海伦为什么会和不喜欢的人交往,但是确实发生了。

问题出现了就需要解决,使用kNN的一般流程上一文也说明了,在本次的案例中kNN的流程如下:

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

那么流程已经说完了,下面就是分步骤完成本次程序。


准备数据:从文本文件中解析数据。

海伦收集约会数据已经有了一段时间,她把这些数据存放在文本文件datingTestSet.txt中,每个样本数据占据一行,总共有1000行。海伦的样本主要包含以下3种特征:

  • 每年获得的飞行客场里程数。
  • 玩视频游戏所耗时间百分比。
  • 每周消费的冰淇淋公斤数。

数据集长这个样子:

这里写图片描述

数据一共有四列,第一列是每年获得的飞行常客里程数,第二列是玩视频游戏所耗时间百分比,第三列是每周消费的冰淇淋公斤数,第四列是对这个人的喜欢程度:largeDoses(极具魅力)、smallDoses(魅力一般)、didntLike(不喜欢)。

看到这些数据集,依据到kNN的工作原理,我们就知道了我们需要计算新数据和这些样本数据的距离,然后得到距离最近的数据的分类标签。

也就是我们最后需要输入:
特征1:每年获得的飞行客场里程数;
特征2:玩视频游戏所耗时间百分比。
特征3:每周消费的冰淇淋公斤数。

然后kNN算法会计算出一个分类,这个分类共有三种情况:largeDoses(极具魅力)、smallDoses(魅力一般)、didntLike(不喜欢)。

我们在将上述特征数据输入到分类器(也就是上一文中创建的classify0方法)之前,必须将待处理数据的格式改变为分类器可以接受的格式,也就是一个numpy.ndarray类型的数组。所以我们创建一个file2matrix的函数,用来处理输入格式的问题,该函数的输入为文本文件名称,输出为训练样本矩阵和分类标签向量,分类向量的话我们将不喜欢的人使用1代替,魅力一般的人用2代替,极具魅力的人用3代替。

file2matrix函数:

import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from KNN import kNN


def file2matrix(filename):
    """
    将文件转换为特征矩阵和对应的标签
    :param filename:
    :return:
    """
    # 打开文件
    fr = open(filename)
    # 按照行进行读取
    arrayOLines = fr.readlines()
    # 计算出总行数,为1000行
    numbserOfLines = len(arrayOLines)
    # 创建一个1000行的0矩阵
    returnMat = np.zeros((numbserOfLines, 3))
    classLabelVector = []
    index = 0

    for line in arrayOLines:
        # 去除前后空格
        line = line.strip()
        # 按照\t将每行内容分割开来
        listFormLine = line.split('\t')
        # 将得到前三项的内容填充到对应的行数矩阵上
        returnMat[index, :] = listFormLine[0:3]
        # 按照喜欢程度进行添加标签
        # classLabelVector.append(int(listFormLine[-1]))
        if listFormLine[-1] == 'largeDoses':
            classLabelVector.append(3)
        if listFormLine[-1] == 'smallDoses':
            classLabelVector.append(2)
        if listFormLine[-1] == 'didntLike':
            classLabelVector.append(1)
        # 行数索引加一
        index += 1

    return returnMat, classLabelVector


if __name__ == '__main__':
    # 拿到数据
    datingDataMat, datingLabels = file2matrix('datingTestSet.txt')
    print(datingDataMat)
    print(datingLabels)

输出内容就是文本中的数据和分类标签:

这里写图片描述


分析数据:使用Matplotlib创建散点图。

Matplotlib是一个非常好用的可视化绘图库,我们将创建两个散点图:

  • 第一个散点图:x轴代表:每年获得飞行客场里程数。y轴代表:玩视频游戏所消耗时间百分比。
  • 第二个散点图:x轴代表:玩视频游戏所消耗时间百分比。y轴代表:每周消耗冰淇淋公斤数。

分别使用两种不同的作图思路进行绘画。蓝色的小点代表不喜欢,黄色的中等点代表魅力一般,红色的大点代表极具魅力。

将用来画图的dataShow函数添加到我们的代码中:

import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from KNN import kNN


def file2matrix(filename):
    """
    将文件转换为特征矩阵和对应的标签
    :param filename:
    :return:
    """
    # 打开文件
    fr = open(filename)
    # 按照行进行读取
    arrayOLines = fr.readlines()
    # 计算出总行数,为1000行
    numbserOfLines = len(arrayOLines)
    # 创建一个1000行的0矩阵
    returnMat = np.zeros((numbserOfLines, 3))
    classLabelVector = []
    index = 0

    for line in arrayOLines:
        # 去除前后空格
        line = line.strip()
        # 按照\t将每行内容分割开来
        listFormLine = line.split('\t')
        # 将得到前三项的内容填充到对应的行数矩阵上
        returnMat[index, :] = listFormLine[0:3]
        # 按照喜欢程度进行添加标签
        # classLabelVector.append(int(listFormLine[-1]))
        if listFormLine[-1] == 'largeDoses':
            classLabelVector.append(3)
        if listFormLine[-1] == 'smallDoses':
            classLabelVector.append(2)
        if listFormLine[-1] == 'didntLike':
            classLabelVector.append(1)
        # 行数索引加一
        index += 1

    return returnMat, classLabelVector


def dataShow(datingDataMat, datingLabels):
    """
    将矩阵可视化,画出每年获得的飞行常客里程数和玩视频游戏所消耗时间百分比的图示
    :param datingDataMat:矩阵
    :param datingLabels:矩阵标签
    :return:
    """

    # 将对应的标签转换为颜色
    LabelsColors = []
    for i in datingLabels:
        if i == 1:
            LabelsColors.append("b")  # 黑色不喜欢
        if i == 2:
            LabelsColors.append("y")  # 黄色一般喜欢
        if i == 3:
            LabelsColors.append("r")  # 红色很喜欢

    # 能够显示中文
    matplotlib.rcParams['font.sans-serif'] = ['SimHei']
    matplotlib.rcParams['font.serif'] = ['SimHei']

    # matplotlib的图像都位于Figure对象中,设置大小和分辨率
    fig = plt.figure(figsize=(12, 7), dpi=80)

    # 第一个图,用来显示每年获得的飞行常客里程数和玩视频游戏所消耗时间百分比
    ax1 = fig.add_subplot(1, 2, 1)
    # 设置x标签
    ax1.set_xlabel('每年获得飞行常客里程数')
    # 设置y标签
    ax1.set_ylabel('玩视频游戏所消耗时间百分比')
    # 添加数据,第一列就是飞行里程数,第二列是玩视频游戏的时间
    ax1.scatter(x=datingDataMat[:, 0], y=datingDataMat[:, 1], color=LabelsColors,
                s=(15.0 * np.array(datingLabels), 15.0 * np.array(datingLabels)), marker='o')

    didnt_Like = ax1.scatter([], [], c='b', s=15)
    smallDoses = ax1.scatter([], [], c='y', s=30)
    largeDoses = ax1.scatter([], [], c=
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值