Como o Dropout Espacial em 2D é implementado?

14

Isso é feito com referência ao documento Localização eficiente de objetos usando redes convolucionais e, pelo que entendi, a desistência é implementada em 2D.

Após ler o código de Keras sobre como o Spatial 2D Dropout é implementado, basicamente uma máscara binária aleatória de forma [batch_size, 1, 1, num_channels] é implementada. No entanto, o que esse Dropout 2D espacial faz exatamente com o bloco de forma de convolução de entrada [batch_size, height, width, num_channels]?

Meu palpite atual é que, para cada pixel, se alguma das camadas / canais do pixel tiver um valor negativo, todos os canais desse pixel serão padronizados como zero. Isso está correto?

No entanto, se meu palpite estiver correto, como o uso de uma máscara binária de forma [batch_size, height, width, num_channels] que estão exatamente na dimensão do bloco de entrada original fornece o abandono usual por elementos (isso é de acordo com o implementação dropout original do tensorflow que define o formato da máscara binária como o formato da entrada)? Como isso significaria, se algum pixel no bloco conv for negativo, o bloco inteiro será padronizado como 0. Essa é a parte confusa que eu não entendo direito.

infomin101
fonte

Respostas:

14

Essa resposta está um pouco atrasada, mas eu precisava resolver isso sozinha e achei que poderia ajudar.

Observando o artigo, parece que no Spatial Dropout, definimos aleatoriamente mapas de recursos inteiros (também conhecidos como canais) como 0, em vez de 'pixels' individuais.

Faz sentido o que eles estão dizendo, que o abandono regular não funcionaria tão bem em imagens porque os pixels adjacentes são altamente correlacionados. Portanto, se você ocultar pixels aleatoriamente, ainda posso ter uma boa idéia do que eles eram apenas olhando os pixels adjacentes. A retirada de mapas de recursos inteiros pode estar melhor alinhada com a intenção original de abandono.

Aqui está uma função que a implementa no Tensorflow, com base em tf.nn.dropout. A única mudança real de tf.nn.dropout é que o formato da nossa máscara de abandono é BatchSize * 1 * 1 * NumFeatureMaps, em oposição a BatchSize * Width * Height * Height * NumFeatureMaps

def spatial_dropout(x, keep_prob, seed=1234):
    # x is a convnet activation with shape BxWxHxF where F is the 
    # number of feature maps for that layer
    # keep_prob is the proportion of feature maps we want to keep

    # get the batch size and number of feature maps
    num_feature_maps = [tf.shape(x)[0], tf.shape(x)[3]]

    # get some uniform noise between keep_prob and 1 + keep_prob
    random_tensor = keep_prob
    random_tensor += tf.random_uniform(num_feature_maps,
                                       seed=seed,
                                       dtype=x.dtype)

    # if we take the floor of this, we get a binary matrix where
    # (1-keep_prob)% of the values are 0 and the rest are 1
    binary_tensor = tf.floor(random_tensor)

    # Reshape to multiply our feature maps by this tensor correctly
    binary_tensor = tf.reshape(binary_tensor, 
                               [-1, 1, 1, tf.shape(x)[3]])
    # Zero out feature maps where appropriate; scale up to compensate
    ret = tf.div(x, keep_prob) * binary_tensor
    return ret

Espero que ajude!

nlml
fonte
3

Meu palpite atual é que, para cada pixel, se alguma das camadas / canais do pixel tiver um valor negativo, todos os canais desse pixel serão padronizados como zero. Isso está correto?

Não sei exatamente o que você quer dizer aqui, mas o abandono ocorre independentemente de quaisquer valores que não sejam aqueles desenhados aleatoriamente para a máscara de abandono. Esse abandono não é afetado pelos valores de pixel , pelos pesos do filtro ou pelos valores do mapa de recursos. Se você usar uma máscara de tamanho [batch_size, 1, 1, num_channels], receberá uma máscara binária desse tamanho durante o abandono. Os zeros nessa máscara binária ocorrem com probabilidade rate(pelo menos na implementação do Keras, primeiro argumento para a Dropoutcamada). Essa máscara é multiplicada pelos mapas de recursos, portanto, qualquer dimensão da máscara é do tamanho 1 - essa dimensão da máscara é transmitida para corresponder à forma do mapa de recursos.
Imagine uma situação mais simples - digamos que você tenha mapas de tamanho de recursos [height, num_channels](vamos ignorar o tamanho do lote por enquanto) e os valores dos mapas de recursos são:

print(feature_maps)

[[2 1 4]
 [1 3 2]
 [5 2 6]
 [2 2 1]]

print(feature_maps.shape)

(4, 3)

Imagine uma máscara de abandono binário de tamanho [1, num_channels], como esta:

print(dropout_mask)

[[0 1 0]]

print(dropout_mask.shape)

(1, 3)

Agora observe o que acontece quando você se multiplica feature_mapse dropout_mask:

print(feature_maps * dropout_mask)

[[0 1 0]
 [0 3 0]
 [0 2 0]
 [0 2 0]]

Os valores em dropout_maskforam transmitidos para corresponder à altura de cada mapa de características e, em seguida, foi realizada a multiplicação elemento a elemento. Como resultado, todos os mapas de recursos foram zerados - e é exatamente isso que o abandono espacial faz.

mmagnuski
fonte