1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 机器学习-k近邻算法(kNN算法)及简单实现

机器学习-k近邻算法(kNN算法)及简单实现

时间:2023-04-25 17:08:35

相关推荐

机器学习-k近邻算法(kNN算法)及简单实现

一、k-近邻算法

1、简述k-近邻算法

k-近邻(k-Nearest Neighbor,简称kNN)是一种常用的监督学习方法,其工作机制非常简单:给定测试样本,基于某种距离度量找出训练集中与其最靠近的k个训练样本,然后基于这k个“邻居”的信息来进行预测,选择这k个样本中出现最多的类别标记作为预测结果。当k取不同值时,分类结果会有显著不同。另一方面,若采用不同的距离计算方式,则找出的“近邻”可能有显著差别,从而也会导致分类结果有显著不同。

如果概念太过于抽象,我们可以举个关于集美大学的例子来理解k-近邻算法:

ps:这里容我简单介绍一下,万人食堂西苑食堂顾名思义是集美大学本部两个主要的食堂,陆大楼是计算机工程学院的楼,与建发楼一样,是学生上课的地方,不同的是陆大五楼是学院领导、辅导员的基地,下面还有各种实验室,而建发楼就可以说是完完全全的教学楼了,为了方便,我们将陆大楼也看作是教学楼。

我们可以使用k-近邻算法分类集美大学的某一个建筑是餐厅还是教学楼。

具体怎么分类呢?

上表是我们已有的数据集,也就是训练样本。这个数据集有两个特征,即午餐时间人数和工作时间人数,我们也知道每个建筑的所属类型,即分类标签。

人是铁饭是钢,一顿不吃饿的慌,作为一名集大的学生,用肉眼可以很明确地观察到,饭点大家都跑去万人、西苑(当然也有某些卷王不干饭...),上课时间大家都跑去陆大、建发(当然也有某些卷王没课跑去食堂开卷...可能图书馆没位置了...怎么这么多卷王...)。

如果现在给我一个建筑,告诉我午餐时间人数和工作时间人数,我可以根据这些判断这个建筑属于食堂还是教学楼,午餐时间人数多而工作时间人数少的是食堂,反之则是教学楼。k-近邻算法也可以像我们人一样做到这一点。

ps:这里会一个问题,假如我拿一个新的建筑来做测试,午餐时间人数和工作时间人数都是1000,这个时候我知道这个建筑可能是陈延奎图书馆也可能是嘉庚图书馆,其类型属于图书馆,而k-近邻算法不会,因为在它眼里,建筑类型只有食堂和教学楼,它会提取样本集中特征最相似数据(最邻近)的分类标签,得到的结果可能是食堂,也可能是教学楼,但绝不会是图书馆。当然,这些取决于数据集的大小以及最近邻的判断标准等因素。

2、k值的选择

一般而言,从开始,随着k的逐渐增大,k近邻算法的分类效果会逐渐提升;在增大到某个值后,随着的进一步增大,k近邻算法的分类效果会逐渐下降。

k值较小,相当于用较小的邻域中的训练实例进行预测,只有距离近的(相似的)起作用

单个样本影响大“学习”的近似误差(approximation error)会减小,但估计误差(estimation error)会增大噪声敏感整体模型变得复杂,容易发生过拟合

k值较大,这时距离远的(不相似的)也会起作用

近似误差会增大,但估计误差会减小整体的模型变得简单

k值选择

一般k值较小k通常取奇数,避免产生相等占比的情况往往需要通过交叉验证(Cross Validation)等方法评估模型在不同取值下的性能,进而确定具体问题的K值

3、距离度量

下面给出两种常见的距离度量方式

3-1、欧氏距离

欧式距离也称欧几里得距离,是最常见的距离度量,衡量的是多维空间中两个点之间的绝对距离。

n维空间点间的欧式距离(两个n维向量):

3.2、曼哈顿距离

在曼哈顿街区要从一个十字路口开车到另一个十字路口,驾驶距离显然不是两点间的直线距离。这个实际驾驶距离就是“曼哈顿距离”。曼哈顿距离也称为“城市街区距离”(City Block distance)。

n维空间点间的曼哈顿距离(两个n维向量):

二、简单测验

如何判断黄点标记的禹洲楼所属的类别呢?

可以从散点图大致推断,这个黄点标记的建筑可能属于教学楼,因为距离已知的两个蓝点更近。k-近邻算法同样是这个原理,专业点的话叫距离度量。这个例子是简单的二维样例,我们可以采用欧氏距离公式计算距离。

