彻底搞懂!MSE vs. MAE !!

哈喽,大家好~

咱们今天系统性地比较均方误差(MSE, Mean Squared Error)与平均绝对误差(MAE, Mean Absolute Error)的核心区别

MSE 的核心:平方惩罚大误差,追求“均值”的最优性。当你关心整体误差的能量(平方)并且你相信噪声近似高斯时,MSE 是统计上最优(MLE)且数值优化极其友好的选择。

MAE 的核心:线性惩罚大误差,追求“中位数”的稳健性。当数据存在重尾(heavy-tailed)或含异常值(outlier)时,MAE 对极端点的影响有上界,因而更稳健,但优化上因不可导点(在0处)相对更困难一些。

形式化定义、风险最小化与最优解

经验风险与目标

给定数据集 ,回归模型  的两个常见经验风险如下:

MSE 经验风险:

MAE 经验风险:

期望风险与贝叶斯最优估计

从统计学习角度,我们常考虑条件风险(以  条件化):

对于 MSE,对任意可测函数 ,其条件期望风险为

  求导并令其为 0:

得到最优解

即 MSE 的贝叶斯最优预测是条件均值。

对于 MAE,

考虑次梯度(用  表示符号函数):

令其包含 0:

从而

即 MAE 的贝叶斯最优预测是条件中位数(在连续分布下唯一)。

结论:MSE 估计条件均值,MAE 估计条件中位数。若噪声对称且均值=中位数(如严格对称分布),两者一致;若噪声偏态或含异常值,它们会系统性偏离。

概率模型视角(MLE)

高斯噪声:若 ,负对数似然

最大似然等价于最小化 MSE。

拉普拉斯噪声:若 ,负对数似然

最大似然等价于最小化 MAE。

这给出“何时谁更优”的统计前提:高斯→MSE;拉普拉斯或重尾→MAE 更稳健。

优化性质与计算层面

凸性与可导性

两者在参数为线性模型的情形下均为凸函数(在  上凸)。

MSE 光滑可导,梯度连续:

大型深度模型中它对优化算法(如 SGD/Adam)更友好。

MAE 在残差为 0 处不可导,但有次梯度:

优化可用亚梯度法或平滑近似(如 Huber 损失)。

问题条件与闭式解

线性回归 + MSE ⇒ 正规方程有闭式解:

线性回归 + MAE ⇒ 无简单闭式解,经典方法可转为线性规划或用坐标下降/内点法,或用深度学习框架的 L1Loss 直接数值优化。

鲁棒性、影响函数与异常值

影响函数视角:

令残差 。从 M-estimation 角度定义“影响函数”近似与  相关。

  • MSE: (无界)。残差越大,影响线性增大,异常值权重爆炸。
  • MAE: (有界)。残差再大,影响也不再增长(就 y 方向而言),因此对 y 方向异常值更稳健。

注意:两者都可能受“高杠杆点”(极端的 x)影响,尤其在回归中,高杠杆点结合大残差会严重拉动拟合;MAE 在 y 异常上的影响有界,但对极端的 x 杠杆并非万无一失。

breakdown point(破坏点)

位置估计:样本均值的破坏点为 0(任意大异常值可将均值拖走),样本中位数破坏点为 0.5(半数以下异常不致于毁掉中位数)。

回归中的 LAD(MAE 回归)在理论上对 y 方向异常更稳健,但总体 breakdown point 仍不是 0.5;若存在强杠杆 x 异常仍可击穿。若需强鲁棒可用 LTS/LMS 或 RANSAC 等方法。

偏差-方差、效率与度量单位

MSE 惩罚平方残差,相当于给大残差更高权重,这通常降低估计的方差但增加对重尾的脆弱性。在高斯噪声下,MSE 对均值估计是有效(Cramér–Rao 下界达到)。

MAE 惩罚线性残差,稳健但在高斯情形下效率低于 MSE(需要更多样本达同样精度)。当噪声重尾或含异常,MAE 的稳健性会带来实际误差更低。

单位与可解释性:MSE 的单位是“平方单位”,RMSE 才回到原单位;MAE 直接是“原单位”,经常更易解释。

与 Huber 的联系

Huber 损失在小误差时像 MSE,大误差时像 MAE:

这是在优化友好与鲁棒性之间的折中。本文聚焦 MSE vs MAE,但实践中 Huber 常见。

一个完整案例

含异方差与异常值的线性回归

