机器学习实战笔记——利用KNN算法改进约会网站的配对效果

一、案例背景

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

(1)不喜欢的人;

(2)魅力一般的人;

(3)极具魅力的人;

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

二、案例分析

(1)收集数据:提供文本文件;

(2)准备数据:使用Python解析文本文件;

(3)分析数据:使用Matplotlib画二维扩散图;

(4)训练算法:此步骤不适用于K-近邻算法;

(5)测试算法:使用海伦提供的部分数据作为测试样本,

测试样本和非测试样本的区别在于:测试样本是已经完成分类的数据,如果预测分类与实际类别不同,则标记为一个错误。

(6)使用算法:产生简单的命令行程序,然后海伦可以输入一些特征数据以判断对方是否为自己喜欢的类型。

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

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

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

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

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

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

将下面的代码增加到kNN.py中:

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

首先我们使用Matplotlib制作原始数据的散点图,在Python命令行环境中,输入下列命令:

#!/usr/bin/python278
# _*_ coding: utf-8 _*_

import kNN
reload(kNN)
datingDataMat,datingLabels=kNN.file2matrix('datingTestSet2.txt')
import matplotlib
import matplotlib.pyplot as plt
zhfont = matplotlib.font_manager.FontProperties(fname='C:\Windows\Fonts\ukai.ttc')
fig=plt.figure()
ax=fig.add_subplot(111)
from numpy import *
ax.scatter(datingDataMat[:,1],datingDataMat[:,2])
plt.xlabel(u'玩游戏所耗时间百分比', fontproperties=zhfont)
plt.ylabel(u'每周消费的冰淇淋公升数', fontproperties=zhfont)
plt.show()

上图是没有样本标签的约会数据散点图,难以辨识图中的点究竟属于哪个样本分类,我们可以利用Matplotlib库提供的scatter函数来用彩色标记散点图上的点。重新输入上面的代码,调用scatter函数:

#!/usr/bin/python278
# _*_ coding: utf-8 _*_

import kNN
reload(kNN)
datingDataMat,datingLabels=kNN.file2matrix('datingTestSet2.txt')
import matplotlib
import matplotlib.pyplot as plt
zhfont = matplotlib.font_manager.FontProperties(fname='C:\Windows\Fonts\ukai.ttc')
fig=plt.figure()
ax=fig.add_subplot(111)
from numpy import *
ax.scatter(datingDataMat[:,1],datingDataMat[:,2],15.0*array(datingLabels),15.0*array(datingLabels))
plt.xlabel(u'玩游戏所耗时间百分比', fontproperties=zhfont)
plt.ylabel(u'每周消费的冰淇淋公升数', fontproperties=zhfont)
plt.show()

上图是带有样本分类标签的约会数据散点图,虽然能够比较容易地区分数据点从属类别,但依然很难根据这张图得出结论信息。

上图使用了datingDataMat矩阵属性列2和列3展示数据,虽然也可以区别,但下图采用列1和列2的属性值却可以得到更好的效果:

#!/usr/bin/env python
# _*_ coding: utf-8 _*_
import kNN
reload(kNN)
import matplotlib
import matplotlib.pyplot as plt
matrix, labels = kNN.file2matrix('datingTestSet2.txt')
print matrix
print labels
zhfont = matplotlib.font_manager.FontProperties(fname='C:\Windows\Fonts\ukai.ttc')
plt.figure(figsize=(8, 5), dpi=80)
axes = plt.subplot(111)
# 将三类数据分别取出来
# x轴代表飞行的里程数
# y轴代表玩视频游戏的百分比
type1_x = []
type1_y = []
type2_x = []
type2_y = []
type3_x = []
type3_y = []
print 'range(len(labels)):'
print range(len(labels))
for i in range(len(labels)):
    if labels[i] == 1:  # 不喜欢
        type1_x.append(matrix[i][0])
        type1_y.append(matrix[i][1])

    if labels[i] == 2:  # 魅力一般
        type2_x.append(matrix[i][0])
        type2_y.append(matrix[i][1])

    if labels[i] == 3:  # 极具魅力
        print i, ':', labels[i], ':', type(labels[i])
        type3_x.append(matrix[i][0])
        type3_y.append(matrix[i][1])

type1 = axes.scatter(type1_x, type1_y, s=20, c='red')
type2 = axes.scatter(type2_x, type2_y, s=40, c='green')
type3 = axes.scatter(type3_x, type3_y, s=50, c='blue')
# plt.scatter(matrix[:, 0], matrix[:, 1], s=20 * numpy.array(labels),
#             c=50 * numpy.array(labels), marker='o',
#             label='test')
plt.xlabel(u'每年获取的飞行里程数', fontproperties=zhfont)
plt.ylabel(u'玩视频游戏所消耗的事件百分比', fontproperties=zhfont)
axes.legend((type1, type2, type3), (u'不喜欢', u'魅力一般', u'极具魅力'), loc=2, prop=zhfont)
plt.show()

