一、KNN 算法核心原理

1. 算法思想

K - 近邻(K Nearest Neighbor,KNN)算法核心逻辑:若一个样本在特征空间中的 k 个最相似(距离最近)样本中,大多数属于某一类别,则该样本也归为这个类别。类比生活场景:通过 “邻居” 的属性推断自身属性。

2. 核心概念

  • 相似性判断:以样本间的距离衡量相似性,距离越近则相似性越高(常用欧氏距离等度量方式)。
  • K 值作用:控制 “邻居” 数量,直接影响模型效果(后续详细说明)。
  • 适用场景:可解决分类问题(如电影类型预测、鸢尾花分类)和回归问题(如数值预测)。

二、KNN 算法流程

1. 分类流程

  1. 计算未知样本与所有训练样本的距离;
  2. 按距离升序排列训练样本;
  3. 选取前 k 个距离最近的训练样本;
  4. 对 k 个样本进行多数表决,统计出现次数最多的类别;
  5. 将未知样本归为该类别。

2. 回归流程

  1. 计算未知样本与所有训练样本的距离;
  2. 按距离升序排列训练样本;
  3. 选取前 k 个距离最近的训练样本;
  4. 计算 k 个样本目标值的平均值;
  5. 该平均值即为未知样本的预测值。

三、距离度量方法

KNN 算法的核心是距离计算,常用 4 种距离度量方式:

  1. 欧氏距离:最直观的 “直线距离”,计算 n 维空间中两点间的欧式距离,是 KNN 默认度量方式。适用于连续型、低维且无明显异常值的数据(如鸢尾花花瓣尺寸、用户身高体重),但需先对特征标准化,避免数值尺度差异干扰,且高维数据下易受 “维度灾难” 影响。
  2. 曼哈顿距离:又称 “城市街区距离”,计算各维度坐标差的绝对值之和。抗异常值能力强,适合离散型数据(如商品销量、用户点击次数)或网格状数据(如地图经纬度、棋盘坐标),对各维度特征权重平等,计算复杂度低于欧氏距离。
  3. 切比雪夫距离:取各维度坐标差绝对值的最大值,模拟国际象棋国王 “一步多向” 的移动逻辑。适用于需关注 “最大差异维度” 的场景(如多指标评价中某一关键指标的极端差异)、路径规划(如机器人移动步数),对微小差异不敏感,计算速度快。
  4. 闵可夫斯基距离:通过参数p统一概括前三种距离的通用公式(p=1为曼哈顿距离、p=2为欧氏距离、p→∞为切比雪夫距离)。多用于学术研究或多距离对比实验,需手动调参p以匹配数据特性,灵活性高但需额外参数优化成本。

常用推荐:默认优先使用欧氏距离,需根据数据特性(如网格数据、高维数据)灵活选择。

四、关键参数:K 值选择

K 值是 KNN 算法最核心的超参数,直接决定模型拟合效果:

1. K 值过小

  • 仅考虑局部少量样本,易受异常点影响;
  • 模型复杂度升高,容易出现过拟合(如 K=1 时,模型完全贴合训练数据,泛化能力差)。

2. K 值过大

  • 考虑过多无关样本,受样本均衡性影响大;
  • 模型复杂度降低,容易出现欠拟合(如 K=N 时,直接预测训练集占比最高的类别,忽略数据特征)。

3. 选择原则

  • 实际应用中优先选择较小的 K 值(通常 5-15 之间);
  • 结合交叉验证 + 网格搜索(后续介绍)自动寻找最优 K 值。

五、Sklearn KNN API 使用

1. 分类 API:KNeighborsClassifier

from sklearn.neighbors import KNeighborsClassifier

# 1. 初始化模型(n_neighbors指定K值)
estimator = KNeighborsClassifier(n_neighbors=5)

# 2. 训练模型(X为特征矩阵,y为标签)
X = [[0], [1], [2], [3]]
y = [0, 0, 1, 1]
estimator.fit(X, y)

# 3. 预测
y_pred = estimator.predict([[4]])  # 注意输入格式为2D数组
print("分类预测结果:", y_pred)

2. 回归 API:KNeighborsRegressor

