Knn算法简介
K最近邻(KNN)是一种简单而有效的机器学习算法,用于分类和回归任务。它的工作原理基于数据点之间的距离度量。以下是KNN算法的简要介绍:
1. **基本概念**:
- KNN是一种基于实例的学习算法,不需要显式地训练模型。它存储训练数据的所有实例,并根据新实例与训练数据中实例的相似度来进行预测。
- KNN算法对应两种基本任务:分类和回归。在分类问题中,它预测实例属于哪个类别;在回归问题中,它预测实例的连续数值。
2. **工作流程**:
- 对于给定的新实例,算法计算它与训练数据中每个实例的距离。
- 然后,选择距离最近的K个训练实例(邻居),这些邻居的数量K是预先指定的。
- 最后,通过投票(对于分类问题)或取平均值(对于回归问题)来预测新实例的标签或数值。
3. **距离度量**:
- KNN算法常用的距离度量包括欧氏距离、曼哈顿距离、闵可夫斯基距离等。
- 对于分类问题,通常使用投票策略,即选择K个邻居中出现最频繁的类别作为预测结果。
- 对于回归问题,通常采用平均值策略,即将K个邻居的目标值的平均值作为预测结果。
4. **参数K的选择**:
- K的选择对KNN算法的性能至关重要。较小的K值会增加模型的复杂度,可能导致过拟合;较大的K值会增加模型的偏差,可能导致欠拟合。
- 一般而言,K的选择是通过交叉验证等技术来确定的。
5. **优点和缺点**:
- 优点:
- 简单易于理解和实现。
- 对于小型数据集表现良好,尤其是数据集中的噪声较少时。
- 缺点:
- 对于大型数据集计算开销较大。
- 对于高维数据集表现较差,因为在高维空间中距离的计算变得困难。
总的来说,KNN是一种简单而有效的机器学习算法,特别适用于小型数据集和低维空间。
算法实现步骤
原理非常简单,下面以一个简单的例子引入。
已知两种酒的标签:赤霞珠和黑皮诺,在这个情景中,我们对酒进行分类的依据是酒精浓度和颜色深度,如下图所示:红色代表赤霞珠,紫色代表黑皮诺,图中有一分类未知的黄点,给定一个K值,我们找到距离黄点最近的K个点,假设K取3,我们发现距离黄点最近的3个点都是红点,0个紫点,根据少数服从多数原则,红:紫 = 3:0,所以认为黄点属于红色这一类,即赤霞珠。
- 确定一个K值, K值我一般取奇数,方便投票;
- 计算已知类别数据集中的点与当前点的距离 ;
- 找到距离最小的K个点 ;
- 确认这K个点的类别 ;
- 把出现次数最多的类别作为当前点的预测类别 ;
如何用python实现KNN算法
1.python实现
#导入需要的库
import numpy as np
import pandas as pd`
import matplotlib.pyplot as plt
#训练数据
rowdata = {'颜色深度':[14.23,13.2,13.16,14.37,13.24,12.07,12.43,11.79,12.37,12.04],
'酒精浓度':[5.64,4.38,5.68,4.80,4.32,2.76,3.94,3. ,2.12,2.6 ],
'品种':[0,0,0,0,0,1,1,1,1,1]}
2.rowdata中的品种为 0 代表 “黑皮诺”,1 代表 “赤霞珠”, 设置一个未知类别的点,变量名为new_data
#新设置一个未知类别的点
new_data = np.array([4.1,12.8])
#把rowdata转换为DataFrame
wine_data = pd.DataFrame(rowdata)
3.wine_data信息
颜色深度 酒精浓度 品种
0 14.23 5.64 0
1 13.20 4.38 0
2 13.16 5.68 0
3 14.37 4.80 0
4 13.24 4.32 0
5 12.07 2.76 1
6 12.43 3.94 1
7 11.79 3.00 1
8 12.37 2.12 1
9 12.04 2.60 1
4.绘制散点图
#修改样式
plt.style.use('ggplot')
#windows电脑电脑正常显示中文
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.figure(figsize=(6,4),dpi = 300)
plt.scatter(wine_data[wine_data.品种 == 0]['酒精浓度'], wine_data[wine_data.品种 == 0]['颜色深度'], c = 'purple', label = '黑皮诺' )
plt.scatter(wine_data[wine_data.品种 == 1]['酒精浓度'], wine_data[wine_data.品种 == 1]['颜色深度'], c = 'red' , label = '赤霞珠' )
plt.scatter(new_data[0] , new_data[1] ,c = 'yellow')
plt.scatter(3.5 , 12.2 ,c = 'green')
plt.title('10瓶红酒')
plt.xlabel('酒精浓度')
plt.ylabel('颜色深度')
# 图例添加 1. scatter 里面 添加 label 2. 添加plt.legend()
plt.legend(loc = 2)
# 将新的数据new_data绘制上来
plt.show()
5.各点分布情况
实现步骤
# 1.确定一个k值 为 3
k = 3
# 2.计算已知类别数据集中的点与当前点的距离
distance = np.sqrt(np.sum((wine_data[['酒精浓度','颜色深度']] - new_data)**2,axis=1))
distance
#3.找到距离最小的K个点
#argsort对其排序,返回其索引值,再切片得到最近的k个值
distance.argsort()[:k]
#4.确认这K个点的类别
k_vote = wine_data.loc[distance.argsort()[:k]]['品种']
#5.把出现次数最多的类别作为当前点的预测类别
k_vote.mode()[0]
结果
0
Sklearn建模流程
Sklearn建模步骤如下:
- 实例化 ,建立评估模型对象;
- 训练模型 ;
- 模型预测 ;
- 模型评估 ;
- 模型调优 ;
#先导入算法模型API
from sklearn.neighbors import KNeighborsClassifier
# 使用KNN类,实例化一个KNN算法的对象
# 模型命名为knn,这里的n_neighbors就是上面的K,这里K依然取3
# K的最优值可以通过绘制学习曲线来
knn = KNeighborsClassifier(n_neighbors=3)
# 提取出输入数据
x = wine_data.iloc[:,:2].values
# 提取出目标标签
y = wine_data.iloc[:,-1].values
#训练模型
knn.fit(x,y)
# 传入的新数据, 必须和原来的X的维度相同,所以需要改变一下new_data的形状
new_data.reshape(1,2)
#使用模型对未知数据进行预测
knn.predict(new_data.reshape(1,2))
#模型评估
knn.score(new_data.reshape(1,2),knn.predict(new_data.reshape(1,2)))
通过训练好的模型可以用于预测未知点,但其实这个模型是不够完美的,在KNN这个算法中,就只有一个参数K,我们还可以通过绘制学习曲线来寻找最优K值。
scores = []
for i in range(1,31):
#建模
knn = KNeighborsClassifier(n_neighbors=i)
#训练
knn.fit(X_train,y_train)
#评估模型 knn.score(X_test,y_test)
scores.append(knn.score(X_test,y_test))
当k大概取17的时候,模型评分是最高的,比K=3的分数高很多,所以我们可以把重新建模,令n_neighbors = 17。