Scikit-Learn K近邻分类
- 1、K近邻分类
- 1.1、K近邻分类及原理
- 1.2、超参数K
- 1.3、K近邻分类的优缺点
- 2、Scikit-Learn K近邻分类
- 2.1、Scikit-Learn K近邻分类API
- 2.2、K近邻分类实践(鸢尾花分类)
- 2.3、交叉验证寻找最佳K
- 2.4、K近邻分类与Pipeline
1、K近邻分类
K近邻是一种常用的分类算法。K近邻在机器学习知识结构中的位置如下:
1.1、K近邻分类及原理
K近邻(K-Nearest Neighbors,KNN)又称最近邻,意思是K个最近的邻居,是一种有监督的学习分类器,虽然它可以用于回归问题,但它通常用作分类算法
KNN算法的历史最早可以追溯到1951年,当时Evelyn Fix和Joseph Hodges提出了“最近邻模型”的概念;1957年,Cover和Hart扩展了他们的概念;1992年,Altman发表的一篇名为“K-Nearest Neighbors”的文章,使得该算法真正得到了广泛的认知和应用
然而,随着数据集的增长,KNN变得越来越低效,影响了模型的整体性能。KNN虽然不能像以前那么受欢迎,但由于其简单性和准确性,使得它仍然是数据科学中的首选算法之一。它通常用于简单的推荐系统、金融市场预测、数据预处理(缺失数据估计插补)等
K近邻假设可以在实例彼此附近找到相似点,根据比重分配类别标签,使用在给定数据点周围最多表示的标签。KNN算法的基本原理是:在特征空间中,如果一个样本最接近的K个邻居中大多数属于某一个类别,则该样本也属于这个类别。这在技术上被称为多数表决(Plurality Voting)
例如,K=3,KNN算法就会找到与预测点距离最近的三个点(如图中圆圈所示),看看哪种类别多一些,就将预测点归为哪类,图示表示预测点将会被归类到Class B
成功的诀窍在于如何确定数据实例之间的相似性,即怎么算是最近?因此,在进行分类之前,必须先定义距离。常见的距离度量有:欧几里得距离(p=2)、曼哈顿距离(p=1)、闵氏距离(详见:传送门)等
值得注意的是,KNN算法也是Lazy Learning模型家族的一部分,这意味着所有计算都发生在进行分类或预测时。由于它严重依赖内存来存储其所有训练数据,因此也称为基于实例或基于内存的学习方法
1.2、超参数K
K-NN算法中的K值定义了将检查多少个邻居以确定查询点的分类。例如,当K=1时,实例将被分配到与其单个最近邻相同的类
K是一种平衡行为,因为不同的值可能会导致过拟合或欠拟合。较小的K值可能具有较高的方差和较低的偏差,较大的K值可能导致较高的偏差和较低的方差
K的选择将很大程度上取决于输入数据,因为有许多异常值或噪声的数据可能会在K值较高时表现更好。总之,建议K值使用奇数以避免分类歧义,交叉验证策略可以帮助我们为数据集选择最佳K值
交叉验证(详见:传送门)会将样本数据按照一定比例拆分成训练数据和验证数据,然后从选取一个较小的K值开始,不断增加K的值,然后计算验证数据的误差,最终找到一个比较合适的K值
一般情况下,K与模型的Validation Error(模型应用于验证数据的错误)的关系如下图所示:
这个图其实很好理解,当K值增大时,一般错误率会降低,因为周围有更多的样本可以借鉴了;但需要注意的是,和K-Means不同,当K值很大时,错误率会更高,例如我们共有35个样本,当K增大到30时,数据的预测会把更多距离较远的数据也放入比较,最终导致预测偏差较大。相反,K值越小,则模型越过拟合。因此,我们需要针对特定问题选择一个最合适的K值,以保证模型的效果最佳
1.3、K近邻分类的优缺点
优点:
- 超参数少,只需要一个K值和一个距离度量,易于理解和使用,预测效果较好
- 基于内存,在数据集较小时可以快速地进行训练和预测
- 对异常值不敏感,根据最邻近实例的类别来进行投票,从而降低了异常值对结果的影响
- 对数据预处理要求较低,KNN不需要对数据进行复杂的预处理,例如标准化、归一化等
缺点:
- 在数据集较大时,需要较大的存储空间和较长的计算时间,从时间和金钱的角度来看,这可能是昂贵的
- 容易出现过拟合,较小的K值可能会过度拟合数据,K值太大,模型可能会欠拟合
- 对噪声数据敏感,如果数据集中存在噪声数据,KNN算法可能会受到较大影响
- 对高维数据输入表现不佳,也称峰值现象,在算法达到最佳特征数量后,额外的特征会增加分类错误的数量
2、Scikit-Learn K近邻分类
2.1、Scikit-Learn K近邻分类API
Scikit-Learn实现了两个不同的最近邻分类器:KNeighborsClassifier
分类器根据每个查询点的K个最近邻实现学习,其中K是用户指定的整数值。RadiusNeighborsClassifier
分类器根据每个训练点的固定半径r
内的邻居数实现学习,其中r
是用户指定的浮点值
K近邻分类模型sklearn.neighbors.KNeighborsClassifier
的API具体如下:
class sklearn.neighbors.KNeighborsClassifier(n_neighbors=5, *, weights='uniform', algorithm='auto', leaf_size=30, p=2, metric='minkowski', metric_params=None, n_jobs=None)
官方对该API的功能描述如下:
最近邻学习有两种方式:离散标签数据的分类和连续标签数据的回归。最近邻方法背后的原理是找到在距离上离新样本最近的一些样本, 并且从这些样本中预测标签。最近邻的样本数可以是用户定义的常数(K-最近邻),也可以根据不同的点的局部密度(基于半径的近邻学习)确定。一般来说,距离可以用任意来度量:标准的欧氏距离是最常见的选择
API官方文档:https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.KNeighborsClassifier.html
API中文官方文档:https://scikit-learn.org.cn/view/695.html
RadiusNeighborsClassifier
分类器官方文档:https://scikit-learn.org.cn/view/704.html
API参数及说明如下:
参数 | 说明 |
---|---|
n_neighbors | KNN算法中的K值,选取最近的K个点,默认值为5 |
weights | 预测中使用的权重函数,默认为uniform ,表示统一权重,每个邻域中的所有点均被加权(权重相等);其他还有distance ,表示权重点与其距离的倒数,这种情况下,距离近的点比距离远的点影响大,另外,还支持用户自定义的函数 |
algorithm | 用于计算最近邻的算法,默认为auto 。ball_tree 将使用BallTree;kd_tree 将使用KDTree;brute 将使用暴力搜索; |
leaf_size | 用于指定传递给给BallTree或KDTree构建叶子节点时使用的最小样本数,默认为30。这会影响构造和查询的速度,以及存储树所需的内存 |