1、knn?
k-近邻算法采用测量不同特征值之间距离的方法进行分类.思想很简单:如果一个样本的特征空间中最为临近(欧式距离进行判断)的K个点大都属于某一个类,那么该样本就属于这个类。这就是物以类聚的思想。
优点:精度高、对异常值不敏感、无数据输入假定
缺点:计算复杂度高、空间复杂度高
适用数据范围:数值型和标称型
通过计算新数据与训练数据特征值之间的距离,然后选取K(K>=1)个距离最近的进行分类判断
1.1 关键
1、数据的所有特征都要做可比较的量化。
若是数据特征中存在非数值的类型,必须采取手段将其量化为数值。另外,样本有多个参数,每一个参数都有自己的定义域和取值范围,他们对distance计算的影响也就不一样,so样本参数必须做一些scale处理,usually所有特征的数值都采取归一化处置。
2、需要一个distance函数以计算两个样本之间的距离。
距离的定义有很多,如欧氏距离、余弦距离、汉明距离、曼哈顿距离等等.about相似性度量的方法可参考‘漫谈:机器学习中距离和相似性度量方法’。usually选欧氏距离作为距离度量,但是这是只适用于连续变量。在文本分类这种非连续变量情况下,汉明距离可以用来作为度量。btw,如果运用一些特殊的算法来计算度量的话,K近邻分类精度可显著提高,如运用大边缘最近邻法或者近邻成分分析法。
3,确定K的值
K是一个自定义的常数,K的值也直接影响最后的估计,一种选择K值得方法是使用 cross-validate(交叉验证)误差统计选择法(就是数据样本的一部分作为训练样本,一部分作为测试样本,比如选择95%作为训练样本,剩下的用作测试样本。)通过训练数据训练一个机器学习模型,然后利用测试数据测试其误差率。 cross-validate(交叉验证)误差统计选择法就是比较不同K值时的交叉验证平均误差率,选择误差率最小的那个K值。例如选择K=1,2,3,… , 对每个K=i做100次交叉验证,计算出平均误差,然后比较、选出最小的那个。
2、原理
存在一个样本数据集合(知道所属的对应分类)。输入没有标签的数据后,将这个没有标签的数据的每个特征与样本集中的数据对应的特征进行比较,然后算法提取样本中特征最相似的数据(最邻近)的分类标签。我们只选择样本数据集中前 k 个最相似的数据,通常 k 是不大于 20 的整数。最后,选择 k 个最相似数据中出现次数最多的类别,作为新数据的分类。
3.1机器学习实战上的电影例子
用 K-近邻算法来分来爱情片和动作片
即使不知道未知电影属于哪种类型,我们也可以通过某种方法计算出来。首先要计算未知电影与样本集中其他电影的距离,计算方法很简单,即欧式空间距离(Euclidean Distance)
现在我们得到了样本集中所有电影与未知电影的距离,按照距离递增排序,可以找到 k 个距离最近的电影,例如 k=3
K-近邻算法按照距离最近的三部电影的类型,决定未知电影的类型,而这三部电影全是爱情片,因此我们判定未知电影是爱情片。
3.2knn流程
距离计算所需要的值,最好是结构化的数据。
KNN算法的过程为:
选择一种距离计算方式, 通过数据所有的特征计算新数据与已知类别数据集中的数据点的距离
按照距离递增次序进行排序,选取与当前距离最小的k个点
对于离散分类,返回k个点出现频率最多的类别作预测分类;对于回归则返回k个点的加权值作为预测值
使用算法:首先需要输入样本数据和待分类数据,然后运行k-近邻算法判定待分类数据分别属于哪个分类,最后应用计算出的分类执行后续的处理
4.python实现knn
4.1python导入数据
将下面的代码保存到名为 kNN.py 的文本文件中:
|
|
|
|
4.2实现knn
|
|
1、shape()函数:返回数组的尺寸信息
2、tile()函数
3、sum()函数
4、argsort()函数,返回排序后的原来位置的索引
5、sorted()函数,按参数 key 排序
def file2matrix(filename):
f = open(filename) # 打开文件
dataSet = f.readlines() # 读取文件的全部内容
numberOfLines = len(dataSet) # 获得数据集的行数
returnMat = zeros((numberOfLines, 3)) # 创建一个初始值为0,大小为 numberOfLines x 3 的数组
classLabelVector = [] # 用于保存没个数据的类别标签
index = 0
for line in dataSet: # 处理每一行数据
line = line.strip() # 去掉行首尾的空白字符,(包括’\n’, ‘\r’, ‘\t’, ‘ ‘)
listFromLine = line.split() # 分割每行数据,保存到一个列表中
returnMat[index, :] = listFromLine[0:3] # 将列表中的特征保存到reurnMat中
classLabelVector.append(int(listFromLine[-1])) # 保存分类标签
index += 1
return returnMat, classLabelVector
5.2分析数据
使用 Matplotlib 创建散点图
Matplotlib 库提供的 scatter 函数支持个性化标记散点图上的点。
将每年获得的飞行常客里程数作为 x 轴,玩视频游戏所耗时间百分比作为 y 轴
另外,为了方便画图,不用每次都输入上面几行代码,我们可以写一个函数 showPlots 来完成同样的功能(将代码添加到 kNN.py 中):
|
|
重新载入 kNN.py ,输入如下代码即可画图:
5.3归一化
处理这种不同取值范围的特征值时,我们需要对数据进行归一化处理(权重一样,但是数值范围不同)
|
|
|
|
5.4测试
分类器的错误率=错误分类次数/分类测试总次数
|
|
|
|
5.5完整系统
|
|
|
|
6.手写识别系统
书本配备了两个数据集,一个是存储在文件夹 trainingDigits 内的训练集,大约2000个样本;另一个是存储在 testDigits 文件夹内的测试集,大约900个样本。如下图所示。两组数据没有重叠,尺寸均为 32行 x 32列。
文件夹 trainingDigits 和文件夹 testDigits 的内容都是如下形式的样列:
将 32x32 的文本处理为一个尺寸为 1x1024 向量
检查
6.2 测试算法
|
|
输入下面的命令对分类器进行测试(k=3)
如果选择最近的一个作为分类标签,那么准确率会非常的高:
总结
1、kNN缺陷是无法给出任何数据的基础结构信息。而决策树能够解决这个问题,并且速度很快。
2、另一个缺点就是既占空间速度又慢