Les couches de regroupement sont-elles ajoutées avant ou après les couches de suppression?

35

Je crée un réseau de neurones à convolution (CNN) dans lequel j'ai une couche de convolution suivie par une couche de mise en commun et je souhaite appliquer la suppression pour réduire le surajustement. J'ai le sentiment que la couche de suppression devrait être appliquée après la couche de mise en commun, mais je n'ai vraiment rien pour la sauvegarder. Où est le bon endroit pour ajouter la couche de suppression? Avant ou après la couche de pooling?

pir
la source

Réponses:

18

Edit: Comme @Toke Faurby l’a correctement souligné, l’implémentation par défaut de tensorflow utilise en réalité un abandon élémentaire. Ce que j'ai décrit précédemment s'applique à une variante spécifique d'abandon dans les CNN, appelée abandon spatial :

Dans un CNN, chaque neurone produit une carte de caractéristiques. Dans la mesure où la suppression spatiale de la suppression spatiale fonctionne par neurone, la suppression d’un neurone signifie que la carte de caractéristiques correspondante est supprimée - chaque position a la même valeur (généralement 0). Ainsi, chaque carte de caractéristiques est entièrement supprimée ou pas du tout.

Le regroupement fonctionne généralement séparément sur chaque carte de fonctionnalités. Par conséquent, cela ne devrait pas changer rien si vous appliquez la suppression avant ou après le regroupement. C'est du moins le cas pour les opérations de mise en commun telles que le max covoiturage ou la moyenne.

Edit: Cependant, si vous utilisez réellement la suppression élément par élément (qui semble être définie par défaut pour tensorflow), le fait que vous appliquiez la suppression avant ou après la mise en pool a une réelle incidence. Cependant, il n'y a pas nécessairement une mauvaise façon de le faire. Considérez l'opération de pooling moyenne: si vous appliquez un abandon avant le pooling, vous effectuez une mise à l'échelle des activations de neurones résultantes 1.0 - dropout_probability, mais la plupart des neurones seront non nuls (en général). Si vous appliquez une suppression après regroupement moyen, vous vous retrouvez généralement avec une fraction d' (1.0 - dropout_probability)activations de neurones "non nulles" non nulles et une fraction de dropout_probabilityneurones nuls. Les deux me semblent viables, ni est tout à fait faux.

Schreon
la source
1
Je ne suis pas sûr que ce soit la manière habituelle de décrocher. Par exemple, dans tf.nn.dropout, il est indiqué "Chaque élément est conservé ou supprimé indépendamment". Avez-vous une source de sauvegarde cette?
Toke Faurby
1
Oh! Ce que j'ai décrit s'appelle maintenant abandon spatial : arxiv.org/pdf/1411.4280.pdf . Donc, @TokeFaurby a raison de douter de mon affirmation. Toutefois, comme vous pouvez également le lire dans le document lié, le fait de supprimer des cartes de caractéristiques entières de manière spatiale permet d’ améliorer les performances. Cela vient sans surprise, que les activations adjacentes sont fortement corrélés et le décrochage scolaire un élément spécifique ne fait pas baisser les informations véhiculées par cet élément du tout (comme il est très peu probable de laisser tomber un « trou » en continu dans une carte de fonction lors de le faire élément sage). Je vais modifier ma réponse pour refléter cette différence.
Schreon
10

Ce tutoriel utilise la mise en commun avant abandon et donne de bons résultats.

Cela ne signifie pas nécessairement que l'ordre inverse ne fonctionne pas, bien sûr. Mon expérience est limitée, je ne les ai utilisées que sur des couches denses sans regroupement.

marque
la source
5

Exemple de convnet ressemblant à VGG de Keras (suppression après regroupement):

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)
mrgloom
la source