从 Keras 中经过训练的自动编码器模型中获取解码器

Posted

技术标签:

【中文标题】从 Keras 中经过训练的自动编码器模型中获取解码器【英文标题】:Get decoder from trained autoencoder model in Keras 【发布时间】:2019-08-22 19:22:48 【问题描述】:

我正在训练深度自动编码器将人脸映射到 128 维潜在空间,然后将它们解码回其原始 128x128x3 格式。

我希望在训练自动编码器之后,我能够以某种方式“切片”自动编码器的后半部分,即负责将潜在空间 (128,) 映射到图像空间 (128, 128) 的解码器网络, 3) 通过使用功能性 Keras API 和autoenc_model.get_layer()

这里是我model的相关层:

INPUT_SHAPE=(128,128,3)
input_img = Input(shape=INPUT_SHAPE, name='enc_input')

#1
x = Conv2D(64, (3, 3), padding='same', activation='relu')(input_img)
x = BatchNormalization()(x)

//Many Conv2D, BatchNormalization(), MaxPooling() layers
.
.
.

#Flatten
fc_input = Flatten(name='enc_output')(x)

y = Dropout(DROP_RATE)(fc_input)
y = Dense(128, activation='relu')(y)
y = Dropout(DROP_RATE)(y)
fc_output = Dense(128, activation='linear')(y)   

#Reshape
decoder_input = Reshape((8, 8, 2), name='decoder_input')(fc_output)

#Decoder part

#UnPooling-1
z = UpSampling2D()(decoder_input)
//Many Conv2D, BatchNormalization, UpSampling2D layers
.
.
.
#16
decoder_output = Conv2D(3, (3, 3), padding='same', activation='linear', name='decoder_output')(z)

autoenc_model = Model(input_img, decoder_output)

here 是包含整个模型架构的笔记本。

为了从训练有素的自动编码器中获取解码器网络,我尝试使用:

dec_model = Model(inputs=autoenc_model.get_layer('decoder_input').input, outputs=autoenc_model.get_layer('decoder_output').output)

dec_model = Model(autoenc_model.get_layer('decoder_input'), autoenc_model.get_layer('decoder_output'))

这两种方法似乎都不起作用。

我需要从自动编码器中提取解码器层,因为我想先训练整个自动编码器模型,然后独立使用编码器和解码器。

我在其他任何地方都找不到满意的答案。关于构建自编码器的Keras blog article 仅介绍了如何为 2 层自编码器提取解码器。

解码器输入/输出形状应为:(128, ) 和 (128, 128, 3),分别是“decoder_input”层的输入形状和“decoder_output”层的输出形状。

【问题讨论】:

【参考方案1】:

需要进行几处更改:

z = UpSampling2D()(decoder_input)

direct_input = Input(shape=(8,8,2), name='d_input')
#UnPooling-1
z = UpSampling2D()(direct_input)

autoenc_model = Model(input_img, decoder_output)

dec_model = Model(direct_input, decoder_output)
autoenc_model = Model(input_img, dec_model(decoder_input))

现在,您可以在自动编码器上进行训练并使用解码器进行预测。

import numpy as np
autoenc_model.fit(np.ones((5,128,128,3)), np.ones((5,128,128,3)))
dec_model.predict(np.ones((1,8,8,2)))

你也可以参考这个独立的例子: https://github.com/keras-team/keras/blob/master/examples/variational_autoencoder.py

【讨论】:

感谢您的回答,但是,dec_model = Model(direct_input, decoder_output) 这一行不应该是dec_model = Model(z, decoder_output) 吗?谢谢。 模型输入需要是一个“输入”层。我们将“输入”层添加到解码器,以便以后可以将其用作独立模型。解码器中名为“z”的上采样层有点误导,因为它通常是为编码器的潜在空间输出保留的。 谢谢。我问了一个与此相关的问题,***.com/questions/63756756/…。【参考方案2】:

我的解决方案不是很优雅,并且可能有更好的解决方案,但是由于没有人回复,我会发布它(我实际上希望有人会这样我可以改进我自己的实现,就像你会在下面看到)。

所以我所做的是构建了一个网络,该网络可以将辅助输入直接输入潜在空间。 不幸的是,这两个输入都是强制性的,所以我最终得到了一个网络,该网络需要为“不需要的”输入填充全零的虚拟数组(稍后您会看到)。

使用 Keras 函数式 API:

image_input = Input(shape=image_shape)
conv1 = Conv2D(...,activation='relu')(image_input)
...
dense_encoder = Dense(...)(<layer>)
z_input = Input(shape=n_latent)
decoder_entry = Dense(...,activation='relu')(Add()([dense_encoder,z_input]))
...
decoder_output = Conv2DTranspose(...)


model = Model(inputs=[image_input,z_input], outputs=decoder_output)
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

encoder = Model(inputs=image_input,outputs=dense_encoder)
decoder = Model(inputs=[z_input,image_input], outputs=decoder_output)

请注意,您不应编译编码器和解码器。

(有些代码要么省略,要么留下...供您填写您的具体需求)。

最后,要进行训练,您必须提供一个空数组。所以要训练整个自动编码器:

图像在这种情况下是 X

model.fit([images,np.zeros((len(n_latent),...))],images)

然后您可以使用以下方法获取潜在特征:

latent_features = encoder.predict(images)

或者使用带有潜在输入和虚拟变量的解码器(注意上面的输入顺序):

decoder.predict([Z_inputs,np.zeros(shape=images.shape)])

最后,我没有尝试过的另一个解决方案是构建并行模型,具有相同的架构,一个是自动编码器,第二个是解码器部分,然后使用:

decoder_layer.set_weights(model_layer.get_weights()) 

它应该可以工作,但我还没有确认。它的缺点是每次训练自动编码器模型时都必须再次复制权重。

所以总结一下,我知道这里有很多问题,但我再次发布这个只是因为我没有看到其他人回复,并希望这对你仍然有用。

如果有不清楚的地方请评论。

【讨论】:

以上是关于从 Keras 中经过训练的自动编码器模型中获取解码器的主要内容,如果未能解决你的问题,请参考以下文章

从经过训练的 keras 模型中获取训练超参数

如果我将层传递给两个 Keras 模型并且只训练一个模型,那么在前者训练后两个模型会共享权重吗

keras:将一个模型的输出作为另一个模型的部分输入。

如何在 Keras 中使用经过训练的模型进行预测

神经网络训练过程诊断

如何在 Keras 中保存经过训练的模型以在应用程序中使用它?