Чи має кожен новий фільтр різні ваги для кожного вхідного каналу, чи однакові ваги кожного фільтра використовуються для вхідних каналів?


28

Я розумію, що згортковий шар конволюційної нейронної мережі має чотири виміри: вхідні_канали, висота фільтра, ширина фільтра, число_фільтрів. Крім того, я розумію, що кожен новий фільтр просто збирається над ВСІМ вхідними каналами (або картами функції / активації з попереднього шару).

ВИНАГО, на графіку нижче CS231 показано, що кожен фільтр (червоним кольором) застосовується до ЄДИННОГО КАНАЛУ, а не той самий фільтр, який використовується в каналах. Це, мабуть, вказує на те, що для каналу EACH існує окремий фільтр (у цьому випадку я припускаю, що вони є трьома кольоровими каналами вхідного зображення, але те саме стосується всіх вхідних каналів).

Це заплутано - чи існує різний унікальний фільтр для кожного вхідного каналу?

введіть тут опис зображення

Джерело: http://cs231n.github.io/convolutional-networks/

Наведене зображення здається суперечливим уривку з Ореллі "Основи глибокого навчання" :

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

... Крім того, наскільки я розумію, що ці зображення нижче вказують на те, що фільтр THE SAME просто зігнутий над усіма трьома вхідними каналами (суперечить тому, що показано на графіці CS231 вище):

введіть тут опис зображення

введіть тут опис зображення


Відповіді:


13

Чи існує в конволюційній нейронній мережі унікальний фільтр для кожного вхідного каналу чи є однакові нові фільтри, які використовуються для всіх вхідних каналів?

Колишній. Насправді існує окреме ядро, визначене для кожної комбінації вхідного каналу / вихідного каналу.

Зазвичай для архітектури CNN в одному фільтрі, як описано вашим number_of_filtersпараметром, є одне 2D ядро ​​на вхідний канал. Існують input_channels * number_of_filtersнабори ваг, кожен з яких описує ядро ​​згортки. Отже діаграми, що показують один набір ваг на вхідний канал для кожного фільтра, є правильними. Перша діаграма також наочно показує, що результати застосування цих ядер поєднуються шляхом підсумовування їх та додавання зміщення для кожного вихідного каналу.

Це також може розглядатися як використання тривимірної згортки для кожного вихідного каналу, яка має ту саму глибину, що і вхід. Що показує ваша друга діаграма, а також те, що багато бібліотеки будуть робити внутрішньо. Математично це той самий результат (за умови, що глибина точно збігається), хоча тип шару зазвичай позначений як "Conv2D" або подібний. Точно так само, якщо ваш тип введення притаманний 3D-формату, наприклад вокселям або відео, ви можете використовувати шар "Conv3D", але всередині він цілком може бути реалізований як 4D-згортка.


дякую за це пояснення. Здається, що кожен фільтр насправді має кількість input_channelsверсій з різною вагою . Чи є у вас "офіційне" джерело, яке підтверджує це розуміння?
Райан Чейз

@RyanChase: Так, це правильно. Я би лише вказав на курс Ендрю Нґ на CNN - почавши тут з того, як оброблятиметься кольорове зображення: coursera.org/learn/convolutional-neural-networks/lecture/ctQZz/…
Ніл Слейтер

Я хотів би зазначити, що в цьому джерелі ( cs231n.github.io/convolutional-networks ) фільтри (ваги або kernesl) є об'ємами (тобто 3-х мірними), і вони мають той самий 3-й вимір має один із вхідних даних обсяг. Крім того, як це (принаймні) зараз зазначено в цьому джерелі, обсяги були нарізані по 3-му виміру, щоб візуалізувати краще застосування фільтра до вхідного об'єму. Я не думаю, що, як правило, "існує окреме ядро ​​для кожної комбінації вхідного каналу / вихідного каналу". правильно.
nbro

Зауважте, що фільтри (або ядра) - це ваги, які потрібно вивчити (тобто вони не зафіксовані, але вони насправді є параметрами CNN). Можливо, вони (тобто фрагменти фільтра), наприкінці, однакові в 3-му вимірі.
nbro

