大数跨境
0
0

一个强大算法模型,K近邻回归 !!

一个强大算法模型,K近邻回归 !! 机器学习和人工智能AI
2025-12-02
14

哈喽,大家好~

最近,我们发布了200个强大算法模型,从原理到案例,带大家非常通透理解,入门机器学习。

还有核心社群,分享干货内容,大家要一起加入进来~

言归正传!

K近邻回归是一种基于实例的非参数学习方法。

与线性回归或者神经网络不同,它不通过显式训练全局参数来拟合函数,而是在预测时直接参考训练数据中距离目标点最近的样本。

其核心思想可概述为:对于一个新的输入点 ,找到训练集中与 距离最近的 个邻居,使用这些邻居的输出 的加权平均作为预测值。

直观上,KNN回归实现了局部平滑:在局部邻域内,假设函数值变化不大,邻居的平均值应当接近目标点的真实值。

这种简单思想却蕴含丰富的理论与实践细节:距离度量选择、邻居数 的选取、权重函数设计、维度灾难、稀疏数据、多输出扩展、搜索结构、偏差-方差权衡、统一的核回归视角、统计一致性与收敛速率等等。


基本定义与估计器

给定训练样本 ,其中 为特征向量, 为标量回归目标。

目标是学习一个函数 ,用于预测新点 的输出。KNN回归的估计器定义为:

第一步:基于某种距离度量 (常用Minkowski距离),找到集合 ,其包含训练集中与 距离最小的 个点。

第二步:计算加权平均输出作为预测:

其中 是对邻居的权重,一般依赖于距离

常见权重方案

均匀权重:

距离权重:

其中 避免除零。

核权重(更一般):

其中 为核函数, 为带宽(局部尺度),可取为到第 近邻的距离 ,形成自适应带宽。

距离度量常选用Minkowski范数:

特别地:

  • 为欧氏距离;
  • 为曼哈顿距离。

也可采用加权距离或马氏距离:

其中 为协方差矩阵或度量学习得到的正定矩阵。

核回归视角与Nadaraya-Watson等价

KNN回归在核回归框架下可视为一种特殊的局部常数估计器。设 是到第 近邻的距离 ,取核函数 为指标核:

则KNN回归的均匀权重估计器等价于Nadaraya-Watson核回归:

其中 是半径为 维球。此时 决定了有效邻域的体积大小,从而控制平滑程度;当 增大时,需要更大的 才能形成稳定估计,这反映了维度灾难。

更一般地,如果采用平滑核(例如高斯核 ),并令 为固定带宽或自适应带宽,则KNN回归成为核回归的一种特例。

权重随距离衰减,使得近邻贡献更大,有助于减少边界效应与提高拟合稳定性。

偏差-方差分析与一致性

设数据生成过程为:

假定 服从密度 在局部满足Lipschitz条件或具有有界平方可积性。

我们希望研究KNN估计 的偏差与方差。

邻域半径的缩放关系

维单位球体积:

对于大样本 、适度的 (随 增长),到第 近邻的距离 近似满足:

因此有:

直觉:在密度 下,半径 的球内期望包含样本数 。令其等于 ,即可得到 的期望。该尺度关系体现了邻域半径在高维空间随 的变化规律。

偏差上界

附近满足Lipschitz条件,即存在常数 使得对于 邻域内有:

均匀权重的KNN估计器的偏差可界定:

因此,偏差随邻域半径(等价于 )缩小而减小。更大的 意味着更大的邻域,偏差不一定更小(若 非线性明显,过大的邻域会引入偏差);但高维下为了方差稳定可能需要更大 ,形成偏差-方差权衡。

方差分析

在均匀权重下,假设噪声同方差 (或者在邻域内近似同方差),则:

若采用距离权重 ,以正规化 ,则有:

当权重更集中于最近邻, 增大,方差变大。距离加权在边界与不均匀密度下有助于减少偏差,但会增大方差,需要通过调参(如更大 )补偿。

一致性与收敛

经典结果指出,在适当条件下(包括 有界或平方可积、点 分布的连续点、用合理的度量与权重):

即KNN回归在该点上一致。

收敛率取决于维度 、光滑性指标以及邻域缩放。粗略地,在Hölder光滑性与均匀密度的情形下,局部常数回归的最优收敛率与核回归相近,受维度 影响显著,体现维度灾难:当 增大,所需样本数呈指数增长。

距离度量、特征缩放与度量学习

特征缩放至关重要。不同量纲的特征会让距离度量失真,应对数值型特征做标准化或归一化。

对相关特征可考虑马氏距离,以适应协方差结构。

在高维或复杂特征下,可以引入度量学习(如LMNN、ITML)以学习 使得 更符合任务结构。

对分类变量需特别处理:可以使用合适的编码方案(如one-hot后采用 距离,或定义混合型距离度量)。

完整案例

