第二篇:基于K-近邻分类算法的约会对象智能匹配系统

前言

假如你想到某个在线约会网站寻找约会对象,那么你很可能将该约会网站的所有用户归为三类:

1. 不喜欢的

2. 有点魅力的

3. 很有魅力的

你如何决定某个用户属于上述的哪一类呢?想必你会分析用户的信息来得到结论,比如该用户 "每年获得的飞行常客里程数","玩网游所消耗的时间比","每年消耗的冰淇淋公升数"。

使用机器学习的K-近邻算法,可以帮助你在获取到用户的这三个信息后(或者更多信息 方法同理),自动帮助你对该用户进行分类,多方便呀!

本文将告诉你如何具体实现这样一个自动分类程序。

第一步:收集并准备数据

首先,请搜集一些约会数据 - 尽可能多。

然后将自行搜集到的数据存放到一个txt文件中,例如,可以将每个样本数据各为一行,

前言中提到的那三个分析数据(特征)以及分析结果(整数表示)各为一列,如下所示:

再编写函数将这些数据从文件中取出并存放到数据结构中:

 1 # 导入numpy数学运算库
 2 import numpy
 3
 4 # ==============================================
 5 # 输入:
 6 #        训练集文件名(含路径)
 7 # 输出:
 8 #        特征矩阵和标签向量
 9 # ==============================================
10 def file2matrix(filename):
11     ‘获取训练集数据‘
12
13     # 打开训练集文件
14     fr = open(filename)
15     # 获取文件行数
16     numberOfLines = len(fr.readlines())
17     # 文件指针归0
18     fr.seek(0)
19     # 初始化特征矩阵
20     returnMat = numpy.zeros((numberOfLines,3))
21     # 初始化标签向量
22     classLabelVector = []
23     # 特征矩阵的行号 也即样本序号
24     index = 0
25
26     for line in fr:     # 遍历训练集文件中的所有行
27         # 去掉行头行尾的换行符,制表符。
28         line = line.strip()
29         # 以制表符分割行
30         listFromLine = line.split(‘\t‘)
31         # 将该行特征部分数据存入特征矩阵
32         returnMat[index,:] = listFromLine[0:3]
33         # 将该行标签部分数据存入标签矩阵
34         classLabelVector.append(int(listFromLine[-1]))
35         # 样本序号+1
36         index += 1
37
38     return returnMat,classLabelVector

获取到数据后就可以print查看获取到的数据内容了,如下:

很显然,这样的显示非常的不友好,可采用Python的Matplotlib库来图像化地展示获取到的数据。

如果你是在Ubuntu下使用Eclipse插件编译PyDev的话,安装Matplotlib是很坑的。

在获取到安装包后,还得在插件设置那里添加新的库路径,因为Matplotlib不会自动安装到Python2.7的库目录下,这和NumPy不同。

下面这个才是正确的库路径:

然后就可以编写以下代码进行数据的分析了:

1 # 新建一个图对象
2     fig = plt.figure()
3     # 设置1行1列个图区域,并选择其中的第1个区域展示数据。
4     ax = fig.add_subplot(111)
5     # 以训练集第一列(玩网游所消耗的时间比)为数据分析图的行,第二列(每年消费的冰淇淋公升数)为数据分析图的列。
6     ax.scatter(datingDataMat[:,1], datingDataMat[:,2])
7     # 展示数据分析图
8     plt.show()

另外在代码顶部记得包含所需的matplotlib库:

1 # 导入Matplotlib库
2 import matplotlib.pyplot as plt
3 import matplotlib

运行完后,输出数据分析图如下:

这里发现一个问题,上面的数据分析图并没有显示分类的结果。

进一步优化数据分析图显示部分代码:

 1 # 新建一个图对象
 2     fig = plt.figure()
 3     # 设置1行1列个图区域,并选择其中的第1个区域展示数据。
 4     ax = fig.add_subplot(111)
 5     # 以训练集第一列(玩网游所消耗的时间比)为数据分析图的行,第二列(每周消费的冰淇淋公升数)为数据分析图的列。
 6     ax.scatter(datingDataMat[:,1], datingDataMat[:,2], 15.0*numpy.array(datingLabels), 15.0*numpy.array(datingLabels))
 7     # 坐标轴定界
 8     ax.axis([-2,25,-0.2,2.0])
 9     # 坐标轴说明 (matplotlib配置中文显示有点麻烦 这里直接用英文的好了)
10     plt.xlabel(‘Percentage of Time Spent Playing Online Games‘)
11     plt.ylabel(‘Liters of Ice Cream Consumed Per Week‘)
12     # 展示数据分析图
13     plt.show()

得到如下数据分析图:

  

也可以用同样方法得到 "每年获得的飞行常客里程数" 和 "玩网游所消耗的时间比" 为轴的图:

  

