3

我已经使用tf.GradientTape(). 我的数据有 2 个类。班级不平衡;class1数据贡献了近 80% 和class2剩余的 20%。因此,为了消除这种不平衡,我尝试编写自定义损失函数,它将考虑这种不平衡并应用相应的类权重并计算损失。即我想使用class_weights = [0.2, 0.8]. 我找不到类似的例子。

但是,我看到的所有示例都使用 model.fit 方法,它更容易通过class_weights. 我无法找到class_weights与自定义训练循环一起使用的示例tf.GradientTape

我确实通过了使用的建议sample_weight,但是我没有可以在其中指定样本权重的数据,因此我的偏好是使用类权重。

我使用BinaryCrossentropy损失作为损失函数,但我想根据class_weights. 这就是我被卡住的地方,如何告诉BinaryCrossentropy考虑class_weights.

我使用自定义损失函数的方法是正确的,还是有更好的方法来使用class_weights自定义训练循环(不使用model.fit)进行训练?

4

2 回答 2

0

您可以编写自己的损失函数。在那个损失函数中调用 BinaryCrossentropy 然后将结果乘以你想要的权重并返回

于 2020-12-29T07:08:06.363 回答
0

这是一个应该适用于n类而不是 2 的实现。

对于您的80:20拆分示例,计算权重如下(假设总共 100 个样本)。

  1. 权重计算(参考:处理类不平衡:TensorFlow):

    weight_class_0 = (1/count_for_class_0) * (total_samples / num_classes) # (80%) 0.625
    weight_class_1 = (1/count_for_class_1) * (total_samples / num_classes) # (20%) 2.5
    class_wts = tf.constant([weight_class_0, weight_class_1])
    
  2. 损失函数:要求标签稀疏且对数未缩放(未应用激活)。

    # Example logits=[[-3.2, 2.0], [1.2, 0.5], ...], (sparse)labels=[0, 1, ...]
    def weighted_sparse_categorical_crossentropy(labels, logits, weights):
        loss = tf.nn.sparse_softmax_cross_entropy_with_logits(labels, logits)
        class_weights = tf.gather(weights, labels)
        return tf.reduce_mean(class_weights * loss)
    

您可以将此损失函数提供给自定义训练循环。

于 2021-09-17T08:29:09.983 回答