马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 v.ki 于 2021-9-2 17:50 编辑
原文链接点击下面橙色字体,最新的更新都会第一时间发布在那
机器学习——knn
说到分类,我们应该都不陌生,小时候父母就教我们认识颜色,给颜色分类。
这样一张图
我们很容易的就可以把他们以横轴5为基准 分为两类。
再来看一张图
这下界限是不是就不那么好分了,既然我们能把这些点画出来,就说明已经有了它们的数据,接下来就差分类了。也就是如何才能把无序的数据转换成对我们有用的信息
这一篇我们介绍的是 KNN(K- Nearest Neighbor)K最邻近法。 从名字可以分析:怎么知道哪家是我们的邻居,当然是最近的那家。
生活中我们可以测量,在数据中就是通过把他们放在空间内,变成点,这样就可以计算彼此间的距离找出邻居了。所谓 ”近朱者赤近墨者黑“找到邻居我们就可以把它们看成一类。
这里计算距离的公式我们一般用欧式距离,也就是初中时学过的两点之间的距离公式 。还有很多种距离大家感兴趣可以自己查看。
注意看算法名字是KNN NN是啥意思我们知道了
那为何要加个k?
k就是选取前k个最近的邻居由前k个最近的邻居来决定最终要归类给哪一类。
让我们熟悉一下使用knn的流程
以上就是理论部分,现在看看怎么把它实现吧。数据集和代码在这里下载
约会预测
约会对象选择预测
可以看一下第二章图总共四列:
分别是飞行里程数
玩游戏的时间占比
每周消耗冰淇淋的公升数
对这个人的喜欢喜欢程度
这是一个约会网站的数据,我们收集了这些数据,希望通过它们和knn算法来对一个新来的约会对象进行一个初步分类,这样可以提高约会的成功率。
我们只需要知道新约会者的里程数等这些数据就可以做出预测。
数据处理
拿到文本文件后我们首先要对它进行数据处理,把里面的数据变成numpy的数据格式用来更好的计算
处理完的结果是这样的,前三列是特征,最后一列数字分别代表者喜欢程度
绘制散点图
为何要绘制散点图,直接计算它不香吗?其实绘制散点图可以帮助我们更好的看出有没有一个特征占的比重比较高。
比如你可以学习不好,可以乱扔垃圾,可以口吐芬芳,但是有钱,长得好看的话,前面那些就会被一些人忽略。
紫色是不喜欢,黄色是有点喜欢,绿色是很喜欢
游戏时间和冰淇淋数的对比:
冰淇淋数和飞行时间:
游戏时间和飞行时间:
很明显可以看出,飞行里程影响最大,这个女人不喜欢飞行里程比较多的男人
可能是想找一个一直陪在自己身边的人吧。
数据归一化
如果你觉得飞行里程不应该影响这么大,三种特征的影响应该是同等重要的,那么现在要做的就是数据归一化。
min-max标准化(Min-Max Normalization)是归一化的一种常用方法。
具体做法就是
用原始值减去最小值与最大值减去最小值作比。可以知道原始值永远小于等于最大值。所以计算结果在0~1之间。
NN分类器核心
计算距离,并且返回k个邻居,k可以自己设定
在上面我们把分类器已经定义好了,现在就可以调用它了
使用现成的sklearn库实现knn
手写字体识别
数据集和代码在这里:
手写字
不要重复造轮子,既然已经有了现成的库,我们直接用就好# -*- coding: UTF-8 -*-
import numpy as np
import operator
from os import listdir
from sklearn.neighbors import KNeighborsClassifier as kNN
def img2vector(filename):
#创建1x1024零向量
returnVect = np.zeros((1, 1024))
#打开文件
fr = open(filename)
#按行读取
for i in range(32):
#读一行数据
lineStr = fr.readline()
#每一行的前32个元素依次添加到returnVect中
for j in range(32):
returnVect[0, 32*i+j] = int(lineStr[j])
#返回转换后的1x1024向量
return returnVect
def handwritingClassTest():
#测试集的Labels
hwLabels = []
#返回trainingDigits目录下的文件名
trainingFileList = listdir('trainingDigits')
#返回文件夹下文件的个数
m = len(trainingFileList)
#初始化训练的Mat矩阵,测试集
trainingMat = np.zeros((m, 1024))
#从文件名中解析出训练集的类别
for i in range(m):
#获得文件的名字
fileNameStr = trainingFileList[i]
#获得分类的数字
classNumber = int(fileNameStr.split('_')[0])
#将获得的类别添加到hwLabels中
hwLabels.append(classNumber)
#将每一个文件的1x1024数据存储到trainingMat矩阵中
trainingMat[i,:] = img2vector('trainingDigits/%s' % (fileNameStr))
#构建kNN分类器
neigh = kNN(n_neighbors = 3, algorithm = 'auto')
#拟合模型, trainingMat为训练矩阵,hwLabels为对应的标签
neigh.fit(trainingMat, hwLabels)
#返回testDigits目录下的文件列表
testFileList = listdir('testDigits')
#错误检测计数
errorCount = 0.0
#测试数据的数量
mTest = len(testFileList)
#从文件中解析出测试集的类别并进行分类测试
for i in range(mTest):
#获得文件的名字
fileNameStr = testFileList[i]
#获得分类的数字
classNumber = int(fileNameStr.split('_')[0])
#获得测试集的1x1024向量,用于训练
vectorUnderTest = img2vector('testDigits/%s' % (fileNameStr))
#获得预测结果
# classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3)
classifierResult = neigh.predict(vectorUnderTest)
print("分类返回结果为%d\t真实结果为%d" % (classifierResult, classNumber))
if(classifierResult != classNumber):
errorCount += 1.0
print("总共错了%d个数据\n错误率为%f%%" % (errorCount, errorCount/mTest * 100))
if __name__ == '__main__':
handwritingClassTest()
最后 ,可以很明显的观察到。knn对于分类数据十分简单有效,但是它的 缺点 是必须保存全部数据集,如果数据集很大,就会很消耗储存空间。而且他要计算每个数据间的距离,比较耗时。下一章我会说说另一个算法,用来弥补knn的一些不足。
最后再次放上knn的核心算法
原文链接点击下面橙色字体,最新的更新都会第一时间发布在那
!
机器学习——knn |