首页 > 解决方案 > Keras 示例中的自动编码器

问题描述

在 Keras 的文档中,有一个 DAE(去噪自动编码器)示例。以下是链接 https://keras.io/examples/mnist_denoising_autoencoder/

众所周知,自动编码器由编码器和解码器网络组成,编码器的输出就是编码器的输入。但是当我反复检查代码时,我发现示例中解码器的输入(称为潜在)也是编码器的输入。这让我很困惑。

以下是相关的代码段

# Build the Autoencoder Model
# First build the Encoder Model
inputs = Input(shape=input_shape, name='encoder_input')
x = inputs
# Stack of Conv2D blocks
# Notes:
# 1) Use Batch Normalization before ReLU on deep networks
# 2) Use MaxPooling2D as alternative to strides>1
# - faster but not as good as strides>1
for filters in layer_filters:
    x = Conv2D(filters=filters,
               kernel_size=kernel_size,
               strides=2,
               activation='relu',
               padding='same')(x)

# Shape info needed to build Decoder Model
shape = K.int_shape(x)

# Generate the latent vector
x = Flatten()(x)
latent = Dense(latent_dim, name='latent_vector')(x)

# Instantiate Encoder Model
encoder = Model(inputs, latent, name='encoder')
encoder.summary()

# Build the Decoder Model
latent_inputs = Input(shape=(latent_dim,), name='decoder_input')
x = Dense(shape[1] * shape[2] * shape[3])(latent_inputs)
x = Reshape((shape[1], shape[2], shape[3]))(x)
# Stack of Transposed Conv2D blocks
# Notes:
# 1) Use Batch Normalization before ReLU on deep networks
# 2) Use UpSampling2D as alternative to strides>1
# - faster but not as good as strides>1
for filters in layer_filters[::-1]:
    x = Conv2DTranspose(filters=filters,
                        kernel_size=kernel_size,
                        strides=2,
                        activation='relu',
                        padding='same')(x)

x = Conv2DTranspose(filters=1,
                    kernel_size=kernel_size,
                    padding='same')(x)

outputs = Activation('sigmoid', name='decoder_output')(x)

# Instantiate Decoder Model
decoder = Model(latent_inputs, outputs, name='decoder')
decoder.summary()

请注意解码器使用latent_inputs 作为其输入,但latent_inputs 来自输入,而不是来自潜在编码器的输出。

谁能告诉我为什么会这样?或者这是文档中的错误?非常感谢。

标签: kerasautoencoder

解决方案


您对使用的输入Model(..)和解码器输入的命名约定感到困惑。

Model(...)在此代码中,为编码器和解码器创建了两个独立的。当您将创建最终的自动编码器模型时,例如在此图中,您需要将编码器的输出馈送到解码器的输入。 在此处输入图像描述

正如您所描述的,“解码器使用latent_inputs 作为其输入,但latent_inputs 来自输入(此输入是解码器模型的输入,而不是自动编码器模型的输入)”。

encoder = Model(inputs, latent, name='encoder')创建编码器模型并decoder = Model(latent_inputs, outputs, name='decoder')创建latent_inputs用作编码器模型输出的输入的解码器模型。

最终的自动编码器模型将由以下生成,

autoencoder = Model(inputs, decoder(encoder(inputs)), name='autoencoder')

在这里,编码器模型inputs的输入来自,解码器模型的输出是自动编码器的最终输出。并且要创建编码器的输出,首先它将编码器的输入和输出馈送inputsencoder(...)解码器,如下所示decoder(encoder(...))

为了您的简单,您也可以创建这样的模型,

# Build the Autoencoder Model
# Encoder
inputs = Input(shape=input_shape, name='encoder_input')
x = inputs
for filters in layer_filters:
    x = Conv2D(filters=filters,
               kernel_size=kernel_size,
               strides=2,
               activation='relu',
               padding='same')(x)
shape = K.int_shape(x)
x = Flatten()(x)
latent = Dense(latent_dim, name='latent_vector')(x)

# Decoder

x = Dense(shape[1] * shape[2] * shape[3])(latent)
x = Reshape((shape[1], shape[2], shape[3]))(x)

for filters in layer_filters[::-1]:
    x = Conv2DTranspose(filters=filters,
                        kernel_size=kernel_size,
                        strides=2,
                        activation='relu',
                        padding='same')(x)

x = Conv2DTranspose(filters=1,
                    kernel_size=kernel_size,
                    padding='same')(x)

outputs = Activation('sigmoid', name='decoder_output')(x)


autoencoder = Model(inputs, outputs, name='autoencoder')
autoencoder.summary()

推荐阅读