KNN算法回归思想代码实现
1 课程概览
本课讲解KNN算法回归问题的代码实现,使用KNeighborsRegressor类。通过多维特征数据集演示回归流程,与分类代码对比,仅模型对象不同,其余步骤一致。同时验证K值过大导致欠拟合的现象。
2 核心概念与定义
- KNeighborsRegressor:scikit-learn中KNN回归器类,位于sklearn.neighbors模块。
- 回归问题:标签连续的监督学习问题,通过求K个邻居目标值的均值作为预测结果。
- 均值预测:将K个最近邻居的目标值相加求平均,作为最终预测值。
3 算法与模型详解
3.1 KNN回归API
from sklearn.neighbors import KNeighborsRegressor
3.2 KNN回归实现思路(六步)
- 导包:从sklearn.neighbors导入KNeighborsRegressor
- 准备数据集:x_train(训练集特征,二维)、y_train(训练集标签,一维,连续值)、x_test(测试集特征,二维)
- 创建模型对象:estimator = KNeighborsRegressor(n_neighbors=k)
- 模型训练:estimator.fit(x_train, y_train)
- 模型预测:y_predict = estimator.predict(x_test)
- 打印结果:print(y_predict)
3.3 分类与回归代码对比
| 步骤 | 分类 | 回归 |
|---|---|---|
| 导包 | KNeighborsClassifier | KNeighborsRegressor |
| 数据集 | 标签离散 | 标签连续 |
| 创建模型 | KNeighborsClassifier(n_neighbors=k) | KNeighborsRegressor(n_neighbors=k) |
| 训练 | fit(x_train, y_train) | fit(x_train, y_train) |
| 预测 | predict(x_test) | predict(x_test) |
| 决策方式 | 投票 | 均值 |
除模型对象不同外,其余代码完全一致。
3.4 K值过大导致欠拟合验证
- K=N(N为样本总数):所有样本参与计算均值。
- 无论测试集特征如何变化,预测结果都是所有训练集标签的均值。
- 模型过于简单 → 欠拟合。
4 数学原理与推导
4.1 欧式距离计算(三维)
$$d = \sqrt{(x_1-y_1)^2 + (x_2-y_2)^2 + (x_3-y_3)^2}$$
4.2 回归预测公式
$$\hat{y} = \frac{1}{K}\sum_{i=1}^{K} y_i$$
4.3 计算示例
训练数据:
| 样本 | 特征1 | 特征2 | 特征3 | 标签 |
|---|---|---|---|---|
| 1 | 0 | 0 | 1 | 0.1 |
| 2 | 1 | 1 | 0 | 0.2 |
| 3 | 3 | 0 | 10 | 0.3 |
| 4 | 4 | 11 | 12 | 0.4 |
测试数据:x_test = [[3, 1, 10]]
距离计算(测试样本到各训练样本):
- 到样本3:(3-3)² + (1-0)² + (10-10)² = 0+1+0 = 1 → √1 = 1
- 到样本4:(3-4)² + (1-11)² + (10-12)² = 1+100+4 = 105 → √105 ≈ 10.25
- 到样本2:(3-1)² + (1-1)² + (10-0)² = 4+0+100 = 104 → √104 ≈ 10.20
- 到样本1:(3-0)² + (1-0)² + (10-1)² = 9+1+81 = 91 → √91 ≈ 9.54
K=3时:最近的3个邻居是样本3(0.3)、样本1(0.1)、样本2(0.2) $$\hat{y} = \frac{0.3 + 0.1 + 0.2}{3} = 0.2$$
实际计算中,平方和越大,开根号后距离越大,无需精确计算即可比较大小。
5 代码示例
# 1. 导包
from sklearn.neighbors import KNeighborsRegressor
# 2. 准备数据集
x_train = [[0, 0, 1], [1, 1, 0], [3, 0, 10], [4, 11, 12]]
y_train = [0.1, 0.2, 0.3, 0.4]
x_test = [[3, 1, 10]]
# 3. 创建模型对象
estimator = KNeighborsRegressor(n_neighbors=3)
# 4. 模型训练
estimator.fit(x_train, y_train)
# 5. 模型预测
y_predict = estimator.predict(x_test)
# 6. 打印结果
print("预测结果值为", y_predict)
输出:预测结果值为 [0.2]
K=2时:最近2个邻居是样本3(0.3)和样本2(0.2) $$\hat{y} = \frac{0.3 + 0.2}{2} = 0.25$$
K=4时(=样本总数):所有样本参与 $$\hat{y} = \frac{0.1 + 0.2 + 0.3 + 0.4}{4} = 0.25$$
K=4时,无论x_test如何变化,结果都是0.25(所有标签均值),验证了K值过大导致欠拟合。
6 重难点与易错提醒
- ❗重点:回归API为KNeighborsRegressor,分类API为KNeighborsClassifier。
- ❗重点:回归预测=K个邻居目标值的均值;分类预测=K个邻居投票。
- ❗重点:K=N时,预测结果永远是所有训练集标签的均值 → 欠拟合。
- ⚠️易错:predict方法必须传入二维格式的特征,即使只有一个样本也要写成
[[3, 1, 10]]。 - ⚠️易错:回归问题的标签必须是数值型(连续),字符串型标签无法求均值。
- 💡深入理解:平方和越大,开根号后距离越大,比较距离时无需精确计算开根号。
7 课堂问答精选
Q: 以下代码哪一行有误?
A. from sklearn.neighbors import KNeighborsClassifier
B. estimator = KNeighborsClassifier(n_neighbors=3)
C. estimator.fit(x_train, y_train)
D. y_predict = estimator.predict([1])
A: 选D。predict方法必须传入二维格式的特征,应写成[[1]]而不是[1]。因为特征可能有多列,必须用嵌套中括号包裹。
Q: K值过大时会发生什么?
A: 欠拟合。K=N时,所有样本参与计算均值,无论测试集如何变化,预测结果都是固定的均值,模型过于简单。
8 本课小结
- KNN回归API:KNeighborsRegressor,位于sklearn.neighbors。
- 回归预测=K个邻居目标值的均值。
- 代码与分类基本一致,仅模型对象不同。
- K=N时预测结果固定为所有标签均值 → 欠拟合。
9 延伸思考与实践
- 实践:修改n_neighbors值为2、3、4,观察预测结果变化。
- 思考:为什么K=N时模型会发生欠拟合?
- 预习:常用的距离度量方式(欧式、曼哈顿、切比雪夫、闵氏)。