机器学习(一)KNN,K近邻算法(K-Nearest Neighbors)
💡 建议初学者掌握KNN作为理解其他复杂算法(如SVM、决策树、神经网络)的基石。
K近邻算法(K-Nearest Neighbors, KNN)详解:原理、实践与优化
K近邻算法(K-Nearest NeighboKrs,简称KNN)是一种经典、直观且易于实现的监督学习方法,既可用于分类,也可用于回归。它“懒惰”地存储所有训练样本,直到有新样本需要预测时才临时计算,因此也被称为“懒惰学习算法”。
本文将系统介绍KNN的核心思想、算法流程、距离度量、超参数、优缺点、使用方法与完整Python实战案例,帮助读者从理论到实践全面掌握这一算法。
一、核心思想 🧠
KNN 基于以下假设:
“近朱者赤,近墨者黑”:一个样本的标签很可能与其最近邻的样本标签一致。
具体流程:
-
对新样本,计算它与训练集中所有样本的距离;
-
选出距离最小的 K 个邻居;
-
分类:根据邻居类别投票(通常为多数投票,但可加权);
-
回归:返回邻居标签的平均值或加权平均值。
其中,三个核心超参数影响性能:
-
K 值
-
距离度量方式
-
投票或加权策略
二、算法流程(以分类为例)
-
准备训练集与测试集
-
对测试集中每个新样本,计算其与所有训练样本的距离
-
对距离排序,选取最近的 K 个邻居
-
投票或加权,输出预测类别
-
返回所有样本的预测值(分类/回归结果)
三、常见距离度量方法
不同的任务场景和数据类型,可能需要不同的距离度量方式:
⚠️ 注意:使用KNN前通常需要对数据做标准化(如Z-score或Min-Max),防止量纲不同导致距离计算失真。
四、KNN的关键超参数
1. K值选择
-
K太小 → 模型复杂,容易过拟合,对噪声敏感;
-
K太大 → 模型过于平滑,可能欠拟合。
通常使用**交叉验证(GridSearchCV)**选择合适的K值。
2. 距离度量方式
根据特征类型和数据分布选择距离函数(见上表)。
3. 权重策略
-
uniform
:每个邻居权重相同; -
distance
:距离越近的邻居权重越大。
4. 最近邻搜索算法
-
brute
:暴力搜索,适合小规模数据; -
kd_tree
/ball_tree
:适合中等维度(<30)的数据; -
高维/大规模数据推荐使用近似搜索库:如 Faiss、Annoy、ScaNN。
五、KNN的优缺点
✅ 优点
-
简单直观,易于实现;
-
无需训练,可直接使用训练数据;
-
天然支持多分类与回归;
-
非线性决策边界处理能力强。
❌ 缺点
-
预测时计算量大,难以实时响应;
-
内存消耗高,需保存全部训练样本;
-
高维数据效果差(维度灾难);
-
对异常值、数据不平衡敏感。
六、KNN使用方法
发挥knn作用的代码:
# 创建一个 KNN 分类器对象,设置邻居数量 k=3knn = KNeighborsClassifier(n_neighbors=3)# 在训练集上训练模型knn.fit(X_train, y_train)# 在测试集上进行预测y_pred = knn.predict(X_test)# 评估预测结果的准确率accuracy = accuracy_score(y_test, y_pred)
核心参数:
-
n_neighbors
- 类型:整数,默认值为 5。
- 作用:指定用于分类的近邻数量(即 K 值)。
- 示例:
n_neighbors=3
表示选择最近的 3 个样本进行投票。
-
weights
- 类型:字符串或可调用函数,默认值为
\'uniform\'
。 - 作用:确定近邻的权重计算方式。
\'uniform\'
:所有近邻权重相等。\'distance\'
:权重与距离成反比(距离越近,权重越大)。- 自定义函数:需接受距离数组并返回权重数组。
- 类型:字符串或可调用函数,默认值为
-
algorithm
- 类型:字符串,可选值为
\'auto\'
、\'ball_tree\'
、\'kd_tree\'
、\'brute\'
,默认\'auto\'
。 - 作用:选择用于计算最近邻的算法。
\'auto\'
:自动选择最合适的算法。\'brute\'
:暴力搜索(适用于小规模数据)。\'kd_tree\'
:KD 树(适用于低维数据)。\'ball_tree\'
:球树(适用于高维数据)。
- 类型:字符串,可选值为
-
leaf_size
- 类型:整数,默认值为 30。
- 作用:控制
ball_tree
或kd_tree
的叶节点大小。 - 影响:较小的值会增加树的构建时间,但可能提高查询效率。
-
p
- 类型:整数,默认值为 2。
- 作用:明可夫斯基距离(Minkowski distance)的参数。
p=1
:曼哈顿距离(L1 范数)。p=2
:欧氏距离(L2 范数)。- 其他值:推广的 Minkowski 距离。
使用案例:
以鸢尾花数据为例(可直接导入数据)完整代码:
# 导入所需的库from sklearn.datasets import load_iris# 用于加载鸢尾花数据集from sklearn.model_selection import train_test_split # 用于划分训练集和测试集from sklearn.neighbors import KNeighborsClassifier # K近邻分类器from sklearn.metrics import accuracy_score # 用于评估模型准确率# 1. 加载鸢尾花数据集(Iris 数据集是一个经典的机器学习分类数据集)iris = load_iris() # 加载数据集X = iris.data # 特征数据:4个特征(花萼长度、花萼宽度、花瓣长度、花瓣宽度)y = iris.target # 标签数据:3个类别(0=setosa,1=versicolor,2=virginica)# 2. 将数据集划分为训练集和测试集# test_size=0.2 表示20%作为测试集,80%作为训练集# random_state=42 保证每次运行划分方式一致(可复现)X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# 3. 创建一个 KNN 分类器对象,设置邻居数量 k=3knn = KNeighborsClassifier(n_neighbors=3)# 4. 在训练集上训练模型knn.fit(X_train, y_train)# 5. 在测试集上进行预测y_pred = knn.predict(X_test)# 6. 评估预测结果的准确率accuracy = accuracy_score(y_test, y_pred)print(\"模型在测试集上的准确率:\", accuracy)
七、实践建议与优化技巧
八、应用场景与适用领域
KNN 虽然简单,但在以下领域仍有广泛应用:
-
推荐系统(基于用户/物品最近邻推荐)
-
图像检索(基于特征向量的最近邻搜索)
-
异常检测(判断样本是否偏离常见邻居)
-
文本分类(TF‑IDF 向量 + 余弦相似度)
九、总结与拓展
-
优点:无训练过程、易于理解、适用性广;
-
挑战:对计算资源依赖高、受高维影响严重;
-
优化路径:标准化、降维、加速邻居搜索、参数调优、类别平衡处理。
KNN凭借其“无需训练,拿来即用”的特点,是机器学习中最容易理解和实现的算法之一。虽然它在高维、高频场景中存在计算瓶颈,但通过特征工程、参数调优和搜索优化,KNN依然能够在推荐系统、图像检索、异常检测、文本分类等任务中大放异彩。
💡 建议初学者掌握KNN作为理解其他复杂算法(如SVM、决策树、神经网络)的基石。