Keras:多输出和自定义损失函数的清晰实现? [英] Keras: clean implementation for multiple outputs and custom loss functions?

查看:714
本文介绍了Keras:多输出和自定义损失函数的清晰实现?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

来自TensorFlow,我觉得除了在Keras中实现基本的顺序模型之外,其他任何事情都可能非常棘手.有这么多东西会自动进行.在TensorFlow中,您始终知道占位符(输入/输出),形状,结构等,因此,例如设置自定义损失非常容易.

Coming from TensorFlow I feel like implementing anything else than basic, sequential models in Keras can be quite tricky. There is just so much stuff going on automatically. In TensorFlow, you always know your placeholders (input/output), shapes, structure, ... so that it is very easy to, for example, set up custom losses.

定义多个输出和自定义损失函数的干净方法是什么?

What is a clean way to define multiple outputs and custom loss functions?

让我们以一个简单的自动编码器为例,并使用MNIST:

Let's take an easy autoencoder as an example and use 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):

Similar architecture for the decoder. We do not care for padding and the decrease in dimensionality due to convolutions, so we just apply bilinear resizing at the end to match (batch, 28, 28, 1) again:

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定义为一个简单的示例...

We define our own MSE to have an easy example...

def custom_loss(y_true, y_pred):
    return K.mean(K.square(y_true - y_pred))

...并最终构建完整的模型:

...and finally build our complete model:

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不会自动使用logits,而是将S形激活输入失利.因此,这要好得多.更快的训练以便在最后一层使用activation="linear".在TensorFlow中,我只需定义两个张量logits=xoutput=sigmoid(x)即可在任何自定义损失函数中使用logits并在绘图或其他应用程序中使用output.

If I define activation="sigmoid" in the last layer of the decoder in order to get nice images (output interval [0.0, 1.0]) the training loss diverges as Keras is not using the logits automatically, but feeding sigmoid activations into the loss. Thus, it is much better & faster for training to use activation="linear" in the last layer. In TensorFlow I would simply define two Tensors logits=x and output=sigmoid(x) to be able to use logits in any custom loss function and output for plotting or other applications.

我将如何在Keras中做这样的事情?

How would I do such a thing in Keras?

此外,如果我有多个输出,如何在自定义损失函数中使用它们?例如VAE的KL差异或GAN的亏损条件.

Additionally, if I have several outputs, how do I use them in custom loss functions? Like KL divergence for VAEs or loss terms for GANs.

功能性API指南并不是很有帮助(尤其是如果您将此与TensorFlow的超级指南进行比较),因为它仅涵盖了基本的LSTM示例,您无需自己定义任何内容,而仅使用预定义的损失函数即可.

The functional API guide is not very helpful (especially if you compare this to the super extensive guides of TensorFlow) since it only covers basic LSTM examples where you do not have to define anything yourself, but only use predefined loss functions.

推荐答案

在TensorFlow中,我仅定义两个Tensors logits = x和output = sigmoid(x),以便能够在任何自定义损失函数和输出中使用logits进行绘图或其他应用.

In TensorFlow I would simply define two Tensors logits=x and output=sigmoid(x) to be able to use logits in any custom loss function and output for plotting or other applications.

在Keras中,您执行的操作完全相同:

In Keras you do exactly the same:

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实现,它具有分类和本地化的损失:

In Keras world your life becomes much easier if you got a single output tensor. Then you can get standard Keras features working for it. For two outputs/losses one possible workaround can be to concatenate them before output and then split again in the loss function. A good example here can be SSD implementation, which has classification and localization losses: https://github.com/pierluigiferrari/ssd_keras/blob/master/keras_loss_function/keras_ssd_loss.py#L133

总的来说,我不理解那些抱怨.可以理解,一个新的框架起初会造成挫败感,但是Keras很棒,因为当您需要标准的东西时它很简单,而当您需要超越标准的东西时它就很灵活.在 Keras模型动物园中,复杂模型的实现数量就是一个很好的证明.通过阅读该代码,您可以学习在Keras中构建模型的各种模式.

In general, I do not understand those complains. It can be understood that a new framework causes frustration at first, but Keras is great because it can be simple when you need standard stuff and flexible when you need to go beyond. Number of complex models' implementations in Keras model zoo is a good justification for that. By reading that code you can learn various patterns for constructing models in Keras.

这篇关于Keras:多输出和自定义损失函数的清晰实现?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