【问题标题】:Custom loss function (focal loss) input size error in KerasKeras中的自定义损失函数(焦点损失)输入大小错误
【发布时间】:2020-03-02 20:22:49
【问题描述】:

我正在使用中性网络进行多类分类。有 3 个不平衡的类,所以我想使用焦点损失来处理不平衡。所以我使用自定义损失函数来适应 Keras 顺序模型。我尝试了在网上找到的焦点损失函数的多个版本的代码,但它们返回相同的错误消息,基本上说输入大小是浴缸大小,而预期为 1。任何人都可以看看这个问题,让我知道你是否可以修理它?真的很感谢!!!

model = build_keras_model(x_train, name='training1')

class FocalLoss(keras.losses.Loss):
    def __init__(self, gamma=2., alpha=4.,
             reduction = tf.keras.losses.Reduction.AUTO, name='focal_loss'):

    super(FocalLoss, self).__init__(reduction=reduction,
                                    name=name)
    self.gamma = float(gamma)
    self.alpha = float(alpha)

def call(self, y_true, y_pred):

        epsilon = 1.e-9
        y_true = tf.convert_to_tensor(y_true, tf.float32)
        y_pred = tf.convert_to_tensor(y_pred, tf.float32)
        model_out = tf.add(y_pred, epsilon)
        ce = tf.multiply(y_true, -tf.math.log(model_out))
        weight = tf.multiply(y_true, tf.pow(
            tf.subtract(1., model_out), self.gamma))
        fl = tf.multiply(self.alpha, tf.multiply(weight, ce))
        reduced_fl = tf.reduce_max(fl, axis=1)
        return tf.reduce_mean(reduced_fl)

model.compile(optimizer = tf.keras.optimizers.Adam(0.001),
          loss = FocalLoss(alpha=1),
          metrics=['accuracy'])
​
class_weight = {0: 1.,
            1: 6.,
            2: 6.}

# fit the model (train for 5 epochs) history = model.fit(x=x_train, y=y_train, batch_size=64, epochs=5, class_weight = class_weight)

ValueError: Can not squeeze dim[0], expected a dimension of 1, got 64 for 'loss/output_1_loss/weighted_loss/Squeeze' (op: 'Squeeze') with input shapes: [64].

【问题讨论】:

    标签: keras neural-network deep-learning loss-function imbalanced-data


    【解决方案1】:

    Keras 损失函数采用一批预测和训练数据,并使用它们产生损失张量。实现这一点的一种方法是简单地定义一个带有两个张量输入的函数,该函数返回一个数字,就像这样

    def mse(y_true, y_pred):
        return K.mean(K.square(y_pred - y_true), axis=-1)
    

    然后像这样在编译时将它传递给模型

    model.compile(optimizer = tf.keras.optimizers.Adam(0.001), loss = mse)
    

    【讨论】:

      【解决方案2】:

      您面临的问题是,您正在利用一些旨在为您执行某些逻辑的帮助程序类,但不幸的是,它的文档对于它为您做了什么并不清楚究竟是什么,并且,因此,究竟是什么你需要自己做。

      在这种情况下,您使用tf.keras.losses.Loss。您需要做的就是实现call()(以及可选的__init__)。不幸的是,documentation 根本没有说明它期望call() 返回什么。但是由于您需要在__init__() 中指定reduction,我们可以假设call() 不仅会返回一个数字。否则reduction 将毫无用处。换句话说:错误告诉您call() 返回一个数字,而预期返回 64 个数字(您的批量大小)。

      因此,与其自己将批次减少为一个数字(通过调用tf.reduce_mean(reduced_fl)),不如让助手类为您执行此操作,然后直接返回reduced_f1。目前您使用reduction=tf.keras.losses.Reduction.AUTO,这可能是您想要的。

      【讨论】:

        猜你喜欢
        • 2019-03-10
        • 1970-01-01
        • 1970-01-01
        • 2017-12-20
        • 1970-01-01
        • 2020-12-19
        • 2017-12-18
        • 2020-03-27
        • 1970-01-01
        相关资源
        最近更新 更多