CrossEntropyLoss

paddle.nn. CrossEntropyLoss ( weight=None, ignore_index=- 100, reduction='mean', soft_label=False, axis=- 1, use_softmax=True, name=None ) [源代码]

默认情况下, CrossEntropyLoss 使用 softmax 实现(即 use_softmax=True )。该函数结合了 softmax 操作的计算和交叉熵损失函数,以提供更稳定的数值计算。

当 use_softmax=False 时,仅计算交叉熵损失函数而不使用 softmax。

默认情况下,计算结果的平均值。可以使用 reduction 参数来影响默认行为。请参考参数部分了解详情。

可以用于计算带有 soft labels 和 hard labels 的 softmax 交叉熵损失。其中,hard labels 表示实际的标签值,例如 0、1、2 等。而 soft labels 表示实际标签的概率,例如 0.6、0.8、0.2 等。

计算包括以下两个步骤:

  • I.softmax 交叉熵

    1. Hard label (每个样本仅表示为一个类别)

    1.1. 当 use_softmax=True 时

    \[\begin{split}\\loss_j=-\text{logits}_{label_j}+\log\left(\sum_{i=0}^{C}\exp(\text{logits}_i)\right) , j = 1,...,N\end{split}\]

    其中,N 是样本数,C 是类别数。

    1.2. 当 use_softmax=False 时

    \[\begin{split}\\loss_j=-\log\left({P}_{label_j}\right) , j = 1,...,N\end{split}\]

    其中,N 是样本数,C 是类别数,P 是输入(softmax 的输出)。

    1. Soft label (每个样本为多个类别分配一定的概率,概率和为 1).

    2.1. 当 use_softmax=True 时

    \[\begin{split}\\loss_j=-\sum_{i=0}^{C}\text{label}_i\left(\text{logits}_i-\log\left(\sum_{i=0}^{C}\exp(\text{logits}_i)\right)\right) , j = 1,...,N\end{split}\]

    其中,N 是样本数,C 是类别数。

    2.2. 当 use_softmax=False 时

    \[\begin{split}\\loss_j=-\sum_{j=0}^{C}\left({label}_j*\log\left({P}_{label_j}\right)\right) , j = 1,...,N\end{split}\]

    其中,N 是样本数,C 是类别数,P 是输入(softmax 的输出)。

  • II.Weight 和 reduction 处理

    1. Weight

      如果 weight 参数为 None , 直接进行下一步.

      如果 weight 参数不为 None , 每个样本的交叉熵按权重加权 根据 soft_label = False 或 True 如下:

      1.1. Hard labels (soft_label = False)

      \[\begin{split}\\loss_j=loss_j*weight[label_j]\end{split}\]

      1.2. Soft labels (soft_label = True)

      \[\begin{split}\\loss_j=loss_j*\sum_{i}\left(weight[label_i]*logits_i\right)\end{split}\]
    2. reduction

      2.1 如果 reduction 参数为 none

      直接返回之前的结果

      2.2 如果 reduction 参数为 sum

      返回之前结果的和

      \[\begin{split}\\loss=\sum_{j}loss_j\end{split}\]

      2.3 如果 reduction 参数为 mean , 则按照 weight 参数进行如下处理。

      2.3.1. 如果 weight 参数为 None

      返回之前结果的平均值

      \[\begin{split}\\loss=\sum_{j}loss_j/N\end{split}\]

      其中,N 是样本数,C 是类别数。

      2.3.2. 如果 weight 参数不为 None,则返回之前结果的加权平均值

      1. Hard labels (soft_label = False)

      \[\begin{split}\\loss=\sum_{j}loss_j/\sum_{j}weight[label_j]\end{split}\]
      1. Soft labels (soft_label = True)

      \[\begin{split}\\loss=\sum_{j}loss_j/\sum_{j}\left(\sum_{i}weight[label_i]\right)\end{split}\]

参数

  • weight (Tensor,可选) - 指定每个类别的权重。其默认为 None。如果提供该参数的话,维度必须为 C (类别数)。数据类型为 float32 或 float64。

  • ignore_index (int64,可选) - 指定一个忽略的标签值,此标签值不参与计算,负值表示无需忽略任何标签值。仅在 soft_label=False 时有效。默认值为-100。数据类型为 int64。

  • reduction (str,可选) - 指定应用于输出结果的计算方式,数据类型为 string,可选值有:none, mean, sum。默认为 mean,计算 mini-batch loss 均值。设置为 sum 时,计算 mini-batch loss 的总和。设置为 none 时,则返回 loss Tensor。

  • soft_label (bool,可选) – 指明 label 是否为软标签。默认为 False,表示 label 为硬标签;若 soft_label=True 则表示软标签。

  • label_smoothing (float,可选)- 指定计算损失时的标签平滑度,它应该在 \([0.0,1.0]\) 范围内。其中 0.0 表示无平滑。使得平滑后的标签变成原始真实标签和均匀分布的混合,默认值: 0.0。

  • axis (int,可选) - 进行 softmax 计算的维度索引。它应该在 \([-1,dim-1]\) 范围内,而 dim 是输入 logits 的维度。默认值:-1。

  • use_softmax (bool,可选) - 指定是否对 input 进行 softmax 归一化。默认值:True。

  • name (str,可选) - 具体用法请参见 Name,一般无需设置,默认值为 None。

