Автоэнкодер на примере Кераса - PullRequest
0 голосов
/ 07 июня 2019

В документе Keras есть пример DAE (Denoising AutoEncoder). Вот ссылка 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 поступает с Input, а не с выходного сигнала скрытого кодера.

Может кто-нибудь сказать мне, почему это так? Или это ошибка в документе? Большое спасибо.

1 Ответ

0 голосов
/ 07 июня 2019

Вы путаетесь между соглашением об именах, которые используются. Ввод Model(..) и ввод декодера.

В этом коде два отдельных Model(...) создаются для кодера и декодера. Когда вы создадите свою окончательную модель автоэнкодера, например, на этом рисунке вам нужно подать выход кодера на вход декодера. enter image description here

Как вы описали, «декодер использует latent_inputs в качестве входных данных, но latent_inputs поступает от Input ( этот вход является входом только для модели декодера, а не модели Autoencoder )».

encoder = Model(inputs, latent, name='encoder') создает модель кодера, а decoder = Model(latent_inputs, outputs, name='decoder') создает модель декодера, которая использует latent_inputs в качестве входа, который является выходом модели кодера.

Окончательная модель автоэнкодера будет сгенерирована,

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

Здесь ваш вход для модели кодера от inputs, а ваш выход от модели декодера - это ваш конечный выход для автоматического кодера. И чтобы создать вывод кодера, сначала он передает inputs в encoder(...), а выход кодера передает в декодер как 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()
...