Keras中的自定义损失函数(focal loss)输入尺寸错误
Custom loss function (focal loss) input size error in Keras
我正在使用中性网络进行多class class化。有 3 个不平衡 classes,所以我想使用 focal loss 来处理不平衡。所以我使用自定义损失函数来适应 Keras 顺序模型。我尝试了在网上找到的多个版本的 focal loss 函数代码,但它们 return 相同的错误消息,基本上说输入大小是浴缸大小,而预期为 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 损失函数采用一批预测和训练数据,并使用它们产生损失张量。实现这一点的一种方法是简单地定义一个具有两个张量输入的函数,其中 returns 一个数字,就像这样
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)
您面临的问题是您正在利用一些帮助程序 class 来为您执行一些逻辑,但不幸的是,它的文档并不清楚究竟是什么 它对你有用,因此,你需要自己做什么。
在这种情况下,您使用 tf.keras.losses.Loss
。您需要做的就是实现 call()
(以及可选的 __init__
)。不幸的是,documentation 根本没有说明它对 call()
到 return 的期望。但是由于您需要在 __init__()
中指定一个 reduction
,我们可以假设 call()
不仅是 return 单个数字。否则 reduction
就没用了。换句话说:错误告诉你 call()
return 是一个数字,而它应该是 return 64 个数字(你的批量大小)。
因此,与其自己将批次减少为单个数字(通过调用 tf.reduce_mean(reduced_fl)
),不如让助手 class 为您完成此操作,只需 return reduced_f1
直接地。目前您使用 reduction=tf.keras.losses.Reduction.AUTO
,这可能是您想要的。
我正在使用中性网络进行多class class化。有 3 个不平衡 classes,所以我想使用 focal loss 来处理不平衡。所以我使用自定义损失函数来适应 Keras 顺序模型。我尝试了在网上找到的多个版本的 focal loss 函数代码,但它们 return 相同的错误消息,基本上说输入大小是浴缸大小,而预期为 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 损失函数采用一批预测和训练数据,并使用它们产生损失张量。实现这一点的一种方法是简单地定义一个具有两个张量输入的函数,其中 returns 一个数字,就像这样
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)
您面临的问题是您正在利用一些帮助程序 class 来为您执行一些逻辑,但不幸的是,它的文档并不清楚究竟是什么 它对你有用,因此,你需要自己做什么。
在这种情况下,您使用 tf.keras.losses.Loss
。您需要做的就是实现 call()
(以及可选的 __init__
)。不幸的是,documentation 根本没有说明它对 call()
到 return 的期望。但是由于您需要在 __init__()
中指定一个 reduction
,我们可以假设 call()
不仅是 return 单个数字。否则 reduction
就没用了。换句话说:错误告诉你 call()
return 是一个数字,而它应该是 return 64 个数字(你的批量大小)。
因此,与其自己将批次减少为单个数字(通过调用 tf.reduce_mean(reduced_fl)
),不如让助手 class 为您完成此操作,只需 return reduced_f1
直接地。目前您使用 reduction=tf.keras.losses.Reduction.AUTO
,这可能是您想要的。