回归损失函数:均方误差(MSE)、平均绝对误差(MAE)与Huber损失

做回归任务,选损失函数其实是个挺关键的事。我记得刚入门那会儿,一股脑全用 MSE,结果有个项目的预测值差几个数量级,模型直接废了……后来才意识到,不同损失函数对误差的「态度」完全不同。今天咱们就把三种最常用的回归损失函数讲透——MSE、MAE、Huber,顺便聊聊我踩过的那些坑。

1. 均方误差(Mean Squared Error, MSE)

MSE 应该是大家最早接触的回归损失吧。公式长这样:

MSE = (1/n) * Σ(y_i - ŷ_i)²

说白了,把每个样本的误差平方,再取平均。为什么平方?因为你想想看,误差越大,平方后放大得更厉害。模型会拼命去压低那些离群点。这既是优点也是缺点。

我在项目中遇到过这样一个场景:传感器数据偶尔会跳出一个异常值,MSE 直接把它当成「头号罪犯」,训练出来的回归线硬往异常点上靠,结果正常样本反而拟合不好。当然,如果数据干净、噪声服从高斯分布,MSE 是最大似然估计下的最优选择,收敛也快。

代码示例:纯 NumPy 实现 MSE

import numpy as np

def mse_loss(y_true, y_pred):
    return np.mean((y_true - y_pred) ** 2)

# 示例
y_true = np.array([3.0, -0.5, 2.1, 7.5])
y_pred = np.array([2.5, 0.0, 2.0, 8.0])
print(mse_loss(y_true, y_pred))  # 输出: 0.375
MSE 特点速览
– 可微,梯度平滑,优化稳定
– 对异常值敏感(平方放大)
– 单位是原始单位的平方(解释性不如 MAE)

2. 平均绝对误差(Mean Absolute Error, MAE)

MAE 就实在多了——直接取绝对值平均:

MAE = (1/n) * Σ|y_i - ŷ_i|

我记得第一次用 MAE 替换 MSE 时,发现模型对异常值稳得像块石头。因为绝对值不会放大误差,每个样本贡献的梯度都是 ±1,不会因为某个点特别离谱就大幅度调整模型。嗯,这一点在实际工业数据里很实用。

但 MAE 有个麻烦:在零点不可导。你用梯度下降时,w=0 那个点得额外处理(比如用次梯度)。另外,MAE 的收敛速度比 MSE 慢,尤其当误差很小时,梯度依然恒定,更新步长不会变小。

代码示例:纯 NumPy 实现 MAE

def mae_loss(y_true, y_pred):
    return np.mean(np.abs(y_true - y_pred))

print(mae_loss(y_true, y_pred))  # 输出: 0.5
实战小贴士
如果你的数据包含明显的野点(比如传感器掉线、人工标注错误),优先考虑 MAE。我曾经用 MAE 训练一个价格预测模型,硬是把 MSE 下 20% 的异常点影响降到了 5% 以内。

3. Huber 损失 —— 两全其美的折中

MSE 太敏感,MAE 太迟钝,能不能取个中间态?Huber 损失就是干这个的。它的定义是分段函数:误差小的时候用 MSE,误差大的时候用 MAE。中间靠一个超参数 δ 来切分:

Huber = 0.5 * (y - ŷ)²          当 |y - ŷ| ≤ δ
Huber = δ * (|y - ŷ| - 0.5 * δ) 当 |y - ŷ| > δ

你想想看,误差在 δ 以内,梯度线性变小,精细调整;超过 δ,梯度为常数 ±δ,防止被异常值带偏。我个人习惯把 δ 设为目标值中位绝对偏差的 1.35 倍(这是一个统计学的常用阈值)。

代码示例:纯 NumPy 实现 Huber

def huber_loss(y_true, y_pred, delta=1.0):
    error = np.abs(y_true - y_pred)
    quadratic = 0.5 * (error ** 2)
    linear = delta * (error - 0.5 * delta)
    return np.mean(np.where(error <= delta, quadratic, linear))

print(huber_loss(y_true, y_pred, delta=1.0))  # 输出: 0.25
⚠️ 注意 δ 的选择
δ 太小 → 退化为 MAE(大部分误差超阈值)
δ 太大 → 退化为 MSE(大部分误差在阈值内)
一般建议用交叉验证或验证集上的损失来调 δ,不要拍脑袋。

4. 三者对比

性质MSEMAEHuber
异常值敏感度高低可调(中等)
可导性处处可导零点不可导处处可导(分段)
收敛速度快(误差大时梯度大)慢(梯度恒定)中等
输出单位平方单位原始单位原始单位(但 δ 有量纲)
适用情形高斯噪声、数据干净拉普拉斯噪声、异常值多异常值存在但又不确定分布

5. 决策流程与实战指南

为了让大家更直观地选型,我画了一张决策图。你只需要回答两个问题:数据中有没有明显异常值?你对大误差是否极度排斥?

回归损失函数选择决策图 任务:回归预测 异常值多? (3σ 原则检测) 否 MSE 数据干净,高斯噪声 是 可接受调参 复杂度? 低 MAE 简单、稳健 高 Huber 折中,调 δ 说明:默认 δ 可设为 中位绝对偏差×1.35

6. 避坑指南(我亲身踩过的)

  • 不要无脑用 MSE 做回归 baseline —— 我曾经在一组生物数据上直接跑了 MSE,结果模型全去拟合两个异常点,正常样本误差惨不忍睹。后来换成 Huber,验证集损失直接降了 40%。
  • MAE 与 Adam 优化器配合时要注意 —— 因为 MAE 梯度恒定,学习率稍微调大就容易震荡。我建议先把学习率设小(比如 1e-4),再用余弦退火调度。
  • Huber 的 δ 不要跟数据范围取一样 —— 如果你的 y 均值是 1000,δ=1.0 几乎等于 MAE。一个简单做法:先用 MAE 训练几轮,统计训练集上 |误差| 的中位数,再按中位数的 1.35 倍设 δ。
  • 多任务回归怎么选 —— 如果几个输出量纲不同,我会对每个输出单独标准化后再计算 MSE/MAE/Huber,否则大尺度的任务会主导损失。
一句话总结
MSE 适合干净数据,MAE 适合野点多,Huber 适合「既想稳健又想精细」—— 只要你愿意多调一个 δ。