TeamClass_MD/Topic1/Tensorflow的损失函数.md
2025-03-16 02:02:53 +08:00

7.9 KiB
Raw Blame History

1. 分类任务损失函数

(1) 交叉熵损失Cross-Entropy Loss

  • 原理
    用于衡量预测概率分布与真实标签分布之间的差异。
  • 稀疏交叉熵SparseCategoricalCrossentropy
    标签为整数(如 [0, 1, 2]),直接计算类别索引的交叉熵。
    公式
    \
    H(y, \hat{y}) = -\sum_{i} y_i \log(\hat{y}_i)
    \ $$ 
    
  • 多分类交叉熵CategoricalCrossentropy
    标签为 One-Hot 编码(如 [[1,0,0], [0,1,0]])。
  • 适用场景
    图像分类、文本分类等离散标签任务。
  • 代码示例
    from tensorflow.keras.losses import SparseCategoricalCrossentropy
    model.compile(optimizer='adam', loss=SparseCategoricalCrossentropy(from_logits=True))
    

(2) 对数损失Logistic Loss / Binary Cross-Entropy

  • 原理
    二分类任务的特例输出为概率值sigmoid 输出)。
    公式
    \
    H(y, \hat{y}) = -\sum_{i} y_i \log(\hat{y}_i) - (1-y_i) \log(1-\hat{y}_i)
    \ $$  
    
  • 适用场景
    二分类任务(如垃圾邮件检测)。
  • 代码示例
    from tensorflow.keras.losses import BinaryCrossentropy
    model.compile(optimizer='adam', loss=BinaryCrossentropy())
    

