我正在尝试用不平衡的数据训练网络。我有 A(198 个样本)、B(436 个样本)、C(710 个样本)、D(272 个样本),我已经阅读了“weighted_cross_entropy_with_logits”,但我发现的所有例子都是二进制分类的,所以我不是很了解对如何设置这些权重充满信心。
样本总数:1616
A_weight:198/1616 = 0.12?
如果我理解的话,其背后的想法是惩罚多数类别的错误并更积极地重视少数类别的命中,对吧?
我的一段代码:
weights = tf.constant([0.12, 0.26, 0.43, 0.17])
cost = tf.reduce_mean(tf.nn.weighted_cross_entropy_with_logits(logits=pred, targets=y, pos_weight=weights))
我已阅读 this one和其他二分类的例子,但仍然不是很清楚。
提前致谢。
最佳答案
请注意,weighted_cross_entropy_with_logits
是 sigmoid_cross_entropy_with_logits
的加权变体。 Sigmoid 交叉熵通常用于二元分类。是的,它可以处理多个标签,但 sigmoid 交叉熵基本上对它们中的每一个做出(二元)决策——例如,对于人脸识别网络,那些(不互斥的)标签可能是“主题是否戴眼镜?”、“对象是女性吗?”等
在二元分类中,每个输出 channel 对应一个二元(软)决策。因此,需要在计算损失时进行加权。这就是 weighted_cross_entropy_with_logits
所做的,通过对交叉熵的一项进行加权。
在互斥的多标签分类中,我们使用 softmax_cross_entropy_with_logits
,其行为不同:每个输出 channel 对应一个类别候选的得分。 在之后做出决定,通过比较每个 channel 的各自输出。
因此,在最终决定之前加权只是在比较分数之前修改分数的简单问题,通常是通过乘以权重。例如,对于一个三元分类任务,
# your class weights
class_weights = tf.constant([[1.0, 2.0, 3.0]])
# deduce weights for batch samples based on their true label
weights = tf.reduce_sum(class_weights * onehot_labels, axis=1)
# compute your (unweighted) softmax cross entropy loss
unweighted_losses = tf.nn.softmax_cross_entropy_with_logits(onehot_labels, logits)
# apply the weights, relying on broadcasting of the multiplication
weighted_losses = unweighted_losses * weights
# reduce the result to get your final loss
loss = tf.reduce_mean(weighted_losses)
您也可以依靠 tf.losses.softmax_cross_entropy
来处理最后三个步骤。
在您需要解决数据不平衡问题的情况下,类权重确实可能与其在您的训练数据中的频率成反比。将它们归一化以便它们总和为一个或类的数量也是有意义的。
请注意,在上面,我们根据样本的真实标签对损失进行了惩罚。我们也可以通过简单地定义
来根据估计标签来惩罚损失weights = class_weights
由于广播魔术,其余代码无需更改。
在一般情况下,您希望权重取决于您所犯的错误类型。换句话说,对于每一对标签 X
和 Y
,当真正的标签是 时,你可以选择如何惩罚选择标签
。你最终得到一个完整的先验权重矩阵,这导致上面的 X
>Yweights
是一个完整的 (num_samples, num_classes)
张量。这有点超出了您的预期,但是知道在上面的代码中只有您对权重张量的定义需要更改可能会很有用。
关于python - 不平衡数据和加权交叉熵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44560549/