整理:熵、KL散度、交叉熵、nn.CrossEntropyLoss()、nn.LogSoftmax()、nn.NLLLoss()

本文深入探讨信息量、熵、相对熵(KL散度)和交叉熵的概念,并结合PyTorch库,详细阐述nn.CrossEntropyLoss()、nn.LogSoftmax()和nn.NLLLoss()的使用方法与计算过程,通过实例验证加深理解。

、信息量、熵、相对熵KL散度)、交叉

二、Softmax 与 交叉熵

pytorch中的交叉熵损失 nn.CrossEntropyLoss()

四、pytorch中的LogSoftmax()nn.NLLLoss()

五、扩展nn.NLLoss()的计算

一、信息量、熵、相对熵(KL散度)、交叉熵

讲解逻辑:

<think>我们被要求详细解释`torch.nn.CrossEntropyLoss(label_smoothing=0.01)`的计算步骤。根据引用[1]和引用[3],我们知道这个损失函数在PyTorch中实现了标签平滑(label smoothing)的交叉熵损失。 ### 交叉熵损失基础 标准的交叉熵损失(没有标签平滑)计算如下: 对于一个样本,假设我们有$C$个类别,模型的输出为$\mathbf{z} = (z_1, z_2, \dots, z_C)$(这些是未归一化的分数,即logits),并且真实的标签用独热编码(one-hot)表示为$\mathbf{y} = (y_1, y_2, \dots, y_C)$,其中$y_i$为1当$i$是真实类别,否则为0。 然后,我们首先将logits通过softmax函数转换为概率分布: $$\mathbf{p}_i = \frac{\exp(z_i)}{\sum_{j=1}^{C} \exp(z_j)} \quad \text{for } i=1,\dots,C$$ 交叉熵损失计算为: $$\mathcal{L} = -\sum_{i=1}^{C} y_i \log(\mathbf{p}_i)$$ ### 标签平滑的交叉熵损失 标签平滑(label smoothing)是一种正则化技术,用于防止模型对真实标签过自信。在标签平滑中,我们不再使用硬标签(hard label,即0和1),而是将真实标签的概率分布调整为平滑后的版本。 具体来说,给定一个平滑参数$\epsilon$(在您的例子中为0.01),真实标签分布$\mathbf{y}$被调整为: $$\mathbf{y}^{\text{smooth}}_i = \begin{cases} 1 - \epsilon + \frac{\epsilon}{C} & \text{如果 } i \text{ 是真实类别} \\ \frac{\epsilon}{C} & \text{其他类别} \end{cases}$$ 这样,真实类别对应的概率被稍微降低,而非真实类别的概率被赋予一个很小的值。 因此,平滑后的损失函数变为: $$\mathcal{L}_{\text{smooth}} = -\sum_{i=1}^{C} \mathbf{y}^{\text{smooth}}_i \log(\mathbf{p}_i)$$ ### 使用`nn.CrossEntropyLoss`的步骤 当我们在PyTorch中使用`nn.CrossEntropyLoss(label_smoothing=0.01)`时,计算步骤如下: 1. **输入**: - 模型的输出:形状为$(N, C)$的logits张量(其中$N$是批量大小,$C$是类别数)。注意:该函数内部会自动对logits进行softmax操作,因此不需要提前做softmax。 - 真实标签:形状为$(N)$或$(N, d_1, d_2, ..., d_K)$的张量(对于$K$维损失)。每个元素是类别索引(在0到$C-1$之间),而不是独热编码。 2. **标签平滑处理**: - 将真实标签(整数形式)转换为平滑后的概率分布。例如,假设一个样本的真实标签为$k$(类别索引),则创建一个长为$C$的向量,其中: - 位置$k$的值:$1 - \epsilon + \frac{\epsilon}{C}$ - 其他位置的值:$\frac{\epsilon}{C}$ 3. **计算交叉熵损失**: - 对每个样本,计算平滑后的标签分布$\mathbf{y}^{\text{smooth}}$与模型预测的概率分布$\mathbf{p}$(由logits经过softmax得到)之间的交叉熵。 - 然后根据设置的`reduction`参数(默认为`'mean'`)进行归约:将所有样本的损失求平均(mean)或求和(sum)等。 ### 示例 假设我们有一个二分类问题($C=2$),一个样本的真实标签为0(即第一个类别),且$\epsilon=0.01$。 平滑后的标签分布为: - 类别0:$1 - 0.01 + 0.01/2 = 0.995$ - 类别1:$0.01/2 = 0.005$ 假设模型输出的logits为$[2.0, 1.0]$(即类别0的分数为2.0,类别1的分数为1.0)。首先计算softmax: - $\mathbf{p}_0 = \frac{\exp(2.0)}{\exp(2.0)+\exp(1.0)} \approx \frac{7.389}{7.389+2.718} \approx 0.731$ - $\mathbf{p}_1 = \frac{\exp(1.0)}{\exp(2.0)+\exp(1.0)} \approx 0.269$ 则交叉熵损失为: $$\mathcal{L}_{\text{smooth}} = - \left( 0.995 \times \log(0.731) + 0.005 \times \log(0.269) \right) \approx - \left( 0.995 \times (-0.313) + 0.005 \times (-1.313) \right) \approx 0.314$$ ### 注意事项 - 在PyTorch中,我们不需要手动将标签转换为独热编码,损失函数内部会自动处理。 - 参数`label_smoothing`的取值范围是$[0, 1]$。 - 标签平滑通常用于分类问题,特别是当训练数据存在噪声或类别标签可能存在错误时,它有助于提高模型的泛化能力[^3]。 ### 代码示例 以下是一个使用`torch.nn.CrossEntropyLoss`并设置标签平滑的简单代码示例: ```python import torch import torch.nn as nn # 设置标签平滑 epsilon = 0.01 loss_fn = nn.CrossEntropyLoss(label_smoothing=epsilon, reduction='mean') # 模拟数据:假设batch_size=2, 类别数=3 logits = torch.tensor([[1.2, 0.5, -0.1], [0.3, 2.1, -0.5]]) # 模型输出 (2, 3) targets = torch.tensor([0, 2]) # 真实类别索引 # 计算损失 loss = loss_fn(logits, targets) print(loss) ``` 在内部,对于第一个样本(真实标签0),平滑后的标签分布为: $$[1-\epsilon + \epsilon/3, \epsilon/3, \epsilon/3] = [0.99, 0.00333, 0.00333]$$ 然后计算该分布与softmax(logits)之间的交叉熵,第二个样本同理,最后根据`reduction`归约。 §§相关问题§§ 1. 标签平滑对模型训练有什么实际影响? 2. 在哪些任务中推荐使用标签平滑? 3. 除了标签平滑,还有哪些方法可以防止模型过自信? </think>### 使用 `torch.nn.CrossEntropyLoss(label_smoothing=0.01)` 的详细计算步骤 `torch.nn.CrossEntropyLoss` 结合标签平滑(label smoothing)时,损失计算分为以下步骤: --- #### **1. 输入准备** - **模型输出(logits)**:形状为 `(N, C)` 的张量 - `N`:批量大小(batch size) - `C`:类别数量 - 例如:`logits = torch.tensor([[2.0, -1.0, 0.5]])`(1个样本,3个类别) - **真实标签(labels)**:形状为 `(N)` 的类别索引张量 - 例如:`labels = torch.tensor([0])`(真实类别为第0类) --- #### **2. 标签平滑处理** 标签平滑通过参数 `label_smoothing=ϵ`(此处 `ϵ=0.01`)修改真实标签的分布: - **平滑前**:真实标签为独热编码(one-hot),如 `[1.0, 0.0, 0.0]` - **平滑后**: - 真实类别的概率调整为 `1 - ϵ + ϵ/C` - 其他类别的概率调整为 `ϵ/C` - 公式: $$ \text{smoothed_label}[i] = \begin{cases} 1 - \epsilon + \frac{\epsilon}{C} & \text{if } i = \text{真实类别} \\ \frac{\epsilon}{C} & \text{otherwise} \end{cases} $$ **示例计算**(`C=3`, `ϵ=0.01`): - 原始标签:`[1.0, 0.0, 0.0]` - 平滑后: - 真实类别(第0类):`1 - 0.01 + 0.01/3 ≈ 0.9933` - 其他类别:`0.01/3 ≈ 0.0033` - 最终标签:`[0.9933, 0.0033, 0.0033]` --- #### **3. Softmax 概率转换** 对模型输出的 logits 应用 Softmax 函数,转换为概率分布: $$ \text{softmax}(z_i) = \frac{\exp(z_i)}{\sum_{j=1}^{C} \exp(z_j)} $$ **示例计算**(logits = `[2.0, -1.0, 0.5]`): - 概率计算: $$ \begin{align*} p_0 &= \exp(2.0) / (\exp(2.0) + \exp(-1.0) + \exp(0.5)) ≈ 0.728 \\ p_1 &= \exp(-1.0) / (\cdots) ≈ 0.040 \\ p_2 &= \exp(0.5) / (\cdots) ≈ 0.232 \end{align*} $$ - 概率分布:`[0.728, 0.040, 0.232]` --- #### **4. 交叉熵损失计算** 使用平滑后的标签 `q` 和 Softmax 概率 `p` 计算交叉熵: $$ \text{Loss} = -\sum_{i=1}^{C} q_i \log(p_i) $$ **示例计算**: - 平滑标签 `q = [0.9933, 0.0033, 0.0033]` - 预测概率 `p = [0.728, 0.040, 0.232]` - 损失: $$ \begin{align*} \text{Loss} &= - \left( 0.9933 \times \log(0.728) + 0.0033 \times \log(0.040) + 0.0033 \times \log(0.232) \right) \\ &\approx - \left( 0.9933 \times (-0.317) + 0.0033 \times (-3.218) + 0.0033 \times (-1.461) \right) \\ &\approx 0.328 \end{align*} $$ --- #### **5. 批量归约(Reduction)** 默认 `reduction='mean'`,计算批次中所有样本损失的平均值: - 若批次有多个样本,先对每个样本独立计算损失,再求平均。 --- #### **PyTorch 代码验证** ```python import torch import torch.nn as nn # 输入数据 logits = torch.tensor([[2.0, -1.0, 0.5]]) # 模型输出 (logits) labels = torch.tensor([0]) # 真实标签 (类别索引) # 定义损失函数(标签平滑=0.01) loss_fn = nn.CrossEntropyLoss(label_smoothing=0.01) # 计算损失 loss = loss_fn(logits, labels) print(loss) # 输出: tensor(0.3285) ``` --- ### **关键点总结** 1. **标签平滑作用**:防止模型对真实标签过自信,提升泛化能力[^3]。 2. **概率调整**:真实类别概率从 `1.0` 降低至 `1-ϵ+ϵ/C`,其余类别从 `0.0` 提升至 `ϵ/C`。 3. **数学本质**:最小化平滑标签分布与预测分布的 KL KL-divergence)。 4. **适用场景**:分类任务中数据存在噪声或需正则化的场景[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值