Keras: чистая реализация для нескольких выходов и пользовательских функций потерь? - PullRequest
0 голосов
/ 28 января 2019

Исходя из 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, в которых вы не должны что-то определять самостоятельно, а использовать только предопределенные функции потерь.

1 Ответ

0 голосов
/ 28 января 2019

В TensorFlow я бы просто определил два Tensors logits = x и output = sigmoid (x), чтобы можно было использовать logits в любой пользовательской функции потерь и выводить данные для построения графиков или других приложений.

В Keras вы делаете то же самое:

x = Conv2D(1, (3, 3), activation="linear")(x)
dec_out = resize_images(x, (28, 28))  # Output tensor used in training, for the loss function

training_model = Model(dec_in, dec_out, name="decoder")

...

sigmoid = Activation('sigmoid')(dec_out)
inference_model = Model(dec_in, sigmoid)

training_model.fit(x=X_train, y=X_train, batch_size=256, epochs=10)

prediction = inference_model.predict(some_input)

В мире Keras ваша жизнь становится намного проще, если у вас есть один выходной тензор.Тогда вы можете получить стандартные функции Keras, работающие на него.Для двух выходов / потерь один из возможных обходных путей может заключаться в том, чтобы объединить их перед выходом и затем снова разделить в функции потерь.Хорошим примером здесь может служить реализация SSD, которая имеет потери при классификации и локализации: https://github.com/pierluigiferrari/ssd_keras/blob/master/keras_loss_function/keras_ssd_loss.py#L133

В общем, я не понимаю этих жалоб.Можно понять, что новый фреймворк сначала вызывает разочарование, но Keras великолепен, потому что он может быть простым, когда вам нужны стандартные вещи, и гибким, когда вам нужно выйти за рамки.Количество реализаций сложных моделей в зоопарке модели Keras - хорошее тому подтверждение.Прочитав этот код, вы сможете изучить различные шаблоны построения моделей в Keras.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...