形状

  • input (Tensor): 输入 Tensor,数据类型为 float32 或 float64。其形状为 \([N, C]\),其中 C 为类别数。对于多维度的情形下,它的形状为 \([N, d_1, d_2, ..., d_k, C]\) ,k >= 1。

  • label (Tensor): 当 soft_label=False 时,输入 input 对应的标签值,数据类型为 int64。其形状为 \([N]\),每个元素符合条件:0 <= label[i] <= C-1。对于多维度的情形下,它的形状为 \([N, d_1, d_2, ..., d_k]\) ,k >= 1;当 soft_label=True 且没有指定 label_smoothing 时,要求 label 的维度、数据类型与 input 相同,每个样本的各标签概率和应为 1;当指定了 label_smoothing (label_smoothing > 0.0) 时, 无论 soft_label 是什么值, label 的维度和数据类型可以是前面两种情况中的任意一种。换句话说,如果 label_smoothing > 0.0, label 可以是独热标签或整数标签。

  • output (Tensor): 计算 CrossEntropyLoss 交叉熵后的损失值。

代码示例

 >>> # hard labels
 >>> import paddle
 >>> paddle.seed(2023)
 >>> N=100
 >>> C=200
 >>> reduction='mean'
 >>> input =  paddle.rand([N, C], dtype='float64')
 >>> label =  paddle.randint(0, C, shape=[N], dtype='int64')
 >>> weight = paddle.rand([C], dtype='float64')

 >>> cross_entropy_loss = paddle.nn.loss.CrossEntropyLoss(
 ...     weight=weight, reduction=reduction)
 >>> dy_ret = cross_entropy_loss(input, label)
 >>> print(dy_ret)
 Tensor(shape=[], dtype=float64, place=Place(cpu), stop_gradient=True,
 5.33697682)
 >>> # soft labels
 >>> import paddle
 >>> paddle.seed(2023)
 >>> axis = -1
 >>> N = 4
 >>> C = 3
 >>> shape = [N, C]
 >>> reduction='mean'
 >>> weight = None
 >>> logits = paddle.uniform(shape, dtype='float64', min=0.1, max=1.0)
 >>> # case1: soft labels without label_smoothing
 >>> labels = paddle.uniform(shape, dtype='float64', min=0.1, max=1.0)
 >>> labels /= paddle.sum(labels, axis=axis, keepdim=True)
 >>> cross_entropy_loss = paddle.nn.loss.CrossEntropyLoss(
 ...     weight=weight, reduction=reduction, soft_label=True, label_smoothing=0.0)
 >>> dy_ret = cross_entropy_loss(logits, labels)
 >>> print(dy_ret)
 Tensor(shape=[], dtype=float64, place=Place(cpu), stop_gradient=True,
 1.14554912)



 >>> # case2: soft labels with label_smoothing
 >>> import paddle
 >>> paddle.seed(2023)
 >>> axis = -1
 >>> N = 4
 >>> C = 3
 >>> shape = [N, C]
 >>> label_smoothing = 0.4
 >>> reduction='mean'
 >>> weight = None
 >>> logits = paddle.uniform(shape, dtype='float64', min=0.1, max=1.0)
 >>> integer_labels = paddle.randint(low=0, high=C, shape=[N], dtype='int64')
 >>> one_hot_labels = paddle.nn.functional.one_hot(integer_labels, C).astype('float32')

 >>> cross_entropy_loss = paddle.nn.loss.CrossEntropyLoss(
 ...     weight=weight, reduction=reduction, label_smoothing=label_smoothing)

 >>> # integer labels
 >>> integer_label_dy_ret = cross_entropy_loss(logits, integer_labels)
 >>> print(integer_label_dy_ret)
 Tensor(shape=[], dtype=float64, place=Place(cpu), stop_gradient=True,
 1.10520368)

 >>> # one_hot labels
 >>> one_hot_label_dy_ret = cross_entropy_loss(logits, one_hot_labels)
 >>> print(one_hot_label_dy_ret)
 Tensor(shape=[], dtype=float64, place=Place(cpu), stop_gradient=True,
 1.10520368)

使用本API的教程文档