从加权平均到多项式拟合:局部加权回归的进阶之路

张开发
2026/4/17 3:12:01 15 分钟阅读

分享文章

从加权平均到多项式拟合:局部加权回归的进阶之路
1. 从加权平均到局部回归理解核平滑的本质我第一次接触核平滑方法时被它优雅的数学形式深深吸引。想象你是一位气象学家手头有一堆散乱的气温观测数据想要绘制一条平滑的气温变化曲线。传统方法可能会对所有数据点一视同仁但核平滑教会我们离目标点越近的数据应该拥有更大的话语权。核平滑的核心思想可以用一个生活场景来理解当你估算某地的房价时周边3公里内的成交价显然比30公里外的更具参考价值。数学上我们通过核函数来实现这种就近原则。最常用的高斯核函数就像一座小山丘山顶对准目标点权重向四周递减def gaussian_kernel(x, xi, h): return np.exp(-(x - xi)**2 / (2 * h**2))这里的h参数控制着邻域范围就像调节望远镜的焦距。h值越小视野越窄只关注极近邻的数据h值越大视野越广考虑更多远处数据。我在处理股票价格数据时发现h0.3能很好捕捉日间波动而h1.0更适合分析长期趋势。但核平滑有个致命弱点——边界效应。就像站在窗户边看风景只能看到单侧的景象。当目标点位于数据边界时比如时间序列的首尾可用的邻域数据严重不足导致拟合曲线出现明显偏差。这个问题在我分析季度销售数据时尤为突出每年Q1和Q4的预测总是不尽人意。2. 加权最小二乘法给数据加上智能滤镜为了突破核平滑的局限我们需要更强大的数学工具——加权最小二乘法(WLS)。这就像给普通最小二乘回归装上了智能滤镜让不同数据点拥有不同的话语权。理解WLS的关键在于认识它的损失函数J(θ) Σ w_i [y_i - f(x_i)]²其中w_i就是数据点的权重。我在电商用户行为分析中应用这个方法时给高价值用户的点击数据赋予更大权重使模型更关注核心用户群体。WLS的求解过程也充满智慧def weighted_least_squares(X, y, weights): W np.diag(weights) theta np.linalg.inv(X.T W X) X.T W y return theta这个公式中的矩阵运算本质上是在寻找能让加权误差最小的解。记得第一次实现这个算法时我忘了对权重矩阵W取逆结果拟合出的曲线完全偏离预期——这个教训让我深刻理解了每个数学符号的实际意义。3. 局部多项式回归给每个点定制拟合曲线将前两节的思路结合就诞生了局部多项式回归这把瑞士军刀。它的精妙之处在于不再满足于简单的加权平均而是为每个点的邻域拟合一个独立的多项式模型。想象你在山区绘制等高线平坦区域用线性近似就够了但在陡峭地带需要更复杂的曲线。局部多项式回归正是这样工作的def local_polynomial_fit(x_target, x, y, degree, h): # 计算权重 weights gaussian_kernel(x, x_target, h) # 构建设计矩阵 X np.column_stack([x**i for i in range(degree1)]) # 加权最小二乘求解 theta weighted_least_squares(X, y, weights) # 返回目标点拟合值 return np.dot([x_target**i for i in range(degree1)], theta)我在处理传感器数据时发现二阶多项式(d2)在大多数情况下表现最佳。它足够灵活以捕捉曲线变化又不会因过度复杂而导致过拟合。下图展示了不同阶数的对比效果多项式阶数优点缺点0 (常数)最稳定无法捕捉趋势1 (线性)计算高效无法拟合弯曲2 (二次)平衡性好可能过拟合≥3 (高次)极度灵活极易过拟合4. 实战用Python实现完整流程让我们通过一个完整案例看看如何用局部多项式回归解决实际问题。假设我们要分析某城市24小时温度变化数据带有噪声import numpy as np import matplotlib.pyplot as plt # 生成模拟数据 np.random.seed(42) hours np.linspace(0, 24, 100) true_temp 10 10*np.sin(2*np.pi*hours/24) noisy_temp true_temp np.random.normal(0, 2, sizelen(hours)) # 局部二次回归实现 def local_quadratic(x, y, h3.0): y_pred np.zeros_like(x) for i, xi in enumerate(x): weights np.exp(-(x - xi)**2 / (2*h**2)) X np.column_stack([np.ones_like(x), x-xi, (x-xi)**2]) W np.diag(weights) theta np.linalg.inv(X.T W X) X.T W y y_pred[i] theta[0] # 在xi处的预测值 return y_pred # 不同带宽比较 plt.figure(figsize(12,6)) plt.scatter(hours, noisy_temp, alpha0.3, label观测数据) plt.plot(hours, true_temp, k--, label真实趋势) for h, color in [(1.5, red), (3.0, blue), (6.0, green)]: pred local_quadratic(hours, noisy_temp, h) plt.plot(hours, pred, labelfh{h}) plt.xlabel(时间(小时)) plt.ylabel(温度(℃)) plt.legend() plt.show()这段代码揭示了几个关键点带宽h的选择至关重要——h1.5捕捉了太多噪声h6.0又过度平滑局部二次回归成功还原了温度变化的周期性特别是在边界处(0点和24点)表现良好计算量较大因为需要为每个点单独求解加权最小二乘问题在实际项目中我通常会使用Scikit-learn的LocalRegression类它优化了计算效率from sklearn.neighbors import KernelRegression model KernelRegression(kernelrbf, gamma0.1, alpha0.5) model.fit(hours[:, None], noisy_temp) pred model.predict(hours[:, None])5. 进阶技巧与常见陷阱经过多个项目的实战我总结出一些宝贵经验。带宽选择是首要难题——太小的带宽导致过拟合太大则欠拟合。我常用的方法是交叉验证from sklearn.model_selection import GridSearchCV params {gamma: np.logspace(-2, 1, 20)} grid GridSearchCV(KernelRegression(kernelrbf), param_gridparams, cv5) grid.fit(X, y) best_gamma grid.best_params_[gamma]另一个常见错误是忽视数据尺度。当特征量纲差异大时如房价vs面积必须先标准化from sklearn.preprocessing import StandardScaler scaler StandardScaler() X_scaled scaler.fit_transform(X) model.fit(X_scaled, y)对于高维数据局部回归会遭遇维度灾难。这时可以考虑使用维度约简技术(PCA/t-SNE)切换到基于树的局部方法(如随机森林)采用加性模型简化结构最让我印象深刻的一个案例是预测共享单车需求。原始数据包含时间、天气、位置等多维特征。通过局部线性回归我们发现不同区域的天气影响差异巨大——商业区对雨天更敏感而居民区则更受温度影响。这种细粒度的洞察是全局模型无法提供的。

更多文章