Я изучаю архитектуру работы сверточных нейронных сетей.В процессе реализации я столкнулся с проблемой изменения весов в фильтрах.
Для простоты рассмотрим следующую структуру слоев:
+-----------------------------------+
| Input image volume |
| HxWxD |
+-----------------------------------+
|
+-----------------------------------+
| Convolution layer |
| |
| in: HxWxD, out: H1xW1xD1 |
| |
| K filters with size FxFxD |
| S - stride, P - zero padding |
| H1 = (H - F + 2P) / S + 1 |
| W1 = (W - F + 2P) / S + 1 |
| D1 = K |
+-----------------------------------+
|
+-----------------------------------+
| ReLU layer |
| |
| in: H1xW1xD1, out: H2xW2xD2 |
| |
| H2 = H1, W2 = W1, D2 = D1 |
+-----------------------------------+
|
+-----------------------------------+
| Maxpooling layer |
| |
| in: H2xW2xD2, out: H3xW3xD3 |
| |
| scale [= 2] |
| H3 = H2 / scale |
| W3 = W2 / scale |
| D3 = D2 |
+-----------------------------------+
|
[convert volume to vector]
[W3xH3xD3 -> W3*H3*D3 = N]
|
+-----------------------------------+
| Full connected layer |
| |
| in: N, out: M |
| |
| W: matrix MxN |
| activate: sigmoid |
+-----------------------------------+
|
Для еще большего упрощения рассмотримпример изображения 32x32 RGB.
Входной объем будет измеряться 32x32x3. В сверточном слое мы будем использовать K = 4 фильтра размером 5x5x3, с S = 1, P = 0, то есть слоем изVolume 32x32x3 получит объем 28x28x4 путем свертки входного объема с каждым из K фильтров.Слой ReLU сбрасывает все отрицательные числа в объеме и возвращает его, так что на выходе снова будет слой 28x28x4. Макспулирующий слой с множителем 2 превратит объем 28x28x4 в объем 14x14x4. Полностью подключенный слой получит вектор 14 * 14.* 4 = 784 элемента на входе, умножив его на матрицу W = [10x784] (мы распознаем 10 классов), получим вектор из 10 элементов со значениями от 0 до 1 (как активируется сигмоидом).После этого мы находим вектор ошибки e, который мы распространяем обратно, умножая транспонированную матрицу W на вектор e, и преобразуем его в объем 14x14x4, последовательно вводя его так же, как и преобразовывая объем в вектор.
Слой maxpooling вернет объем 28x28x4, в котором будут нули в немаксимальных элементах и в элементах, где максимальным значением были соответствующие значения объема 14x14x4.
Уровень ReLU умножает каждый элемент на 1 или 0, в зависимости от того, получено ли положительное или отрицательное число на выходе, и возвращает тот же слой 28x28x4.
И здесь возникает проблема.Чтобы получить изменение весов, необходимо выполнить свертку входного объема 32x32x3 с объемом 28x28x4, получая при этом 4 тома 5x5x3.Предполагая, что дельта-объем разбит на 4 тома 28x28x1, но опять же, как получить 5x5x3, а не 5x5x1, чтобы изменить веса?
Еще раз кратко:
Вперед: [32x32x3]=> свертка с 4 фильтрами [5x5x3] => [28x28x4] => ReLu => [28x28x4] => maxpooling => [14x14x4] => векторизация => [784] => W * X => [10]
в обратном направлении: [10] => W ^ T * e => [784] => 'volumize' => [14x14x4] => unpool => [28x28x4] => * relu grad => [28x28x4] => ???