Реалізація Зворотного Поширення Помилки
Свайпніть щоб показати меню
Загальний підхід
Під час прямого поширення кожен шар l отримує на вхід вихідні значення попереднього шару, al−1, і обчислює власні виходи. Тому метод forward() класу Layer приймає вектор попередніх виходів як єдиний параметр, а вся інша необхідна інформація зберігається всередині класу.
Під час зворотного поширення кожному шару l потрібен лише dal для обчислення відповідних градієнтів і повернення dal−1, тому метод backward() приймає вектор dal як параметр. Вся інша необхідна інформація вже зберігається в класі Layer.
Похідні функцій активації
Оскільки для зворотного поширення потрібні похідні функцій активації, такі функції активації, як ReLU та sigmoid, слід реалізовувати у вигляді класів, а не окремих функцій. Така структура дозволяє чітко визначити обидва компоненти:
- Сама функція активації — реалізується через метод
__call__(), щоб її можна було застосовувати безпосередньо в класіLayerза допомогоюself.activation(z); - Її похідна — реалізується через метод
derivative(), що забезпечує ефективне обчислення під час зворотного поширення черезself.activation.derivative(z).
Представлення функцій активації у вигляді об'єктів спрощує їх передачу різним шарам і динамічне застосування під час як прямого, так і зворотного поширення.
ReLu
Похідна функції активації ReLU виглядає наступним чином, де zi — це елемент вектора преактивацій z:
f′(zi)={1,zi>00,zi≤0class ReLU:
def __call__(self, z):
return np.maximum(0, z)
def derivative(self, z):
return (z > 0).astype(float)
Сигмоїда
Похідна сигмоїдної функції активації має вигляд:
f′(zi)=f(zi)⋅(1−f(zi))class Sigmoid:
def __call__(self, x):
return 1 / (1 + np.exp(-z))
def derivative(self, z):
sig = self(z)
return sig * (1 - sig)
Для обох функцій активації операція застосовується до всього вектора z, а також до його похідної. NumPy автоматично виконує обчислення елементно, тобто кожен елемент вектора обробляється незалежно.
Наприклад, якщо вектор z містить три елементи, похідна обчислюється так:
f′(z)=f′z1z2z3=f′(z1)f′(z2)f′(z3)Метод backward()
Метод backward() відповідає за обчислення градієнтів за допомогою наступних формул:
a^{l-1} та zl зберігаються як атрибути inputs та outputs відповідно у класі Layer. Функція активації f зберігається як атрибут activation.
Після обчислення всіх необхідних градієнтів можна оновити ваги та зміщення, оскільки вони більше не потрібні для подальших обчислень:
Wlbl=Wl−α⋅dWl=bl−α⋅dblТаким чином, learning_rate (α) є ще одним параметром цього методу.
def backward(self, da, learning_rate):
dz = ...
d_weights = ...
d_biases = ...
da_prev = ...
self.weights -= learning_rate * d_weights
self.biases -= learning_rate * d_biases
return da_prev
Оператор * виконує покомпонентне множення, тоді як функція np.dot() виконує скалярний добуток у NumPy. Атрибут .T транспонує масив.
Дякуємо за ваш відгук!
Запитати АІ
Запитати АІ
Запитайте про що завгодно або спробуйте одне із запропонованих запитань, щоб почати наш чат