Добавлены ли пулы слоев до или после выпадающих слоев?

35

Я создаю сверточную нейронную сеть (CNN), где у меня есть сверточный слой, за которым следует слой пула, и я хочу применить выпадение для уменьшения переобучения. У меня такое чувство, что слой удаления должен быть применен после слоя объединения, но у меня нет ничего, чтобы поддержать это. Где правильное место для добавления выпадающего слоя? До или после пула?

PIR
источник

Ответы:

18

Редактировать: Как правильно заметил @Toke Faurby, реализация по умолчанию в tenorflow фактически использует поэлементное выпадение. То, что я описал ранее, относится к конкретному варианту отсева в CNN, называемому пространственным отсевом :

В CNN каждый нейрон создает одну карту объектов. Поскольку выпадение пространственного выпадения работает для каждого нейрона, отбрасывание нейрона означает, что соответствующая карта объектов отброшена - например, каждая позиция имеет одинаковое значение (обычно 0). Таким образом, каждая карта объектов либо полностью отброшена, либо не сброшена вовсе

Объединение в пул обычно выполняется отдельно для каждой карты объектов, поэтому не должно иметь никакого значения, если вы применяете отсев до или после объединения. По крайней мере, так обстоит дело с операциями объединения, такими как максимальное объединение или усреднение.

Редактировать: Однако, если вы на самом деле используете поэлементное выпадение (которое, по-видимому, установлено по умолчанию для тензорного потока), это на самом деле имеет значение, если вы применяете выпадение до или после объединения. Однако, это не обязательно неправильный способ сделать это. Рассмотрим среднюю операцию объединения: если вы применяете отсев перед пулированием, вы эффективно масштабируете результирующие активации нейронов 1.0 - dropout_probability, но большинство нейронов будет отличным от нуля (в общем). Если вы применяете отсев после среднего пула, вы, как правило, получаете долю (1.0 - dropout_probability)ненулевых «немасштабированных» активаций нейронов и долю dropout_probabilityнулевых нейронов. И то, и другое кажется мне жизнеспособным, и ни одно не является неправильным.

schreon
источник
1
Я не уверен, что это стандартный способ выполнения отсева. Например, в tf.nn.dropout говорится: «По умолчанию каждый элемент сохраняется или удаляется независимо». У вас есть источник, подтверждающий это?
Toke Faurby
1
Ой! То, что я описал, теперь называется пространственным выпадением : arxiv.org/pdf/1411.4280.pdf . Так что @TokeFaurby прав в том, что усомнился в моем утверждении. Однако, как вы также можете прочитать в связанном документе, удаление целых карт объектов в виде пространственного выпадения повышает производительность. Это неудивительно, поскольку смежные активации сильно коррелированы, и удаление одного конкретного элемента фактически не удаляет информацию, переносимую этим элементом вообще (поскольку при выполнении этого действия очень маловероятно, чтобы при создании карты была выброшена непрерывная «дыра»). поэлементно). Я отредактирую свой ответ, чтобы отразить эту разницу.
Шреон
10

Этот урок использует объединение перед выпадением и дает хорошие результаты.

Это не обязательно означает, что другой порядок не работает, конечно. Мой опыт ограничен, я использовал их только на плотных слоях без объединения.

отметка
источник
5

Пример VGG-подобного коннета от Keras (выпадение, использованное после объединения):

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
источник