我正在创建一个具有多个输出的Keras GAN模型,因为我想为其添加更多目标功能。但是,添加第三个输出和损失函数会完全使我的训练过程崩溃,即使将此特定损失函数的权重设置为0,损失之一也会给出NaN结果。
因此,尽管有两个最常见的输出和与之相关的损耗-鉴频器的二进制交叉熵和发生器的L1差,我还是想创建一个连接到发生器输出的Lambda层来执行Sobel边缘检测。我的预训练模型的输出令人满意,因为Lambda层创建了不错的边缘贴图,并且生成器和鉴别器的输出保持不变。现在,我要定义损耗-我对Lambda层实施了L1损耗函数,方法与标准生成器的输出相同。由于我已经准备了具有真实边缘图的数据集,因此该问题应该微不足道,但是在训练过程中,在第一批处理之后,生成器的输出变为黑色并且边缘损失为NaN-即使将边缘层的损失权重设置为0。如果我理解正确,如果在编译模型时将损失权重设置为0,则此特定损失函数不应影响模型的学习过程。我进行了双重甚至三重检查,是否存在任何数字错误,但没有。 在我对测试批次进行测试时编译模型后,损失就是一个数值。即使只训练一批,它也变成NaN。
如您所见,“边缘”权重设置为0。它仍然会影响训练。 从声明中删除“ edge”线会得到以前的结果,因此没有Sobel层的模型可以正常工作。
gen_losses = {
"gen": L1,
"edge": L1,
"disc": "binary_crossentropy"
}
alpha = 0.3
beta = 0.0
gen_loss_weights = {
"gen": alpha,
"edge": beta,
"disc": 1.0-alpha-beta
}
d_on_g = generator_containing_discriminator(gen, disc)
d_optim = keras.optimizers.Adam(lr=2e-6, beta_1=0.5)
dg_optim = keras.optimizers.Adam(lr=2e-4, beta_1=0.5)
g_optim = keras.optimizers.SGD(lr=2e-7, momentum=0.9, nesterov=True, decay=0)
gen.compile(loss='mean_squared_error', optimizer=g_optim, metrics=['acc'])
d_on_g.compile(loss=gen_losses, loss_weights=gen_loss_weights, optimizer=dg_optim, metrics=['acc'])
make_trainable(disc, True)
disc.compile(loss='binary_crossentropy', optimizer=d_optim, metrics=['acc'])
这是我在Lambda层中使用的函数。
def sobel_custom(x):
x = tf.image.rgb_to_grayscale(x)
x = tf.image.sobel_edges(x)
x1 = K.pow(x[:, :, :, :, 0], 2)
x2 = K.pow(x[:, :, :, :, 1], 2)
x = K.sqrt(x1 + x2)
x = x/(tf.reduce_max(x) - tf.reduce_min(x)) * 2 - 1 - tf.reduce_min(x)
return x
训练部分-适当的数据被馈送到反向传播算法。
g_loss = d_on_g.train_on_batch(features, {"gen": np.array(labels),
"disc": np.array([1]*batch_size),
"edge": np.array(labels_edges)})
整个模型创建部分。
def generator_containing_discriminator(g, d):
print("GAN:")
gan_input = layers.Input(shape=(feature_size, feature_size, 3))
g._name = "gen"
d._name = "disc"
gen_output = g(gan_input)
edge_output = Lambda(sobel_custom, name="edge")(gen_output)
make_trainable(d, False)
disc_output = d(gen_output)
model = keras.models.Model(inputs=[gan_input], outputs=[gen_output,
disc_output, edge_output])
model.summary()
plot_model(model, to_file="GAN.png")
print(model.output_shape)
return model
我只想知道我在做什么错。我确定使用多个加权损失函数计算损失的形式如下:L = w1 * l1 + w2 * l2 + ... + wn * ln,但显然我是错误的,因为即使一个权重等于0,它仍然影响结果。
Tensorflow 1.12.0 GPU / Python 3.6