Вы правы, что MC Dropout применяется и во время вывода, в отличие от обычного ухода. Если вы воспользуетесь Google, вы можете легко найти много информации об обоих.
Что касается отсева каналов, я понимаю, что вместо отбрасывания определенных нейронов он отбрасывает все каналы.
Теперь реализация в Keras (я собираюсь использовать tf.keras
).
MC Выпадение
Как обычно Keras, вы определяете пользовательский слой, который применяет отсев вне зависимости от того, тренируется он или тестирует, поэтому мы можем просто использовать tf.nn.dropout()
с постоянной скоростью отсева:
import tensorflow as tf
class MCDropout(tf.keras.layers.Layer):
def __init__(self, rate):
super(MCDropout, self).__init__()
self.rate = rate
def call(self, inputs):
return tf.nn.dropout(inputs, rate=self.rate)
Пример использования:
import tensorflow as tf
import numpy as np
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Conv2D(filters=6, kernel_size=3))
model.add(MCDropout(rate=0.5))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(2))
model.compile(optimizer=tf.keras.optimizers.SGD(0.001),
loss='binary_crossentropy',
metrics=['accuracy'])
# generate dummy data for illustration
x_train = np.random.normal(size=(10, 4, 4, 3))
x_train = np.vstack([x_train, 2*np.random.normal(size=(10, 4, 4, 3))])
y_train = [[1, 0] for _ in range(10)] + [[0, 1] for _ in range(10)]
y_train = np.array(y_train)
model.fit(x_train,
y_train,
epochs=2,
batch_size=10,
validation_data=(x_train, y_train))
Выпадение по каналу
Здесь вы можете использовать ту же функцию tf.nn.dropout()
, однако вам необходимо указать форму шума. Документация из tf.nn.dropout()
дает точный пример того, как добиться пропущенных каналов:
shape (x) = [k, l, m, n] и noise_shape = [k, 1, 1, n], каждый пакет и компонент канала будут сохраняться независимо, а каждая строка и столбец будут сохраняться или не сохраняться вместе.
Это то, что мы собираемся сделать в методе call()
:
class ChannelWiseDropout(tf.keras.layers.Layer):
def __init__(self, rate):
super(ChannelWiseDropout, self).__init__()
self.rate = rate
def call(self, inputs):
shape = tf.keras.backend.shape(inputs)
noise_shape = (shape[0], 1, 1, shape[-1])
return tf.nn.dropout(inputs,
rate=self.rate,
noise_shape=noise_shape)
Применение к какому-то примеру:
model = tf.keras.models.Sequential()
model.add(tf.keras.layers.InputLayer(input_shape=(4, 4, 3)))
model.add(tf.keras.layers.Conv2D(filters=3, kernel_size=3))
model.add(ChannelWiseDropout(rate=0.5))
x_train = np.random.normal(size=(1, 4, 4, 3))
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
res = sess.run(model.output, feed_dict={model.inputs[0]:x_train})
print(res[:, :, :, 0])
print(res[:, :, :, 1])
print(res[:, :, :, 2])
# [[[2.5495746 1.3060737 ]
# [0.47009617 1.0427766 ]]]
# [[[-0. 0.]
# [-0. -0.]]] <-- second and third channels were dropped
# [[[-0. -0.]
# [-0. -0.]]]
Примечание
Я использую tf.__version__ == '1.13.1'
. В старых версиях tf
вместо аргумента rate
используется keep_prob = 1 - rate
.