我正在训练一个深层的自动编码器,将人的脸映射到128维的潜在空间,然后将它们解码回原来的128x128x3格式。
我希望在训练了自动编码器之后,我能以某种方式“分割”自动编码器的下半部分,即通过函数Keras和autoenc_model.get_layer(),负责将潜在空间(128 )映射到图像空间(128、128、3)的解码器网络。
以下是我的模型的相关层
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)这里是包含整个模型体系结构的笔记本。
为了从经过训练的自动编码器获得解码器网络,我尝试使用:
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博客文章只介绍了如何为2层自动编码器提取解码器。
解码器的输入/输出形状应该是:(128,)和(128,128,3),这分别是'decoder_input‘和'decoder_output’层的输出形状。
发布于 2019-04-02 05:07:53
需要进行以下几项修改:
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)))您还可以参考这个自包含的示例:autoencoder.py。
发布于 2019-04-02 03:50:31
我的解决方案并不是很优雅,而且可能有更好的解决方案,但是由于还没有人回答,我会发布它(我实际上希望有人能改进我自己的实现,如下所示)。
所以我所做的就是建立一个网络,它可以接受一个次要的输入,直接进入潜在的空间。不幸的是,这两种输入都是必需的,所以我最终使用了一个网络,它需要为“不想要的”输入设置满是零的虚拟数组(您马上就会看到)。
使用Keras functional:
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()) 应该能用,但我还没确认。它确实有一个缺点,就是每次你训练自动编码器模型时,都要再次复制重量。
因此,最后,我知道这里有很多问题,但再次,我只是张贴了这个,因为我没有看到其他人答复,并希望这将仍然是一些有用的你。
如果有什么不清楚的地方,请评论。
发布于 2022-03-14 17:24:48
一个选项是定义一个使用get_layer的函数,然后在其中重构解码器部分。例如,考虑具有以下体系结构的简单自动编码器: n_inputs、500、100、500、n_outputs。能够在下半部分运行一些输入(即通过500层和n_outputs层运行100个输入)。
# Function to get outputs from a given set of bottleneck inputs
def bottleneck_to_outputs(bottleneck_inputs, autoencoder):
# Run bottleneck_inputs (eg 100 units) through decoder layer (eg 500 units)
x = autoencoder.get_layer('decoder')(bottleneck_inputs)
# Run x (eg 500 units) through output layer (n units = n features)
x = autoencoder.get_layer('output')(x)
return x对于您的示例,这个函数应该可以工作(假设您已经给您的层指定了这里引用的名称)。
def decoder_part(autoenc_model, image):
#UnPooling-1
z = autoenc_model.get_layer('upsampling1')(image)
#9
z = autoenc_model.get_layer('conv2d1')(z)
z = autoenc_model.get_layer('batchnorm1')(z)
#10
z = autoenc_model.get_layer('conv2d2')(z)
z = autoenc_model.get_layer('batchnorm2')(z)
#UnPooling-2
z = autoenc_model.get_layer('upsampling2')(z)
#11
z = autoenc_model.get_layer('conv2d3')(z)
z = autoenc_model.get_layer('batchnorm3')(z)
#12
z = autoenc_model.get_layer('conv2d4')(z)
z = autoenc_model.get_layer('batchnorm4')(z)
#UnPooling-3
z = autoenc_model.get_layer('upsampling3')(z)
#13
z = autoenc_model.get_layer('conv2d5')(z)
z = autoenc_model.get_layer('batchnorm5')(z)
#14
z = autoenc_model.get_layer('conv2d6')(z)
z = autoenc_model.get_layer('batchnorm6')(z)
#UnPooling-4
z = autoenc_model.get_layer('upsampling4')(z)
#15
z = autoenc_model.get_layer('conv2d7')(z)
z = autoenc_model.get_layer('batchnorm7')(z)
#16
decoder_output = autoenc_model.get_layer('decoder_output')(z)
return decoder_output有了这个函数,也有一种方法来测试它是否正常工作是有意义的。为了做到这一点,定义另一个从输入到瓶颈(潜在空间)的模型,例如:
bottleneck_layer = Model(inputs= input_img,outputs=decoder_input)然后,作为测试,在模型的第一部分中运行一个向量并获得潜在空间:
import numpy as np
ones_image = np.ones((128,128,3))
bottleneck_ones = bottleneck_layer(ones_image.reshape(1,128,128,3))然后通过上面定义的函数运行这个潜在空间来创建一个变量,您将根据整个网络的输出测试该变量:
decoded_test = decoder_part(autoenc_model, bottleneck_ones)现在,在整个网络中运行ones_image并验证您是否得到了相同的结果:
model_test = autoenc_model.predict(ones_image.reshape(1,128,128,3))
tf.debugging.assert_equal(model_test, decoder_test, message= 'Tensors are not equivalent') 如果assert_equal行没有抛出错误,则解码器工作正常。
https://stackoverflow.com/questions/55458306
复制相似问题