(3) Hinge Loss

  • 原理
    最大间隔分类器(如 SVM关注正确分类的边界。
    公式
    \
    L(y, \hat{y}) = \max(0, 1 - y \cdot \hat{y})
    \ $$  
    - \( y \in \{-1, 1\} \)\( \hat{y} \) 为模型输出(未归一化)。
    
  • 适用场景
    文本分类、图像识别中的边界敏感任务。
  • 代码示例
    from tensorflow.keras.losses import Hinge
    model.compile(optimizer='adam', loss=Hinge())
    

2. 回归任务损失函数

(1) 均方误差MSE / Mean Squared Error

  • 原理
    预测值与真实值差的平方的平均值。
    公式
    \
    MSE = \frac{1}{N} \sum_{i=1}^{N} (y_{\text{true}}^{(i)} - y_{\text{pred}}^{(i)})^2
    \ $$  
    
  • 适用场景
    回归任务(如房价预测、图像修复)。
  • 代码示例
    from tensorflow.keras.losses import MeanSquaredError
    model.compile(optimizer='adam', loss=MeanSquaredError())
    

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

  • 原理
    预测值与真实值差的绝对值的平均值。
    公式
    \
    MAE = \frac{1}{N} \sum_{i=1}^{N} |y_{\text{true}}^{(i)} - y_{\text{pred}}^{(i)}|
    \ $$  
    
  • 适用场景
    对异常值不敏感的任务(如推荐系统评分预测)。
  • 代码示例
    from tensorflow.keras.losses import MeanAbsoluteError
    model.compile(optimizer='adam', loss=MeanAbsoluteError())
    

(3) Huber Loss

  • 原理
    结合 MSE 和 MAE对中等误差平方处理对大误差线性处理降低敏感度
    公式
    \
    L_\delta(y, \hat{y}) = 
    \begin{cases} 
    \frac{1}{2}\delta^2 (y - \hat{y})^2 & \text{if } |y - \hat{y}| \leq \delta \\
    \delta (|y - \hat{y}| - \delta) & \text{otherwise}
    \end{cases}
    \ $$  
    - $\delta$: 阈值(默认 1.0)。
    
  • 适用场景
    存在异常值的回归任务(如自动驾驶中的目标检测)。
  • 代码示例
    from tensorflow.keras.losses import Huber
    model.compile(optimizer='adam', loss=Huber(delta=1.0))
    

3. 序列任务损失函数

(1) CTC LossConnectionist Temporal Classification

  • 原理
    用于序列到序列任务(如语音识别),解决标签序列与预测序列长度不一致的问题。
    特点
    • 自动对齐输入和输出序列。
    • 支持空格分隔符(如 "hello world"[h, e, l, l, o, _, w, o, r, l, d])。
  • 适用场景
    语音识别、文本生成、时间序列预测。
  • 代码示例
    from tensorflow.keras.losses import CTCLoss
    model.compile(optimizer='adam', loss=CTCLoss())
    

(2) 自回归损失AutoRegressive Loss

  • 原理
    逐个预测序列中的每个时间步,累积误差。
    公式

    \
    L = \sum_{t=1}^{T} \log P(y_t | y_{1:t-1}, x)
    \ $$ 
    
    
  • 适用场景
    机器翻译、文档摘要生成。


4. 自定义损失函数

当内置损失函数无法满足需求时,可以自定义损失函数。以下是一个示例:

(1) 自定义 MSE 损失

import tensorflow as tf
def custom_mse(y_true, y_pred):
    return tf.reduce_mean(tf.square(y_true - y_pred))
model.compile(optimizer='adam', loss=custom_mse)

(2) 多任务损失(加权组合)

def multi_task_loss(y_true, y_pred):
    # 假设有两个输出层output1 和 output2
    loss1 = tf.keras.losses.mse(y_true[0], y_pred[0])
    loss2 = tf.keras.losses.binary_crossentropy(y_true[1], y_pred[1])
    return 0.7 * loss1 + 0.3 * loss2  # 加权组合
model.compile(optimizer='adam', loss=multi_task_loss)

5. 其他特殊损失函数

(1) Poisson Loss

  • 原理
    适用于计数数据(如用户点击率预测)。
    公式
    \
    L = \sum_{i=1}^{N} \left( y_{\text{true}}^{(i)} \log(y_{\text{pred}}^{(i)}) - y_{\text{pred}}^{(i)} \right)
    \ $$  
    
  • 适用场景
    推荐系统、自然语言处理中的词频预测。
  • 代码示例
    from tensorflow.keras.losses import Poisson
    model.compile(optimizer='adam', loss=Poisson())
    

(2) Contrastive Loss

  • 原理
    通过对比正负样本的相似度来学习特征表示。
    公式
    \
    L = y \cdot \log(d) + (1-y) \cdot \log(1-d)
    \ $$  
    - \( d \): 正样本相似度,\( 1-d \): 负样本相似度。
    
  • 适用场景
    图像检索、相似性学习。
  • 代码示例
    # 需自定义实现或使用库(如 TensorFlow Addons
    

6. 如何选择损失函数?

任务类型 推荐损失函数 场景说明
二分类 BinaryCrossentropy 标签为 0/1 或 One-Hot 编码
多分类 SparseCategoricalCrossentropy 标签为整数(未 One-Hot
回归 MeanSquaredError 或 Huber 数据分布均匀或存在异常值
序列标注 CTC Loss 语音识别、文本对齐
多任务学习 加权组合损失(如 MSE + CrossEntropy 同时优化多个输出
异常检测 Huber Loss 对离群值不敏感

7. 高级配置

(1) 加权损失Weighted Loss

用于为不同类别分配不同的损失权重。

  • 代码示例:
# 为不同类别赋予不同权重
model.compile(
 optimizer='adam',
 loss='sparse_categorical_crossentropy',
 loss_weights={'class_0': 1.0, 'class_1': 5.0}  # 类别1的权重更高
)

(2) 自定义梯度裁剪

用于限制梯度的大小,防止梯度爆炸。

p.s. 梯度爆炸是指在训练深度学习模型时,梯度(即损失函数关于模型参数的导数)的值变得非常大,导致模型参数更新过大,从而使得模型无法收敛到一个稳定的解。

  • 代码示例:
optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)
optimizer.clipnorm = 1.0  # 梯度范数不超过1.0
model.compile(optimizer=optimizer, loss='mse')

总结

  • 分类任务:优先选择交叉熵或其变体(如 SparseCategoricalCrossentropyCategoricalCrossentropy)。
  • 回归任务:根据数据分布选择 MeanSquaredErrorMSEMeanAbsoluteErrorMAEHuber
  • 序列任务:使用 CTC Loss 或自回归损失。
  • 自定义需求:通过继承 tf.keras.losses.Loss 类实现灵活的损失函数。 通过合理选择损失函数,可以显著提升模型性能。建议结合具体任务和数据特点进行对比实验,以确定最佳的损失函数。在实际应用中,损失函数的选择可能会影响模型的收敛速度和最终性能,因此需要根据具体情况进行调整。