0
点赞
收藏
分享

微信扫一扫

【skLearn 分类算法】K-近邻(KNN)



文章目录

  • ​​一、KNN概述​​
  • ​​二、原理类比例证​​
  • ​​三、K-近邻算法实现​​
  • ​​① 构建已经分类好的数据集​​
  • ​​② 引入新数据,计算距离​​
  • ​​③ 对距离进行排序​​
  • ​​④ 判定k个点所在类别的频率​​

一、KNN概述

k近邻算法(k–Nearest Neighbour algorithm),又称为KNN算法,是数据挖掘技术中原理最简单的算法, K-近邻分类算法是一种有监督的分类算法。。KNN的工作原理:给定一个已知标签类别的训练数据集,输入没有标签的新数据后,在训练数据集中找到与新数据最邻近的k个实例,如果这k个实例的多数属于某个类别,那么新数据就属于这个类别。可以简单理解为:​由那些离最近的k个点来投票决定归为哪一类​

【skLearn 分类算法】K-近邻(KNN)_数据


如上图所示,原数据集中含有红蓝两类已经划分好的数据类,现加入一组样本为绿色,需要判断其属于原有的哪一类数据集。

K = 3的时候,绿色圆点周围红色多,所以划分为红色三角类别
​K = 5​的时候,绿色圆点周围蓝色多,所以划分为蓝色方块类别

所以不难发现,新数据的类别划分,与超参数 K 的取值密不可分。

​​返回顶部​​

二、原理类比例证

通过KNN的算法原理,可以来举个简单的例子。在电影中包含有许多的类别,已经规定好的,现在有一部新电影需要被划分类型,如下图所示。

【skLearn 分类算法】K-近邻(KNN)_机器学习_02

上图就是我们已有的数据集合,也就是训练样本集。这个数据集有两个特征一一​打斗镜头数和接吻镜头数​。除此之外,我们也知道​每部电影的所属类型,即分类标签​。粗略看来,接吻镜头多的就是爱情片,打斗镜头多的就是动作片。以我们多年的经验来看,这个分类还算合理。如果现在给我一部新的电影告诉我电影中的打斗镜头和接吻镜头分别是多少,那么我可以根据你给出的信息进行判断,这部电影是属于爱情片还是动作片。而k近邻算法也可以像我们人一样做到这一点。

【skLearn 分类算法】K-近邻(KNN)_k近邻_03


我们可以从散点图中大致推断,这个未知电影有可能是爱情片,因为看起来距离已知的三个爱情片更近一点。k近邻算法是用什么方法进行判断呢?没错,就是距离度量。这个电影分类例子中有两个特征,也就是在二维平面中计算两点之间的距离,就可以用我们高中学过的距离计算公式:

【skLearn 分类算法】K-近邻(KNN)_机器学习_04


当前案例仅是二维特征,如果扩展到高维空间,也同样如此,只是在不同特征间的距离计算,使用的方式就是欧式距离(也称欧几里得度量):

【skLearn 分类算法】K-近邻(KNN)_k近邻_05


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

【skLearn 分类算法】K-近邻(KNN)_数据_06


通过上图的计算结果,我们可以知道绿点标记的电影到爱情片《后来的我们》距离最近,为29.1。如果仅仅根据这个结果,判定绿点电影的类别为爱情片,这个算法叫做最近邻算法,而非k近邻算法。k近邻算法步骤如下:

  • (1)计算已知类别数据集中的点与当前点之间的距离;
  • (2)按照距离递增次序排序;
  • (3)选取与当前点距离最小的k个点;
  • (4)确定前k个点所在类别的出现频率;
  • (5)返回前k个点出现频率最高的类别作为当前点的预测类别。

比如,现在K=4,那么在这个电影例子中,把距离按照升序排列,距离绿点电影最近的前4个的电影分别是《后来的我们》、《前任3》、《无问西东》和《红海行动》,​这四部电影的类别统计为爱情片动作片=3:1​,​出现频率最高的类别为爱情片​,​所以在k=4时,绿点电影的类别为爱情片​这个判别过程就是k-近邻算法

​​返回顶部​​

三、K-近邻算法实现

① 构建已经分类好的数据集

# 1.构建已经分类好的数据集
rowdata = {
'电影名称': ['无问西东', '后来的我们', '前任3', '红海行动', '唐人街探案', '战狼2'],
'打斗镜头': [1, 5, 12, 108, 112, 115],
'接吻镜头': [101, 89, 97, 5, 9, 8],
'电影类型': ['爱情片', '爱情片', '爱情片', '动作片', '动作片', '动作片']
}
movie_data = pd.DataFrame(rowdata)

【skLearn 分类算法】K-近邻(KNN)_k近邻_07

② 引入新数据,计算距离

# 2.引入新数据,计算距离 [(x1-x2)^2+(y1-y2)^2]**(1/2)
new_data = [24,67]
old_data = movie_data.iloc[:,1:3] # 提取原数据集x\y
dist_2 = (old_data-new_data)**2 # 计算距离平方
distance = dist_2.sum(axis=1)**(1/2) # 开根

【skLearn 分类算法】K-近邻(KNN)_k近邻_08

③ 对距离进行排序

# 3.对距离进行排序
distances = pd.DataFrame(distance,columns=['dist'])
distances['types'] = movie_data['电影类型'].values
distances = distances.sort_values(by='dist')

【skLearn 分类算法】K-近邻(KNN)_机器学习_09

④ 判定k个点所在类别的频率

# 4.设超参数k=4,提取前四个
k_sample = distances[:4]

# 判定k个点所在类别的频率
amount = k_sample['types'].value_counts()

【skLearn 分类算法】K-近邻(KNN)_数据集_10


这四部电影的类别统计为爱情片:动作片=3:1,出现频率最高的类别为爱情片​,​所以在k=4时,新数据电影的类别为爱情片。

本案例函数封装:

import pandas as pd
'''
函数功能:KNN分类器
参数说明:
new_data需要预测分类的数据集
dataSet:已知分类标签的数据集(训练集)
k:k-近邻算法参数,选择距离最小的k个点
返回:
result:分类结果
'''
def classify(new_data, dataSet, k):
# 最终返回的预测标签结果
result = []
# 计算样本距离
dist = list((((dataSet.iloc[:, 1:3] - new_data) ** 2).sum(1)) ** 0.5)
# 排序处理
dist_l = pd.DataFrame({'dist': dist, 'labels': (dataSet.iloc[:, 3])})
dr = dist_l.sort_values(by='dist')[:k]
# 计算前k个各类数目
re = dr.loc[:, 'labels'].value_counts()
result.append(re.index[0])
return

“上面定义分类器何种情况下会出错?“或者分类器给出的答案是否永远都正确?“答案一定是否定的,分类器并不会得到百分百正确的结果,我们可以使用很多种方法来验证分类器的准确率。此外,分类器的性能也会受到很多因素的影响,比如k的取值就在很大程度上影响了分类器的预测结果,还有分类器的设置、原始数据集等等。为了测试分类器的效果,我们可以把原始数据集分为两部分,一部分用来训练算法(称为训练集),一部分用来测试算法的准确率(称为测试集)。同时,我们不难发现,k近邻算法没有进行数据的训练,直接使用未知的数据与已知的数据进行比较,得到结果。因此,可以说,k近邻算法不具有显式的学习过程。

​​返回顶部​​


举报

相关推荐

0 条评论