Як реалізується просторовий викид у 2D?


14

Це стосується статті " Ефективна локалізація об'єктів за допомогою згорткових мереж" , і з того, що я розумію, випадання реалізується в 2D.

Після прочитання коду від Кераса про те, як реалізовано просторовий 2D випадання, в основному реалізується випадкова бінарна маска форми [batch_size, 1, 1, num_channels]. Однак що саме робить цей просторовий 2D-випадаючий вхідний блок згортки форми [batch_size, висота, ширина, кількість_каналів]?

Я вважаю, що для кожного пікселя, якщо будь-який з шарів / каналів пікселя має негативне значення, для всіх каналів цього пікселя буде встановлено значення нуля. Це правильно?

Однак, якщо я здогадуюсь, правильно, то як використання двійкової маски форми [batch_size, висоти, ширини, num_channels], які точно відповідають розміру вихідного блоку введення, дає звичайний відкидання елементів (це відповідно до оригінальна реалізація відмови від tensorflow, яка встановлює форму двійкової маски як форму вводу)? Тому що це означатиме, що будь-який піксель у блоці conv негативний, то весь блок conv буде встановлений за замовчуванням до 0. Це заплутана частина, яку я не зовсім розумію.

Відповіді:


14

Ця відповідь трохи запізнюється, але мені потрібно було це вирішити самостійно, і я вважав, що це може допомогти.

Дивлячись на папір, здається, що в просторовому випаді ми випадковим чином встановлюємо цілі карти функцій (також відомі як канали) до 0, а не окремі «пікселі».

Має сенс, що вони говорять, що регулярні відсідання не працюватимуть так добре на зображеннях, оскільки сусідні пікселі сильно корелюються. Отже, якщо ви ховаєте пікселі випадковим чином, я все ще можу мати гарне уявлення про те, якими вони були, просто переглянувши сусідні пікселі. Випадання цілих карт функцій може бути краще узгоджене з початковим наміром випадання.

Ось функція, яка реалізує її в Tensorflow, засновану на tf.nn.dropout. Єдиною реальною зміною від tf.nn.dropout є те, що форма нашої відмітної маски - BatchSize * 1 * 1 * NumFeatureMaps, на відміну від BatchSize * Ширина * Висота * 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(принаймні, в реалізації Кераса, перший аргумент до 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транслювались відповідно до висоти кожної карти об’єктів, після чого виконувались множення елементів за елементами. В результаті цілі карти функцій вийшли на нуль - і саме це робить просторовий випадання.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.