Получить декодер от обученной модели автоэнкодера в Керасе - PullRequest
2 голосов
/ 01 апреля 2019

Я тренирую глубокий автоэнкодер, чтобы отобразить человеческие лица в 128-мерное скрытое пространство, а затем декодировать их обратно в исходный формат 128x128x3.

Я надеялся, что после обучения автоэнкодеру я каким-то образомвозможность «нарезать» вторую половину автоэнкодера, то есть сеть декодера, отвечающую за отображение скрытого пространства (128,) в пространство изображения (128, 128, 3), используя функциональный API Keras и autoenc_model.get_layer()

Вот соответствующие слои моей модели :

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 о создании автоэнкодеров рассказывается только о том, как извлечь декодер для двухслойных автоэнкодеров.

Форма ввода / вывода декодера должна быть: (128,) и (128, 128,3), который является входной формой слоев 'decoder_input' и выходной формой слоев 'decoder_output' соответственно.

Ответы [ 2 ]

2 голосов
/ 02 апреля 2019

Требуется пара изменений:

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

1 голос
/ 02 апреля 2019

Мое решение не очень элегантное, и, возможно, есть более лучшие решения, но поскольку никто еще не ответил, я опубликую его (я действительно надеялся, что кто-то сделает так, чтобы я мог улучшить свою собственную реализацию, как вы увидим ниже).

Итак, я построил сеть, которая может принимать вторичный вход непосредственно в скрытое пространство. К сожалению, оба ввода являются обязательными, поэтому я получаю сеть, в которой требуются фиктивные массивы, заполненные нулями для «нежелательного» ввода (вы увидите через секунду).

Использование функционального API Keras:

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()) 

Это должно сработать, но я не подтвердил это. У него есть недостаток, заключающийся в том, что он должен копировать веса каждый раз, когда в вашем поезде используется модель автоэнкодера.

Итак, в заключение я знаю о многих проблемах здесь, но опять же, я опубликовал это только потому, что видел, что никто не ответил, и надеялся, что это все равно будет вам полезно.

Пожалуйста, прокомментируйте, если что-то не понятно.

...