如何拆分卷积自动编码器?

Posted

技术标签:

【中文标题】如何拆分卷积自动编码器?【英文标题】:How do I split an convolutional autoencoder? 【发布时间】:2018-07-14 04:09:41 【问题描述】:

我已经编译了一个自动编码器(完整代码如下),在训练它之后,我想将它分成两个独立的模型:编码器(层 e1...编码)和解码器(所有其他层)在其中馈送手动修改已由解码器编码的图像。我已经成功地将编码器创建为一个单独的模型:

encoder = Model(input_img, autoencoder.layers[6].output)

但是当我尝试制作解码器时,同样的方法失败了:

encoded_input = Input(shape=(4,4,8))
decoder = Model(input_img, decoded)

这是我的完整代码:

from keras.layers import Input, Dense, Conv2D, MaxPooling2D, UpSampling2D
from keras.models import Model
from keras import backend as K
from keras.models import load_model

input_img = Input(shape=(28, 28, 1))  # adapt this if using channels_first` image data format

e1 = Conv2D(16, (3, 3), activation='relu', padding='same')(input_img)
e2 = MaxPooling2D((2, 2), padding='same')(e1)
e3 = Conv2D(8, (3, 3), activation='relu', padding='same')(e2)
e4 = MaxPooling2D((2, 2), padding='same')(e3)
e5 = Conv2D(8, (3, 3), activation='relu', padding='same')(e4)
encoded = MaxPooling2D((2, 2), padding='same')(e5)

# at this point the representation is (4, 4, 8) i.e. 128-dimensional

d1 = Conv2D(8, (3, 3), activation='relu', padding='same')(encoded)
d2 = UpSampling2D((2, 2))(d1)
d3 = Conv2D(8, (3, 3), activation='relu', padding='same')(d2)
d4 = UpSampling2D((2, 2))(d3)
d5 = Conv2D(16, (3, 3), activation='relu')(d4)
d6 = UpSampling2D((2, 2))(d5)
decoded = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(d6)

autoencoder = Model(input_img, decoded)
autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')

请帮忙。

编辑 顺便说一句,我可以使用由密集层组成的自动编码器来做到这一点:

from keras.layers import Input, Dense
from keras.models import Model

# this is the size of our encoded representations
encoding_dim = 32  # 32 floats -> compression of factor 24.5, assuming     the input is 784 floats

# this is our input placeholder
input_img = Input(shape=(784,))

# "encoded" is the encoded representation of the input
encoded = Dense(encoding_dim, activation='relu')(input_img)

# "decoded" is the lossy reconstruction of the input
decoded = Dense(784, activation='sigmoid')(encoded)

# this model maps an input to its reconstruction
autoencoder = Model(input_img, decoded)

# this model maps an input to its encoded representation
encoder = Model(input_img, encoded)

# create a placeholder for an encoded (32-dimensional) input
encoded_input = Input(shape=(encoding_dim,))

# retrieve the last layer of the autoencoder model
decoder_layer = autoencoder.layers[-1]

# create the decoder model
decoder = Model(encoded_input, decoder_layer(encoded_input))

【问题讨论】:

尝试遵循answer中显示的想法。 【参考方案1】:

好的,我在几个小时后发现了这一点。对我有用的是: 1.为编码器创建一个单独的模型 2.为解码器创建一个单独的模型 3.为自动编码器创建一个通用模型:

autoencoder = Model(input, Decoder()(Encoder(input))

完整的工作代码如下:

def Encoder():
    input_img = Input(shape=(28, 28, 1))  # adapt this if using `channels_first` image data format   
    e1 = Conv2D(16, (3, 3), activation='relu', padding='same')(input_img)
    e2 = MaxPooling2D((2, 2), padding='same')(e1)
    e3 = Conv2D(8, (3, 3), activation='relu', padding='same')(e2)
    e4 = MaxPooling2D((2, 2), padding='same')(e3)
    e5 = Conv2D(8, (3, 3), activation='relu', padding='same')(e4)
    e6 = MaxPooling2D((2, 2), padding='same')(e5)
    return Model(input_img, e6)


def Decoder():
    input_img = Input(shape=(4, 4, 8))  # adapt this if using `channels_first` image data format   
    d1 = Conv2D(8, (3, 3), activation='relu', padding='same')(input_img)
    d2 = UpSampling2D((2, 2))(d1)
    d3 = Conv2D(8, (3, 3), activation='relu', padding='same')(d2)
    d4 = UpSampling2D((2, 2))(d3)
    d5 = Conv2D(16, (3, 3), activation='relu')(d4)
    d6 = UpSampling2D((2, 2))(d5)
    d7 = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(d6)
    return Model(input_img, d7)


# define input to the model:
x = Input(shape=(28, 28, 1))

# make the model:
autoencoder = Model(x, Decoder()(Encoder()(x)))

# compile the model:
autoencoder.compile(optimizer='adadelta', loss='binary_crossentropy')

【讨论】:

这可行,但真正的问题是,自动编码器经过训练之后,如何提取编码器/解码器组件 @pcko1 这已经有一段时间了,但我认为您至少可以使用 get_weights() 获取层权重,或者您可以将autoencoder = Model(x, d(e(x))) 设为d = Decoder()e = Encoder()。训练自编码器后,您可以分别使用de 是的,正确!我只是想知道是否可以训练任意复杂的网络,然后将其拆分为两个子模型,而无需在训练之前将网络明确定义为两个子模型的模型。不过不用担心,你的方案也适用于我:)

以上是关于如何拆分卷积自动编码器?的主要内容,如果未能解决你的问题,请参考以下文章

Keras中的卷积自动编码器解码器错误

3D 卷积自动编码器未返回正确的输出形状

用于 keras 中可变大小图像的全卷积自动编码器

tensorflow,训练后拆分自动编码器

Pytorch Note43 自动编码器(Autoencoder)

cifar 10 的自动编码器,精度低