第三步:数据归一化

想必你会发现,我们分析的这三个特征,在距离计算公式中所占的权重是不同的:飞机历程肯定要比吃冰淇淋的公升数大多了。

因此,需要将它们转为同样的一个数量区间,再进行距离计算。 --- 这个步骤就叫做数据归一化。

可以使用如下公式对数据进行归一化:

newValue = (oldValue - min) / (max - min)

即用旧的特征值去减它取到的最小的值,然后再除以它的取值范围。

很显然,所有得到的新值取值均在 0 -1 。

这部分代码如下:

 1 # ==============================================
 2 # 输入:
 3 #        训练集
 4 # 输出:
 5 #        归一化后的训练集
 6 # ==============================================
 7 def autoNorm(dataSet):
 8     ‘数据归一化‘
 9
10     # 获得每列最小值
11     minVals = dataSet.min(0)
12     # 获得每列最大值
13     maxVals = dataSet.max(0)
14     # 获得每列特征的取值范围
15     ranges = maxVals - minVals
16     # 构建初始矩阵(模型同dataSet)
17     normDataSet = numpy.zeros(numpy.shape(dataSet))
18
19     # 数据归一化矩阵运算
20     m = dataSet.shape[0]
21     normDataSet = dataSet - numpy.tile(minVals, (m,1))
22     # 注意/是特征值相除法。/在别的函数库也许是矩阵除法的意思。
23     normDataSet = normDataSet/numpy.tile(ranges, (m,1))
24
25     return normDataSet

第四步:测试算法

测试的策略是随机取10%的数据进行分析,再判断分类准确率如何。

这部分代码如下:

 1 # ================================================
 2 # 输入:
 3 #        空
 4 # 输出:
 5 #        对指定训练集文件进行K近邻算法测试并打印测试结果
 6 # ================================================
 7 def datingClassTest():
 8     ‘分类算法测试‘
 9
10     # 设置要测试的数据比重
11     hoRatio = 0.10
12     # 获取训练集
13     datingDataMat,datingLabels = file2matrix(‘datingTestSet.txt‘)
14     # 数据归一化
15     normMat, ranges, minVals = autoNorm(datingDataMat)
16     # 计算实际要测试的样本数
17     m = normMat.shape[0]
18     numTestVecs = int(m*hoRatio)
19     # 存放错误数
20     errorCount = 0.0
21
22     # 对测试集样本一一进行分类并分析打印结果
23     print "错误的分类结果如下:"
24     for i in range(numTestVecs):
25         classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
26         if (classifierResult != datingLabels[i]):
27             print "分类结果: %d, 实际结果: %d" % (classifierResult, datingLabels[i])
28             errorCount += 1.0
29     print "总错误率: %.2f"  % (errorCount/float(numTestVecs))
30     print "总错误数:%.2f" % errorCount

其中,classify0 函数在文章K-近邻分类算法原理分析与代码实现中有具体实现。

打印出如下结果:

错误率为5%左右,这是应该算是比较理想的状况了吧。

第五步:使用算法构建完整可用系统

下面,可以在这个训练集和分类器之上构建一个完整的可用系统了。

系统功能很简单:用户输入要判断对象三个特征 - "每年获得的飞行常客里程数","玩网游所消耗的时间比","每年消耗的冰淇淋公升数"。

PS:在真实系统中,这部分输入可不由用户来输入,而从网站直接下载数据。

程序帮你判断你是不喜欢还是有点喜欢,抑或是很喜欢。

这部分代码如下:

 1 # ===========================================================
 2 # 输入:
 3 #        空
 4 # 输出:
 5 #        对用户指定的对象以指定的训练集文件进行K近邻分类并打印结果信息
 6 # ===========================================================
 7 def classifyPerson():
 8     ‘约会对象分析系统‘
 9
10     # 分析结果集合
11     resultList = [‘不喜欢‘, ‘有点喜欢‘, ‘很喜欢‘]
12
13     # 获取用户输入的目标分析对象的特征值
14     percentTats = float(raw_input("玩网游所消耗的时间比:"))
15     ffMiles = float(raw_input("每年获得的飞行常客里程数:"))
16     iceCream = float(raw_input("每年消费的冰淇淋公升数:"))
17
18     # 获取训练集
19     datingDataMat, datingLabels = file2matrix(‘datingTestSet.txt‘)
20     # 数据归一化
21     normMat, ranges, minVals = autoNorm(datingDataMat)
22     # 获取分类结果
23     inArr = numpy.array([ffMiles, percentTats, iceCream])
24     classifierResult = classify0((inArr-minVals)/ranges, normMat, datingLabels, 3)
25
26     print "分析结果:", resultList[classifierResult-1]

运行结果:

至此,该系统编写完毕。

小结

