损失函数的定义和实现(附代码演示)

530 阅读3分钟

损失函数的定义与作用

什么是损失函数?

  • 损失函数(Loss Function)——是一个衡量预测结果与真实结果之间差异的函数 ,也称为误差函数。它通过计算模型的预测值与真实值之间的不一致程度,来评估模型的性能。

损失函数的作用

  • 简单来说,测试数据通过模型计算会得到一个预测值,而损失函数就是反应预测值与真实值之间的差距,损失值越小,那么说明模型预测效果越好。
  • 损失函数的作用:损失函数除了反应模型拟合数据的优劣,还经常用于指导神经网络的参数优化。在神经网络的训练过程,损失函数通过反向传播,梯度下降实现参数更新。

常用的损失函数

回归任务与分类任务的损失对比

对比维度回归任务损失分类任务损失
输出类型连续值离散类别(概率分布)
计算方式直接计算数值间的距离计算概率分布的差异
典型函数MSE、MAE交叉熵、Hinge Loss
  • 总结
    • 回归损失:衡量数值准确性,适用于连续值的预测。
    • 分类损失:衡量概率匹配性,适用于离散标签预测。

回归任务常用的损失函数

1. MSE均方误差

  • **均方误差(MSE)**是回归任务中最常用的损失函数之一,用于衡量模型预测值与真实值之间的差异。它的核心思想是计算预测误差的平方均值,使较大的误差受到更严重的惩罚。

  • 均方误差的数学定义如下:

    MSE(y,y^)=1ni=1n(yiy^i)2\text{MSE}(y, \hat{y}) = \frac{1}{n} \sum_{i=1}^{n} (y_i - \hat{y}_i)^2
    • nn是样本数量。
    • yiy_i是第ii个真实值。
    • yi^\hat{y_i}是第ii个预测值。
  • 均方误差的特点

    • 优点:

      可导性:MSE 是光滑可导的函数,便于梯度下降优化。 对大误差敏感:平方操作使较大的误差被放大,促使模型更关注异常值。

    • 缺点:

      对异常值敏感:如果数据中存在离群点(Outliers),MSE 会变得很大,影响模型训练。

      量纲问题:由于计算的是平方误差,MSE 的单位是原单位的平方(如预测房价时,单位是“元²”),解释性稍差。

  • 均方误差的代码实现:

    • numpy实现:

      import numpy as np
      
      def mean_squared_error(y_true, y_pred):
          return np.mean((y_true - y_pred) ** 2)
      
      # 示例
      y_true = np.array([3, -0.5, 2, 7])  # 真实值
      y_pred = np.array([2.5, 0.0, 2, 8])  # 预测值
      
      mse = mean_squared_error(y_true, y_pred)
      print(f"MSE: {mse:.4f}")  # 输出: MSE: 0.3750
      
    • pytorch实现:

      import torch
      import torch.nn as nn
      
      # 定义 MSE 损失
      mse_loss = nn.MSELoss()
      
      # 输入必须是张量(Tensor)
      y_true = torch.tensor([3.0, -0.5, 2.0, 7.0])
      y_pred = torch.tensor([2.5, 0.0, 2.0, 8.0])
      
      loss = mse_loss(y_pred, y_true)
      print(f"MSE: {loss.item():.4f}")  # 输出: MSE: 0.3750
      

2. MAE平均绝对误差

  • 平均绝对误差(MAE)是回归任务中常用的损失函数,用于衡量模型预测值与真实值之间的绝对差异的平均值。与均方误差(MSE)不同,MAE 对误差的惩罚是线性的,因此对异常值(Outliers)的敏感度较低。

  • 平均绝对误差的数学定义如下:

    MAE(y,y^)=1ni=1nyiyi^MAE(y,\hat{y})=\frac{1}{n}\sum_{i=1}^n|y_i-\hat{y_i}|

    其中:

    • nn是样本数量。
    • yiy_i是第ii个真实值。
    • yi^\hat{y_i}是第ii个预测值。
  • 平均绝对误差的特点

    • 优点对异常值鲁棒性强:由于采用绝对值而非平方,MAE 不会过度放大异常值的影响,适用于噪声较多的数据。

      直观易解释:MAE 的单位与原始数据一致(如预测房价时,单位是“元”),便于业务理解。

      梯度稳定:梯度始终为 ±1,优化过程更稳定(相比 MSE 的梯度随误差增大而增大)。

    • 缺点

      在优化中可能收敛较慢:由于梯度恒定,模型在接近最优解时可能调整较慢(MSE 的梯度会逐渐减小,收敛更快)。

      不可导的点:在 yi=y^iy**i=y^i 处不可导(但实际优化中可通过次梯度方法处理)。

  • 平均绝对误差的代码实现

    • numpy实现:

      import numpy as np
      
      def mean_absolute_error(y_true, y_pred):
          return np.mean(np.abs(y_true - y_pred))
      
      # 示例
      y_true = np.array([3, -0.5, 2, 7])  # 真实值
      y_pred = np.array([2.5, 0.0, 2, 8])  # 预测值
      
      mae = mean_absolute_error(y_true, y_pred)
      print(f"MAE: {mae:.4f}")  # 输出: MAE: 0.5000
      
    • pytorch实现:

      import numpy as np
      
      def mean_absolute_error(y_true, y_pred):
          return np.mean(np.abs(y_true - y_pred))
      
      # 示例
      y_true = np.array([3, -0.5, 2, 7])  # 真实值
      y_pred = np.array([2.5, 0.0, 2, 8])  # 预测值
      
      mae = mean_absolute_error(y_true, y_pred)
      print(f"MAE: {mae:.4f}")  # 输出: MAE: 0.5000
      

