Werden Pool-Layer vor oder nach Dropout-Layern hinzugefügt?


35

Ich erstelle ein Convolutional Neural Network (CNN), bei dem auf eine Convolutional Layer eine Pooling Layer folgt und ich Dropout anwenden möchte, um die Überanpassung zu reduzieren. Ich habe das Gefühl, dass die Dropout-Schicht nach der Pooling-Schicht aufgetragen werden sollte, aber ich habe wirklich nichts, um das zu unterstützen. Wo ist der richtige Ort, um die Dropout-Ebene hinzuzufügen? Vor oder nach der Poolschicht?

Antworten:


18

Bearbeiten: Wie @Toke Faurby richtig hervorhob, verwendet die Standardimplementierung in Tensorflow tatsächlich ein elementweises Dropout. Was ich zuvor beschrieben habe, gilt für eine bestimmte Variante des Ausfalls in CNNs, die als räumlicher Ausfall bezeichnet wird :

In einem CNN erzeugt jedes Neuron eine Merkmalskarte. Da Dropout räumliche Dropout Arbeiten per-Neuron, Fallenlassen eines Neurons bedeutet , dass die entsprechende Merkmalskarte abgelegt wird - beispielsweise jede Position hat den gleichen Wert (normalerweise 0). Daher wird jede Feature-Map entweder vollständig oder gar nicht gelöscht.

Das Pooling wird in der Regel für jede Feature-Map separat ausgeführt. Daher sollte es keinen Unterschied machen, ob Sie vor oder nach dem Pooling Dropout anwenden. Zumindest ist dies bei Pooling-Operationen wie Maxpooling oder Mittelwertbildung der Fall.

Bearbeiten: Wenn Sie jedoch tatsächlich elementweise Dropouts verwenden (was als Standard für Tensorflow festgelegt zu sein scheint), macht es tatsächlich einen Unterschied, ob Sie Dropouts vor oder nach dem Pooling anwenden. Es gibt jedoch nicht unbedingt eine falsche Vorgehensweise. Berücksichtigen Sie die durchschnittliche Pooling-Operation: Wenn Sie vor dem Pooling Dropout anwenden, skalieren Sie die resultierenden Neuronenaktivierungen effektiv nach 1.0 - dropout_probability, aber die meisten Neuronen sind (im Allgemeinen) ungleich Null. Wenn Sie Dropout nach dem durchschnittlichen Pooling anwenden, werden im Allgemeinen nur ein Bruchteil der " (1.0 - dropout_probability)nicht skalierten" Neuronenaktivierungen und ein Bruchteil der dropout_probabilityNeuronen von Null angezeigt . Beides scheint mir realisierbar, und beides ist absolut falsch.


1
Ich bin mir nicht sicher, ob dies die Standardmethode für Dropouts ist. In tf.nn.dropout heißt es beispielsweise "Standardmäßig wird jedes Element unabhängig beibehalten oder gelöscht". Haben Sie eine Quelle, die dies sichert?
Toke Faurby

1
Oh! Was ich jetzt beschrieben habe, heißt räumlicher Ausfall : arxiv.org/pdf/1411.4280.pdf . @TokeFaurby hat also Recht, meine Behauptung anzuzweifeln. Wie Sie jedoch auch im verlinkten Artikel lesen können , wird die Leistung verbessert , wenn Sie ganze Feature-Maps auf räumliche Dropout- Weise löschen. Dies ist nicht verwunderlich, da benachbarte Aktivierungen in hohem Maße korrelieren und das Herausfallen eines bestimmten Elements die von diesem Element übertragenen Informationen überhaupt nicht fallen lässt (da es sehr unwahrscheinlich ist, dass dabei ein kontinuierliches "Loch" in einer Feature-Map fällt) elementweise). Ich werde meine Antwort bearbeiten, um diesen Unterschied widerzuspiegeln.
Schreon

10

In diesem Tutorial wird das Pooling vor dem Abbruch verwendet und es werden gute Ergebnisse erzielt.

Das heißt natürlich nicht, dass die andere Reihenfolge nicht funktioniert. Meine Erfahrung ist begrenzt, ich habe sie nur auf dichten Schichten ohne Pooling verwendet.


5

Beispiel für ein VGG-ähnliches Convnet aus Keras (Dropout nach Pooling):

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)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.