局部加权回归(Locally Weighted Regression)是机器学习中一种经典的回归方法,它通过赋予不同数据点不同的权重来捕捉数据的局部特征。与全局回归方法不同,局部加权回归能够更好地适应数据的非线性结构,因此在许多实际应用中表现出色。然而,要真正掌握这一方法,我们需要深入理解其背后的核心概念和原理。
核函数在局部加权回归中扮演着至关重要的角色,它决定了不同数据点对当前预测点的贡献程度。很多人误以为核函数仅仅是距离的权重函数,实际上它的作用远不止于此。
核函数的本质在于它定义了局部邻域的形状和大小,同时控制了权重随距离变化的衰减方式。不同的核函数会导致回归结果表现出不同的特性:
高斯核(Gaussian Kernel):
python复制def gaussian_kernel(distance, h):
return np.exp(-(distance**2)/(2*h**2))
高斯核是最常用的核函数之一,它平滑地衰减权重,没有明确的边界。这意味着理论上所有数据点都会对当前预测点产生一定影响,尽管远处的点影响微乎其微。
Epanechnikov核:
python复制def epanechnikov_kernel(distance, h):
t = distance / h
return 0.75 * (1 - t**2) if t <= 1 else 0
这是一个抛物线形状的核函数,具有明确的边界(当距离超过h时权重直接降为0),计算效率高但不够平滑。
Tri-cube核:
python复制def tri_cube_kernel(distance, h):
t = distance / h
return (1 - abs(t)**3)**3 if t <= 1 else 0
Tri-cube核在边界处更加平滑,能够产生比Epanechnikov核更稳定的结果。
这三种核函数的区别可以通过下表清晰对比:
| 特性 | 高斯核 | Epanechnikov核 | Tri-cube核 |
|---|---|---|---|
| 支撑集 | 无限 | 有限 | 有限 |
| 平滑度 | C∞ | C1 | C2 |
| 计算效率 | 较低 | 高 | 中等 |
| 边界效应 | 无 | 明显 | 较轻微 |
提示:在实际应用中,Tri-cube核通常是一个很好的折中选择,它既有有限支撑集带来的计算优势,又保持了较好的平滑性。
带宽参数h是局部加权回归中最重要的超参数之一,它直接影响模型的性能表现。理解h的作用机制对于正确使用局部加权回归至关重要。
带宽的双重作用体现在:
控制邻域大小:h越大,参与局部拟合的数据点越多,回归曲线越平滑;h越小,回归曲线越能捕捉细节特征,但也更容易受到噪声影响。
调节方差-偏差权衡:
在实际操作中,我们可以通过交叉验证来选择最优带宽。以下是一个简单的带宽选择示例:
python复制from sklearn.model_selection import GridSearchCV
from sklearn.neighbors import KernelRegression
# 假设X和y是我们的数据
param_grid = {'bandwidth': np.logspace(-2, 1, 20)}
grid = GridSearchCV(KernelRegression(kernel='gaussian'), param_grid, cv=5)
grid.fit(X, y)
best_h = grid.best_params_['bandwidth']
带宽选择的一些经验法则:
注意:最优带宽通常与数据尺度相关,因此在应用前最好对数据进行标准化处理。
局部多项式回归的核心思想可以形象地描述为"移动的加权最小二乘",这一概念揭示了其与传统回归方法的本质区别。
移动加权最小二乘的过程:
这个过程可以用数学公式表示为:
对于每个x₀,我们求解:
math复制\hat{\beta}(x_0) = \arg\min_{\beta} \sum_{i=1}^n K_h(x_i - x_0)(y_i - \sum_{j=0}^p \beta_j(x_i - x_0)^j)^2
其中p是多项式阶数,K_h是带宽为h的核函数。
**局部线性回归(p=1)**是最常用的形式,它在每个局部邻域内拟合一条直线。相比简单的核平滑,局部线性回归能更好地处理边界效应。
实现局部线性回归的关键步骤:
python复制def local_linear_regression(x, X, y, h, kernel):
"""
x: 预测点
X: 训练数据特征
y: 训练数据标签
h: 带宽
kernel: 核函数
"""
# 计算权重
weights = kernel(np.abs(X - x)/h)
W = np.diag(weights)
# 设计矩阵
X_design = np.column_stack([np.ones_like(X), X - x])
# 加权最小二乘解
beta = np.linalg.inv(X_design.T @ W @ X_design) @ X_design.T @ W @ y
# 返回预测值(即截距项)
return beta[0]
边界偏差是核平滑方法中常见的问题,理解其产生原因和解决方案对于实际应用至关重要。
边界偏差的产生原因:
局部多项式回归通过以下机制缓解边界偏差:
我们可以通过一个简单的例子来展示边界偏差及其改善:
python复制# 生成边界效应明显的数据
x = np.linspace(0, 2, 100)
y = np.exp(x) + np.random.normal(0, 0.2, 100)
# 核平滑
kern_smooth = KernelRegression(kernel='gaussian', bandwidth=0.3).fit(x[:, None], y)
y_kern = kern_smooth.predict(x[:, None])
# 局部线性回归
local_linear = KernelRegression(kernel='gaussian', bandwidth=0.3).fit(x[:, None], y)
y_linear = local_linear.predict(x[:, None])
# 绘图比较
plt.figure(figsize=(10, 6))
plt.scatter(x, y, s=10, label='Data')
plt.plot(x, np.exp(x), 'k-', label='True function')
plt.plot(x, y_kern, 'r-', label='Kernel smoothing')
plt.plot(x, y_linear, 'b--', label='Local linear')
plt.legend()
plt.title('Boundary Bias Comparison')
从图中可以明显看出,局部线性回归在边界区域(特别是右边界)的表现要优于简单的核平滑方法。
在实际应用中,核函数和多项式阶数的选择需要综合考虑数据特征和计算需求。以下是一些实用的选择指南:
核函数选择考虑因素:
| 数据特征 | 推荐核函数 | 原因 |
|---|---|---|
| 计算资源有限 | Epanechnikov | 计算效率高 |
| 需要高平滑性 | 高斯核 | 无限支撑,非常平滑 |
| 边界效应明显 | Tri-cube | 平衡平滑与边界表现 |
| 数据有离群点 | 稳健核(如双平方) | 对异常值不敏感 |
多项式阶数选择指南:
零阶(核平滑):
一阶(局部线性):
二阶(局部二次):
噪声水平的影响:
一个实用的选择流程:
python复制def select_model(X, y):
# 尝试不同组合
models = {
'Epanechnikov_0': KernelRegression(kernel='epanechnikov', bandwidth=0.5),
'Gaussian_1': KernelRegression(kernel='gaussian', bandwidth=0.5),
'Tri-cube_2': KernelRegression(kernel='tricube', bandwidth=0.5)
}
# 交叉验证
results = {}
for name, model in models.items():
scores = cross_val_score(model, X, y, cv=5, scoring='neg_mean_squared_error')
results[name] = -scores.mean()
# 返回最佳模型
best_name = min(results, key=results.get)
return models[best_name], results
在实际项目中,我经常发现局部线性回归(一阶多项式)配合Tri-cube核是一个稳健的默认选择。它能在大多数情况下提供良好的性能,同时不会引入过多的计算复杂度。对于特别复杂的数据模式,可以尝试二阶多项式,但要注意验证其是否真的带来了性能提升。