首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从Keras中经过训练的自动编码器模型中获取解码器

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

Stack Overflow用户
提问于 2019-04-01 15:09:52
回答 3查看 2.4K关注 0票数 3

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

我希望在训练了自动编码器之后,我能以某种方式“分割”自动编码器的下半部分,即通过函数Keras和autoenc_model.get_layer(),负责将潜在空间(128 )映射到图像空间(128、128、3)的解码器网络。

以下是我的模型的相关层

代码语言:javascript
复制
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)

这里是包含整个模型体系结构的笔记本。

为了从经过训练的自动编码器获得解码器网络,我尝试使用:

代码语言:javascript
复制
dec_model = Model(inputs=autoenc_model.get_layer('decoder_input').input, outputs=autoenc_model.get_layer('decoder_output').output)

代码语言:javascript
复制
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’层的输出形状。

EN

回答 3

Stack Overflow用户

发布于 2019-04-02 05:07:53

需要进行以下几项修改:

代码语言:javascript
复制
z = UpSampling2D()(decoder_input)

代码语言:javascript
复制
direct_input = Input(shape=(8,8,2), name='d_input')
#UnPooling-1
z = UpSampling2D()(direct_input)

代码语言:javascript
复制
autoenc_model = Model(input_img, decoder_output)

代码语言:javascript
复制
dec_model = Model(direct_input, decoder_output)
autoenc_model = Model(input_img, dec_model(decoder_input))

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

代码语言:javascript
复制
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

票数 2
EN

Stack Overflow用户

发布于 2019-04-02 03:50:31

我的解决方案并不是很优雅,而且可能有更好的解决方案,但是由于还没有人回答,我会发布它(我实际上希望有人能改进我自己的实现,如下所示)。

所以我所做的就是建立一个网络,它可以接受一个次要的输入,直接进入潜在的空间。不幸的是,这两种输入都是必需的,所以我最终使用了一个网络,它需要为“不想要的”输入设置满是零的虚拟数组(您马上就会看到)。

使用Keras functional:

代码语言:javascript
复制
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

代码语言:javascript
复制
model.fit([images,np.zeros((len(n_latent),...))],images)

然后,您可以使用以下方法获得潜在的特性:

代码语言:javascript
复制
latent_features = encoder.predict(images)

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

代码语言:javascript
复制
decoder.predict([Z_inputs,np.zeros(shape=images.shape)])

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

代码语言:javascript
复制
decoder_layer.set_weights(model_layer.get_weights()) 

应该能用,但我还没确认。它确实有一个缺点,就是每次你训练自动编码器模型时,都要再次复制重量。

因此,最后,我知道这里有很多问题,但再次,我只是张贴了这个,因为我没有看到其他人答复,并希望这将仍然是一些有用的你。

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

票数 1
EN

Stack Overflow用户

发布于 2022-03-14 17:24:48

一个选项是定义一个使用get_layer的函数,然后在其中重构解码器部分。例如,考虑具有以下体系结构的简单自动编码器: n_inputs、500、100、500、n_outputs。能够在下半部分运行一些输入(即通过500层和n_outputs层运行100个输入)。

代码语言:javascript
复制
# 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

对于您的示例,这个函数应该可以工作(假设您已经给您的层指定了这里引用的名称)。

代码语言:javascript
复制
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

有了这个函数,也有一种方法来测试它是否正常工作是有意义的。为了做到这一点,定义另一个从输入到瓶颈(潜在空间)的模型,例如:

代码语言:javascript
复制
bottleneck_layer = Model(inputs= input_img,outputs=decoder_input)

然后,作为测试,在模型的第一部分中运行一个向量并获得潜在空间:

代码语言:javascript
复制
import numpy as np
ones_image = np.ones((128,128,3))
bottleneck_ones = bottleneck_layer(ones_image.reshape(1,128,128,3))

然后通过上面定义的函数运行这个潜在空间来创建一个变量,您将根据整个网络的输出测试该变量:

代码语言:javascript
复制
decoded_test = decoder_part(autoenc_model, bottleneck_ones)

现在,在整个网络中运行ones_image并验证您是否得到了相同的结果:

代码语言:javascript
复制
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行没有抛出错误,则解码器工作正常。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55458306

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档