Сверточная сеть на python. Часть 2. Вывод формул для обучения модели

Сверточная сеть на python. Часть 2. Вывод формул для обучения модели

Сначала я использовал среднеквадратическое отклонение, но для задачи классификации лучше применить cross-entropy (ссылка с объяснением). Ниже формула для backprop, попытался максимально подробно написать вывод формулы:

Вывод формулы backprop через функции активации … через ReLU

где — обозначение backprop через функцию активации.

То есть мы пропускаем ошибку через те элементы, которые были выбраны максимальными во время прямого прохождения через функцию активации (умножаем ошибку с предыдущих слоев на единицу), и не пропускаем для тех, которые не были выбраны и, соответственно, не повлияли на результат (умножаем ошибку с предыдущих слоев на ноль).

… через сигмоиду

Здесь нужно помнить, что При этом — это формула сигмоиды

Далее обозначим как (где )

… также через softmax (или здесь)

Применяем формулу где и При этом

И частная производная по :

Исходя из формулы выше, есть нюанс с тем, что должна возвращать функция (в коде) при обратном распространении ошибки для при softmax, так как в этом случае для расчета одной используются все , или, другими словами, каждая влияет на все :

При этом значения для всех у нас есть, это backprop через лосс функцию. Осталось найти для всех и всех — то есть это матрица. Ниже матричное умножение в “развернутом” виде, чтобы лучше было понятно, почему — матрица и откуда появляется матричное умножение.

Речь шла как раз об этой последней в разложении матрице — . Посмотрите, как при перемножении матриц и мы получаем . А значит, выходом функции backprop (в коде) для softmax должна быть матрица , при умножении на которую уже рассчитанного на тот момент , мы и получим .

Бэкпроп через полносвязную сеть Вывод формулы backprop для обновления матрицы весов fc-сети

Раскладываем сумму в числителе и получаем, что все частные производные равны нулю, кроме случая , что равняется . Этот случай происходит, когда . Штрих здесь для обозначения “внутреннего” цикла по , то есть это совсем другой итератор, не связанный с из

И вот так это будет выглядеть матричном виде:

Размерность матрицы равна , и для того, чтобы произвести матричное умножение, матрицу следует транспонировать. Ниже привожу матрицы полностью, в “развернутом” виде, чтобы выкладки казались яснее.

Вывод формулы backprop для обновления матрицы

В матричном виде тоже все довольно просто:

Вывод формулы backprop через

Раскладываем числитель и видим, что все частные производные равны нулю, кроме того случая, когда :

И в матричном виде:

Далее матрицы в “раскрытом” виде. Замечу, что индексы самой последней матрицы я намеренно оставил в том виде, в каком они были до транспонирования, чтобы лучше было видно, какой элемент куда перешел после транспонирования.

Бэкпроп через макспулинг

Вот демонстрация макспулинга на python: demo_of_maxpooling.ipynb Здесь вторая матрица, которую возвращает функция, и есть координаты выбранных максимальных значений на этапе макспулинга.

Бэкпроп через сверточную сеть Вывод формулы backprop для обновления ядра свертки

(1) здесь просто подставляем формулу для , штрихи над и просто обозначают, что это другой итератор. (2) здесь раскладываем сумму в числителе по и :

то есть все частные производные в числителе, кроме тех, для которых которых , будут равны нулю. При этом равен

Все выше относится к конволюции. Формула backprop для кросс-корреляции выглядит аналогично, за исключением смены знака при и :

Здесь важно увидеть, что в итоговой формуле не участвует само ядро свертки. Происходит некое подобие операции свертки, но с участием уже и , причем в роли ядра выступает , но все-таки это мало напоминает свертку, особенно при значении шага больше единицы: тогда “распадается” по , что совсем перестает напоминать привычную свертку. Этот “распад” происходит от того, что параметры и итерируются внутри цикла формулы. Посмотреть, как все это выглядит, можно с помощью демонстрационного кода: demo_of_conv_backprop_through_kernel.ipynb

Вывод формулы backprop для обновления весов bias

то есть, если разложить сумму по всем и , мы увидим, что все частные производные по будут равны единице:

Для одной карты признаков всего один bias, который “связан” со всеми элементами этой карты. Соответственно, при корректировке значения bias должны учитываться все значения из карты, полученные при обратном распространении ошибки. В качества альтернативного варианта можно брать столько bias для отдельной карты признаков, сколько элементов находится в этой карте, но в таком случае параметров bias будем слишком много — больше, чем параметров самих ядер свертки. Для второго случая также легко посчитать производную — тогда каждая (обратите внимание, у bias уже появились подстрочные индексы ) будет равна каждой .

Вывод формулы backprop через слой конволюции

Раскладывая сумму в числителе по и , получим, что все частные производные равны нулю, кроме того случая, когда и , и, соответственно, , . Это справедливо только для конволюции, для кросс-корреляции должно быть и и, соответственно, и . И тогда итоговая формула в случае кросс-корреляции будет выглядеть так:

Получившиеся выражения — это та же самая операция свертки, причем в качестве ядра выступает знакомое нам ядро . Но, правда, все похоже на привычную свертку только если stride равен единице, в случаях же другого шага, получается уже что-то совсем другое (аналогично случаю backprop для обновления ядра свертки): матрица начинает “ломаться” по всей матрице , захватывая разные ее части (опять-таки потому, что индексы и при итерируются внутри цикла формулы). Здесь можно посмотреть демонстрационный код: demo_of_conv_backprop_through_input.ipynb

Интересно, что если мы выполняем кросс-корреляцию, то на этапе прямого прохождения через сеть мы не переворачиваем ядро свертки, но переворачиваем его при обратном распространении ошибки при прохождении через слой свертки. Если же применяем формулу конволюции — все происходит ровно наоборот.

В этой статье мы вывели и подробно рассмотрели все формулы обратного распространения ошибки, то есть формулы, позволяющие будущей модели обучаться. В следующей статье мы соединим все это в один цельный код, который и будет называться сверточной сетью, и попробуем эту сеть обучить предсказывать классы на настоящем датасете. А также проверим, насколько все вычисления корректны в сравнении с библиотекой для машинного обучения pytorch.

📎📎📎📎📎📎📎📎📎📎