Эпоха 1 · Истоки · 1970 / 1974

5 Предыстория backprop

Reverse-mode AD (Linnainmaa, 1970) · применение к нейросетям (Werbos, 1974)
🟦 хватит конспекта~20–30 миноригинал ↗
Суть за 20 секунд. Backprop — это не магия 1986-го, а обратный режим автоматического дифференцирования, открытый Линнайнмаа в 1970-м (как анализ ошибок округления!) и применённый к сетям Вербосом в 1974-м. Он считает градиент по всем параметрам за стоимость одного прохода — вычислительное ядро всего глубокого обучения.

Контекст

Чтобы обучать сеть градиентным спуском, нужна производная ошибки по каждому весу. Наивный подсчёт (по одному весу) для сети с миллионами параметров безнадёжно дорог. Решение пришло не из ИИ, а из численного анализа.

Идея и механизм

Любое вычисление — это граф: узлы-операции, рёбра-значения. Производную даёт цепное правило; вопрос — в каком порядке его применять. Адъоинт (чувствительность выхода к узлу) накапливается из «детей» узла:

v = ∂L∂v = Σc ∈ children(v) c · ∂c∂v

Линнайнмаа описал это в 1970-м как способ отслеживать ошибки округления — без всякой связи с нейросетями (диплом на финском). Вербос (1974, Гарвард) первым предложил применить приём к обучению сетей.

мат. анализ Forward-mode vs reverse-mode: почему для ML выигрывает обратный

Пусть сеть — композиция f = fL ∘ … ∘ f1. Градиент по цепному правилу — это произведение якобианов JL · … · J1. Стоимость зависит от порядка умножения матриц:

  • Forward-mode умножает со стороны входа (производит Якобиан-вектор произведения). Цена ∝ числу входов n.
  • Reverse-mode умножает со стороны выхода (вектор-Якобиан произведения). Цена ∝ числу выходов m.

В машинном обучении выход — один скаляр потерь (m = 1), а параметров миллионы (n огромно). Значит:

reverse-mode: все n частных производных за ≈ 1 проход  vs  forward-mode: ≈ n проходов

Отсюда и эффективность backprop: один обратный проход даёт градиент по всем весам ценой порядка одного прямого. Плата — нужно хранить промежуточные значения (память ∝ размеру графа).

Python Обратный проход вручную на маленьком выражении
# f(a,b) = a*b + a;  найдём ∂f/∂a и ∂f/∂b обратным проходом
a, b = 3.0, 4.0
u = a * b                 # прямой проход
f = u + a

df = 1.0                  # адъоинты от выхода к входам:
du = df * 1.0             # f = u + a  →  ∂f/∂u = 1
da = df * 1.0             #            →  вклад в ∂f/∂a = 1
da += du * b              # u = a*b   →  ∂u/∂a = b
db = du * a               #            →  ∂u/∂b = a
print(da, db)             # → 5.0, 3.0   (∂f/∂a = b+1, ∂f/∂b = a)
x ·w +b σ L прямой проход: значения → ← обратный проход: адъоинты (градиенты)
Граф вычислений. Прямой проход считает значения; обратный распространяет градиент справа налево, давая ∂L по всем параметрам за один проход.
Аналогия. Разбор полётов после провала. Вместо того чтобы по очереди спрашивать каждого «насколько ты виноват?» (forward-mode — дорого при большой команде), руководитель один раз проходит по цепочке назад от итога и распределяет ответственность пропорционально влиянию каждого звена. Reverse-mode — это «обратная рассылка ответственности».

Почему это важно

Reverse-mode AD — вычислительный движок всего глубокого обучения. Когда PyTorch вызывает loss.backward(), он исполняет ровно этот алгоритм. А ещё это хрестоматийный пример многократного независимого открытия: алгоритм появился за 12–16 лет до знаменитой статьи 1986-го (#7), которая лишь сделала его известным.

Связи

→ популяризуется в7. Backpropagation

Та же идея обратного режима, но громко и с демонстрацией: статья 1986-го показывает, что им реально обучаются многослойные сети и что скрытые слои учат признаки. Изобретение — здесь; слава — там.

← мотивируется3. Перцептрон

Обучение одного слоя простое. Как только захотели скрытые слои (чтобы обойти XOR), понадобился эффективный способ считать градиент сквозь них — его и даёт обратный режим.

↔ дополняется23. Adam

Backprop даёт градиент; оптимизатор решает, какой шаг по нему сделать. Разделение «как посчитать производную» (AD) и «как по ней двигаться» (SGD/Adam) — два независимых слоя, на которых стоит всё обучение.

Вопросы пытливого ума

Если reverse-mode так эффективен, зачем вообще нужен forward-mode?

Он выигрывает в обратной ситуации: мало входов, много выходов (тогда цена ∝ числу входов мала). Forward-mode даёт Якобиан-вектор произведения, удобен для анализа чувствительности и не требует хранить весь граф — память постоянна. В ML же выход один (скаляр потерь), а входов-параметров тьма, поэтому почти всегда правит reverse.

Reverse-mode требует хранить активации всего графа — это не дорого по памяти?

Дорого, и это реальная проблема обучения больших моделей: память ∝ размеру графа (всем промежуточным активациям). Лечат gradient checkpointing — часть активаций не хранят, а пересчитывают на обратном проходе, меняя память на дополнительные вычисления. Классический trade-off compute↔memory.

Почему тогда честь достаётся 1986-му, а не Линнайнмаа?

Потому что наука награждает не только за открытие, но и за «доведение до сообщества». Диплом Линнайнмаа на финском про ошибки округления никто не связал с нейросетями; статья 1986-го в Nature показала пользу и попала в нужный момент. Юрген Шмидхубер много лет настаивает, что приоритет за Линнайнмаа — и формально он прав.

Что читать в оригинале

Первоисточники нишевые и труднодоступные. Достаточно понять идею обратного режима и историю многократного открытия — это лучшее, что даёт работа для канона.