我们构造一个线性真模型,叠加随 x 变化的异方差高斯噪声,并注入一批强异常值。

分别使用 MSE 与 MAE 训练线性模型,比较拟合曲线、残差分布与训练动态。

import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
import copy
import random

# 1) 随机种子
seed = 42
np.random.seed(seed)
torch.manual_seed(seed)
random.seed(seed)

# 2) 生成虚拟数据:线性真值 + 异方差 + 异常值
n = 2000
x = np.random.uniform(-33, size=n)
x = np.sort(x)  # 方便可视化
true_w, true_b = 1.2-0.7
y_clean = true_w * x + true_b

# 异方差噪声: sigma 随 |x| 增大
sigma = 0.2 + 0.3 * np.abs(x)
y = y_clean + np.random.normal(0, sigma, size=n)

# 注入异常值(y方向):10%
outlier_ratio = 0.1
o = int(n * outlier_ratio)
outlier_idx = np.random.choice(n, size=o, replace=False)
y[outlier_idx] += np.random.normal(06.0, size=o) + np.random.choice([-11], size=o) * 8.0
is_outlier = np.zeros(n, dtype=bool)
is_outlier[outlier_idx] = True

# 转为 tensor
X = torch.tensor(x, dtype=torch.float32).view(-11)
Y = torch.tensor(y, dtype=torch.float32).view(-11)

# 3) 定义简单线性模型
class LinReg(nn.Module):
    def __init__(self):
        super().__init__()
        self.linear = nn.Linear(11, bias=True)
    def forward(self, x):
        return self.linear(x)

base_model = LinReg()
# 为公平性,MSE 与 MAE 从相同初始化出发
model_mse = copy.deepcopy(base_model)
model_mae = copy.deepcopy(base_model)

# 4) 训练设置
epochs = 800
lr = 0.05

criterion_mse = nn.MSELoss()
criterion_mae = nn.L1Loss()

opt_mse = optim.Adam(model_mse.parameters(), lr=lr)
opt_mae = optim.Adam(model_mae.parameters(), lr=lr)

loss_hist_mse = []
loss_hist_mae = []

# 5) 同步训练
for ep in range(epochs):
    # MSE step
    opt_mse.zero_grad()
    pred_mse = model_mse(X)
    loss_mse = criterion_mse(pred_mse, Y)
    loss_mse.backward()
    opt_mse.step()
    loss_hist_mse.append(loss_mse.item())

    # MAE step
    opt_mae.zero_grad()
    pred_mae = model_mae(X)
    loss_mae = criterion_mae(pred_mae, Y)
    loss_mae.backward()
    opt_mae.step()
    loss_hist_mae.append(loss_mae.item())

# 6) 训练后预测与残差
with torch.no_grad():
    yhat_mse = model_mse(X).numpy().ravel()
    yhat_mae = model_mae(X).numpy().ravel()

res_mse = y - yhat_mse
res_mae = y - yhat_mae

# 7) 计算评估指标
def rmse(a): 
    return np.sqrt(np.mean(a**2))
def mae(a): 
    return np.mean(np.abs(a))

rmse_mse_fit = rmse(res_mse)
mae_mse_fit = mae(res_mse)
rmse_mae_fit = rmse(res_mae)
mae_mae_fit = mae(res_mae)

# 8) 为绘图准备网格线
xx = np.linspace(x.min()-0.3, x.max()+0.3200)
with torch.no_grad():
    XX = torch.tensor(xx, dtype=torch.float32).view(-1,1)
    yy_mse_line = model_mse(XX).numpy().ravel()
    yy_mae_line = model_mae(XX).numpy().ravel()
yy_true_line = true_w * xx + true_b

# 9) 可视化
plt.figure(figsize=(1410))

# 子图1:数据+拟合曲线(含异常值标记)
ax1 = plt.subplot(2,2,1)
ax1.scatter(x[~is_outlier], y[~is_outlier], s=22, c='cyan', edgecolor='k', alpha=0.75, label='Inliers')
ax1.scatter(x[is_outlier], y[is_outlier], s=28, c='magenta', edgecolor='k', alpha=0.9, label='Outliers')
ax1.plot(xx, yy_true_line, color='limegreen', lw=3, label='True line')
ax1.plot(xx, yy_mse_line, color='crimson', lw=2.5, label='MSE fit')
ax1.plot(xx, yy_mae_line, color='dodgerblue', lw=2.5, label='MAE fit')
ax1.set_title('拟合对比:含异方差与异常值', fontsize=12)
ax1.set_xlabel('x')
ax1.set_ylabel('y')
ax1.legend(loc='best')
ax1.grid(True, alpha=0.3)

