Правило цепочки: главная идея backprop
Урок объясняет, как правило цепочки превращает вычисление градиентов в проход «назад» по слоям.
Обратное распространение ошибки (backpropagation) — это применение правила цепочки к сети: производная потери передаётся от выхода ко входу, слой за слоем.
Сеть как композиция функций
Вычисление потери — это цепочка вложенных функций. На простом примере: вес w участвует в сумме z, та проходит через активацию a = f(z), а из a считается потеря L. Запишем цепочку зависимостей: w → z → a → L. Чтобы узнать dL/dw, нужно «протащить» производную через всю цепочку.
Правило цепочки
Из математики анализа: производная композиции — это произведение производных звеньев. Для нашей цепочки: dL/dw = (dL/da) * (da/dz) * (dz/dw). Каждый множитель — локальная производная одного звена, посчитать которую легко. Backprop просто перемножает эти локальные производные в обратном порядке — от потери к весу.
Считаем градиент по цепочке руками
Возьмём один нейрон: z = w*x + b, a = sigmoid(z), потеря L = (a - y)^2. Локальные производные: dL/da = 2*(a - y); da/dz = a*(1 - a) (производная sigmoid); dz/dw = x. Перемножим.
import math
def sigmoid(z):
return 1.0 / (1.0 + math.exp(-z))
x, y = 1.5, 0.0
w, b = 0.8, 0.1
# forward
z = w * x + b
a = sigmoid(z)
L = (a - y) ** 2
# локальные производные
dL_da = 2 * (a - y)
da_dz = a * (1 - a) # производная sigmoid через её же выход
dz_dw = x
# правило цепочки
dL_dw = dL_da * da_dz * dz_dw
print("a (выход):", round(a, 4))
print("Потеря L:", round(L, 4))
print("dL/da =", round(dL_da, 4))
print("da/dz =", round(da_dz, 4))
print("dL/dw =", round(dL_dw, 4))
Вывод:
a (выход): 0.7858 Потеря L: 0.6175 dL/da = 1.5717 da/dz = 0.1683 dL/dw = 0.3968
Готово: dL/dw = 0.3968. Мы получили производную потери по весу, ни разу не дёргая вес численно — только перемножив три простые локальные производные. Это и есть магия backprop.
Почему «обратное»
Forward pass идёт от входа к выходу. А производные считаются в обратном порядке: сначала dL/da (у самого выхода), потом da/dz, потом dz/dw (ближе ко входу). Сигнал ошибки как бы течёт назад по сети. В глубокой сети к этому добавляется ещё один множитель на каждый слой — но принцип ровно тот же.
Хитрость с производной sigmoid
Обратите внимание: da/dz = a*(1-a) выражается через уже посчитанный выход a. Не нужно заново вычислять экспоненту. Поэтому forward pass сохраняет активации — на обратном проходе они превращаются в готовые локальные производные почти даром.
Итог
- Сеть — композиция функций; правило цепочки даёт производную композиции как произведение локальных производных.
- Backprop перемножает локальные производные от потери ко входу — отсюда «обратное».
- Сохранённые активации делают локальные производные дешёвыми (например,
a*(1-a)для sigmoid).