from sklearn.neighbors import KNeighborsRegressor

# 1. 初始化模型
estimator = KNeighborsRegressor(n_neighbors=2)

# 2. 训练模型
X = [[0, 0, 1], [1, 1, 0], [3, 10, 10], [4, 11, 12]]
y = [0.1, 0.2, 0.3, 0.4]
estimator.fit(X, y)

# 3. 预测
y_pred = estimator.predict([[3, 11, 10]])
print("回归预测结果:", y_pred)

API 参数说明

  • n_neighbors:默认 5,指定 K 值;
  • 其他参数(如weights):可选 "uniform"(等权)或 "distance"(加权,距离越近权重越高)。

六、特征预处理(归一化 / 标准化)

1. 为什么需要预处理?

特征单位 / 数值范围差异较大(如身高 1.7m、体重 67kg、视力 1.5)时,数值大的特征会 “支配” 距离计算,导致模型无法学习到其他特征的重要性。

2. 两种预处理方式

方法核心公式适用场景Sklearn API
归一化(Min-Max Scaling)x′=max−minx−min​×(mx−mi)+mi数据无异常点,需映射到 [mi,mx](默认 [0,1])sklearn.preprocessing.MinMaxScaler
标准化(Standard Scaling)x′=σx−mean​数据有异常点,转换为均值 0、标准差 1 的正态分布sklearn.preprocessing.S

3. 代码示例(标准化)

from sklearn.preprocessing import StandardScaler

# 1. 准备数据
data = [[90, 2, 10, 40], [60, 4, 15, 45], [75, 3, 13, 46]]

# 2. 初始化标准化对象
scaler = StandardScaler()

# 3. 拟合+转换(训练集用fit_transform,测试集仅用transform)
data_scaled = scaler.fit_transform(data)

print("标准化后数据:\n", data_scaled)
print("均值:", scaler.mean_)
print("标准差:", scaler.var_** 0.5)

注意:测试集必须使用训练集的均值和标准差(即仅调用transform),避免数据泄露。

七、超参数调优:交叉验证 + 网格搜索

1. 核心目的

  • 交叉验证:解决数据集划分随机导致的模型评分不可靠问题;
  • 网格搜索:自动遍历超参数组合,寻找最优参数(如最优 K 值)。

2. 交叉验证原理

将训练集划分为cv份,循环用 1 份作为验证集、其余cv-1份作为训练集,最终取cv次评分的平均值作为模型得分,结果更可信。

3. 网格搜索 + 交叉验证 API:GridSearchCV

from sklearn.model_selection import GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

# 1. 加载数据+预处理
iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.2, random_state=22)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# 2. 初始化模型和参数网格
estimator = KNeighborsClassifier()
param_grid = {"n_neighbors": [1, 3, 5, 7, 9]}  # 待搜索的K值

# 3. 网格搜索+交叉验证(cv=5表示5折交叉验证)
grid_search = GridSearchCV(estimator, param_grid, cv=5)
grid_search.fit(X_train_scaled, y_train)

# 4. 查看最优结果
print("最优K值:", grid_search.best_params_)
print("最优交叉验证得分:", grid_search.best_score_)
print("最优模型:", grid_search.best_estimator_)

# 5. 用最优模型评估测试集
test_score = grid_search.score(X_test_scaled, y_test)
print("测试集准确率:", test_score)

八、常见问题与注意事项

  1. K 值选择:优先用交叉验证 + 网格搜索自动选择,避免手动调参的主观性;
  2. 特征预处理:KNN 对特征尺度敏感,必须进行归一化或标准化;
  3. 过拟合 / 欠拟合:K 值过小→过拟合,K 值过大→欠拟合,结合交叉验证平衡。

九、总结

KNN 算法是入门机器学习的经典算法,核心优势是简单易懂、无需训练过程、可直接预测,适用于中小型数据集的分类和回归任务。关键要点:

  1. 掌握距离度量方法(重点欧氏距离);
  2. 做好特征预处理(标准化优先);
  3. 用交叉验证 + 网格搜索调优 K 值;
  4. 结合实际场景选择合适的参数和预处理方式。

更多推荐