# 子图2:残差分布对比(直方图+位置统计)
ax2 = plt.subplot(2,2,2)
bins = 32
ax2.hist(res_mse, bins=bins, color='crimson', alpha=0.55, density=True, label=f'MSE残差\nRMSE={rmse_mse_fit:.3f}\nMAE={mae_mse_fit:.3f}')
ax2.hist(res_mae, bins=bins, color='dodgerblue', alpha=0.55, density=True, label=f'MAE残差\nRMSE={rmse_mae_fit:.3f}\nMAE={mae_mae_fit:.3f}')
# 标注均值与中位数
mse_mean = np.mean(res_mse); mse_med = np.median(res_mse)
mae_mean = np.mean(res_mae); mae_med = np.median(res_mae)
ax2.axvline(mse_mean, color='crimson', ls='--', lw=2, label=f'MSE-mean={mse_mean:.2f}')
ax2.axvline(mae_med, color='dodgerblue', ls='-.', lw=2, label=f'MAE-median={mae_med:.2f}')
ax2.set_title('残差分布与位置统计', fontsize=12)
ax2.set_xlabel('residual')
ax2.set_ylabel('density')
ax2.legend(loc='best', fontsize=9)
ax2.grid(True, alpha=0.3)

# 子图3:训练曲线(log y 轴)
ax3 = plt.subplot(2,2,3)
epochs_arr = np.arange(1, epochs+1)
ax3.plot(epochs_arr, loss_hist_mse, color='crimson', lw=2.2, label='MSE loss')
ax3.plot(epochs_arr, loss_hist_mae, color='dodgerblue', lw=2.2, label='MAE loss')
ax3.set_yscale('log')
ax3.set_title('训练损失曲线(对数刻度)', fontsize=12)
ax3.set_xlabel('epoch')
ax3.set_ylabel('training loss (log)')
ax3.legend(loc='best')
ax3.grid(True, alpha=0.3)

# 子图4:损失与梯度对残差的形状(理论曲线)
ax4 = plt.subplot(2,2,4)
e = np.linspace(-1010400)
L_mse = e**2
L_mae = np.abs(e)
g_mse = 2*e
g_mae = np.sign(e)
# 左轴:损失
ln1, = ax4.plot(e, L_mse, color='crimson', lw=2, label='MSE loss e^2')
ln2, = ax4.plot(e, L_mae, color='dodgerblue', lw=2, label='MAE loss |e|')
ax4.set_xlabel('residual e')
ax4.set_ylabel('loss')
ax4.set_title('损失与梯度随残差的变化', fontsize=12)
ax4.grid(True, alpha=0.3)
# 右轴:梯度
ax4b = ax4.twinx()
ln3, = ax4b.plot(e, g_mse, color='orange', lw=2, ls='--', label='d/d e MSE = 2e')
ln4, = ax4b.plot(e, g_mae, color='limegreen', lw=2, ls='-.', label='d/d e MAE = sign(e)')
ax4b.set_ylabel('gradient w.r.t e')
# 合并图例
lines = [ln1, ln2, ln3, ln4]
labels = [l.get_label() for l in lines]
ax4.legend(lines, labels, loc='upper left', fontsize=9)

plt.tight_layout()
plt.show()

# 10) 打印回归系数
w_mse = list(model_mse.parameters())[0].detach().numpy().ravel()[0]
b_mse = list(model_mse.parameters())[1].detach().numpy().ravel()[0]
w_mae = list(model_mae.parameters())[0].detach().numpy().ravel()[0]
b_mae = list(model_mae.parameters())[1].detach().numpy().ravel()[0]

print(f"True w={true_w:.3f}, b={true_b:.3f}")
print(f"MSE  fit: w={w_mse:.3f}, b={b_mse:.3f}, RMSE={rmse_mse_fit:.3f}, MAE={mae_mse_fit:.3f}")
print(f"MAE  fit: w={w_mae:.3f}, b={b_mae:.3f}, RMSE={rmse_mae_fit:.3f}, MAE={mae_mae_fit:.3f}")
彻底搞懂!MSE vs. MAE !!图1

图一,拟合对比:展示在异方差与存在 10% 明显异常值(y 方向)的情况下,两种损失学得的回归直线。