我们构造一个非线性、异方差、含少量异常值的二维特征数据集(并附加一个无关噪声特征,以体现维度/无关特征对KNN的影响),训练KNN回归模型并进行多维度分析。

数据构建思路

  • 特征维度 ,其中 为有用特征, 为无关噪声特征。
  • 定义真实函数:
  • 异方差噪声:
  • 异常值:随机挑选约2%样本将 加上较大偏移。
  • 样本规模:
  • 训练/测试划分:训练70%,测试30%。

模型与调参

  • 标准化特征(StandardScaler)。
  • 使用KNeighborsRegressor,算法选择auto,权重尝试uniform与distance, 选择范围{1, 2, 3}, 选择范围{3, 5, 7, 11, 21, 31, 51}。
  • 使用GridSearchCV进行5折交叉验证,以负均方误差为评分。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.neighbors import KNeighborsRegressor
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
import seaborn as sns

np.random.seed(42)

# 1) 构造虚拟数据集
n = 2000
# x1, x2 在 [-2, 2] 范围均匀分布,x3 为无关噪声特征
X1 = np.random.uniform(-22, size=n)
X2 = np.random.uniform(-22, size=n)
X3 = np.random.normal(01, size=n)  # 无关噪声特征
X = np.column_stack([X1, X2, X3])

# 真实函数
def f_true(x1, x2):
    return (np.sin(3*x1) + 0.5*np.cos(5*x2) 
            + 0.3*np.sqrt(x1**2 + x2**2)
            + 0.7*np.exp(-2*(x1 - 0.5)**2 - 1.5*(x2 + 0.3)**2))

# 异方差噪声
def sigma(x1, x2):
    return0.15 + 0.35 * (x1 > 0) * np.abs(x2)

y_true = f_true(X1, X2)
noise = np.random.normal(0, sigma(X1, X2))
y = y_true + noise

# 注入异常值(2%)
outlier_mask = np.random.rand(n) < 0.02
y[outlier_mask] += np.random.choice([5.0-5.0], size=np.sum(outlier_mask))

# 训练/测试划分
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.30, random_state=42
)

# 2) 构建Pipeline并进行GridSearchCV
pipe = Pipeline([
    ('scaler', StandardScaler()),
    ('knn', KNeighborsRegressor(algorithm='auto'))
])

param_grid = {
    'knn__n_neighbors': [35711213151],
    'knn__weights': ['uniform''distance'],
    'knn__p': [123],
    'knn__leaf_size': [3060]
}

grid = GridSearchCV(
    estimator=pipe,
    param_grid=param_grid,
    scoring='neg_mean_squared_error',
    cv=5,
    n_jobs=-1,
    verbose=1
)

grid.fit(X_train, y_train)
best_model = grid.best_estimator_
best_params = grid.best_params_
best_score = -grid.best_score_

print("最佳参数:", best_params)
print("CV最优MSE:", best_score)

# 3) 测试集评估
y_pred_test = best_model.predict(X_test)
mse_test = mean_squared_error(y_test, y_pred_test)
mae_test = mean_absolute_error(y_test, y_pred_test)
r2_test = r2_score(y_test, y_pred_test)
print(f"Test MSE={mse_test:.4f}, MAE={mae_test:.4f}, R2={r2_test:.4f}")

# 4) 构造网格以绘制热力图(忽略x3,令其取训练集均值或0)
x1_lin = np.linspace(-22200)
x2_lin = np.linspace(-22200)
X1g, X2g = np.meshgrid(x1_lin, x2_lin)
X3_fixed = np.zeros_like(X1g)  # 固定第三特征为0
X_grid = np.dstack([X1g, X2g, X3_fixed]).reshape(-13)

# 网格上的真实值与预测值
Y_true_grid = f_true(X_grid[:, 0], X_grid[:, 1]).reshape(X1g.shape)
Y_pred_grid = best_model.predict(X_grid).reshape(X1g.shape)
err_grid = (Y_pred_grid - Y_true_grid)

# 5) 为绘制第4子图,统计不同k与weights的CV MSE曲线
# 为了可视化,我们对GridSearch结果进行聚合
results = []
for i in range(len(grid.cv_results_['params'])):
    params = grid.cv_results_['params'][i]
    mean_mse = -grid.cv_results_['mean_test_score'][i]
    results.append((params['knn__weights'], params['knn__n_neighbors'], params['knn__p'], mean_mse))
results = np.array(results, dtype=object)

# 构造两条曲线:p=2时,weights=uniform 与 weights=distance 的MSE随k变化
def aggregate_curve(weight_type, p_val):
    mask = (results[:, 0] == weight_type) & (results[:, 2] == p_val)
    sub = results[mask]
    # 按k排序
    order = np.argsort(sub[:, 1].astype(int))
    k_vals = sub[order, 1].astype(int)
    mse_vals = sub[order, 3].astype(float)
    return k_vals, mse_vals

k_u2, mse_u2 = aggregate_curve('uniform'2)
k_d2, mse_d2 = aggregate_curve('distance'2)

