目录
2、 使用 matplotlib 对wine数据集进行可视化
一、KNN算法概述
KNN算法,也叫做k-最近邻算法,是有监督学习中的分类算法。它可以用于分类或回归问题,但它通常用作分类算法。
二、KNN算法原理
当预测一个新样本的类别时,根据它距离最近的 K 个样本点是什么类别来判断该新样本属于哪个类别(多数投票)。
实例
如上图,绿色圆要被决定属于哪个类,是红色三角形还是蓝色四方形?
- 如果k=3,由于红色三角形所占比例为2/3,绿色圆将属于红色三角形那个类。
- 如果k=5,由于蓝色四方形比例为3/5,因此绿色圆将属于蓝色四方形类。
分析:K 值的影响
如果k值比较小,相当于我们用较小的领域内的训练样本对实例进行预测。这时,算法的近似误差(Approximate Error)会比较小,因为只有与输入实例相近的训练样本才会对预测结果起作用。但是,它也有明显的缺点:算法的估计误差比较大,预测结果会对近邻点十分敏感,也就是说,如果近邻点是噪声点的话,预测就会出错。因此,k值过小容易导致KNN算法的过拟合。
同理,如果k值选择较大的话,距离较远的训练样本也能够对实例预测结果产生影响。这时候,模型相对比较鲁棒,不会因为个别噪声点对最终预测结果产生影响。但是缺点也十分明显:算法的近邻误差会偏大,距离较远的点(与预测实例不相似)也会同样对预测结果产生影响,使得预测结果产生较大偏差,此时模型容易发生欠拟合。
三、KNN的关键
KNN 算法有两个关键点:1. 点之间距离的计算;2. K 值的选取。
距离计算
样本空间内的两个点之间的距离量度表示两个样本点之间的相似程度:距离越短,表示相似程度越高;反之,相似程度越低。
常用的距离量度方式包括:
- 闵可夫斯基距离
- 曼哈顿距离
- 欧氏距离
- 切比雪夫距离
- 余弦距离
其中,常用的距离量度方式是欧氏距离和曼哈顿距离
1.曼哈顿距离
根据闵可夫斯基距离定义,曼哈顿距离的计算公式可以写为:
它测量两点之间的绝对值。
2. 欧氏距离
根据以上定义,欧氏距离可以写为:
欧氏距离(L2范数)是最易于理解的一种距离计算方法,源自欧氏空间中两点间的距离公式,也是最常用的距离量度。它测量两点之间的直线距离。
通常 KNN 算法中使用的是欧式距离。
K值选择
kNN中的k是一个超参数,需要我们进行指定,一般情况下这个k和数据有很大关系,都是交叉验证进行选择,但是建议使用交叉验证的时候,k∈[2,20],使用交叉验证得到一个很好的k值。需注意最好K的取值为奇数,防止出现平票而无法分类的情况。
通过交叉验证计算方差后你大致会得到下面这样的图:
这个图其实很好理解,当你增大k的时候,一般错误率会先降低,因为有周围更多的样本可以借鉴了,分类效果会变好。但注意,和K-means不一样,当K值更大的时候,错误率会更高。这也很好理解,比如说你一共就35个样本,当你K增大到30的时候,KNN基本上就没意义了。
所以选择K点的时候可以选择一个较大的临界K点,当它继续增大或减小的时候,错误率都会上升,比如图中的K=10。
四、KNN算法的优势和劣势
优势:
- 简单好用,容易理解,精度高,理论成熟,既可以用来做分类也可以用来做回归;
- 可用于数值型数据和离散型数据;
- 训练时间复杂度为O(n);无数据输入假定;
- 对异常值不敏感。
劣势:
- 计算复杂性高;空间复杂性高;
- 样本不平衡问题(即有些类别的样本数量很多,而其它样本的数量很少);
- 一般数值很大的时候不用这个,计算量太大。但是单个样本又不能太少,否则容易发生误分。
- 最大的缺点是无法给出数据的内在含义。
五、KNN算法实现红酒分类
样例内容:
1.加载红酒数据集并使用matplotlib将数据可视化
2、 将数据集随机拆分为训练集和测试集
3、 构建K-最近邻算法分类模型并评估其准确性
样例分析:
红酒数据集包括178条红酒样本数据,每个样本有13个特征值(13个化学成分测量值),同时还给出了这178条红酒样本对应的品种(共三个种类——class0、class1、class2)。我们需要根据这些数据建立红酒分类模型,并能够预测新的样本数据的品种。因为样本数据中已经包含了对应的红酒品种(即数据的标签),所以这是一个监督学习中的分类(Classification)问题。
样例实施:
1、 加载、查看红酒数据集
红酒数据集是Scikit-learn自带的数据集,我们通过load_wine ()函数来加载
在加载数据集后,使用 keys()
方法查看数据集中的键,可以得到数据集的属性、样本特征、标签、描述等信息。然后分别打印了样本数据的形状、标签数据的形状、红酒类别名称和样本的十三个特征名称。其中,数据集的形状表明该数据集共有178个样本,每个样本有13个特征;标签数据则对应每个样本所属的三个不同类别之一。
from sklearn.datasets import load_wine
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 加载wine数据集
wine = load_wine()
print(wine.keys()) # 查看数据集构成
print('shape of data:', wine.data.shape) # 查看样本数据的形状
print('shape of target:', wine.target.shape) # 查看标签数据的形状
print('target_names:', wine.target_names) # 查看红酒类别名称
print('feature_names:', wine.feature_names) # 样本的十三个特征名称
输出结果:
使用pandas查看数据:
使用 pandas
将样本数据转换成DataFrame格式,并设置列名为wine数据集中的特征名
# 使用pandas查看样本数据
df = pd.DataFrame(wine.data, columns=wine.feature_names)
df
输出结果
2、 使用 matplotlib
对wine数据集进行可视化
首先,通过 plt.figure(figsize=(16,25))
创建了一个画板,指定了画板的尺寸为16x25。随后,从wine数据集中获取样本数据、数据标签、标签名称和特征名称。
接下来,使用循环生成10个子图,每个子图显示两个随机选取的特征的散点图。循环中的 random_feature = random.sample(range(13), 2)
随机选择了两个不同的特征,用于绘制散点图。在每个子图中,根据数据标签的不同,使用不同的颜色和样式绘制三个类别的数据点。
最后,为每个子图添加x轴和y轴的标签,以及图例。通过 plt.show()
将图像显示出来。
红酒数据样本有13个特征,任意2个都可以形成1幅散点图,这里我们随机选2个特征,生成10幅散点图,查看数据分布情况。
import random
# wine数据集可视化
fig = plt.figure(figsize=(16,25)) # 定义画板尺寸
data = wine.data # 样本数据
target = wine.target # 数据标签
target_names = wine.target_names # 标签名称
feature_names = wine.feature_names # 特征名称
# 任选2个特征生成散点图,共生成10个子图
for i in range(10):
random_feature = random.sample(range(13), 2) # 任选2个特征
ax = fig.add_subplot(5, 2, i+1) # 添加子图(5行2列,第i+1个子图)
for j in range(3): # 依次显示每个种类(共3类)的数据
ax.scatter(data[:,random_feature[0]][target==j], data[:,random_feature[1]][target==j], label=target_names[0])
ax.set_xlabel(feature_names[random_feature[0]], fontsize=15)
ax.set_ylabel(feature_names[random_feature[1]], fontsize=15)
ax.legend()
plt.show()
输出结果:
红酒数据集有13个特征,可以形成一个13维的空间,为了方便显示,我们只是在2维空间里(每次随机选2个特征作为X轴和y轴)对数据进行简单可视化。
可视化的目的是更好地了解数据。从随机生成的散点图中可以发现,有些特征组合在2维空间上就已经比较容易分类(如图2和图4),有些特征组合在二维空间上的重叠度较高,不容易分类,需要考虑更多维度。
3、 将数据集拆分为训练集和测试集
Scikit-learn提供了train_test_split函数将红酒数据集(形状为(178, 13))随机拆分为训练集和测试集,参数除了样本数据和数据标签外,还包括:
test_size参数:测试集比例(默认为0.25)。
random_state参数:随机数种子(为了固定随机结果,便于数据重现。如果不指定,每次拆分结果都不同)。
拆分完成后,将训练集的特征数据赋值给 X_train
,训练集的标签数据赋值给 y_train
,测试集的特征数据赋值给 X_test
,测试集的标签数据赋值给 y_test
。
最后,通过 print(X_train.shape, X_test.shape)
打印训练集和测试集的形状,即输出它们的样本数和特征数。
# 拆分数据集
# test_size=0.25(25%作为测试集,75%作为训练集)
# random_state=0(随机数种子,固定随机结果,便于数据重现)
X_train, X_test, y_train, y_test = train_test_split(data, target, test_size=0.25, random_state=0)
print(X_train.shape, X_test.shape)
输出结果:
4、 构建K-NN模型,评估并预测
创建了一个K最近邻分类器模型,并将n_neighbors
参数设置为3,表示选择3个最近邻样本进行分类。然后,使用训练集数据(X_train
和y_train
)调用fit
方法来拟合训练数据,即对模型进行训练。
接下来,使用测试集数据(X_test
和y_test
)调用score
方法来评估模型的准确率。将得到的评估结果赋值给score
变量,并通过print
语句打印出来。
然后,使用已训练的模型对测试集前5个样本的红酒种类进行预测,通过调用predict
方法并传入X_test[:5]
来获取预测结果,将结果赋值给y_pred
变量。再次使用print
语句打印出预测结果。
最后,通过print(y_test[:5])
语句打印出实际品种,以便与预测结果进行比较。
# 构建模型
model = KNeighborsClassifier(n_neighbors=3)
model.fit(X_train, y_train) # 拟合训练数据
# 评估模型
score = model.score(X_test, y_test)
print('Score:{:.2f}'.format(score))
# 预测红酒种类
y_pred = model.predict(X_test[:5]) # 预测测试集前五个样本的品种
print(y_pred) # 打印预测结果
print(y_test[:5]) # 打印实际品种
输出结果:
六、出现的问题和解决办法
1.问题:输出出现中文乱码:
解决办法:VsCode中文输出为乱码的原因及解决方法_vscode输出中文乱码-优快云博客
2.问题:文件出现汇编问题
解决办法:python打包软件后报错 :SyntaxError: Non-UTF-8 code starting with ‘\x90‘ in file 的原因及解决方法_任聪聪的博客-优快云博客
3.问题:vscode控制台无法输入数字
解决办法:vscode 控制台没办法键盘输入 只能显示输出 的 [解决方式]_调试控制台无法输入_chuanauc的博客-优快云博客
4.问题:电脑内有多个anaconda,导致代码运行时混乱
解决办法:卸载全部anacanda,并重新下载