@nbro: Так, ви можете реалізувати 2D згортку через декілька 2D-зрізів як одну 3D-згортку з глибиною ядра, такою ж, як кількість каналів. Математично це ідентично моєму опису. Ви також можете розглядати її як усічену повністю пов'язану мережу прямої передачі каналів із загальною вагою (багато з яких дорівнюють нулю). Ця відповідь фокусується на тому, що таке перегляд 2D-фільтрів, оскільки ОП запитує про те, як влаштовані 2D-фільтри. Насправді вони можуть бути впорядковані у більш велике 3D-ядро, але вони все ще застосовуються як 2D-ядра, використовуючи "трюк", що конверсія 3D рівнозначна.
Ніл Слейтер

12

Наступна картина, яку ви використали у своєму запитанні, дуже точно описує те, що відбувається. Пам’ятайте, що кожен елемент 3D-фільтра (сірий куб) складається з різного значення ( 3x3x3=27значення). Отже, три різних двомірних фільтра розміром 3x3можна об'єднати для формування цього 3D-фільтра розміром 3x3x3.

convnet2D

3x3x3RGB - фрагмент з картини примножує поелементно з допомогою 3D - фільтра (показано сірого кольору). У цьому випадку фільтр має 3x3x3=27ваги. Коли ці ваги перемножуються на елементі, а потім підсумовуються, це дає одне значення.


Отже, чи є окремий фільтр для кожного вхідного каналу?

Так , на зображенні є стільки двовимірних фільтрів , скільки вхідних каналів. Однак це допомагає, якщо ви думаєте, що для вхідних матриць з більш ніж одним каналом існує лише один 3D-фільтр (як показано на зображенні вище).


Тоді чому це називається 2D згорткою (якщо фільтр - 3D, а матриця введення - 3D)?

Це 2D згортка, оскільки кроки фільтра мають лише розміри висоти та ширини ( НЕ глибина), а отже, вихід, отриманий цим згортанням, також є двовимірною матрицею. Кількість напрямків руху фільтра визначають розміри згортки.

Примітка. Якщо ви будуєте своє розуміння, візуалізуючи єдиний 3D-фільтр замість декількох 2D-фільтрів (по одному для кожного шару), то вам буде легко зрозуміти передові архітектури CNN, такі як Resnet, InceptionV3 тощо.


це хороше пояснення, але конкретніше питання, яке я намагаюся зрозуміти, чи є фільтри, які працюють на кожному вхідному каналі, копії одних і тих же ваг, або зовсім різні ваги. Це насправді не відображається на зображенні, і фактично для мене такий вид зображення говорить про те, що це однакові ваги, застосовані до кожного каналу (оскільки їх однаковий колір) ... Відповідь на @neil slater, це звучить як кожен filter насправді має кількість input_channelsверсій з різною вагою. Якщо це теж ваше розуміння, чи існує "офіційне" джерело, яке підтверджує це?
Райан Чейз

Так, справді, це теж моє розуміння. Для мене це було зрозуміло, коли я намагався придумати той сірий кубик, який складається з 27 різних значень ваги. Це означає, що для кожного вхідного шару застосовано 3 різних 2D фільтри, а саме той самий 2D фільтр.
Мохсін Бухарі

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

Якщо ви дотримуєтеся шляху Тенсдорфлоу. Ви можете роздрукувати свій фільтр ваги після того, як показали вашому макетному шару CNN вхідний зразок.
Мохсін Бухарі

@Moshsin Bukhari Я обов'язково спробую дослідити фільтри в межах TensorFlow. Чи бажаєте ви поділитися своїм кодом щодо того, як ви займалися вивченням того, що міститься у фільтрах? Чи можете ви, наприклад, надрукувати значення фільтра на кожному кроці в мережі?
Райан Чейз

3

Я продовжую пояснювати відповіді вище на конкретному прикладі, сподіваючись додатково уточнити, як працює згортка щодо каналів вводу та виходу та ваг відповідно:

