张量stream中类不平衡二元分类器的损失函数
我正在尝试将深度学习应用于目标类之间高级别不平衡的二元分类问题(500k,31k)。 我想写一个自定义的损失函数应该是这样的:最小化(100 – ((predicted_smallerclass)/(total_smallerclass))* 100)
欣赏任何关于如何build立这个逻辑的指针。
您可以通过乘以logits将类权重添加到损失函数中。 正则交叉熵损失是这样的:
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]))
所以通过乘以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")
现在有一个标准的损失函数支持每批重量:
tf.losses.sparse_softmax_cross_entropy(labels=label, logits=logits, weights=weights)
权重应从类别权重转换为每个示例的权重(形状为[batch_size])。 在这里看文档 。
你提出的代码似乎对我来说是错误的。 我同意,损失应该乘以重量。
但是,如果您将类别权重乘以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
使用tf.nn.weighted_cross_entropy_with_logits()并将pos_weight设置为1 /(期望的正数比率)。
您可以通过tensorflow查看指南https://www.tensorflow.org/api_guides/python/contrib.losses
…
虽然指定标量损失重新调整整个批次的损失,但我们有时希望重新调整每批样品的损失。 例如,如果我们有一些例子对我们来说更重要,那么我们可能想要让其他错误较less的样本产生更高的损失。 在这种情况下,我们可以提供一个长度为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)
做了两个类的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)