Обратное распространение (Backpropagation): как ИИ выявляет виновника ошибки (с цепным правилом)

1. Введение: виновник внутри



В предыдущей статье мы узнали, что дифференцирование — это «компас», который показывает, в каком направлении менять параметры, чтобы уменьшить ошибку.

Однако в глубоком обучении существует критическая проблема: модель слишком глубока.

Слои от входа к выходу могут быть десятками, сотнями.

Ситуация: в выходном слое возникает ошибка (Loss): «Эй! Результат отличается от правильного на 10!».

Вопрос: кто виноват?

Невозможно понять, виноват ли параметр рядом с входом, вызвавший эффект бабочки, или параметр прямо перед выходом, который в конце концов «пошалил».

Именно здесь глубокое обучение использует хитрый метод, чтобы найти виновника: «обвинять того, кто прямо позади» (Chain Rule).

2. Цепное правило (Chain Rule): математическое определение «передачи ответственности»

В учебниках математики цепное правило записывается так:

$$\frac{dz}{dx} = \frac{dz}{dy} \cdot \frac{dy}{dx}$$

Для нас, как разработчиков, это выглядит как формула, но с точки зрения управления организацией это «распределение ответственности».

Представьте себе цепочку утверждений: Команда A (вход) -> Бот B (скрытый слой) -> Глава C (выход).

  1. Глава C (выход) ломает проект (возникает ошибка).
  2. Глава C не хочет нести всю ответственность, поэтому анализирует: «Бот B предоставил плохой отчёт, поэтому мой результат тоже плохой» ((\frac{dz}{dy}): насколько мой результат испорчен из‑за B).
  3. Бот B возмущён: «А, команда A дала неверные данные, поэтому мой отчёт тоже плохой!» ((\frac{dy}{dx}): насколько мой результат испорчен из‑за A).

В итоге влияние команды A на весь проект ((\frac{dz}{dx})) можно посчитать как (влияние C на B) × (влияние B на A).

Это и есть цепное правило дифференцирования: связываем удалённые причины и следствия через произведение промежуточных шагов.

3. Обратное распространение (Backpropagation): отладка «обратным ходом»



Расширяя этот процесс «передачи ответственности» на всю систему, мы получаем обратное распространение.

  1. Forward (прямой проход): вводим данные, получаем результат.
  2. Loss Calculation: сравниваем с правильным ответом, вычисляем ошибку.
  3. Backward (обратный проход): начиная с выходного слоя, «обвиняем» каждый слой, говоря: «из‑за тебя ошибка составила столько».

Для разработчика это как чтение стека вызовов (Stack Trace) снизу вверх, чтобы найти корень проблемы.

Смотрим сообщение об ошибке (Loss), затем вызывающий его слой, затем его вызывающий слой… и так далее, как будто делаем git blame.

4. Autograd PyTorch: автоматизированная аудит‑команда

Когда мы пишем глубокое обучение на numpy, нам приходится вручную выводить и кодировать дифференциалы — это утомительно.

PyTorch делает это проще, рисуя сложный процесс «передачи ответственности» в виде Computational Graph (граф вычислений) и автоматически обрабатывая его.

  • Когда вы вызываете loss.backward(),
  • Автоград (Autograd) PyTorch начинает работу.
  • Он идёт от конца графа к началу, последовательно применяя цепное правило.
  • И каждому параметру (Weight) присваивает «вес ответственности» (Gradient).

Нам остаётся только обновить параметры (optimizer.step()).

5. Итоги: но что, если ответственность исчезнет? (Vanishing Gradient)

У этой идеальной системы есть критический недостаток.

При многократном «обвинении» (умножении) и при слишком глубоком слое, ответственность может стать нулевой.

«Не виноват» × 0.1 × 0.1 × 0.1 … приводит к тому, что в начале сети сигнал «нет градиента» (Gradient = 0) передаётся, что мешает обучению.

Это и есть известная проблема исчезновения градиента (Vanishing Gradient). Как современные ИИ‑системы решают эту проблему? (Подсказка: ReLU и ResNet)

image of backpropagation