如何在卷积自动编码器中的 2d 卷积层之后添加密集层?

人工智能 卷积神经网络 喀拉斯 自动编码器 卷积层 致密层
2021-10-18 13:10:42

我正在尝试在瓶颈处实现一个具有密集层的卷积自动编码器,以进行一些降维。我已经看到了两种方法,它们不是特别可扩展的。第一个是引入 2 个密集层(一个在瓶颈处,一个在其前后具有与编码器部分中密集层之前的 conv2d 层相同的节点数:

input_image_shape=(200,200,3)
encoding_dims = 20

encoder = Sequential()
encoder.add(InputLayer(input_image_shape))
encoder.add(Conv2D(32, (3,3), activation="relu, padding="same"))
encoder.add(MaxPooling2D((2), padding="same"))
encoder.add(Flatten())
encoder.add(Dense(32*100*100, activation="relu"))
encoder.add(Dense(encoding_dims, activation="relu"))

#The decoder
decoder = Sequential()
decoder.add(InputLayer((encoding_dims,)))
decoder.add(Dense(32*100*100, activation="relu"))
decoder.add(Reshape((100, 100, 32)))
decoder.add(UpSampling2D(2))
decoder.add(Conv2D(3, (3,3), activation="sigmoid", padding="same"))

很容易看出为什么这种方法会爆炸,因为有两个密集连接的层,每个或更多节点都有(32 100 100)个节点,或者在那个疯狂的球场中。

我发现另一种对黑白图像有意义的方法是引入任意数量的编码维度并对其进行重塑(https://medium.com/analytics-vidhya/building-a-convolutional-autoencoder -using-keras-using-conv2dtranspose-ca403c8d144e)。以下代码块是从链接中复制的,我不承认它的功劳:

#ENCODER
inp = Input((28, 28,1))
e = Conv2D(32, (3, 3), activation='relu')(inp)
e = MaxPooling2D((2, 2))(e)
e = Conv2D(64, (3, 3), activation='relu')(e)
e = MaxPooling2D((2, 2))(e)
e = Conv2D(64, (3, 3), activation='relu')(e)
l = Flatten()(e)
l = Dense(49, activation='softmax')(l)
#DECODER
d = Reshape((7,7,1))(l)
d = Conv2DTranspose(64,(3, 3), strides=2, activation='relu', padding='same')(d)
d = BatchNormalization()(d)
d = Conv2DTranspose(64,(3, 3), strides=2, activation='relu', padding='same')(d)
d = BatchNormalization()(d)
d = Conv2DTranspose(32,(3, 3), activation='relu', padding='same')(d)
decoded = Conv2D(1, (3, 3), activation='sigmoid', padding='same')(d)

那么,有没有更严格的方法在 2d 卷积层之后添加密集层呢?

1个回答

对我来说,这非常有效。我使用 conv2d 和密集编码,然后在密集层之后在解码器中展平 I 并重塑,因此编码器和解码器是对称的。唯一的区别是,在我的情况下,我使用图像 (224,224,1)

# create encoder
# 28,28 -> 1st conv2d (filter 3x3,relu activation, padding, strides == 'jumps')
self.encoder = tf.keras.Sequential([layers.Input(shape=(224,224,1)),
                                    layers.Conv2D(16,kernel_size=3,activation='relu',padding='same',strides=2),                
                                    layers.Conv2D(8,kernel_size=3,activation='relu',padding='same',strides=2),
                                    layers.Conv2D(4,kernel_size=3,activation='relu',padding='same',strides=2),
                                    layers.Flatten(),
                                    layers.Dense(units=3136,activation='sigmoid')]) # (28,28,4)

# deconvolution -> decoding 
self.decoder = tf.keras.Sequential([layers.Input(shape=(3136)),
                                    layers.Dense(units=3136,activation='sigmoid'),
                                    layers.Reshape((28,28,4)),
                                    layers.Conv2DTranspose(4,kernel_size=3,activation='relu',padding='same',strides=2),
                                    layers.Conv2DTranspose(8,kernel_size=3,strides=2,activation='relu',padding='same'),
                                    layers.Conv2DTranspose(16,kernel_size=3,strides=2,activation='relu',padding='same'),
                                    layers.Conv2D(1,kernel_size=(3,3),activation='sigmoid',padding='same')])