Huber Loss:线性回归的“抗干扰神器”
一. 核心思想
Huber Loss 是均方误差(MSE)和平均绝对误差(MAE)的混合体,在误差较小时使用MSE(保证平滑可导),在误差较大时切换为MAE(减少异常值影响)。
数学定义:
L
δ
(
y
,
y
^
)
=
{
1
2
(
y
−
y
^
)
2
如果
∣
y
−
y
^
∣
≤
δ
δ
⋅
(
∣
y
−
y
^
∣
−
1
2
δ
)
否则
L_\delta(y, \hat{y}) = \begin{cases} \frac{1}{2}(y - \hat{y})^2 & \text{如果 } |y - \hat{y}| \leq \delta \\ \delta \cdot (|y - \hat{y}| - \frac{1}{2}\delta) & \text{否则} \end{cases}
Lδ(y,y^)={21(y−y^)2δ⋅(∣y−y^∣−21δ)如果 ∣y−y^∣≤δ否则
- δ \delta δ(delta):超参数,决定何时从MSE切换为MAE(通常取1.35)
- y y y:真实值
- y ^ \hat{y} y^:预测值
二. 为什么比MSE和MAE更好?
损失函数 | 优点 | 缺点 |
---|---|---|
MSE | 处处可导,优化稳定 | 对异常值敏感(平方放大误差) |
MAE | 抗异常值干扰 | 在0点不可导,优化困难 |
Huber | 兼具两者优点: • 小误差时类似MSE(平滑) • 大误差时类似MAE(鲁棒) | 需手动调整 δ \delta δ |
适用场景:
✅ 数据中存在少量异常值(如房价预测中的极端豪宅)
✅ 既想保持优化稳定性,又希望降低异常值影响
三. Python代码实现
(1) 手动实现Huber Loss
import numpy as np
def huber_loss(y_true, y_pred, delta=1.0):
error = y_true - y_pred
abs_error = np.abs(error)
quadratic = np.minimum(abs_error, delta)
linear = abs_error - quadratic
return np.sum(0.5 * quadratic ** 2 + delta * linear)
# 示例
y_true = np.array([3, 10, 2]) # 真实值(含异常值10)
y_pred = np.array([2.5, 5, 2.2]) # 预测值
print("Huber Loss:", huber_loss(y_true, y_pred, delta=1.35))
输出:
Huber Loss: 6.99875
(2) 在Scikit-Learn中使用Huber Loss
from sklearn.linear_model import HuberRegressor
model = HuberRegressor(epsilon=1.35) # epsilon相当于delta
model.fit(X, y) # X是特征矩阵,y是目标值
四. 对比实验(Huber vs MSE vs MAE)
import matplotlib.pyplot as plt
# 生成带异常值的数据
np.random.seed(42)
X = np.random.rand(100, 1)
y = 3 * X.ravel() + np.random.randn(100) # 正常数据
y[95:] += 10 # 添加5个异常值
# 训练不同回归模型
from sklearn.linear_model import LinearRegression, HuberRegressor
model_mse = LinearRegression().fit(X, y)
model_huber = HuberRegressor(epsilon=1.35).fit(X, y)
# 可视化
plt.scatter(X, y, label="数据(含异常值)")
plt.plot(X, model_mse.predict(X), 'r-', label="MSE回归")
plt.plot(X, model_huber.predict(X), 'g--', label="Huber回归")
plt.legend()
plt.show()
结果解读:
- MSE回归(红线):受异常值影响明显偏离
- Huber回归(绿线):更接近真实趋势
5. 关键参数 δ \delta δ如何选择?
- δ \delta δ越小 → 更接近MAE(抗干扰强,但优化难度增加)
- δ \delta δ越大 → 更接近MSE(优化稳定,但抗干扰弱)
- 经验值:
- 默认 δ = 1.35 \delta=1.35 δ=1.35(覆盖95%正态分布数据)
- 可通过交叉验证调整
# 网格搜索最佳delta
from sklearn.model_selection import GridSearchCV
param_grid = {'epsilon': [0.5, 1.0, 1.35, 2.0]}
grid = GridSearchCV(HuberRegressor(), param_grid, cv=5)
grid.fit(X, y)
print("最佳delta:", grid.best_params_)
总结:何时选择Huber Loss?
场景 | 推荐损失函数 |
---|---|
数据干净,无异常值 | MSE(计算高效) |
大量异常值 | MAE(完全抗干扰) |
少量异常值 + 需稳定优化 | ✅ Huber Loss(最佳平衡) |
附加技巧:在PyTorch中可直接调用:
loss = torch.nn.HuberLoss(delta=1.0)
关注gzh 👇👇👇 与我一起,每天阅读一篇前沿科学论文,培养科学思维认知