池化层是在 dropout 层之前还是之后添加的?

机器算法验证 深度学习 卷积神经网络 辍学
2022-02-05 12:37:22

我正在创建一个卷积神经网络 (CNN),其中我有一个卷积层,然后是一个池化层,我想应用 dropout 来减少过度拟合。我有这种感觉,应该在池化层之后应用 dropout 层,但我真的没有什么可以支持的。添加 dropout 层的正确位置在哪里?在池化层之前还是之后?

3个回答

编辑:正如@Toke Faurby 正确指出的那样,张量流中的默认实现实际上使用了逐元素丢弃。我之前描述的适用于 CNN 中 dropout 的特定变体,称为空间 dropout

在 CNN 中,每个神经元产生一个特征图。由于dropout 空间 dropout对每个神经元起作用,因此删除一个神经元意味着删除相应的特征图 - 例如,每个位置具有相同的值(通常为 0)。所以每个特征图要么被完全丢弃,要么根本不被丢弃。

池化通常在每个特征图上单独运行,因此如果在池化之前或之后应用 dropout,应该不会有任何区别。至少对于像 maxpooling 或平均化这样的池化操作是这种情况。

编辑:但是,如果您实际上使用逐元素dropout(这似乎被设置为 tensorflow 的默认值),那么如果您在池化之前或之后应用 dropout,它实际上会有所不同。但是,不一定有错误的方法。考虑平均池化操作:如果您在池化之前应用 dropout,您可以有效地将生成的神经元激活缩放1.0 - dropout_probability,但大多数神经元将非零(通常)。如果在平均池化后应用 dropout,通常会得到一小部分(1.0 - dropout_probability)非零“未缩放”神经元激活和一小部分dropout_probability零神经元。两者在我看来都是可行的,都不是完全错误的。

本教程在 dropout 之前使用 pooling 并获得了不错的结果。

这并不一定意味着其他顺序当然不起作用。我的经验是有限的,我只在密集层上使用它们而没有池化。

来自 Keras 的 VGG-like convnet 示例(池化后使用的 dropout):

import numpy as np
import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras.optimizers import SGD

# Generate dummy data
x_train = np.random.random((100, 100, 100, 3))
y_train = keras.utils.to_categorical(np.random.randint(10, size=(100, 1)), num_classes=10)
x_test = np.random.random((20, 100, 100, 3))
y_test = keras.utils.to_categorical(np.random.randint(10, size=(20, 1)), num_classes=10)

model = Sequential()
# input: 100x100 images with 3 channels -> (100, 100, 3) tensors.
# this applies 32 convolution filters of size 3x3 each.
model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(100, 100, 3)))
model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Flatten())
model.add(Dense(256, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(10, activation='softmax'))

sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd)

model.fit(x_train, y_train, batch_size=32, epochs=10)
score = model.evaluate(x_test, y_test, batch_size=32)