Я создаю модель Keras GAN, которая имеет несколько выходов, поскольку я хотел добавить к ней больше целевых функций.Однако добавление третьей функции вывода и потерь полностью приводит к сбою моего тренировочного процесса, и одна из потерь дает результат NaN, даже если вес этой конкретной функции потерь установлен на 0.
Таким образом, несмотря на два наиболее распространенных выхода и потери, связанные с этим -Бинарная перекрестная энтропия дискриминатора и разность L1 генератора. Я хотел создать один лямбда-слой, соединенный с выходом генератора, чтобы выполнить определение края Собеля.Вывод моей предварительно обученной модели удовлетворителен, поскольку лямбда-слой создает хорошие карты краев, а выходные данные генератора и дискриминатора остаются нетронутыми.Теперь я хочу определить потери - я реализовал функцию потерь 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'])
Это моя функция, которая используется в лямбда-слое.
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