如何在Tensorflow中对S形交叉熵损失函数应用权重?

时间:2018-04-13 09:15:13

标签: python tensorflow

训练数据集包含两个类A和B,我们在目标标签中相应地表示为10。 Out标签数据严重偏向于0类,它占据了大约95%的数据,而我们的班级1只有5%。在这种情况下我们应该如何构建损失函数?

我发现Tensorflow有一个可以用于权重的函数:

tf.losses.sigmoid_cross_entropy
  

weights充当损失的系数。如果提供了标量,那么损失将简单地按给定值进行缩放。

听起来不错。我将权重设置为2.0以使损失更高并且更多地惩罚错误。

loss = loss_fn(targets, cell_outputs, weights=2.0, label_smoothing=0)

然而,不仅损失没有减少,而且数据集的最终准确度略有下降。好吧,也许我误解了它应该< 1.0,我尝试了一个较小的数字。这没有改变任何东西,我得到了几乎相同的损失和准确性。 O_O

毋庸置疑,在相同数据集上训练但损失权重为0.3的同一网络在Torch / PyTorch中显着降低了高达x10倍的损失。

有人可以解释如何在Tensorflow中使用损失权重吗?

2 个答案:

答案 0 :(得分:2)

如果您使用标量(如2.0)来缩放损失,那么基本上您将增加损失,从而增加反向传播的梯度。它类似于提高学习率,但不完全相同,因为你也将比率改为正规化损失,如体重衰减。

如果您的课程严重偏差,并且您希望在计算损失时进行平衡,那么您必须指定 tensor 作为权重,如tf.losses.sigmoid_cross_entropy()手册中所述:

  

权重:可选的Tensor,其等级为0或与标签相同的等级,并且必须可以向标签广播(即,所有维度必须为1,或与相应的损失相同尺寸)。

这使得0级的权重张量为1.0,而1级的权重可能为10,现在“假阴性”的损失计算得更多。

这是一门艺术,你应该过多地权衡那些代表性不足的阶级。如果你做得太过分,模型就会崩溃,并且会一直预测过度加权的类。

实现相同目标的替代方法是使用tf.nn.weighted_cross_entropy_with_logits(),其具有pos_weight参数用于完全相同的目的。但它位于tf.nn而非tf.losses,因此您必须手动将其添加到损失集合中。

通常,处理此问题的另一种方法是在抽样时任意增加代表性不足的类别的比例。但是,这也不应该过头了。你也可以做这两件事。

答案 1 :(得分:1)

您可以为每个样本的错误分类设置惩罚。如果weights是形状张量[batch_size],则每个样本的损失将乘以相应的权重。因此,如果为所有样本分配相同的权重(与使用标量权重相同),则您的损失将仅通过此标量进行缩放,并且准确性不应更改。

如果您为少数类和多数类指定不同的权重,则样本对损失函数的贡献会有所不同,您应该能够通过不同的方式选择权重来影响准确性。

一些场景(您的选择将取决于您的需求):

1。)如果你想要一个良好的整体准确性,你可以选择大多数类的权重非常大,少数类的权重要小得多。这可能会导致将所有事件分类为多数类(即总分类准确率的95%,但少数类通常会被归类为错误的类。

2.。)如果您的信号是少数类别且背景是大多数类别,您可能希望预测信号中的背景污染很少,即您几乎不需要将背景样本预测为信号。如果您选择的多数权重远大于少数权重,也会发生这种情况,但您可能会发现网络倾向于预测所有样本都是背景。所以你不会留下任何信号样本。 在这种情况下,您应该考虑少数类别的大权重+背景样本被归类为信号样本(误报)的额外损失,如下所示:

loss = weighted_cross_entropy + extra_penalty_for_false_positives