[英]Keras functional API: My model is only optimizing for one loss function instead of 2 loss functions while training
我的 model 中有 2 个损失函数——交叉熵和均方。 我希望我的 model 最大限度地减少损失,但 model 仅在训练期间最大限度地减少均方误差。
def buildGenerator(dmodel, batch=100):
inputs = Input(shape=(256,256,1))
x = Conv2D(
filters = 32,
kernel_size = 3,
padding = 'same',
strides = 1
)(inputs)
x = BatchNormalization(momentum = 0.9)(x)
x = LeakyReLU(alpha=0.2)(x)
.........................
...........................
outputs1 = Conv2D(
filters = 2,
kernel_size = 3,
padding = 'same',
strides = 1
)(x)
outputs2 = dmodel(outputs1)
model = Model(inputs = inputs, outputs = [ outputs2, outputs1], name = 'functional_model')
model.compile(
loss = ['binary_crossentropy','mse' ],
optimizer = 'Adam',
loss_weights = [1.0, 0.6],
metrics=['accuracy', 'mse']
)
return model
在这段代码中,dmodel 是另一个 model。 我正在使用 dmodel 对 model 生成的输出 1 进行分类,然后找到输入标签和 output 标签之间的交叉熵。
我就是这样训练的
dmodel = buildDiscriminator()
dmodel.load_weights('./GAN/discriminator')
dmodel.trainable = False
x, y1 = getGeneratorData()
y2 = np.ones((batch, 1))
model = buildGenerator(dmodel)
model.fit(x,[y2, y1],epochs=1)
我尝试了很多方法,例如更改 loss_weights、更改损失函数,但没有任何效果。 我的 model 只是最小化了 MSE function。
我不明白我做错了什么。
我认为在生成器内部使用鉴别器 model 是问题,但我不确定。
不知道有没有简单的语法可以组合不同的损失函数,但是可以尝试定义一个自己的损失class。 在另一个线程中,我发现这个代码片段定义了一个自己的损失 class ,它结合了其他两个损失函数:
rho = 0.05
class loss_with_KLD(losses.Loss):
def __init__(self, rho):
super(loss_with_KLD, self).__init__()
self.rho = rho
self.kl = losses.KLDivergence()
self.mse = losses.MeanSquaredError(reduction=tf.keras.losses.Reduction.SUM)
def call(self, y_true, y_pred):
mse = self.mse(y_true, y_pred)
kl = self.kl(self.rho, y_pred)
return mse + kl
如果您只是用二进制交叉熵替换 KLDivergence,那么这应该可以工作。 此外,您需要更改 call() function,因为此实现在相同的预测 y 值上应用了两个损失 function,但您实际上预测了两个不同的 y 值。 在这种情况下,您的 y_true 和 y_pred 都将包含两个值,并且您只需要在其中一个上应用每个损失 function。 我不知道是否可以轻松地从向量中获取单个元素(以 y_true[0] 的样式),但如果不是,您可以通过乘以对向量应用“掩码”来解决此问题它们使用 [0, 1] 或 [1, 0],具体取决于您需要的值。 完成此操作后,您可以使用 reduce_sum() function 获取单个值并在新的 y_true 和 y_pred 上应用损失 function。
这有点复杂,但它应该可以完成工作。
当您指定 2 个损失函数时,它们适用于您的 2 个不同的输出。 即在您的示例中,binary_crossentropy 适用于 output2,它的 y_true 值全为 1。 并且是不可训练的 model 的 output。
您似乎想从 model 返回单个值,因为您似乎没有 output2 的标签。 虽然您可以定义自己的自定义损失 function 将两个损失结合在相同的值上,但我建议不要这样做。 如果 output 值是单个 class 预测(即像素开/关),则 binary_crossentrophy 有意义; 如果它应该是一个离散值,那么 mse 是有意义的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.