张量流中类不平衡二元分类器的损失函数
classification
tensorflow
5
0

我正在尝试将深度学习应用于目标类别(500k,31k)之间类别高度不平衡的二进制分类问题。我想编写一个自定义损失函数,该函数应类似于:minimal(100-((predicted_smallerclass)/(total_smallerclass))* 100)

感谢有关如何构建此逻辑的任何指示。

参考资料:
Stack Overflow
收藏
评论
共 6 个回答
高赞 时间 活跃

您提出的代码对我来说似乎是错误的。我同意,损失应乘以重量。

但是,如果将logit乘以类权重,则结尾为:

weights[class] * -x[class] + log( \sum_j exp(x[j] * weights[class]) )

第二项不等于:

weights[class] * log(\sum_j exp(x[j]))

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

log( (\sum_j exp(x[j]) ^ weights[class] )

所以这是我提议的代码:

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
收藏
评论

我必须处理多个类的不平衡的相似数据集,这就是我的工作方式,希望它可以帮助寻找相似解决方案的人:

这是您的训练模块中的内容:

from sklearn.utils.class_weight import compute_sample_weight
#use class weights for handling unbalanced dataset
if mode == 'INFER' #test/dev mode, not weighing loss in test mode
   sample_weights = np.ones(labels.shape)
else:
   sample_weights = compute_sample_weight(class_weight='balanced', y=labels)

这在模型类定义中:

#an extra placeholder for sample weights
#assuming you already have batch_size tensor
self.sample_weight = tf.placeholder(dtype=tf.float32, shape=[None],
                       name='sample_weights')
cross_entropy_loss = tf.nn.sparse_softmax_cross_entropy_with_logits(
                       labels=self.label, logits=logits, 
                       name='cross_entropy_loss')
cross_entropy_loss = tf.reduce_sum(cross_entropy_loss*self.sample_weight) / batch_size
收藏
评论

使用tf.nn.weighted_cross_entropy_with_logits()并将pos_weight设置为1 /(期望的正比)。

收藏
评论

是否针对两个类操作了tf.nn.weighted_cross_entropy_with_logits()

classes_weights = tf.constant([0.1, 1.0])
cross_entropy = tf.nn.weighted_cross_entropy_with_logits(logits=logits, targets=labels, pos_weight=classes_weights)
收藏
评论

您可以在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)
收藏
评论

您可以通过乘以logit将类权重添加到损失函数。规则的交叉熵损失是这样的:

loss(x, class) = -log(exp(x[class]) / (\sum_j exp(x[j])))
               = -x[class] + log(\sum_j exp(x[j]))

在加权情况下:

loss(x, class) = weights[class] * -x[class] + log(\sum_j exp(weights[class] * x[j]))

因此,通过乘以对数,您可以按类别权重重新调整每个类别的预测。

例如:

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")

现在有一个标准的损失功能可以支持每批次的重量:

tf.losses.sparse_softmax_cross_entropy(labels=label, logits=logits, weights=weights)

权重应从类权重转换为每个示例的权重(形状为[batch_size])。请参阅此处的文档

收藏
评论
新手导航
  • 社区规范
  • 提出问题
  • 进行投票
  • 个人资料
  • 优化问题
  • 回答问题

关于我们

常见问题

内容许可

联系我们

@2020 AskGo
京ICP备20001863号