《机器学习实战》第二章:k-近邻算法(2)约会对象分类
来源:互联网 发布:c语言编99乘法表 编辑:程序博客网 时间:2024/05/21 06:59
这是KNN的一个新例子。
在一个约会网站里,每个约会对象有三个特征:
(1)每年获得的飞行常客里程数(额...这个用来判断你是不是成功人士?)
(2)玩视频游戏所耗时间百分比(额...这个用来判断你是不是肥宅?)
(3)每周消费的冰激凌公升数(额...这个是何用意我真不知道了...)
然后给贴标签。标签种类有三种:
(1)根本不喜欢
(2)有一点喜欢
(3)喜欢得不得了
------------------------------------------------------------------------------------------------------------------
我们首先要从数据文件里面把训练集读入内存。
数据文件大概长这样:
第一列是飞行里程数的特征值,第二列是游戏百分比,第三列是冰淇淋公升数。最后一列是标签,1~3表示喜欢程度。
接下来是代码,file2matrix 函数将文件中的特征数据和标签读到矩阵和list里面
def file2matrix(filename): fr = open(filename) arrayOLines = fr.readlines() numberOfLines = len(arrayOLines) returnMat = zeros((numberOfLines,3)) classLabelVector = [] index = 0 for line in arrayOLines: line = line.strip() listFromLine = line.split('\t') returnMat[index,:] = listFromLine[0:3] classLabelVector.append(int(listFromLine[-1])) index += 1 return returnMat, classLabelVector
值得注意的是这个 zeros 函数,构造一个n×n的零矩阵。
另外第12行,偷懒的话可以这样写:
returnMat[index] = listFromLine
------------------------------------------------------------------------------------------------------------------
然后作者介绍了通过散点图来分析数据的方法,用的是metplotlib这个包。
import matplotlib.pyplot as pltdef matrix2plot(dataSet): fig = plt.figure() ax = fig.add_subplot(111) ax.scatter(dataSet[:, 0], dataSet[:, 1], 15 * array(datingLabels), array(datingLabels)) plt.show()
figure()用来创建一个图的对象。
add_subplot(x,y,z) 是这么个意思:将画布划分为x行y列,图像画在从左到右从上到下的第z块。
scatter() 用来画出散点。这里它接收了4个参数:
(1)横轴数据。这里是dataSet[:, 0],也就是数据集的第1个特征(飞行里程数)
(2)纵轴数据。这里是dataSet[:, 1],也就是数据集的第2个特征(游戏百分比)
(3)每个散点的标度(scalar),从实际上看是散点的半径,或者说有多“粗”。这里是15 * array(datingLabels)。什么意思呢?每个散点对应一个标签datingLabel,要么1,要么2,要么3。把这个值乘以15,变成15,30,45,意思就是标签为1的散点的“粗度”是15,以此类推。其实就是为了在图上面好看出散点的标签。
(4)每个散点的颜色。这里是array(datingLabels)。意思是不同的散点,按照他的标签(1或2或3)给他分配一种颜色。目的也是为了在图上面好看出散点的标签。
效果如下:
横坐标是飞行里程数,纵坐标是游戏百分比。绿色点标签是1(根本不喜欢),黄色点标签是2(有一点不喜欢),紫色点标签是3( 喜欢得不得了)。
------------------------------------------------------------------------------------------------------------------
我们现在有个问题。不是要算欧氏距离吗,那么比如(20000, 0, 0.1)和(32000, 67, 0.1)这两组数据,如果要算欧氏距离的话,那么显然第一个特征的贡献率是最大的,因为其他两个特征的数量级和他没法比啊。
这就需要做一个预处理,叫做“数值归一化”,把任意取值范围的特征值转化为0到1区间内的值。公式如下:
newValue = (oldVlue - min) / (max - min)
代码很容易理解:
def autoNorm(dataSet): minVals = dataSet.min(0) # 每列的最小值 maxVals = dataSet.max(0) # 每列的最大值 ranges = maxVals - minVals #取值范围 normDataSet = zeros(shape(dataSet)) # 按数据的行数、列数构造0 m = dataSet.shape[0] # 数据的条数 normDataSet = dataSet - tile(minVals, (m,1)) # tile:构造每一行都是minVals的数据 normDataSet = normDataSet / tile(ranges, (m,1)) # tile:构造每一行都是ranges的数据 return normDataSet, ranges, minVals
------------------------------------------------------------------------------------------------------------------
现在来测试一下分类器的效果。大概过程是:
(1)从文件中读取数据,并归一化特征值;
(2)抽出一部分来用作分类器的训练样本,剩下的用于测试。
(3)开始训练+测试,并统计错误率
def datingClassTest(): hoRatio = 0.50 datingDataMat, datingLabels = file2matrix('datingTestSet2.txt') 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))
normMat 是特征值归一化后的矩阵。m是数据的条数。hoRatio是测试样本的比例,这里是50%,所以有一半的样本拿去训练,另一半做测试。numTestVecs是测试样本数量。
第9行调用classify0(源码在上篇博客),逐条地将测试样本(前numTestVecs条数据)进行分类,然后验证准确与否。normMat[numTestVecs:m,:] 就是训练集(下标从numTestVecs到m-1的数据)。
测试结果:
错误率为5.0%。还...不错
------------------------------------------------------------------------------------------------------------------
好。现在我们将这个分类器“产品化”,就是可以接受用户输入,然后帮忙分类与预测。
def classifyPerson(): resultList = ['压根不喜欢', '有一点喜欢', '喜欢得不得了'] ffMiles = float(raw_input("飞行里程?")) percentTats = float(raw_input("喜欢玩电子游戏的时间?")) iceCream = float(raw_input("吃冰淇淋的量?")) datingDataMat, datingLabels = file2matrix('datingTestSet2.txt') normMat, ranges, minVals = autoNorm(datingDataMat) inArr = array([ffMiles, percentTats, iceCream]) classifierResult = classify0((inArr - minVals)/ranges, normMat, datingLabels, 3) print "你喜欢这个人的程度很可能是:", resultList[classifierResult - 1];
resultList枚举了标签的种类。inArr是待预测数据,在传入classify0前进行了归一化。
运行结果:
- 《机器学习实战》第二章:k-近邻算法(2)约会对象分类
- 机器学习实战之k-近邻算法(5)--- 完整版约会网站数据分类
- 《机器学习实战》第二章 2.2用k-近邻算法改进约会网站的配对效果
- 机器学习实战-第二章(k-近邻算法)
- 机器学习实战笔记(第二章:k近邻算法)
- Python3:《机器学习实战》之k近邻算法(2)我们约会吧
- 《机器学习实战》学习-第二章 k-近邻算法
- 机器学习实战——第二章:K-近邻算法
- 《机器学习实战》读书笔记:第二章 k-近邻算法
- 【1】机器学习实战 第二章 k近邻算法
- 《机器学习实战》第二章 - k-近邻算法
- 机器学习实战第二章K近邻算法照葫芦画瓢实践。
- 《机器学习实战》第二章 k-近邻算法
- 机器学习实战-第2章(k-近邻算法)
- 机器学习实战(第2章 k-近邻算法)
- [完]机器学习实战 第二章 k-近邻算法(k Nearest Neighbor)
- 机器学习实战——K-近邻算法【2:改进约会网站配对效果】
- 机器学习实战笔记-K近邻算法2(改进约会网站的配对效果)
- 黑马程序员 一、java 概述与基础知识
- 算法--冒泡排序
- 神奇的angularJS --连接controller的桥梁 service
- 关于ListView控件使用的个人总结--以一个简单的新闻客户端开发为例
- Qt实现读取显示obj文件——说明
- 《机器学习实战》第二章:k-近邻算法(2)约会对象分类
- 数据平面、控制平面、管理平面
- 从零开始,学习web前端之js特效
- pytorch学习笔记(二):gradient
- Coverity 静态分析 VS Code Review 代码审查
- C# DataTable数据量大,循环处理数据的时候优化速度
- Spring data jpa
- 调用 cordova 插件 IllegalAccessException
- MFC窗口支持文件拖入