图中清晰的标识了三个不同的样本分类区域,具有不同爱好的人其类别区域也不同,可以看出用图中展示的“每年获取飞行常客里程数”和“玩视频游戏所耗时间百分比”两个特征更容易区分数据点从属的类别。

五、准备数据:归一化数值

为了防止特征值数量上的差异对预测结果的影响,比如计算距离时,量值较大的特征值对结果影响较大,所以我们对数据所有的特征值会进行归一化到[0,1]的预处理。

def autoNorm(dataSet):
    minVals = dataSet.min(0)
    maxVals = dataSet.max(0)
    ranges = maxVals - minVals
    normDataSet = zeros(shape(dataSet))
    m = dataSet.shape[0]
    normDataSet = dataSet - tile(minVals, (m,1))
    normDataSet = normDataSet/tile(ranges, (m,1))   #element wise divide
    return normDataSet, ranges, minVals

代码讲解:函数autoNorm()中,每列的最小值放在变量minVals中,最大值放在maxVals中,其中dataSet.min(0)中的参数0使得函数可以从列中选取最小值,而不是选取当前行的最小值。因为特征值矩阵dataSet是1000X3,而minVals和range都是1X3,所以需要利用tile()函数将minVals和range的内容复制成输入矩阵同样大小的矩阵。

>>> import kNN
>>> reload(kNN)
<module 'kNN' from 'kNN.pyc'>
>>> datingDataMat,datingLabels=kNN.file2matrix('datingTestSet2.txt')
>>> normMat,ranges,minVals=kNN.autoNorm(datingDataMat)
>>> normMat
array([[ 0.44832535,  0.39805139,  0.56233353],
       [ 0.15873259,  0.34195467,  0.98724416],
       [ 0.28542943,  0.06892523,  0.47449629],
       ...,
       [ 0.29115949,  0.50910294,  0.51079493],
       [ 0.52711097,  0.43665451,  0.4290048 ],
       [ 0.47940793,  0.3768091 ,  0.78571804]])
>>> ranges
array([  9.12730000e+04,   2.09193490e+01,   1.69436100e+00])
>>> minVals
array([ 0.      ,  0.      ,  0.001156])

六、测试算法

机器学习算法中一个很重要的工作就是评估算法的正确率,通常我们会将已有数据的90%作为训练样本来训练分类器,而使用其余10%的数据去测试分类器,检测分类器的正确率。

1.分类器对约会网站的测试代码:

