Tensor流中类不平衡二元分类器的损失函数

Ven*_*ppu 51 classification tensorflow

我正在尝试将深度学习应用于目标类(500k,31K)之间的高级不平衡的二进制分类问题.我想写一个自定义的损失函数,应该是这样的:最小化(100 - ((predict_smallerclass)/(total_smallerclass))*100)

欣赏有关如何构建此逻辑的任何指示.

ilb*_*gon 46

您可以通过乘以logits将类权重添加到损失函数.定期交叉熵损失是这样的:

loss(x, class) = -log(exp(x[class]) / (\sum_j exp(x[j])))
               = -x[class] + log(\sum_j exp(x[j]))
Run Code Online (Sandbox Code Playgroud)

在加权情况下:

loss(x, class) = weights[class] * -x[class] + log(\sum_j exp(weights[class] * x[j]))
Run Code Online (Sandbox Code Playgroud)

因此,通过乘以logits,您可以按类的权重重新缩放每个类的预测.

例如:

ratio = 31.0 / (500.0 + 31.0)
class_weight = tf.constant([ratio, 1.0 - ratio])
logits = ... # shape [batch_size, 2]
weighted_logits = tf.mul(logits, class_weight) # shape [batch_size, 2]
xent = tf.nn.softmax_cross_entropy_with_logits(
  weighted_logits, labels, name="xent_raw")
Run Code Online (Sandbox Code Playgroud)

现在有一个标准损失功能,支持每批重量:

tf.losses.sparse_softmax_cross_entropy(labels=label, logits=logits, weights=weights)
Run Code Online (Sandbox Code Playgroud)

其中权重应从类权重转换为每个示例的权重(具有形状[batch_size]).见这里的文档.


小智 40

你提出的代码对我来说似乎不对.我同意,损失应乘以重量.

但是如果你将logit乘以类权重,你会得到:

weights[class] * -x[class] + log( \sum_j exp(x[j] * weights[class]) )
Run Code Online (Sandbox Code Playgroud)

第二项不等于:

weights[class] * log(\sum_j exp(x[j]))
Run Code Online (Sandbox Code Playgroud)

为了表明这一点,我们可以将后者重写为:

log( (\sum_j exp(x[j]) ^ weights[class] )
Run Code Online (Sandbox Code Playgroud)

所以这是我提出的代码:

ratio = 31.0 / (500.0 + 31.0)
class_weight = tf.constant([[ratio, 1.0 - ratio]])
logits = ... # shape [batch_size, 2]

weight_per_label = tf.transpose( tf.matmul(labels
                           , tf.transpose(class_weight)) ) #shape [1, batch_size]
# this is the weight for each datapoint, depending on its label

xent = tf.mul(weight_per_label
         , tf.nn.softmax_cross_entropy_with_logits(logits, labels, name="xent_raw") #shape [1, batch_size]
loss = tf.reduce_mean(xent) #shape 1
Run Code Online (Sandbox Code Playgroud)

  • 我认为这应该是公认的答案,因为我们想要通过权重乘以距离而不是logits. (4认同)
  • 我面临同样的问题,但是在试图理解上面的代码时我不明白`\ sum_` - 你能解释一下吗?它似乎是乳胶代码; 这在Python中有用吗? (3认同)

小智 11

使用tf.nn.weighted_cross_entropy_with_logits()并设置pos_weight为1 /(预期的正数比率).


小智 5

您可以在 tensorflow https://www.tensorflow.org/api_guides/python/contrib.losses查看指南

...

虽然指定标量损失会重新调整整个批次的损失,但我们有时希望重新调整每个批次样本的损失。例如,如果我们有某些示例对我们更重要,我们可能希望得到比错误无关紧要的其他样本更高的损失。在这种情况下,我们可以提供一个长度为 batch_size 的权重向量,这导致批次中每个样本的损失由相应的权重元素缩放。例如,考虑分类问题的情况,我们希望最大限度地提高准确度,但我们对获得特定类别的高准确度特别感兴趣:

inputs, labels = LoadData(batch_size=3)
logits = MyModelPredictions(inputs)

# Ensures that the loss for examples whose ground truth class is `3` is 5x
# higher than the loss for all other examples.
weight = tf.multiply(4, tf.cast(tf.equal(labels, 3), tf.float32)) + 1

onehot_labels = tf.one_hot(labels, num_classes=5)
tf.contrib.losses.softmax_cross_entropy(logits, onehot_labels, weight=weight)
Run Code Online (Sandbox Code Playgroud)