3. 两种损失函数的对比

损失函数MAEMSE
误差惩罚方式绝对值(线性)平方(非线性)
对异常值敏感性鲁棒(低敏感)敏感(放大异常值)
梯度性质恒定(±1)随误差增大而增大
适用场景数据含噪声/异常值需要强调大误差的任务
单位与原数据一致(如“元”)原数据的平方(如“元²”)
  • 总结

    • 选MAE

      数据中存在异常值或者需要直观的误差解释。

    • 选MSE

      需要强调误差或者模型优化依赖于梯度下降。

分类任务常用的损失函数

Cross Entropy Loss交叉熵损失

  • 交叉熵损失函数经常用于分类问题中,特别是在神经网络做分类问题时,也经常使用交叉熵作为损失函数,此外,由于交叉熵涉及到计算每个类别的概率,所以交叉熵几乎每次都和sigmoid(或softmax)函数一起出现。

  • 交叉熵损失函数的数学定义如下:

    • 二分类

      在二分类情况中,模型预测的结果只有两种情况,所以预测为正类与负类的概率可以写为:p1pp和1-p

      此时损失函数可以写为:

      Loss=1NiLi=1Ni[yilog(pi)+(1yi)log(1pi)]Loss = \frac{1}{N}\sum_{i}L_i=\frac{1}{N}\sum_{i}-[y_i·log(p_i)+(1-y_i)·log(1-p_i)]

      其中:

      • NN是样本数量。
      • yiy_i是样本ii的label,正类为1,负类为0。
      • pip_i是样本ii预测为正类的概率。
    • 多分类

      在多分类情况中,模型预测的结果有多种可能,此时每类的概率可以写为:picp_{ic}

      此时损失函数可以写为:

      Loss=1NiLi=1Nic=1Myiclog(pic)Loss = \frac{1}{N}\sum_{i}L_i=-\frac{1}{N}\sum_i\sum_{c=1}^My_{ic}·log(p_{ic})

      其中:

      • MM是类别的数量。
      • yicy_{ic}是样本ii的真实类别等于cc取1,否则取0。
      • picp_{ic}是观测样本ii属于类别cc的预测概率。
  • 交叉熵损失的特点

    • 优点

      梯度优化友好

      • 对数函数使梯度与误差成比例,避免 MSE 在饱和区的梯度消失问题(如 Sigmoid 输出接近 0/1 时)。

      概率解释性强

      • 直接优化预测概率与真实分布的匹配度,符合分类任务的评估目标。

      对错误预测惩罚大

      • 当预测概率 y^\hat{y} 远离真实标签时,损失急剧增大(如真实 yy=1,预测 y^\hat{y}=0.1 时 L≈2.3)。
    • 缺点

      对噪声标签敏感

      • 若真实标签错误(如错误标注),交叉熵会给出高惩罚,可能导致模型过拟合噪声。

      需概率输入

      • 预测值必须经过 Sigmoid(二分类)或 Softmax(多分类)压缩到 [0, 1]。
  • 交叉熵的代码实现

    • 二分类任务:(由于二分类问题和多分类问题在pytorch实现有差别,所以需要分开进行演示) 二分类使用BCELoss()Binary Cross-Entropy方法

      import torch
      import torch.nn as nn
      
      # 定义 Sigmoid 激活和 BCELoss
      sigmoid = nn.Sigmoid()
      bce_loss = nn.BCELoss()
      
      # 模型的原始输出,未经过激活函数,值域为 (−∞,+∞)。
      y_pred = torch.tensor([[1.2], [-0.5], [0.3]])  # 形状 [3, 1]
      # 真实标签(0 或 1)
      y_true = torch.tensor([[1.0], [0.0], [1.0]])   # 形状 [3, 1]
      
      # 将预测值通过 Sigmoid 压缩到 [0, 1]
      y_pred_sigmoid = sigmoid(y_pred)  # 得到概率
      
      # 计算损失
      loss = bce_loss(y_pred_sigmoid, y_true)
      print("BCELoss:", loss.item())
      
    • 多分类任务: 多分类任务使用CrossEntropyLoss()方法,理论上数据需要经过softmax,但该方法内部集成了softmax方法,所以无需显性使用softmax。

      import torch
      import torch.nn as nn
      
      # 设置随机种子(保证可复现)
      torch.manual_seed(40)
      
      # 多分类任务:输入无需 Softmax
      loss_function = nn.CrossEntropyLoss()
      
      y_pred = torch.randn(3, 5)  # 3个样本,5个类别(原始分数)
      y_true = torch.tensor([1, 0, 4])  # 真实类别索引
      
      loss = loss_function(y_pred, y_true)
      print(loss)