Исходя из TensorFlow, я чувствую, что реализовать что-либо кроме базовых последовательных моделей в Keras может быть довольно сложно.Просто так много всего происходит автоматически.В TensorFlow вы всегда знаете свои заполнители (ввод / вывод), формы, структуру, ... так что очень легко, например, настроить пользовательские потери.
Что такое чистый способ определениянесколько выходов и пользовательские функции потерь?
Давайте возьмем в качестве примера простой авто-кодер и используем MNIST:
(X_train, Y_train), (X_test, Y_test) = mnist.load_data()
X_train = X_train.reshape(-1, 28, 28, 1)
Короткий сверточный кодер:
enc_in = Input(shape=(28, 28, 1), name="enc_in")
x = Conv2D(16, (3, 3))(enc_in)
x = LeakyReLU()(x)
x = MaxPool2D()(x)
x = Conv2D(32, (3, 3))(x)
x = LeakyReLU()(x)
x = Flatten()(x)
z = Dense(100, name="z")(x)
enc = Model(enc_in, z, name="encoder")
Подобная архитектурадля декодера.Мы не заботимся о заполнении и уменьшении размерности из-за свертки, поэтому мы просто применяем билинейное изменение размера в конце, чтобы снова соответствовать (batch, 28, 28, 1)
:
def resize_images(inputs, dims_xy):
x, y = dims_xy
return Lambda(lambda im: K.tf.image.resize_images(im, (y, x)))(inputs)
# decoder
dec_in = Input(shape=(100,), name="dec_in")
x = Dense(14 * 14 * 8)(dec_in)
x = LeakyReLU()(x)
x = Reshape((14, 14, 8))(x)
x = Conv2D(32, (3, 3))(x)
x = LeakyReLU()(x)
x = UpSampling2D()(x)
x = Conv2D(16, (3, 3))(x)
x = LeakyReLU()(x)
x = Conv2D(1, (3, 3), activation="linear")(x)
dec_out = resize_images(x, (28, 28))
dec = Model(dec_in, dec_out, name="decoder")
Мы определяем нашу собственную MSE, чтобы иметь простой пример...
def custom_loss(y_true, y_pred):
return K.mean(K.square(y_true - y_pred))
... и, наконец, построим нашу полную модель:
outputs = dec(enc(enc_in))
ae = Model(enc_in, outputs, name="ae")
ae.compile(optimizer=Adam(lr=1e-4), loss=custom_loss)
# training
ae.fit(x=X_train, y=X_train, batch_size=256, epochs=10)
Если я определю activation="sigmoid"
в последнем слое декодера, чтобы получить хорошие изображения(выходной интервал [0.0, 1.0]) тренировочная потеря расходится, поскольку Keras не использует логиты автоматически, а подает сигмовидные активации в потерю.Таким образом, для обучения гораздо лучше и быстрее использовать activation="linear"
в последнем слое.В TensorFlow я бы просто определил два тензора logits=x
и output=sigmoid(x)
, чтобы можно было использовать logits
в любой пользовательской функции потерь и output
для построения графиков или других приложений.
Как бы я сделал такойчто в Керасе?
Кроме того, если у меня есть несколько выходов, как их использовать в пользовательских функциях потерь?Например, дивергенция KL для VAE или условия потерь для GAN.
Функциональное руководство по API не очень полезно (особенно если сравнить его с очень обширными руководствами TensorFlow), поскольку оно охватывает только основныеПримеры LSTM, в которых вы не должны что-то определять самостоятельно, а использовать только предопределенные функции потерь.