# 6) 可视化
plt.figure(figsize=(1612))

# 图A:真实函数热力图
ax1 = plt.subplot(221)
im1 = ax1.imshow(Y_true_grid, origin='lower', extent=[-22-22], cmap='plasma', aspect='auto')
ax1.set_title('A. Ground Truth f(x1, x2)', fontsize=14, color='#222222')
ax1.set_xlabel('x1')
ax1.set_ylabel('x2')
cb1 = plt.colorbar(im1, ax=ax1, fraction=0.046, pad=0.04)
cb1.set_label('True Value', color='#222222')

# 图B:KNN预测热力图
ax2 = plt.subplot(222)
im2 = ax2.imshow(Y_pred_grid, origin='lower', extent=[-22-22], cmap='viridis', aspect='auto')
ax2.set_title('B. KNN Prediction', fontsize=14, color='#222222')
ax2.set_xlabel('x1')
ax2.set_ylabel('x2')
cb2 = plt.colorbar(im2, ax=ax2, fraction=0.046, pad=0.04)
cb2.set_label('Predicted Value', color='#222222')

# 图C:误差热力图(Pred - True)
ax3 = plt.subplot(223)
im3 = ax3.imshow(err_grid, origin='lower', extent=[-22-22], cmap='magma', aspect='auto')
ax3.set_title('C. Error Map (Prediction - Truth)', fontsize=14, color='#222222')
ax3.set_xlabel('x1')
ax3.set_ylabel('x2')
cb3 = plt.colorbar(im3, ax=ax3, fraction=0.046, pad=0.04)
cb3.set_label('Error', color='#222222')

# 图D:CV MSE随k的变化曲线(p=2)
ax4 = plt.subplot(224)
ax4.plot(k_u2, mse_u2, marker='o', color='#E91E63', label='uniform, p=2', linewidth=2)
ax4.plot(k_d2, mse_d2, marker='s', color='#00BCD4', label='distance, p=2', linewidth=2)
ax4.set_title('D. CV MSE vs k (p=2)', fontsize=14, color='#222222')
ax4.set_xlabel('k (n_neighbors)')
ax4.set_ylabel('Cross-validated MSE')
ax4.grid(True, alpha=0.3)
ax4.legend()

plt.tight_layout(rect=[00.0310.95])
plt.show()

# 7) 更多评估指标与分析
print("更多评估指标:")
print(f"- Test MSE: {mse_test:.4f}")
print(f"- Test MAE: {mae_test:.4f}")
print(f"- Test R2:  {r2_test:.4f}")
print(f"- GridSearch最佳参数: {best_params}")

真实函数热力图

显示 空间内的实际函数形状,包括正弦、余弦、径向项与局部高斯峰的组合。目的在于建立基准参考,观察复杂非线性结构与峰谷分布。

KNN预测热力图

展示模型在同一空间的预测值分布。对比A与B可以直观看出KNN对复杂非线性的拟合能力。一般而言,KNN对局部结构拟合较好,但在数据稀疏或噪声较大区域可能出现过度平滑或者局部抖动现象。

误差热力图

展示预测误差的空间分布。该图对诊断模型的弱点至关重要。通常会观察到在数据密度较低区域(例如边缘)或噪声方差较高区域,误差较大。此外,在函数变化剧烈的区域(例如高斯峰边缘或正弦/余弦急剧变化处),局部常数估计的偏差更显著。

CV MSE vs k

表明模型复杂度(由 控制)与泛化误差的关系。曲线一般呈现U型或缓慢下降-上升的趋势:小 表现为高方差,较大的 实现更稳健但可能引入偏差。对比uniform与distance权重曲线,可以观察到距离加权在某些 范围内或整体上提供更低的MSE(依赖数据结构)。

综上所有的内容,K近邻回归是一个直观、易用且理论基础扎实的非参数回归方法。

通过在局部邻域内对输出进行加权平均实现复杂函数的拟合,具有良好的可解释性与统计一致性。

在合适的距离度量、权重方案与参数选择下,它可以对非线性、异方差数据提供高质量拟合。

然而,其性能与效率高度依赖于特征尺度、维度与数据分布,并且在海量数据与高维场景下面临挑战。通过特征工程、降维、度量学习、鲁棒处理与近似近邻技术,可以显著扩展KNN的适用性与表现。

最后

最近准备了16大块的内容,124个算法问题的总结,完整的机器学习小册,免费领取~
领取:备注「算法小册」即可~
扫码如有问题,记得添加微信号:xiaobai_ml012

【声明】内容源于网络
0
0
机器学习和人工智能AI
让我们一起期待 AI 带给我们的每一场变革!推送最新行业内最新最前沿人工智能技术!
内容 333
粉丝 0
机器学习和人工智能AI 让我们一起期待 AI 带给我们的每一场变革!推送最新行业内最新最前沿人工智能技术!
总阅读220
粉丝0
内容333