Нехай приклад буде наступним (wrt до 1 згорткового шару):

  • вхідний тензор - 9x9x5, тобто 5 вхідних каналів, так input_channels=5
  • розмір фільтра / ядра становить 4х4, а крок - 1
  • вихідний тензор становить 6x6x56, тобто 56 вихідних каналів, так output_channels=56
  • тип прокладки "VALID" (тобто відсутність прокладки)

Відзначимо, що:

  • оскільки вхід має 5 каналів, розмір фільтра стає 4x4x5, тобто є 5 окремих унікальних 2D фільтрів розміром 4х4 (тобто кожен має 16 ваг); щоб перетворитись на вхід розміром 9x9x5, фільтр стає 3D і повинен бути розміром 4х4x5
  • отже: для кожного вхідного каналу існує окремий 2D фільтр з 16 різними вагами кожен. Іншими словами, кількість 2D фільтрів відповідає кількості вхідних каналів
  • Оскільки існує 56 вихідних каналів, то має бути 56 тривимірних фільтрів W0, W1, ..., W55 розміром 4x4x5 (пор. на графіці CS231 є 2 тривимірні фільтри W0, W1 для обліку 2 виходу каналів), де 3-й вимір розміром 5 являє собою посилання на 5 вхідних каналів (див. у графіці CS231 кожен 3D-фільтр W0, W1 має 3-й розмір 3, який відповідає 3-х вхідним каналам)
  • отже: кількість 3D-фільтрів дорівнює кількості вихідних каналів

Цей згортковий шар таким чином містить:

56 3-х мірних фільтрів розміром 4х4x5 (= 80 різних ваг кожен) для обліку 56 вихідних каналів, де кожен має значення для 3-го виміру 5, щоб відповідати 5 вхідним каналам. Всього є

number_of_filters=input_channel*output_channels=5*56=280

2D-фільтри розміром 4х4 (тобто загальна вага 280х16 різних).


0

Є обмеження лише у 2D. Чому?

Уявіть повністю пов'язаний шар.

Це було б жахливо величезно, кожен нейрон був би підключений до нейронів, що вводять 1000x1000x3. Але ми знаємо, що обробка пікселя поблизу має сенс, тому ми обмежуємося невеликим 2D-сусідством, тому кожен нейрон пов'язаний лише з 3x3 поблизу нейронів у 2D. Ми нічого не знаємо про канали, тому ми підключаємось до всіх каналів.

Все-таки ваги були б занадто великими. Але через інваріантність перекладу, фільтр, який добре працює в одній області, є, ймовірно, корисним в іншій області. Таким чином, ми використовуємо однаковий набір ваг через 2D. Знову ж таки, немає такої інваріантності перекладу між каналами, тому такого обмеження там немає.


0

Дивіться розділ "Локальне підключення" в http://cs231n.github.io/convolutional-networks/ та слайд 7-18.

Гіперпараметр фільтра "Приймальне поле" визначається лише висотою та шириною, оскільки глибина фіксується глибиною попереднього шару.

Зверніть увагу, що "Ступінь з'єднання по осі глибини завжди дорівнює DEPTH вхідного об'єму" - або DEPTH карти активації (у випадку пізніших шарів).

Інтуїтивно це має бути пов'язано з тим, що дані каналів зображення переплетені, а не планарні. Таким чином, застосувати фільтр можна просто шляхом множення векторів стовпців.

Зверніть увагу, що Конволюційна мережа вивчає всі параметри фільтра (включаючи розмір глибини), і вони є загальними "h w input_layer_depth + 1 (зміщення)".


0

Я рекомендую розділ 2.2.1 магістерської роботи як відповідь. Щоб додати до решти відповідей:

Керас - твій друг, щоб зрозуміти, що відбувається:

from keras.models import Sequential
from keras.layers import Conv2D

model = Sequential()
model.add(Conv2D(32, input_shape=(28, 28, 3),
          kernel_size=(5, 5),
          padding='same',
          use_bias=False))
model.add(Conv2D(17, (3, 3), padding='same', use_bias=False))
model.add(Conv2D(13, (3, 3), padding='same', use_bias=False))
model.add(Conv2D(7, (3, 3), padding='same', use_bias=False))
model.compile(loss='categorical_crossentropy', optimizer='adam')

