我正在训练一个针对严重代表不足的目标类别的循环二元分类器。假设我们的目标类别1在所有训练数据中占比不到1%,而类别0超过99%。为了更严厉地惩罚模型对少数类别的错误预测,我想在损失函数中使用权重。对于每个小批次,我创建了一个对应的权重小批次,其中我们的目标类别获得大于1.0的权重标量,而多数类别则相应地小于1.0。例如,在下面的代码中,我们对类别1使用了2.0,对类别2使用了0.6。
loss_sum = 0.0for t, o, tw in zip(self._targets_uns, self._logits_uns, self._targets_weight_uns): # t -- 目标张量 [batchsize x 1], tw -- 权重张量 [batchsize x 1] # 例如 [0, 0, 0, 0, 1, 1, 0] -- [0.5, 0.5, 0.5, 0.5, 2.0, 2.0, 0.5] _loss = tf.losses.sigmoid_cross_entropy(t, o, weights=tw, label_smoothing=0, scope="sigmoid_cross_entropy", loss_collection=tf.GraphKeys.LOSSES) loss_sum += _loss
模型训练完成后,我检查了预测准确率,发现它略低于无权重的准确率。我继续尝试使用不同的权重对,如[1.4, 0.8], [1.6, 0.4], [4.0, 0.1], [3.0, 1.0], ...
等。然而,除了2-3%的微小差异外,我没有得到比无权重训练更好的结果。好吧,也许我误解了tf.losses.sigmoid_cross_entropy函数的文档说明。
weights作为损失的系数。如果提供了一个标量,那么损失只是简单地按给定值进行缩放。如果weights是一个形状为[batch_size]的张量,那么损失权重将应用于每个相应的样本。
我反转了对,并对类别0使用了更高的权重,对类别1使用了较低的权重:[0.5, 2.0], [0.8, 1.3], [0.2, 1.0], ...
。这也没有带来任何改进,除了略差于无权重版本。
请有人能解释一下加权损失的行为吗?我这样做正确吗?我应该怎么做才能增加少数类别的权重?
回答:
加权是一种用于解决过度指定的方程组形式Wx=y
的一般数学技术,其中x
是输入向量,y
是输出向量,W
是你希望找到的转换矩阵。这些问题通常使用诸如SVD之类的方法来解决。SVD通过最小化过度指定系统的最小二乘误差
来找到W
的解决方案。Tensorflow基本上是通过其最小化过程来解决类似的问题。
在你的情况下,发生的情况是你有1个类别A的样本和99个类别B的样本。因为求解过程致力于最小化总体误差,类别B对解决方案的贡献是类别A的99倍。为了解决这个问题,你应该调整你的权重,使类别A和B对解决方案的贡献均衡,即将类别B的权重降低到0.01。
更一般地,你可以这样做…
ratio = num_B / (num_A + num_B)weights = [ratio, 1.0 - ratio]