卷积自动编码器
Convolutional Autoencoders
我正在为 CIFAR10 数据集上的 运行 自动编码器编写代码并查看重建图像。
要求是创建
编码器第一层
- 输入形状:(32,32,3)
- 具有 (3,3) 的 64 个过滤器的 Conv2D 层
- BatchNormalization 层
- ReLu 激活
- 带 (2,2) 过滤器的 2D MaxpoolingLayer
编码器第二层
- 具有 16 个过滤器 (3,3) 的 Conv2D 层
- BatchNormalization 层
- ReLu 激活
- 带 (2,2) 过滤器的 2D MaxpoolingLayer
- 最终编码为具有 (2,2) 的 MaxPool 以及之前的所有层
解码器第一层
- 输入形状:编码器输出
- 具有 (3,3) 的 16 个过滤器的 Conv2D 层
- BatchNormalization 层
- ReLu 激活
- 带 (2,2) 过滤器的 UpSampling2D
带第二层的解码器
- 具有 (3,3) 的 32 个过滤器的 Conv2D 层
- BatchNormalization 层
- ReLu 激活
- 带 (2,2) 过滤器的 UpSampling2D
- 最终解码为具有所有先前层的 Sigmoid
我明白
- 当我们创建卷积自动编码器(或任何 AE)时,我们需要将上一层的输出传递到下一层。
- 所以,当我用 ReLu 创建第一个 Conv2D 层然后执行 BatchNormalization 时......我在其中传递了 Conv2D 层......对吧?
- 但是当我做 MaxPooling2D .. 我应该传递什么.. BatchNormalization 输出或 Conv2D 层输出?
另外,我执行这些操作有什么顺序吗?
- Conv2D --> BatchNormalization --> MaxPooling2D
- 或
- Conv2D --> MaxPooling2D --> BatchNormalization
我在下面附上我的代码...我尝试了两种不同的方式,因此得到了不同的输出(在模型摘要和模型训练图方面)
谁能帮我解释一下哪个是正确的方法(方法 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)
更多详情,请点击这里:
我正在为 CIFAR10 数据集上的 运行 自动编码器编写代码并查看重建图像。
要求是创建
编码器第一层
- 输入形状:(32,32,3)
- 具有 (3,3) 的 64 个过滤器的 Conv2D 层
- BatchNormalization 层
- ReLu 激活
- 带 (2,2) 过滤器的 2D MaxpoolingLayer
编码器第二层
- 具有 16 个过滤器 (3,3) 的 Conv2D 层
- BatchNormalization 层
- ReLu 激活
- 带 (2,2) 过滤器的 2D MaxpoolingLayer
- 最终编码为具有 (2,2) 的 MaxPool 以及之前的所有层
解码器第一层
- 输入形状:编码器输出
- 具有 (3,3) 的 16 个过滤器的 Conv2D 层
- BatchNormalization 层
- ReLu 激活
- 带 (2,2) 过滤器的 UpSampling2D
带第二层的解码器
- 具有 (3,3) 的 32 个过滤器的 Conv2D 层
- BatchNormalization 层
- ReLu 激活
- 带 (2,2) 过滤器的 UpSampling2D
- 最终解码为具有所有先前层的 Sigmoid
我明白
- 当我们创建卷积自动编码器(或任何 AE)时,我们需要将上一层的输出传递到下一层。
- 所以,当我用 ReLu 创建第一个 Conv2D 层然后执行 BatchNormalization 时......我在其中传递了 Conv2D 层......对吧?
- 但是当我做 MaxPooling2D .. 我应该传递什么.. BatchNormalization 输出或 Conv2D 层输出?
另外,我执行这些操作有什么顺序吗?
- Conv2D --> BatchNormalization --> MaxPooling2D
- 或
- Conv2D --> MaxPooling2D --> BatchNormalization
我在下面附上我的代码...我尝试了两种不同的方式,因此得到了不同的输出(在模型摘要和模型训练图方面)
谁能帮我解释一下哪个是正确的方法(方法 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)
更多详情,请点击这里: