【发布时间】:2017-11-11 06:10:14
【问题描述】:
假设在对用于分割的图像进行中频平衡后,我们有这些类权重:
class_weights = {0: 0.2595,
1: 0.1826,
2: 4.5640,
3: 0.1417,
4: 0.9051,
5: 0.3826,
6: 9.6446,
7: 1.8418,
8: 0.6823,
9: 6.2478,
10: 7.3614,
11: 0.0}
这个想法是创建一个 weight_mask 以便它可以乘以两个类的交叉熵输出。要创建此权重掩码,我们可以根据 ground_truth 标签或预测广播值。我的实现中的一些数学:
label 和 logits 的形状都是
[batch_size, height, width, num_classes]权重掩码的形状为
[batch_size, height, width, 1]权重掩码被广播到
num_classeslogit 的 softmax 和标签之间相乘的通道数,以给出[batch_size, height, width, num_classes]的输出形状。在这种情况下,num_classes是 12。对一个批次中的每个示例求和,然后对一个批次中的所有示例执行归约均值以获得单个标量损失值。
在这种情况下,我们应该根据预测还是根据实际情况创建权重掩码?
如果我们基于 ground_truth 构建它,那么这意味着无论预测的像素标签是什么,它们都会根据类的实际标签受到惩罚,这似乎并不能以一种明智的方式指导训练。
但是,如果我们基于预测构建它,那么对于生成的任何 logit 预测,如果预测标签(来自 logit 的 argmax)占主导地位,那么该像素的 logit 值将全部减少相当大的数额。
--> 虽然这意味着最大 logit 仍然是最大值,因为 12 个通道中的所有 logit 都将按相同的值缩放,但预测的标签的最终 softmax 概率(之前和之前仍然相同)缩放后),将低于缩放前(做了一些简单的数学估计)。 --> 预计损失会更低
但问题是这样的:如果由于这种加权而预测出较低的损失,那么这不会与预测主导标签应该给您带来更大损失的想法相矛盾吗? p>
我对这种方法的总体印象是:
- 对于占主导地位的标签,他们受到的惩罚和奖励要少得多。
- 对于不占优势的标签,如果预测正确,他们会获得高额奖励,但如果预测错误,他们也会受到重罚。
那么这对解决类平衡问题有何帮助?我不太明白这里的逻辑。
实施
这是我目前计算加权交叉熵损失的实现,虽然我不确定它是否正确。
def weighted_cross_entropy(logits, onehot_labels, class_weights):
if not logits.dtype == tf.float32:
logits = tf.cast(logits, tf.float32)
if not onehot_labels.dtype == tf.float32:
onehot_labels = tf.cast(onehot_labels, tf.float32)
#Obtain the logit label predictions and form a skeleton weight mask with the same shape as it
logit_predictions = tf.argmax(logits, -1)
weight_mask = tf.zeros_like(logit_predictions, dtype=tf.float32)
#Obtain the number of class weights to add to the weight mask
num_classes = logits.get_shape().as_list()[3]
#Form the weight mask mapping for each pixel prediction
for i in xrange(num_classes):
binary_mask = tf.equal(logit_predictions, i) #Get only the positions for class i predicted in the logits prediction
binary_mask = tf.cast(binary_mask, tf.float32) #Convert boolean to ones and zeros
class_mask = tf.multiply(binary_mask, class_weights[i]) #Multiply only the ones in the binary mask with the specific class_weight
weight_mask = tf.add(weight_mask, class_mask) #Add to the weight mask
#Multiply the logits with the scaling based on the weight mask then perform cross entropy
weight_mask = tf.expand_dims(weight_mask, 3) #Expand the fourth dimension to 1 for broadcasting
logits_scaled = tf.multiply(logits, weight_mask)
return tf.losses.softmax_cross_entropy(onehot_labels=onehot_labels, logits=logits_scaled)
谁能验证我的这种加权损失的概念是否正确,以及我的实现是否正确?这是我第一次了解具有不平衡类的数据集,如果有人能验证这一点,我将不胜感激。
测试结果:在做了一些测试后,我发现上面的实现导致更大的损失。应该是这样吗?即,这是否会使训练更加困难,但最终会产生更准确的模型?
类似的线程
请注意,我在这里查看过类似的帖子:How can I implement a weighted cross entropy loss in tensorflow using sparse_softmax_cross_entropy_with_logits
但似乎 TF 对损失只有样本加权,而没有分类加权。
非常感谢大家。
【问题讨论】:
-
"如果我们基于ground_truth构建它,那么这意味着无论预测的像素标签是什么,它们都会根据类的实际标签进行惩罚,这似乎并不能指导以明智的方式进行训练。”这是为什么呢?
-
意思是说如果某个像素 [x,y] 应该被标记为 1,但预测可以是从 0 到 11 的任何值,那么无论该标签给出什么预测,无论它是什么 logit 预测,应用于 logit 的特定像素的缩放比例都是相同的。考虑到我们想要自适应地惩罚预测的标签,我认为这会很奇怪。您对此有一些见解吗?
标签: machine-learning tensorflow computer-vision deep-learning image-segmentation