不啰嗦了,直接进入正题。
很多人学机器学习,第一个接触的算法往往不是线性回归,就是KNN。线性回归好歹还能画条线出来,看着直观;KNN这玩意儿第一次听名字容易懵,“K近邻”到底在说什么?但等你真的用一遍会发现,它可能是所有经典算法里,思想最简单、实现最直接、也最容易解释清楚的一个——简单到哪怕没有调库,用纯Python写个几十行也能跑起来。
这篇文章就把KNN从头到尾拆开揉碎讲清楚。内容包括它的核心原理、三个关键要素、为什么数据归一化如此重要、如何用sklearn实现红酒分类、怎么通过交叉验证挑出最优K值、实战中经常踩的坑,以及KNN和KMeans这两个名字相似但八竿子打不着的算法到底有什么区别。无论你是刚入门想搞懂原理,还是准备在项目里用它当baseline,这篇文章都能给你一个完整的参考。
1. KNN到底在做什么:一个投票游戏而已
1.1 从“物以类聚”说起
KNN的全称是K-Nearest Neighbors,中文叫K近邻。它的核心思想四个字就能说完:物以类聚。
这句话翻译成可操作的语言就是:一个样本的类别,由它身边最近的K个样本投票决定。大家投出来哪个类别票数多,这个样本就归为哪个类别。
举个例子你立刻就懂了。
假设你刚搬进一个新小区,想知道这个小区的住户大概是什么收入水平。你不需要看整个城市的数据,也不需要分析小区物业的报告,你只需要认识你隔壁、楼下、对门这几户邻居,看看他们的职业和消费习惯,基本就能判断出这个小区属于什么档次。这个判断过程,就是KNN在做的事——通过邻近样本的特征来推测未知样本的属性。
放到机器学习里,邻居就是那些已经有了标签的历史数据,也就是训练集。新来的那个样本没有标签,KNN就去找离它最近的K个有标签样本,让它们投票。
这里面的逻辑假设是:在特征空间中,距离越近的样本,其特征越相似,而特征相似的样本大概率属于同一个类别。这个假设在大多数场景下是成立的,也是KNN能用的根本原因。
1.2 分类和回归都能干
KNN不只是能做分类,也能做回归。两者的差别只在“投票”之后怎么汇总。
分类问题里,K个邻居一人一票,统计各类别出现的次数,取票数最多的那个作为预测结果。比如K=5,3个邻居说是A类,2个说B类,那就判为A类。
回归问题里,K个邻居不再投票了,而是把它们的标签值取平均(或者加权平均)作为预测结果。比如要预测一套房子的租金,找到最相似的5套房,租金分别是3000、3200、3100、3300、3050,那预测值就是它们加起来除以5,得到3130。
严格来说回归的KNN还有一种加权方式,就是距离越近的邻居说话分量越重。这个后面讲权重参数时细说。
1.3 懒人算法:训练就是在“记笔记”
KNN有个非常著名的特性,叫“懒学习”(Lazy Learning)。什么意思?其他算法比如线性回归、决策树,在训练阶段就要拟合参数、建树,忙活半天得到模型。KNN不一样,它的训练阶段几乎什么都不干——就是把训练数据存下来而已。你没看错,就是存储。
真正干活的时候是在预测阶段。来一个新样本,它要现跑去训练集里挨个算距离,找出最近的K个,再投票出结果。所以KNN也被叫做“基于实例的学习”(Instance-Based Learning),因为它没有显式的模型参数,所有的“知识”都藏在训练样本里。
这个特性带来了一个直接后果:KNN的预测速度完全取决于训练集的大小和特征维度。训练集越大、特征越多,每次预测要算的距离就越多,速度就越慢。如果你的线上服务有上百万条样本,特征还有几百维,那每次预测的延迟会非常感人。
这也是为什么KNN适合中小规模数据集,或者作为baseline做对比,而不太适合海量高维数据实时预测的场景。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. KNN的三个关键要素:K值、距离度量、决策规则
理解了KNN是“让邻居投票”之后,你会发现这个算法其实全靠三个旋钮在控制:K取多大、距离怎么算、票怎么数。这三个旋钮的设定直接决定了模型的效果。
2.1 K值:太小吃不准,太大没个性
K是KNN里最重要的超参数。它的选择直接影响模型的偏差和方差。
K太小,比如K=1,模型会变得非常敏感。新样本身边只要有一个噪声样本,就会被带偏。用机器学习的话说,这是过拟合,模型太“有个性”了,把训练集中的噪声都背下来了。
K太大,比如K等于整个训练集的大小,那就相当于把所有样本的类别统计一遍,不管新样本长什么样,永远预测为训练集中数量最多的那个类别。这是欠拟合,模型完全失去了个性。
实际调参中,K一般取奇数,主要是为了避免平票。虽然平票也有解决方案,但取奇数在分类问题里可以省去很多麻烦。经验上K的取值范围可以从小往大试,2到20这个区间比较常见。更严谨的做法是配合交叉验证,这个后面专门讲。
2.2 距离度量:相似度用什么尺子量
KN
