《机器学习实战》读书笔记(二)K-近邻算法(中)(使用K-近邻算法改进约会网站的配对效果(上))

前言:本文中所有的资源我均已上传到CSDN的资源库中(文章中会附上链接),有需要的小伙伴可以帮帮忙,下载一下,毕竟写文章不易,我可以保证,用我所上传的文件在我的电脑绝对能跑通!有不懂的小伙伴可以私聊我哦,基本上每天在线。

本篇文章中所有的资料均放在下载链接中:https://download.csdn.net/download/qq_38172282/11232025

2.2实例:使用K-近邻算法改进约会网站的配对效果

示例背景

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

      (1)不喜欢的人;

      (2)魅力一般的人;

      (3)极具魅力的人;

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

从文本文件中解析数据

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

        1.每年获得的飞行常客里程数;

        2.玩视频游戏所耗时间百分比;

        3.每周消费的冰淇淋公升数;

       在将上述特征数据输入到分类器之前,必须将待处理数据的格式改变为分类器可以接受的格式。在KNN.py中创建名为file2matrix的函数,以此来处理输入格式问题。该函数的输入为文本文件名字符串,输出为训练样本矩阵和类标签向量。

本篇文章中所有的资料均放在下载链接中:https://download.csdn.net/download/qq_38172282/11232025

注意:使用文件时,在VScode软件中打开文件夹,否则不能运行,这是因为文件夹下的文件,软件是没有没有办法读取到的!

import numpy as np

def file2matrix(filename):
    love_dictionary = {'largeDoses':3, 'smallDoses':2, 'didntLike':1}    # 三个类别
    # 打开文件
    fr = open(filename) 
    # 逐行打开,readlines()方法用于读取所有行(直到结束符 EOF)并返回列表,该列表可以由 Python 的 for... in ... 结构进行处理。
    arrayOLines = fr.readlines() 
    #得到文件的行数
    numberOfLines = len(arrayOLines) 
    #返回numpy矩阵,numberOfLines行,3列的零元素矩阵//初始化特征矩阵
    returnMat = np.zeros((numberOfLines, 3))   
    #返回分类的标签向量//初始化输出标签向量
    classLabelVector = []                     
    #行的索引值
    index = 0
    for line in arrayOLines:
        # 删去字符串首尾空格
        line = line.strip()  
        # 按'\t'对字符串进行分割,listFromLine 是列表
        listFromLine = line.split('\t')   
        #将数据前三列提取出来,存放到returnMat的numpy矩阵中,也就是不含标签变量,只有特征变量。
        # listFromLine的0,1,2元素是特征,赋值给returnMat的当前行
        #一行一行的存储
        returnMat[index, :] = listFromLine[0:3]    
        # 如果listFromLine最后一个元素是数字
        if(listFromLine[-1].isdigit()): 
            # 直接赋值给classLabelVector
            classLabelVector.append(int(listFromLine[-1]))    
        else:   
            # 如果listFromLine最后一个元素不是数字,而是字符串。根据字典love_dictionary转化为数字
            # Python 字典(Dictionary) get() 函数返回指定键的值
            classLabelVector.append(love_dictionary.get(listFromLine[-1]))    
        index += 1
    return returnMat, classLabelVector    # 返回的类别标签classLabelVector是1,2,3

## 书上的原句子为datingDataMat,datingLabels = file2matrix('datingTestSet2.txt') 
## 这里和之所以没有用书上的,是因为程序2.2清单中的返回值为returnMat, classLabelVector,为了直观且方便!  
returnMat,classLabelVector = file2matrix('datingTestSet2.txt')      
print(returnMat)
# print(classLabelVector)
print(classLabelVector[0:20])

上面程序,可以正常运行,运行结果如下图所示,现在我们已经从文本文件中导入了数据,并将其格式化为我们想要的数据。


 

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

还是先放代码,书中图2-3+图示例2-4,所示的代码如下(注:本篇文章所用全部代码均为未删减,可直接使用(前提是正确使用)),代码在文件中KNN_test2.py下。

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

