一、KNN 是什么?—— 机器学习里的 “少数服从多数”

KNN(K-Nearest Neighbors,K 近邻算法)是机器学习中最经典的监督学习算法之一,核心逻辑堪称 “朴素又直白”:

“要判断一个样本属于什么类别,就看看它周围最近的 K 个样本里,哪种类别占多数。”

打个生活比方:如果你新搬到一个小区,想知道邻居们喜欢吃甜口还是咸口,不用挨个调研 —— 只要问最近的 3 户(K=3)邻居,若 2 户爱吃甜口,就可以推测这个区域更偏爱甜口。KNN 的 “判断逻辑” 和这完全一致,只不过把 “距离” 换成了数据维度的计算,把 “口味偏好” 换成了数据标签。

二、KNN 的核心原理:3 个关键问题

1. 如何衡量 “距离”?

KNN 靠 “距离” 判断样本相似度,常用 3 种距离公式:

  • 欧氏距离(最常用):适用于连续型特征,类似平面上两点间的直线距离,公式为:

\(d(x,y) = \sqrt{\sum_{i=1}^{n}(x_i - y_i)^2}\)

例:用 “年龄(25 vs 30)”“收入(8k vs 10k)” 判断用户相似度,直接算两点间距离。

  • 曼哈顿距离:适用于高维稀疏数据(如文本特征),公式为:

\(d(x,y) = \sum_{i=1}^{n}|x_i - y_i|\)

  • 余弦相似度:衡量向量方向的相似度,适用于文本、图像等特征向量(值越大越相似)。
2. K 值怎么选?—— 决定算法效果的关键

K 值是 KNN 的 “灵魂参数”,选大或选小都会出问题:

  • K 值太小(如 K=1):容易受 “异常值” 影响。比如判断一个用户是否流失时,恰好最近的 1 个样本是异常离网用户,就会误判。
  • K 值太大(如 K=100):会忽略局部特征,被 “多数类” 带偏。比如样本中 90% 是 “未流失用户”,K=100 时几乎全判为未流失,漏掉真实离网用户。

实用技巧:K 值通常选奇数(避免平局),通过 “交叉验证” 筛选(比如从 3、5、7 中选效果最好的)。

3. 特征需要 “特殊对待” 吗?

必须!KNN 对特征尺度非常敏感:

比如用 “年龄(0-100)” 和 “收入(0-10000)” 做特征,收入的数值范围远大于年龄,计算距离时会被收入 “主导”,导致年龄特征失效。

解决方法:先做 “特征标准化”,把所有特征缩放到同一尺度:

  • 标准化(Z-score):\(x' = \frac{x - \mu}{\sigma}\)(均值为 0,标准差为 1)
  • 归一化(Min-Max):\(x' = \frac{x - min}{max - min}\)(缩到 0-1 区间)

三、实战:用 KNN 做 “客户离网预测”

以电信客户数据为例,用 KNN 判断用户是否会离网,代码简洁到新手也能看懂:

1. 准备工作(安装库)

pip install pandas scikit-learn

2. 核心代码

# 1. 加载数据(包含19个特征,标签为Churn?:0=未离网,1=离网)

import pandas as pd

data = pd.read_csv("telecom_churn.csv")

# 2. 提取特征和标签

X = data.iloc[:, 1:-1] # 前19列特征

y = data.iloc[:, -1] # 最后一列标签

# 3. 特征标准化(关键步骤!)

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()

X_scaled = scaler.fit_transform(X)

# 4. 划分训练集和测试集

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(

X_scaled, y, test_size=0.3, random_state=0

)

# 5. 训练KNN模型(K=5)

from sklearn.neighbors import KNeighborsClassifier

knn = KNeighborsClassifier(n_neighbors=5) # 设K=5

knn.fit(X_train, y_train)

# 6. 评估效果

from sklearn.metrics import classification_report

y_pred = knn.predict(X_test)

print(classification_report(y_test, y_pred, target_names=['未离网', '离网']))

3. 输出结果(示例)

precision recall f1-score support

未离网 0.93 0.95 0.94 862

离网 0.72 0.65 0.68 138

accuracy 0.91 1000

macro avg 0.82 0.80 0.81 1000

weighted avg 0.90 0.91 0.90 1000

可以看到,KNN 对 “未离网” 用户的识别精度(93%)较高,对 “离网” 这类少数类也有不错的召回率(65%)。

四、KNN 的 “生存法则”:适合与不适合的场景

✅ 适合用 KNN 的情况
  1. 小数据集:无需训练 “模型”,直接用原始数据判断,大数据会变慢;
  1. 可解释性要求高:能明确说出 “根据哪几个样本判断的”,比神经网络更透明;
  1. 特征维度不高:高维数据(如图片)计算距离耗时,且容易 “维度灾难”;
  1. 实时更新需求:新增样本直接加入数据集,不用重新训练模型(如实时推荐)。
❌ 不适合用 KNN 的情况
  1. 大数据集:每次预测都要计算与所有样本的距离,速度极慢;
  1. 高维数据:比如 1000 维的文本特征,距离计算会失效(“维度灾难”);
  1. 特征不均衡:比如 “收入” 占比远大于 “年龄”,不标准化就会出错;
  1. 实时性要求极高:比如自动驾驶的决策,KNN 的计算速度跟不上。

五、新手必懂:KNN 调优 3 个技巧

  1. 选对 K 值:用 “网格搜索” 找最优 K,比如GridSearchCV(knn, param_grid={'n_neighbors': [3,5,7]});
  1. 加权 KNN:让距离近的样本 “话语权更大”,设置weights='distance'(默认是uniform平等权重);
  1. 降维预处理:高维数据先做 PCA 降维,再用 KNN,既快又准。

六、总结:KNN 的 “朴素哲学”

KNN 没有复杂的数学推导,也不用迭代训练,却能解决很多实际问题 —— 它的核心是 “相信相似性”:相似的样本大概率属于同一类。

作为机器学习入门算法,KNN 能帮你快速理解 “特征、距离、标签” 的关系;而在实际工作中,它更适合做 “基线模型”—— 先用 KNN 跑出基础效果,再用随机森林、XGBoost 等算法优化,效率更高。

下次遇到 “分类” 问题,不妨先试试 KNN,说不定简单的方法就是最好的方法~

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