从 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 中经过训练的自动编码器模型中获取解码器的主要内容,如果未能解决你的问题,请参考以下文章