【问题标题】:Weighted categorical cross entropy semantic segmentation加权分类交叉熵语义分割
【发布时间】:2018-12-23 23:25:58
【问题描述】:

我想使用 FCN(一种 U-Net)来进行语义分割。 我使用基于 Tensorflow 后端的 Python 和 Keras 执行它。现在我得到了很好的结果,我正在努力改进它们,我认为做这件事的一种方法是改进我的损失计算。 我知道在我的输出中,几个类是不平衡的,使用默认的categorical_crossentropy 函数可能会出现问题。 我的模型输入和输出都是 float32 格式,输入是 channel_first 和 output 和 channel_last (排列在模型末尾完成) 在二进制情况下,当我只想分割一个类时,我以这种方式更改了损失函数,以便它可以根据输出的内容逐个添加权重:

def weighted_loss(y_true, y_pred):
    def weighted_binary_cross_entropy(y_true, y_pred):
        w = tf.reduce_sum(y_true)/tf_cast(tf_size(y_true), tf_float32)
        real_th = 0.5-th 
        tf_th = tf.fill(tf.shape(y_pred), real_th) 
        tf_zeros = tf.fill(tf.shape(y_pred), 0.)
        return (1.0 - w) * y_true * - tf.log(tf.maximum(tf.zeros, tf.sigmoid(y_pred) + tf_th)) +
               (1- y_true) * w * -tf.log(1 - tf.maximum(tf_zeros, tf.sigmoid(y_pred) + tf_th))
    return weighted_binary_coss_entropy

请注意,th 是激活阈值,默认情况下为 1/nClasses,我已对其进行了更改,以查看哪个值能给我最好的结果 你怎么看待这件事? 如何改变它,以便能够计算加权分类交叉熵(在多类的情况下)

【问题讨论】:

    标签: python tensorflow keras deep-learning


    【解决方案1】:

    您的实现将适用于二进制类,对于多类它只是

      -y_true * tf.log(tf.sigmoid(y_pred)) 
    

    并使用内置的 tensorflow 方法来计算分类熵,因为它避免了 y_pred 的溢出

    你可以查看这个答案Unbalanced data and weighted cross entropy,它解释了加权分类交叉熵的实现。

    categorical_crossentropy 的唯一变化是

    def weighted_loss(y_true, y_pred):
        def weighted_categorical_cross_entropy(y_true, y_pred):
            w = tf.reduce_sum(y_true)/tf_cast(tf_size(y_true), tf_float32)
            loss = w * tf.nn.softmax_cross_entropy_with_logits(onehot_labels, logits)
            return loss
        return weighted_categorical_cross_entropy
    

    提取单个类的预测

    def loss(y_true, y_pred):
        s = tf.shape(y_true)
    
        # if number of output classes  is at last
        number_classses = s[-1]
    
        # this will give you one hot code for your prediction
        clf_pred = tf.one_hot(tf.argmax(y_pred, axis=-1), depth=number_classses, axis=-1)
    
        # extract the values of y_pred where y_pred is max among the classes
        prediction = tf.where(tf.equal(clf_pred, 1), y_pred, tf.zeros_like(y_pred))
    
        # if one hotcode == 1 then class1_prediction == y_pred  else class1_prediction ==0
        class1_prediction = prediction[:, :, :, 0:1]
        # you can compute your loss here on individual class and return the loss ,just for simplicity i am returning the class1_prediction
        return class1_prediction
    

    模型输出

    y_pred = [[[[0.5, 0.3, 0.7],
       [0.6, 0.3, 0.2]]
    ,
      [[0.7, 0.9, 0.6],
       [0.3 ,0.9, 0.3]]]]
    

    相应的基本事实

    y_true =  [[[[0,  1, 0],
       [1 ,0, 0]]
    ,
      [[1,0 , 0],
       [0,1, 0]]]]
    

    第 1 类预测

    prediction = loss(y_true, y_pred)
    # prediction =  [[[[0. ],[0.6]],[0. ],[0. ]]]]
    

    【讨论】:

    • 我同意你的观点,但我不想将权重作为先验知识,我希望在训练期间直接计算它们,因为权重可能因一个样本与另一个样本有很大不同在火车组中
    • 这就是为什么我在我发布的代码中使用了 tensorflow reduce_sum 函数来计算过程中每个案例的权重
    • 你可以对你的代码做同样的事情,检查我编辑的答案
    • 我有更改,但看起来仍然可以提供可接受的结果,但我不知道我所做的是否正确,顺便说一下,我有一个包含激活阈值的自定义 softmax_cross_entropy_with_logits 函数,默认为 1/nClasses(我猜)
    • 我已经更改了代码以便在二进制情况下解释这部分(可能是错误的,但看起来效果很好)
    猜你喜欢
    • 2020-04-23
    • 2021-03-19
    • 2017-06-26
    • 2022-11-20
    • 2021-03-19
    • 2020-03-16
    • 2017-11-11
    • 2019-07-13
    • 2021-07-17
    相关资源
    最近更新 更多