跟着老师做一个项目,关于行车记录仪识别前方车辆,并判断车距,不太好做。本来是用 OpenCV,做着做着,突然发现需要补习一下机器学习的内容。
这本书买了很久了,当时还是看了很多人推荐,不过到现在才想起翻出来看。第二章 kNN 的例子刚跟着做完,书里讲的很清楚,代码条理分明,只不过我是用 Python3 实现的。具体的过程不再赘述,只是把自己的理解放在这里。
- 《机器学习实战(machine learing in action)》
先来看看书里第一章的部分。
原理:已知一组数据的属性值和类别标签,给定一个输入数据,判断所属类别。kNN 的做法是计算输入数据与所有已知数据的空间距离(欧氏距离),然后从小到大排列,取前 k 个数据,出现次数最多的类别标签作为输入数据的所属类别。优点:精度高、对异常值不敏感、无数据输入假定
缺点:计算复杂度高、空间复杂度高
适用数据范围:数值型和标称型
欧式距离计算:$\sqrt {\left( x-x_{i}\right) ^{2}+\left(y-y_{i}\right) ^{2}+\ldots }$
核心代码如下:
- """
- Created on 2017/12/30 19:13
- kNN: k-近邻算法
- Input: inX: 用于判断类别的矩阵 (1xN)
- dataSet: 已知类别的数据集向量 (NxM)
- labels: 数据集的标签 (1xN)
- k: 用于比较的近邻的数量 (应该是奇数)
- Output: 最可能的类标签
- @author: Lucifer
- @site: plantree.me
- @email: wpy1174555847@outlook.com
- """
- import numpy as np
- import os
- import operator
- # kNN
- def classify0(inX, dataSet, labels, k):
- dataSetSize = dataSet.shape[0]
- # np.tile()将inX重复(dataSetSize, 1)次
- diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
- sqDiffMat = diffMat ** 2
- sqDistances = sqDiffMat.sum(axis=1)
- distances = sqDistances ** 0.5
- # 排序后的索引
- sortedDistanceIndices = distances.argsort()
- classCount = {}
- for i in range(k):
- # 寻找出现次数最的标签
- voteILabel = labels[sortedDistanceIndices[i]]
- classCount[voteILabel] = classCount.get(voteILabel, 0) + 1
- # 字典的排序
- sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1),
- reverse=True)
- return sortedClassCount[0][0]
核心的代码并不算复杂,这里用到了 numpy 提供的 tile() 函数,用于将矩阵横向或者纵向复制,然后利用 numpy 中广播的概念:对于矩阵的操作,会具体到矩阵中每一个元素上,这样计算效率无疑会很高。
书里提供的两个例子:
两个例子都提供了原始数据,都很有意思,具体代码详见 我的 GitHub 。
这两个例子,有几点经验需要学习。
第一步,数据的格式化是非常有必要的。因为现在数据来源广泛,可以来自网络,可以来自文本文件,也可以来自数据库,但是具体到算法,输入数据的格式是固定的,这就有必要进行数据的格式化,但是具体格式化的方式是不固定的,这个要看具体算法输入的要求,像这里输入的数据必须是 numpy 的 array 格式,但是数据源是文本文件,这就需要另写方法来自动执行这些转换。
不同属性之间的数据,不具备可对比度,有些尺度相差很大,很影响算法执行的效果,因此在真正的输入数据到算法之前,需要进行归一化。其实归一化也很简单,方式也不止一种,比如:
newValue = (oldValue - min) / (max - min)
可以看出,归一化后的数据,范围落在 [-1, 1], 而且避免了不同尺度数据造成的偏差。
说是探索型数据分析,显得有些专业,其实就是在具体执行机器学习算法之前,先来看看数据长什么样子。可以采用一些统计参数,如均值和方差等,另外一种很重要的方式就是可视化,Python 中最常见的自然是 Matplotlib 绘图库了,Seaborn 也不错,可以尝试学学,可以很直观的看到数据长什么样子。
通常会将原始数据分割为训练集和预测集,比如 90% 的数据作为训练集,用于训练模型,剩下 10% 作为预测集,来预测模型的准确度,由于预测集的预测目标值已知,因此可以通过判断模型输出结果与原有结果比较,得出错误的数量,然后除以预测集总数,即可得到错误率,来表征模型质量。
kNN 存在的问题:
Reference: https://github.com/plantree/Machine-Learing-In-Action/tree/master/chapter2
来源: http://www.bubuko.com/infodetail-2447280.html