卷积自动编码器

Convolutional Autoencoders

我正在为 CIFAR10 数据集上的 运行 自动编码器编写代码并查看重建图像。

要求是创建

编码器第一层

编码器第二层


解码器第一层

带第二层的解码器


我明白

  1. 当我们创建卷积自动编码器(或任何 AE)时,我们需要将上一层的输出传递到下一层。
  2. 所以,当我用 ReLu 创建第一个 Conv2D 层然后执行 BatchNormalization 时......我在其中传递了 Conv2D 层......对吧?
  3. 但是当我做 MaxPooling2D .. 我应该传递什么.. BatchNormalization 输出或 Conv2D 层输出?

另外,我执行这些操作有什么顺序吗?


我在下面附上我的代码...我尝试了两种不同的方式,因此得到了不同的输出(在模型摘要和模型训练图方面)

谁能帮我解释一下哪个是正确的方法(方法 1 或方法 2)?另外,我如何理解哪个图表显示出更好的模型性能?

方法 - 1

input_image = Input(shape=(32, 32, 3))

### Encoder
conv1_1 = Conv2D(64, (3, 3), activation='relu', padding='same')(input_image)
bnorm1_1 = BatchNormalization()(conv1_1)
mpool1_1 = MaxPooling2D((2, 2), padding='same')(conv1_1)

conv1_2 = Conv2D(16, (3, 3), activation='relu', padding='same')(mpool1_1)
borm1_2 = BatchNormalization()(conv1_2)

encoder = MaxPooling2D((2, 2), padding='same')(conv1_2)

### Decoder
conv2_1 = Conv2D(16, (3, 3), activation='relu', padding='same')(encoder)
bnorm2_1 = BatchNormalization()(conv2_1)
up1_1 = UpSampling2D((2, 2))(conv2_1)

conv2_2 = Conv2D(32, (3, 3), activation='relu', padding='same')(up1_1)
bnorm2_2 = BatchNormalization()(conv2_2)
up2_1 = UpSampling2D((2, 2))(conv2_2)

decoder = Conv2D(3, (3, 3), activation='sigmoid', padding='same')(up2_1)

model = Model(input_image, decoder)
model.compile(optimizer='adam', loss='binary_crossentropy')
model.summary()

history = model.fit(trainX, trainX, 
                    epochs=50, 
                    batch_size=1000, 
                    shuffle=True,
                    verbose=2,
                    validation_data=(testX, testX)
                    )

作为模型摘要的输出,我得到了这个

Total params: 18,851

Trainable params: 18,851

Non-trainable params: 0

plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper right')
plt.show()


方法 - 2

input_image = Input(shape=(32, 32, 3))

### Encoder
x = Conv2D(64, (3, 3), activation='relu', padding='same')(input_image)
x = BatchNormalization()(x)
x = MaxPooling2D((2, 2), padding='same')(x)

x = Conv2D(16, (3, 3), activation='relu', padding='same')(x)
x = BatchNormalization()(x)

encoder = MaxPooling2D((2, 2), padding='same')(x)

### Decoder

x = Conv2D(16, (3, 3), activation='relu', padding='same')(encoder)
x = BatchNormalization()(x)
x = UpSampling2D((2, 2))(x)

x = Conv2D(32, (3, 3), activation='relu', padding='same')(x)
x = BatchNormalization()(x)
x = UpSampling2D((2, 2))(x)

decoder = Conv2D(3, (3, 3), activation='sigmoid', padding='same')(x)

model = Model(input_image, decoder)
model.compile(optimizer='adam', loss='binary_crossentropy')
model.summary()

history = model.fit(trainX, trainX, 
                        epochs=50, 
                        batch_size=1000, 
                        shuffle=True,
                        verbose=2,
                        validation_data=(testX, testX)
                        )

作为模型摘要的输出,我得到了这个

Total params: 19,363

Trainable params: 19,107

Non-trainable params: 256

plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper right')
plt.show()

在方法 1 中,编译模型中不存在 BatchNormalization 层,因为这些层的输出未在任何地方使用。您可以通过 运行 model1.summary()

检查

方法二完全没问题。

操作顺序: Conv2D --> BatchNormalization --> MaxPooling2D 通常是常用的方法。 尽管这两种顺序都可以,因为 BatchNorm 只是均值和方差归一化。

编辑:

对于 Conv2D --> BatchNormalization --> MaxPooling2D :

conv1_1 = Conv2D(64, (3, 3), activation='relu', padding='same')(input_image) bnorm1_1 = BatchNormalization()(conv1_1) mpool1_1 = MaxPooling2D((2, 2), padding='same')(bnorm1_1) 然后使用 mpool1_1 作为下一层的输入。

对于 Conv2D --> MaxPooling2D --> BatchNormalization:

conv1_1 = Conv2D(64, (3, 3), activation='relu', padding='same')(input_image) mpool1_1 = MaxPooling2D((2, 2), padding='same')(conv1_1) bnorm1_1 = BatchNormalization()(mpool1_1) 然后使用 bnorm1_1 作为下一层的输入。

要有效地使用 BatchNormalization 层,您应该始终在激活之前使用它。

而不是:

conv1_1 = Conv2D(64, (3, 3), activation='relu', padding='same')(input_image)
bnorm1_1 = BatchNormalization()(conv1_1)
mpool1_1 = MaxPooling2D((2, 2), padding='same')(bnorm1_1)

这样使用:

conv1_1 = Conv2D(64, (3, 3), padding='same')(input_image)
bnorm1_1 = BatchNormalization()(conv1_1)
act_1 = Activation('relu')(bnorm1_1)
mpool1_1 = MaxPooling2D((2, 2), padding='same')(act_1)

更多详情,请点击这里: