219 lines
7.9 KiB
Markdown
219 lines
7.9 KiB
Markdown
|
|
|||
|
### **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]]`)。
|
|||
|
- **适用场景**:
|
|||
|
图像分类、文本分类等离散标签任务。
|
|||
|
- **代码示例**:
|
|||
|
```python
|
|||
|
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)
|
|||
|
\ $$
|
|||
|
- **适用场景**:
|
|||
|
二分类任务(如垃圾邮件检测)。
|
|||
|
- **代码示例**:
|
|||
|
```python
|
|||
|
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} \) 为模型输出(未归一化)。
|
|||
|
- **适用场景**:
|
|||
|
文本分类、图像识别中的边界敏感任务。
|
|||
|
- **代码示例**:
|
|||
|
```python
|
|||
|
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
|
|||
|
\ $$
|
|||
|
- **适用场景**:
|
|||
|
回归任务(如房价预测、图像修复)。
|
|||
|
- **代码示例**:
|
|||
|
```python
|
|||
|
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)}|
|
|||
|
\ $$
|
|||
|
- **适用场景**:
|
|||
|
对异常值不敏感的任务(如推荐系统评分预测)。
|
|||
|
- **代码示例**:
|
|||
|
```python
|
|||
|
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)。
|
|||
|
- **适用场景**:
|
|||
|
存在异常值的回归任务(如自动驾驶中的目标检测)。
|
|||
|
- **代码示例**:
|
|||
|
```python
|
|||
|
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]`)。
|
|||
|
- **适用场景**:
|
|||
|
语音识别、文本生成、时间序列预测。
|
|||
|
- **代码示例**:
|
|||
|
```python
|
|||
|
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 损失**
|
|||
|
```python
|
|||
|
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) 多任务损失(加权组合)**
|
|||
|
```python
|
|||
|
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)
|
|||
|
\ $$
|
|||
|
- **适用场景**:
|
|||
|
推荐系统、自然语言处理中的词频预测。
|
|||
|
- **代码示例**:
|
|||
|
```python
|
|||
|
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 \): 负样本相似度。
|
|||
|
- **适用场景**:
|
|||
|
图像检索、相似性学习。
|
|||
|
- **代码示例**:
|
|||
|
```python
|
|||
|
# 需自定义实现或使用库(如 TensorFlow Addons)
|
|||
|
```
|
|||
|
---
|
|||
|
### **6. 如何选择损失函数?**
|
|||
|
| 任务类型 | 推荐损失函数 | 场景说明 |
|
|||
|
|----------|--------------|----------|
|
|||
|
| 二分类 | BinaryCrossentropy | 标签为 0/1 或 One-Hot 编码 |
|
|||
|
| 多分类 | SparseCategoricalCrossentropy | 标签为整数(未 One-Hot) |
|
|||
|
| 回归 | MeanSquaredError 或 Huber | 数据分布均匀或存在异常值 |
|
|||
|
| 序列标注 | CTC Loss | 语音识别、文本对齐 |
|
|||
|
| 多任务学习 | 加权组合损失(如 MSE + CrossEntropy) | 同时优化多个输出 |
|
|||
|
| 异常检测 | Huber Loss | 对离群值不敏感 |
|
|||
|
|
|||
|
### 7. 高级配置
|
|||
|
#### (1) 加权损失(Weighted Loss)
|
|||
|
用于为不同类别分配不同的损失权重。
|
|||
|
- 代码示例:
|
|||
|
```python
|
|||
|
# 为不同类别赋予不同权重
|
|||
|
model.compile(
|
|||
|
optimizer='adam',
|
|||
|
loss='sparse_categorical_crossentropy',
|
|||
|
loss_weights={'class_0': 1.0, 'class_1': 5.0} # 类别1的权重更高
|
|||
|
)
|
|||
|
```
|
|||
|
#### (2) 自定义梯度裁剪
|
|||
|
用于限制梯度的大小,防止梯度爆炸。
|
|||
|
>p.s. 梯度爆炸是指在训练深度学习模型时,梯度(即损失函数关于模型参数的导数)的值变得非常大,导致模型参数更新过大,从而使得模型无法收敛到一个稳定的解。
|
|||
|
- 代码示例:
|
|||
|
```python
|
|||
|
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` 类实现灵活的损失函数。
|
|||
|
通过合理选择损失函数,可以显著提升模型性能。建议结合具体任务和数据特点进行对比实验,以确定最佳的损失函数。在实际应用中,损失函数的选择可能会影响模型的收敛速度和最终性能,因此需要根据具体情况进行调整。
|