I livelli di pooling vengono aggiunti prima o dopo i layer di dropout?


35

Sto creando una rete neurale convoluzionale (CNN), in cui ho uno strato convoluzionale seguito da uno strato di pooling e desidero applicare il dropout per ridurre l'overfitting. Ho la sensazione che il livello di abbandono debba essere applicato dopo il livello di raggruppamento, ma in realtà non ho nulla per sostenerlo. Qual è il posto giusto per aggiungere il livello di abbandono? Prima o dopo il livello di pooling?

Risposte:


18

Modifica: Come ha sottolineato correttamente @Toke Faurby, l'implementazione predefinita in tensorflow utilizza effettivamente un dropout saggio di elementi. Ciò che ho descritto in precedenza si applica a una variante specifica di dropout nelle CNN, chiamata dropout spaziale :

In una CNN, ogni neurone produce una mappa caratteristica. Poiché il dropout dropout spaziale funziona per neurone, rilasciare un neurone significa che la mappa caratteristica corrispondente viene rilasciata, ad esempio ogni posizione ha lo stesso valore (di solito 0). Pertanto, ogni mappa delle caratteristiche viene completamente eliminata o non rilasciata affatto.

Il pool di solito funziona separatamente su ogni mappa delle caratteristiche, quindi non dovrebbe fare alcuna differenza se si applica il dropout prima o dopo il pool. Almeno questo è il caso delle operazioni di pooling come i passaggi massimi o la media.

Modifica: Tuttavia, se si utilizza effettivamente il dropout per elemento (che sembra essere impostato come predefinito per tensorflow), in realtà fa la differenza se si applica il dropout prima o dopo il pool. Tuttavia, non esiste necessariamente un modo sbagliato di farlo. Considera l'operazione di pooling media: se applichi il dropout prima del pool, ridimensiona efficacemente le attivazioni neuronali risultanti da 1.0 - dropout_probability, ma la maggior parte dei neuroni sarà diversa da zero (in generale). Se si applica il dropout dopo un pool medio, si finisce generalmente con una frazione di (1.0 - dropout_probability)attivazioni di neuroni "non scalate" diverse da zero e una frazione di dropout_probabilityzero neuroni. Entrambi mi sembrano fattibili, né è assolutamente sbagliato.


1
Non sono sicuro che questo sia il modo standard di eseguire l'abbandono. Ad esempio in tf.nn.dropout afferma "Per impostazione predefinita, ogni elemento viene mantenuto o eliminato in modo indipendente". Hai una fonte che lo supporta?
Toke Faurby,

1
Oh! Quello che ho descritto ora è chiamato dropout spaziale : arxiv.org/pdf/1411.4280.pdf . Quindi @TokeFaurby ha ragione nel dubitare della mia richiesta. Tuttavia, come puoi anche leggere nel documento collegato, rilasciare intere mappe delle caratteristiche nel modo di rilascio spaziale migliora le prestazioni. Questo avviene in non è una sorpresa, come attivazioni adiacenti sono altamente correlati e far cadere fuori uno specifico elemento in realtà non rilasciare le informazioni trasportate da quell'elemento a tutti (come è molto improbabile far cadere un "buco" continua in una mappa funzione quando farlo elemento-saggio). Modificherò la mia risposta per riflettere questa differenza.
schreon,

10

Questo tutorial utilizza il pooling prima dell'abbandono e ottiene buoni risultati.

Ciò non significa necessariamente che l'altro ordine non funzioni ovviamente. La mia esperienza è limitata, li ho usati solo su strati densi senza raggruppamento.


5

Esempio di convnet simile a VGG da Keras (dropout utilizzato dopo il pool):

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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.