def datingClassTest():
    hoRatio = 0.50      #hold out 10%
    datingDataMat,datingLabels = file2matrix('datingTestSet2.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 = 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
>>> kNN.datingClassTest()
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1

.

.

the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 3, the real answer is: 3
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 2, the real answer is: 1
the classifier came back with: 2, the real answer is: 2
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 1, the real answer is: 1
the classifier came back with: 2, the real answer is: 2
the total error rate is: 0.064000

七、使用算法

输入某人信息,预测出海伦对对方喜欢程度:

def classifyPerson():
    resultList=['not at all','in small doses','in large doses']
    percentTats=float(raw_input("percentage of time spent playing video games?"))
    ffMiles=float(raw_input("frequent flier miles earned per year?"))
    iceCream=float(raw_input("liters of ice cream consumed per year?"))
    datingDataMat,datingLabels=file2matrix('datingTestSet2.txt')
    normMat,ranges,minVals=autoNorm(datingDataMat)
    inArr=array([ffMiles,percentTats,iceCream])
    classifierResult=classify0((inArr-minVals)/ranges,normMat,datingLabels,3)
    print "You will probably like this person:",resultList[classifierResult-1]

代码讲解:Python中的raw_input()允许用户输入文本行命令并返回用户所输入的命令

>>> import kNN
>>> reload(kNN)
<module 'kNN' from 'kNN.py'>
>>> kNN.classifyPerson()
percentage of time spent playing video games?10
frequent flier miles earned per year?10000
liters of ice cream consumed per year?0.5
You will probably like this person: in small doses

时间: 2024-08-06 16:04:36

机器学习实战笔记——利用KNN算法改进约会网站的配对效果的相关文章

吴裕雄--天生自然python机器学习:使用K-近邻算法改进约会网站的配对效果

在约会网站使用K-近邻算法 准备数据:从文本文件中解析数据 海伦收集约会数据巳经有了一段时间,她把这些数据存放在文本文件(1如1^及抓 比加 中,每 个样本数据占据一行,总共有1000行.海伦的样本主要包含以下3种特征: 每年获得的飞行常客里程数 玩视频游戏所耗时间百分比 每周消费的冰淇淋公升数 将文本记录到转换NumPy的解析程序 import operator from numpy import * from os import listdir def file2matrix(filenam

K-近邻算法改进约会网站的配对效果

摘自:<机器学习实战>,用python编写的(需要matplotlib和numpy库) 海伦一直使用在线约会网站寻找合适自己的约会对象.尽管约会网站会推荐不同的人选,但她没有从中找到喜欢的人.经过一番总结,她发现曾交往过三种类型的人: 1.不喜欢的人( 以下简称1 ): 2.魅力一般的人( 以下简称2 ): 3.极具魅力的人(以下简称3 ) 尽管发现了上述规律,但海伦依然无法将约会网站推荐的匹配对象归入恰当的分类.她觉得可以在周一到周五约会哪些魅力一般的人,而周末则更喜欢与那些极具魅力的人为伴

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

---恢复内容开始--- < Machine Learning 机器学习实战>的确是一本学习python,掌握数据相关技能的,不可多得的好书!! 最近邻算法源码如下,给有需要的入门者学习,大神请绕道. 数字识别文件 ''' Created on Sep 16, 2010 kNN: k Nearest Neighbors Input: inX: vector to compare to existing dataset (1xN) dataSet: size m data set of know

《机器学习实战》代码实现学习一 使用K-近邻算法改进约会网站的配对效果(数据准备)

1.数据准备:从文本文件中解析数据 文本文件datingTestSet2.txt网盘地址为: https://pan.baidu.com/s/19HNwo1TSWjWhbRwsyL-itg 提取码为:mz11 约会数据由1000行,主要包含一下三种特征: 每年获得的飞行常客里程数 玩视频游戏所耗时间百分比 每周消费的冰淇淋公升数 但是在把这些特征输入到分类器之前,必须将待处理数据格式改变为分类器可以接受的格式,在kNN.py中创建名为file2matrix的函数,以此来处理输入格式问题,该函数的

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

案例二.:使用K-近邻算法改进约会网站的配对效果 案例分析: 海伦收集的数据集有三类特征,分别是每年获得的飞行常客里程数.玩视频游戏所耗时间百分比. 每周消费的冰淇淋公升数.我们需要将新数据的每个新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签.一般来说,我们只选择样本数据集中前k个最相似的数据,这就是k-近邻算法中k的出处,通常k是不大于20的整数.最后,选择k个最相似数据中出现次数最多的分类,作为新数据的分类. 流程:在约会网站上使用K

机器学习实战1-2 KNN改进约会网站的配对效果 datingTestSet2.txt 下载方法

今天读<机器学习实战>读到了使用k-临近算法改进约会网站的配对效果,道理我都懂,但是看到代码里面的数据样本集 datingTestSet2.txt 有点懵,这个样本集在哪里,只给了我一个文件名,没有任何内容啊. 上网百度了这个文件名,发现很多博主的博客里可以下载,我很好奇,同样是读<机器学习实战>,他们是从哪里下载的数据样本集呢?就重新读了这本书.终于在"关于本书"最后的"作者在线里面"找到了网址!就是这个,大家需要可以来这里下载. http

KNN算法项目实战——改进约会网站的配对效果

KNN项目实战--改进约会网站的配对效果 1.项目背景: 海伦女士一直使用在线约会网站寻找适合自己的约会对象.尽管约会网站会推荐不同的人选,但她并不是喜欢每一个人.经过一番总结,她发现自己交往过的人可以进行如下分类: 不喜欢的人 魅力一般的人 极具魅力的人 2.项目数据 海伦收集约会数据已经有了一段时间,她把这些数据存放在文本文件datingTestSet.txt中,每个样本数据占据一行,总共有1000行. datingTestSet.txt数据集下载 海伦收集的样本数据主要包含以下3种特征:

机器学习实战笔记——基于KNN算法的手写识别系统

本文主要利用k-近邻分类器实现手写识别系统,训练数据集大约2000个样本,每个数字大约有200个样本,每个样本保存在一个txt文件中,手写体图像本身是32X32的二值图像,如下图所示: 首先,我们需要将图像格式化处理为一个向量,把一个32X32的二进制图像矩阵通过img2vector()函数转换为1X1024的向量: def img2vector(filename): returnVect = zeros((1,1024)) fr = open(filename) for i in range(

《机器学习实战》之k-近邻算法(改进约会网站的配对效果)

示例背景: 我的朋友海伦一直使用在线约会网站寻找合适自己的约会对象.尽管约会网站会推荐不同的人选,但她并不是喜欢每一个人.经过一番总结,她发现曾交往过三种类型的人: (1)不喜欢的人: (2)魅力一般的人: (3)极具魅力的人: 尽管发现了上述规律,但海伦依然无法将约会网站推荐的匹配对象归入恰当的分类,她觉得可以在周一到周五约会那些魅力一般的人,而周末则更喜欢与那些极具魅力的人为伴.海伦希望我们的分类软件可以更好地帮助她将匹配对象划分到确切的分类中.此外,海伦还收集了一些约会网站未曾记录的数据信