MSE 曲线更受异常值牵引(尤其是偏离极大的点),出现明显偏斜,使整体拟合偏离多数样本的“中位趋势”;

MAE 曲线对极端点的影响有上限,拟合更贴近主干数据云的中位走向,更稳健。

这印证了“平方惩罚更偏重大残差”的直觉。

图二,残差分布:叠加两种残差的直方图(密度化),并标注位置统计(例如 MSE 残差均值、MAE 残差中位数)。说明:

MSE 优化使“平方意义下的平均偏差”最小,残差均值更趋近 0;但在重尾/异常值下,方差更大(长尾更明显)。

MAE 优化使“绝对偏差的中位位置”居中,残差中位数更接近 0;分布对异常值相对不那么敏感。

图三,训练曲线:对数刻度下显示两种损失的训练过程。

MSE 的梯度平滑、收敛稳定,下降较为迅速;

MAE 因不可导点(在 e=0)存在,用次梯度下降会出现台阶感、收敛相对缓一些,但能到稳健解。

若在没有异常值的理想高斯环境中,MSE 往往更快更优(统计效率高);但有异常时,MAE 的最终质量更可能更好(具体看你评价指标)。

图四,损失与梯度形状:理论曲线清晰展示了

MSE 损失  随残差幅度快速增长,其梯度  无界;大残差样本在训练中被赋予极高“话语权”,是异常值敏感的根源;

MAE 损失  线性增长,其梯度  有界;残差再大也不会成倍放大训练驱动力,解释了其鲁棒性。

核心区别

  • 统计目标:MSE 学的是条件均值,MAE 学的是条件中位数;
  • 分布假设:高斯噪声 → MSE 为 MLE;拉普拉斯或重尾 → MAE 更稳健;
  • 鲁棒性:MSE 对大残差影响无界,异常值会极大牵引;MAE 在 y 方向有界影响,更稳健,但仍可能受高杠杆 x 的影响;
  • 优化:MSE 光滑易优化有闭式解(线性情形);MAE 不可导但可用次梯度、线性规划或 Huber 平滑;
  • 可解释性:MAE 单位与原量纲一致;MSE 需取平方根(RMSE)才具直观单位。

侧重点与选择建议

  • 如果数据干净、噪声近似高斯、且你关心整体平方误差:优先 MSE(或 RMSE 作为指标)。
  • 如果数据含异常或重尾、你关心典型个体的偏差或中位趋势:考虑 MAE 或 Huber。
  • 如果你需要分布的不同分位数(如 90% 分位的保障水平):用分位数回归(pinball loss)。
  • 若你处在工业系统中,先做数据清洗/异常检测,再用 MSE 通常也能得到优雅解;清洗不充分时,MAE/Huber 能提供更稳健的第一道防线。

本文案例中,在含异方差与 10% 异常值的设置下,MAE 拟合更贴近主干数据,中位残差居中更明显;MSE 则更受异常点牵引,残差长尾更显著。

损失与梯度曲线清楚说明了“权重放大”的机制差别:平方损失“惩大放小”、绝对损失“等权对待”。

最后

最近准备了的总结,完整的机器学习小册,免费领取~
彻底搞懂!MSE vs. MAE !!图2
领取:备注「算法小册」即可~
彻底搞懂!MSE vs. MAE !!图3

声明:内容取材于网络,仅代表作者观点,如有内容违规问题,请联系处理。 
more
上海半导体制造“小巨人”启动IPO!给晶圆厂打通“高速公路”
刚刚,上海GPU龙头IPO注册生效!
首发2000万台?消息称苹果首款折叠iPhone 屏幕供应链、组装厂已定
变厚变重!iPhone 18 Pro Max反向升级,把果粉整懵了
Cloudflare全球故障影响众多网站,iPhone Air设计师离职,Gemini 3预览版上线,这就是今天的其他大新闻!
688795,北京“英伟达”启动发行!上海“英伟达” IPO获批!
iPhone可以检测针孔摄像头?官方回应
氮矽累计推出两款GaN PIIP低压氮化镓芯片,有效简化电源系统设计
1.8万元起售的iPhone Fold,凭什么敢卖这么贵?看完这3个技术突破,我懂了!
砸 43 亿!长江存储是大股东的武汉新芯启动IPO
Copyright © 2025 成都区角科技有限公司
蜀ICP备2025143415号-1
  
川公网安备51015602001305号