print(model.summary())

дає

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_1 (Conv2D)            (None, 28, 28, 32)        2400      
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 28, 28, 17)        4896      
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 28, 28, 13)        1989      
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 28, 28, 7)         819       
=================================================================
Total params: 10,104

Спробуйте сформулювати свої варіанти. Що це означатиме для параметрів, якщо щось інше було б?

2400=32(355)

Такий підхід також допомагає вам з іншими типами шарів, а не лише із звивистими шарами.

Також зверніть увагу, що ви можете реалізувати різні рішення, які можуть мати інші параметри.


0

Просто щоб зробити дві деталі абсолютно зрозумілими:

NN3×3N2N

N2N3×3×

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


0

Для тих, хто намагається зрозуміти, як обчислюються згортки, ось корисний фрагмент коду в Pytorch:

batch_size = 1
height = 3 
width = 3
conv1_in_channels = 2
conv1_out_channels = 2
conv2_out_channels = 2
kernel_size = 2
# (N, C_in, H, W) is shape of all tensors. (batch_size, channels, height, width)
input = torch.Tensor(np.arange(0, batch_size*height*width*in_channels).reshape(batch_size, in_channels, height, width))
conv1 = nn.Conv2d(in_channels, conv1_out_channels, kernel_size, bias=False) # no bias to make calculations easier
# set the weights of the convolutions to make the convolutions easier to follow
nn.init.constant_(conv1.weight[0][0], 0.25)
nn.init.constant_(conv1.weight[0][1], 0.5)
nn.init.constant_(conv1.weight[1][0], 1) 
nn.init.constant_(conv1.weight[1][1], 2) 
out1 = conv1(input) # compute the convolution

conv2 = nn.Conv2d(conv1_out_channels, conv2_out_channels, kernel_size, bias=False)
nn.init.constant_(conv2.weight[0][0], 0.25)
nn.init.constant_(conv2.weight[0][1], 0.5)
nn.init.constant_(conv2.weight[1][0], 1) 
nn.init.constant_(conv2.weight[1][1], 2) 
out2 = conv2(out1) # compute the convolution

for tensor, name in zip([input, conv1.weight, out1, conv2.weight, out2], ['input', 'conv1', 'out1', 'conv2', 'out2']):
    print('{}: {}'.format(name, tensor))
    print('{} shape: {}'.format(name, tensor.shape))

Запуск цього дає наступний вихід:

input: tensor([[[[ 0.,  1.,  2.],
          [ 3.,  4.,  5.],
          [ 6.,  7.,  8.]],

         [[ 9., 10., 11.],
          [12., 13., 14.],
          [15., 16., 17.]]]])
input shape: torch.Size([1, 2, 3, 3])
conv1: Parameter containing:
tensor([[[[0.2500, 0.2500],
          [0.2500, 0.2500]],

         [[0.5000, 0.5000],
          [0.5000, 0.5000]]],


        [[[1.0000, 1.0000],
          [1.0000, 1.0000]],

         [[2.0000, 2.0000],
          [2.0000, 2.0000]]]], requires_grad=True)
conv1 shape: torch.Size([2, 2, 2, 2])
out1: tensor([[[[ 24.,  27.],
          [ 33.,  36.]],

         [[ 96., 108.],
          [132., 144.]]]], grad_fn=<MkldnnConvolutionBackward>)
out1 shape: torch.Size([1, 2, 2, 2])
conv2: Parameter containing:
tensor([[[[0.2500, 0.2500],
          [0.2500, 0.2500]],

         [[0.5000, 0.5000],
          [0.5000, 0.5000]]],


        [[[1.0000, 1.0000],
          [1.0000, 1.0000]],

         [[2.0000, 2.0000],
          [2.0000, 2.0000]]]], requires_grad=True)
conv2 shape: torch.Size([2, 2, 2, 2])
out2: tensor([[[[ 270.]],

         [[1080.]]]], grad_fn=<MkldnnConvolutionBackward>)
out2 shape: torch.Size([1, 2, 1, 1])

Зауважте, як кожен канал згортки підсумовує всі вихідні канали попередніх каналів.

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