## 书中清单2-1:k-近邻算法
def classify0(inX, dataSet, labels, k):
    """
    函数作用:使用k-近邻算法将每组数据划分到某个类中
    :param inX:用于分类的输入数据(测试集)
    :param dataSet:输入的训练样本集
    :param labels:训练样本标签
    :param k:用于选择最近邻居的数目,即kNN算法参数,选择距离最小的k个点
    :return:返回分类结果
    """
    # dataSet.shape[0]返回训练样本集的行数
    dataSet_size = dataSet.shape[0]
    # 在列方向上重复inX,1次,行方向上重复inX,dataSet_size次
    diff_mat = np.tile(inX, (dataSet_size, 1)) - dataSet
    # diff_mat:输入样本与每个训练样本的差值,然后对其每个x和y的差值进行平方运算
    sq_diff_mat = diff_mat ** 2
    # 按行进行累加,axis=1表示按行。
    sq_distances = sq_diff_mat.sum(axis=1)
    # 开方运算,求出距离
    distances = sq_distances ** 0.5
    # 返回distances中元素从小到大排序后的索引值
    sorted_dist_indices = distances.argsort()
    # 定一个字典:统计类别次数
    class_count = {}

    for i in range(k):
        # 取出前k个元素的类别
        vote_index_label = labels[sorted_dist_indices[i]]
        # 统计类别次数
        class_count[vote_index_label] = class_count.get(vote_index_label, 0) + 1
        # 把分类结果进行降序排序,然后返回得票数最多的分类结果
        sorted_class_count = sorted(class_count.items(), key=operator.itemgetter(1), reverse=True)
        return sorted_class_count[0][0]

## 书中清单2-2:将文本记录转化为Numpy的解析程序
def file2matrix(filename):
    """
    函数作用:从文件中读入训练数据,并存储为矩阵
    :param filename:文件名字符串
    :return:训练样本矩阵和类标签向量
    """
    # 打开文件
    fr = open(filename)
    # 读取文件内容
    array_lines = fr.readlines()
    # 得到文件行数
    number_0f_lines = len(array_lines)
    # 返回解析后的数据
    return_mat = np.zeros((number_0f_lines,3))
    # 定义类标签向量
    class_label_vector = []
    # 行索引值
    index = 0
    for line in array_lines:
        # 去掉回车符号
        line = line.strip()
        # 用\t分割每行数据
        list_from_line = line.split('\t')
        # 选取前三个元素,将他们存储在特征矩阵中
        # x[n,:]表示在n个数组(维)中取全部数据,直观来说,x[n,:]就是取第n集合的所有数据,
        return_mat[index,:] = list_from_line[0:3]
        # 把该样本对应的标签放至标签向量,顺序与样本集对应
        class_label_vector.append(int(list_from_line[-1]))
        index += 1
    return return_mat, class_label_vector

# 图示例2-3+图示例2-4
if __name__ == '__main__':
    dating_data_mat, dating_labels = file2matrix('datingTestSet2.txt')
    fig = plt.figure()
    ax = fig.add_subplot(111)
    # 使用矩阵中第二、三列数据,非彩色
    # ax.scatter(dating_data_mat[:, 1], dating_data_mat[:, 2])
    # 彩色
    ax.scatter(dating_data_mat[:, 1], dating_data_mat[:, 2], 15.0 * np.array(dating_labels),
                15.0 * np.array(dating_labels))
    # 保证图片中输出的文字为中文
    plt.rcParams['font.sans-serif']=['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    # 输出横纵坐标上的文字
    plt.xlabel("玩游戏所耗时间百分比")
    plt.ylabel("每周消耗的冰淇淋公升数")
    plt.show()

上面的代码运行出来的结果如下图所示

 

若想运行出书中P24,图2-5的效果仅需将上面的if __name__ == '__main__':以下的代码换成下述代码即可

代码在文件中KNN_test2.py下。

# 图示例2-5
if __name__ == '__main__':    
    dating_data_mat, dating_labels = file2matrix('datingTestSet2.txt')
    fig = plt.figure()
    ax = fig.add_subplot(111)
    dating_labels = np.array(dating_labels)
    idx_1 = np.where(dating_labels == 1)
    p1 = ax.scatter(dating_data_mat[idx_1, 0], dating_data_mat[idx_1, 1], marker='o', color = 'r', label = '不喜欢', s = 30)
    idx_2 = np.where(dating_labels == 2)
    p2 = ax.scatter(dating_data_mat[idx_2, 0], dating_data_mat[idx_2, 1], marker='o', color = 'g', label = '魅力一般', s = 45)
    idx_3 = np.where(dating_labels == 3)
    p3 = ax.scatter(dating_data_mat[idx_3, 0], dating_data_mat[idx_3, 1], marker='o', color = 'b', label = '极具魅力', s = 60)
    # 保证图片中输出的文字为中文
    plt.rcParams['font.sans-serif']=['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
    plt.legend(loc = 'upper left')
    # 输出横纵坐标上的文字
    plt.xlabel("玩游戏所耗时间百分比")
    plt.ylabel("每周消耗的冰淇淋公升数")
    plt.show()

代码实现的效果图如下图所示:

 

由于作者错误的估计了这篇示例所占的篇幅,故将此篇分为两篇来书写,《《机器学习实战》读书笔记(二)K-近邻算法(中)(使用K-近邻算法改进约会网站的配对效果())》为该篇文章的下半部分,很抱歉,另外所需要下载的资源不变,仍为同一个文件!

本篇文章中所有的资料均放在下载链接中:https://download.csdn.net/download/qq_38172282/11232025

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值