2Dでの空間ドロップアウトの実装方法


14

これは、「畳み込みネットワークを使用した効率的なオブジェクトのローカリゼーション」という論文を参照しており、ドロップアウトは2Dで実装されていると理解しています。

空間2Dドロップアウトの実装方法に関するコードをKerasから読んだ後、基本的に形状[batch_size、1、1、num_channels]のランダムバイナリマスクが実装されます。しかし、この空間2Dドロップアウトは、形状[batch_size、height、width、num_channels]の入力コンボリューションブロックに対して正確に何をしますか?

私の現在の推測では、ピクセルのレイヤー/チャンネルのいずれかが負の値を持っている場合、そのピクセルのチャンネル全体がデフォルトでゼロになります。これは正しいです?

しかし、私の推測が正しい場合、元の入力ブロックの次元に正確にある形状[batch_size、height、width、num_channels]のバイナリマスクを使用すると、通常の要素ごとのドロップアウトが得られます(これはバイナリマスクの形状を入力の形状として設定するtensorflowの元のドロップアウト実装)convブロックのピクセルが負の場合、convブロック全体がデフォルトで0になります。これは、私がよく理解していない紛らわしい部分です。

回答:


14

この反応は少し遅れていますが、私は自分でこれに対処する必要があり、それが役立つかもしれないと考えました。

論文を見ると、Spatial Dropoutでは、個々の「ピクセル」ではなく、機能マップ(チャネルとも呼ばれる)全体をランダムに0に設定しているようです。

彼らが言っていることは理にかなっています、隣接するピクセルは非常に相関しているので、通常のドロップアウトは画像ではそれほどうまく機能しないでしょう したがって、ピクセルをランダムに非表示にした場合でも、隣接するピクセルを見るだけで、それらが何であるかをよく理解できます。フィーチャーマップ全体をドロップアウトすることは、ドロップアウトの元の意図とより良く整合する可能性があります。

以下は、tf.nn.dropoutに基づいてTensorflowで実装する関数です。tf.nn.dropoutからの唯一の実際の変更は、ドロップアウトマスクの形状がBatchSize *幅*高さ* NumFeatureMapsではなく、BatchSize * 1 * 1 * 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

お役に立てば幸いです!


3

私の現在の推測では、ピクセルのレイヤー/チャンネルのいずれかが負の値を持っている場合、そのピクセルのチャンネル全体がデフォルトでゼロになります。これは正しいです?

ここでの意味は正確にはわかりませんが、ドロップアウトマスク用にランダムに描画された値以外の値に関係なくドロップアウトが発生します。つまり、ドロップアウトはピクセル値、フィルターの重み、または機能マップの値の影響を受けません。サイズのマスクを使用すると、[batch_size, 1, 1, num_channels]ドロップアウト中にこのサイズのバイナリマスクが取得されます。そのバイナリマスクのゼロは、確率で発生しますrate(少なくともKeras実装では、Dropoutレイヤーへの最初の引数)。次に、このマスクにフィーチャマップが乗算されるため、サイズ1のマスクディメンションが使用されます。そのマスクディメンションは、フィーチャマップの形状に一致するようにブロードキャストされます。
より単純な状況を想像してください-サイズのフィーチャマップがあり[height, num_channels](今はバッチサイズを無視しましょう)、フィーチャマップの値は次のとおりです。

print(feature_maps)

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

print(feature_maps.shape)

(4, 3)

次に[1, num_channels]、次のようなサイズのバイナリドロップアウトマスクを想像してください。

print(dropout_mask)

[[0 1 0]]

print(dropout_mask.shape)

(1, 3)

ここで、乗算feature_mapsしてdropout_mask

print(feature_maps * dropout_mask)

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

の値はdropout_mask、各機能マップの高さに一致するようにブロードキャストされた後、要素ごとの乗算が実行されました。その結果、フィーチャマップ全体がゼロになりました-これがまさに空間ドロップアウトの機能です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.