通过计算,我们可以得到如下结果:

禹洲楼(980,150)->教学楼(1000,100)的距离约为53.85禹洲楼(980,150)->教学楼(850,20)的距离约为183.85禹洲楼(980,150)->食堂(30,800)的距离约为1151.09禹洲楼(980,150)->食堂(50,1000)的距离约为1259.92

现在k值取3,那么按距离依次排序的三个点分别是教学楼(1000,100)、教学楼(850,20)、食堂(30,800)、食堂(50,1000)。在这三个点中,教学楼出现的频率为2/3,食堂出现的频率为1/3,所以该黄点标记的建筑为教学楼。这个判别过程就是k-近邻算法。

三、Python实现

我们对上面的例子进行Python的实现

1、准备数据集

创建数据集并打印查看创建结果

# -*- coding = utf-8 -*-# @Time : /10/26 14:20# @Author : Nch# @File : kNN.py# @Software : PyCharmimport numpy as npdef createDataSet():#四组二维特征features = np.array([[1000,100],[850,20],[30,800],[50,1000]])#四组特征的标签labels = ['教学楼','教学楼','食堂','食堂']return features, labels#创建数据集features,labels = createDataSet()#打印数据集print(features,'\n',labels)

运行结果如下,创建数据集成功

2、k-近邻算法

根据欧氏公式计算距离,选择距离最小的前k个点,并返回分类结果

def classify0(inX, dataSet, labels, k):# numpy函数shape[0]返回dataSet的行数dataSetSize = dataSet.shape[0]# 在列向量方向上重复inX共1次(横向),行向量方向上重复inX共dataSetSize次(纵向)diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet# 二维特征相减后平方sqDiffMat = diffMat ** 2# sum()所有元素相加,sum(0)列相加,sum(1)行相加sqDistances = sqDiffMat.sum(axis=1)# 开方,计算出距离distances = sqDistances ** 0.5# 返回distances中元素从小到大排序后的索引值sortedDistIndices = distances.argsort()# 定一个记录类别次数的字典classCount = {}for i in range(k):# 取出前k个元素的类别voteIlabel = labels[sortedDistIndices[i]]# dict.get(key,default=None),字典的get()方法,返回指定键的值,如果值不在字典中返回默认值。# 计算类别次数classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1# python3中用items()替换python2中的iteritems()# key=operator.itemgetter(1)根据字典的值进行排序# key=operator.itemgetter(0)根据字典的键进行排序# reverse降序排序字典sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)# 返回次数最多的类别,即所要分类的类别return sortedClassCount[0][0]

3、预测禹洲楼(980,150)

# -*- coding = utf-8 -*-# @Time : /10/26 14:20# @Author : Nch# @File : kNN.py# @Software : PyCharmimport numpy as npimport operatordef createDataSet():#四组二维特征features = np.array([[1000,100],[850,20],[30,800],[50,1000]])#四组特征的标签labels = ['教学楼','教学楼','食堂','食堂']return features, labels#创建数据集# features,labels = createDataSet()#打印数据集# print(features,'\n',labels)def classify0(inX, dataSet, labels, k):# numpy函数shape[0]返回dataSet的行数dataSetSize = dataSet.shape[0]# 在列向量方向上重复inX共1次(横向),行向量方向上重复inX共dataSetSize次(纵向)diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet# 二维特征相减后平方sqDiffMat = diffMat ** 2# sum()所有元素相加,sum(0)列相加,sum(1)行相加sqDistances = sqDiffMat.sum(axis=1)# 开方,计算出距离distances = sqDistances ** 0.5# 返回distances中元素从小到大排序后的索引值sortedDistIndices = distances.argsort()# 定一个记录类别次数的字典classCount = {}for i in range(k):# 取出前k个元素的类别voteIlabel = labels[sortedDistIndices[i]]# dict.get(key,default=None),字典的get()方法,返回指定键的值,如果值不在字典中返回默认值。# 计算类别次数classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1# python3中用items()替换python2中的iteritems()# key=operator.itemgetter(1)根据字典的值进行排序# key=operator.itemgetter(0)根据字典的键进行排序# reverse降序排序字典sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)# 返回次数最多的类别,即所要分类的类别return sortedClassCount[0][0]features,labels = createDataSet()test = [980,150]test_class = classify0(test,features,labels,3)print(test_class)

运行结果如下,根据我们给出的测试集和算法,可以判断禹洲楼是教学楼。

希望以上内容对读者有帮助,大家一起进步! 对集美大学感兴趣的也欢迎来咨询我!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。