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