1. KNN算法其实并没有一个实际的 "训练" 过程。取得了数据就当作是训练过了的。在下下篇文章将讲解决策树,它就有详细的训练,或者说知识学习的过程。

2. 可采用从网站自动下载数据的方式,让这个系统的决策更为科学,再加上良好的界面,就能投入实际使用了。

3. 下篇文章将讲解KNN算法一个更为高级的应用 - 手写识别系统。

4. 这个程序也看出,处理文本/字符串方面,Python比C++好用多了。

时间: 2024-10-01 05:25:51

第二篇:基于K-近邻分类算法的约会对象智能匹配系统的相关文章

K近邻分类算法

1 # -*- coding: utf-8 -*- 2 """ 3 Created on Thu Jun 28 17:16:19 2018 4 5 @author: zhen 6 """ 7 from sklearn.model_selection import train_test_split 8 import mglearn 9 import matplotlib.pyplot as plt 10 x, y = mglearn.dataset

K近邻分类算法实现 in Python

K近邻(KNN):分类算法 * KNN是non-parametric分类器(不做分布形式的假设,直接从数据估计概率密度),是memory-based learning. * KNN不适用于高维数据(curse of dimension) * Machine Learning的Python库很多,比如mlpy(更多packages),这里实现只是为了掌握方法 * MATLAB 中的调用,见<MATLAB分类器大全(svm,knn,随机森林等)> * KNN算法复杂度高(可用KD树优化,C中可以用

查看neighbors大小对K近邻分类算法预测准确度和泛化能力的影响

代码: 1 # -*- coding: utf-8 -*- 2 """ 3 Created on Thu Jul 12 09:36:49 2018 4 5 @author: zhen 6 """ 7 """ 8 分析n_neighbors的大小对K近邻算法预测精度和泛化能力的影响 9 """ 10 from sklearn.datasets import load_breast_canc

机器学习经典算法详解及Python实现--K近邻(KNN)算法

(一)KNN依然是一种监督学习算法 KNN(K Nearest Neighbors,K近邻 )算法是机器学习所有算法中理论最简单,最好理解的.KNN是一种基于实例的学习,通过计算新数据与训练数据特征值之间的距离,然后选取K(K>=1)个距离最近的邻居进行分类判断(投票法)或者回归.如果K=1,那么新数据被简单分配给其近邻的类.KNN算法算是监督学习还是无监督学习呢?首先来看一下监督学习和无监督学习的定义.对于监督学习,数据都有明确的label(分类针对离散分布,回归针对连续分布),根据机器学习产

【学习笔记】K近邻归类算法

# -*- coding:utf-8 -*- __author__ = 'Ghostviper' """ K近邻归类算法 """ from numpy import * import operator def createDataset():     group = array([         [1.0, 1.1],         [1.0, 1.0],         [0, 0],         [0, 0.1]     ])    

机器学习经典算法具体解释及Python实现--K近邻(KNN)算法

(一)KNN依旧是一种监督学习算法 KNN(K Nearest Neighbors,K近邻 )算法是机器学习全部算法中理论最简单.最好理解的.KNN是一种基于实例的学习,通过计算新数据与训练数据特征值之间的距离,然后选取K(K>=1)个距离近期的邻居进行分类推断(投票法)或者回归.假设K=1.那么新数据被简单分配给其近邻的类.KNN算法算是监督学习还是无监督学习呢?首先来看一下监督学习和无监督学习的定义.对于监督学习.数据都有明白的label(分类针对离散分布,回归针对连续分布),依据机器学习产

第二篇 基于微擎的模块开发—PHP

从陌生到如今能勉强完成第一个微网站模块的实现.也算是一个小小的进步,从设计数据库到,返回数据,前端模版渲染 每一点都是有点难度的.所以我想总结一下,我是如何实现一个微擎模块. 第一,首先得分析某个模块的想实现什么需求,根据需求设计合理的数据库结构. 第二,了解微擎的结构,运行流程,设计模块结构. 第三,重点就是site.php , 完成site.php 需要一定的php的编程能力, 第四,site.php 其中 通过 pdo 从数据库的获取我们想得到数据源. 微擎已封装其路由机制, doWeb

Machine Learning—k-nearest neighbor classification(k近邻分类)

印象笔记同步分享:Machine Learning-k-nearest neighbor classification(k近邻分类)

每日一个机器学习算法——k近邻分类

K近邻很简单. 简而言之,对于未知类的样本,按照某种计算距离找出它在训练集中的k个最近邻,如果k个近邻中多数样本属于哪个类别,就将它判决为那一个类别. 由于采用k投票机制,所以能够减小噪声的影响. 由于KNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为适合. 一个不足之处是计算量较大,因为对每一个待分类的样本都要计算它到全体已知样本的距离,才能求得它的K个最近邻点.