机器学习实战-3-KNN算法实战
本文中介绍的是《机器学习实战》一书中关于KNN算法的一个实战案例:海伦约会案例
海伦约会
整体过程
- 收集数据:提供文本文件
- 准备数据:通过pandas来读取数据
- 分析数据:通过matplotlib来绘制散点图
- 测试算法:将海伦提供的数据随机分成训练集和测试集
背景
海伦女士一直在使用约会网站来寻找适合自己的约会对象。尽管约会网站会推荐不同的人选,但是海伦不是喜欢每个人。经过一番的总结,她发现自己喜欢过3个类型的人:
- 完全不喜欢的人
- 魅力一般的人
- 极具魅力的人
海伦自己通过一段时间搜集一份数据,她将这些数据存放在文本文件datingTestSet中,每个样本数据占据一行,总共有1000行,主要包含以下3种特征:
- 每年获得的飞行常客里程数
- 玩视频游戏所消耗时间百分比
- 每周消费的冰淇淋公升数
真心吃货,冰淇淋都能成为其找对象的指标😃
数据的大致样貌如下:
准备数据
在将上面的数据输入到分类器之前,必须将待处理的数据格式改变为分类器可以接受的格式。分类器接受的数据格式分为两个部分:
- 特征矩阵:数据部分
- 数据标签:分类标签
因此将文本记录转成Numpy的解析程序:
1 | import numpy as np |
调用上面的函数并执行观察效果:
数据可视化
在上面我们已经顺利导入了数据,并且进行了解析,格式化为分类器需要的数据,接下来需要通过可视化的方式来直观地呈现数据,得到一些初步的结论。
1 | # -*- coding: UTF-8 -*- |
数据归一化
下表中给出了一部分数据,如果想计算样本3和样本4之间的距离,可以使用欧式距离的公式来进行计算:
样本 | 玩游戏所耗时间占比 | 每年获得的飞行里程数 | 每周消耗的冰淇淋公升数 | 样本分类 |
---|---|---|---|---|
1 | 0.8 | 4000 | 0.5 | 1 |
2 | 12 | 134000 | 1 | 3 |
3 | 0 | 20000 | 1.2 | 2 |
4 | 62 | 32000 | 0.3 | 2 |
计算公式如下图所示:
$$\sqrt{(0-62)2+(20000-32000)2+(1.2-0.3)^2}$$
我们发现:上面方程中数字差值最大的属性对计算结果的影响是最大的,也就是说:
每年获取的飞行里程数对于计算结果的影响是远大于其他两个特征的
但是在海伦的心中:这3个因素是同等重要的,因此作为作为3个等权重的特征之一,飞行里程数并不应该严重地影响到计算的结果。
在处理这种不同取值范围的特征值时,我们通常采用的是归一化的方法,将取值范围控制在0-1或者-1到1之间,常用的归一化方法有:
- 0-1标准化
- Z-score标准化
- Sigmoid压缩法
下面是一个0-1归一化的函数:
1 | import numpy as np |
测试算法:验证分类器
上面我们已经按照需求处理了数据,并且对数据做了归一化处理,接下来我们将开展机器学习中一个重要的内容:评估算法的准确率。通常我们使用提供的数据中90%作为训练集,剩下的10%作为测试集去检验分类器的准确率。
10%的测试集是随机选择的
1 | import numpy as np |
jupyter notebook中实现
导入库
1 | import numpy as np |
读取数据
1 | data = pd.read_table('datingTestSet.txt',header=None) |
查看数据信息
查看的主要信息包含
-
大小shape
-
字段类型、是否有缺失值
-
统计值信息
绘制不同属性的散点图
使用matplotlib包绘制不同属性两两之间的散点图
1、对每行数据的标签进行颜色的标注
1 | colors = [] |
2、解决中文字体无法显示问题
一般情况下,通过下面的代码是可以直接在Jupyter notebook中显示中文的:
1 | plt.rcParams['font.sans-serif']=['SimHei'] # 用来显示中文 |
但是可能自己的电脑系统中没有安装相应的字体,因此需要查看系统的字体,找到和中文相关的,查看系统字体的方法:
1 | from matplotlib import font_manager |
看到了一个宋体,设置成宋体即可:
1 | # 显示中文配置:Songti SC 是上面查看到的字体之一 |
使用plotly_express绘制图形
1 | px.scatter(data, # 绘图的数据 |
同理绘制另外两个图形:
数据归一化
在这里我们采用0-1标准化
过程:(x-min) / (max - min),定义一个归一化函数:
1 | ## 定义归一化函数 |
对测试数据的归一化(只对数据部分归一化,标签不用):
1 | # 1、只对数据部分归一化 |
切分训练集和测试集
对原始数据的归一化:
1 | # 原始数据的归一化 |
取出前90%的数据,因为本身海伦收集的数据就是无任何特殊意义随机收集的,所以我们直接取出前90%作为训练集,剩下的作为测试集即可:
1 | # 海伦的数据本身就是无意义的排列,因此取出前90%作为训练集,后面的10%作为测试集 |
定义KNN分类器
1 | def dataClassify(train,test,k): |
对测试集的数据调用分类器,显示出判断效果: