🧠 Машинне навчання · Глибоке навчання
📅 Березень 2026⏱ ≈ 12 хв читання🟡 Середній · Останнє оновлення: 23 червня 2026 р.

Зворотне поширення в нейромережах

Нейромережа навчається, раз за разом запитуючи: «які ваги, якщо їх трохи змінити, зменшили б похибку?» Зворотне поширення — це ефективний алгоритм, що відповідає на це запитання одночасно для кожної ваги, використовуючи не більш ніж ланцюгове правило диференціювання.

1. Прямий прохід

Нейромережа — це композиція функцій. Кожен шар обчислює лінійне перетворення, за яким іде нелінійність:

Обчислення шару z^(l) = W^(l) · a^(l−1) + b^(l) // переддактивація a^(l) = σ(z^(l)) // постактивація (напр. ReLU) Розмірності: W^(l) ∈ ℝ^(n_l × n_{l-1}), b^(l) ∈ ℝ^(n_l)

Прямий прохід пропускає вхід x крізь усі L шарів, щоб отримати вихід ŷ = a^(L). Поки що жодного «навчання» — це лише обчислення функції.

Прямий прохід →

Обчислюємо всі активації від входу до виходу. Зберігаємо проміжні значення (потрібні для зворотного поширення).

← Зворотний прохід

Поширюємо сигнал похибки від виходу назад до входу. Обчислюємо градієнт втрат за кожною вагою.

2. Функції втрат

Втрати L(ŷ, y) вимірюють, наскільки прогноз хибний. Вони мають бути диференційовними, щоб ми могли обчислювати градієнти.

3. Ланцюгове правило

Якщо f і g — диференційовні функції та h(x) = f(g(x)), то:

Ланцюгове правило dh/dx = (df/dg) · (dg/dx) Або в позначеннях частинних похідних: ∂L/∂w = ∂L/∂a · ∂a/∂z · ∂z/∂w

Нейромережа — це композиція багатьох функцій. Втрати залежать від кінцевого виходу, який залежить від вагів останнього шару, які залежать від активацій попереднього шару — і так аж до входу. Ланцюгове правило дозволяє обчислити ∂L/∂w для будь-якої ваги w, перемножуючи локальні градієнти вздовж шляху.

Чому це ефективно: наївне обчислення ∂L/∂w_ij для кожної ваги окремо потребувало б одного повного прямого проходу на кожну вагу — неприйнятно для мільйонів вагів. Зворотне поширення повторно використовує проміжні обчислення, тож один зворотний прохід обчислює всі градієнти одночасно за час O(P), що відповідає вартості прямого проходу.

4. Зворотне поширення

Означимо «дельта»-сигнал похибки δ^(l) = ∂L/∂z^(l). Алгоритм зворотного поширення обчислює ці дельти від виходу до входу:

Рівняння зворотного поширення // Дельта вихідного шару: δ^(L) = ∂L/∂a^(L) ⊙ σ'(z^(L)) // Дельта прихованого шару (поширення назад): δ^(l) = (W^(l+1)ᵀ · δ^(l+1)) ⊙ σ'(z^(l)) // Градієнти для параметрів цього шару: ∂L/∂W^(l) = δ^(l) · (a^(l-1))ᵀ ∂L/∂b^(l) = δ^(l) ⊙ = поелементний добуток ᵀ = транспонування

Це повний алгоритм. У коді сучасні фреймворки обчислюють це за допомогою обчислювального графа, де кожна операція реєструє свою зворотну функцію. «Зворотний прохід» обходить граф у зворотному топологічному порядку.

5. Градієнтний спуск

Щойно градієнти відомі, ваги оновлюються, щоб зменшити втрати:

Оновлення вагів SGD W ← W − α · ∂L/∂W α = темп навчання (зазвичай від 1e-4 до 1e-2)

Варіанти усувають обмеження SGD:

Мінібатчевий градієнтний спуск: замість одного зразка (стохастичний) чи всіх зразків (пакетний) використовуйте батчі по 32–256. Це дає вдалий компроміс між шумом і обчисленнями — достатньо шумно, щоб уникати локальних мінімумів, і достатньо ефективно для паралелізму на GPU.

6. Функції активації та зникнення градієнтів

Вибір σ визначає, як градієнти проходять крізь багато шарів.

Пакетна нормалізація: нормалізує входи шару до нульового середнього/одиничної дисперсії під час навчання. Зменшує внутрішній коваріаційний зсув, стабілізує градієнти, дозволяє вищі темпи навчання. Робить дуже глибокі мережі придатними до навчання.

7. Автоматичне диференціювання

Сучасні фреймворки (PyTorch, JAX, TensorFlow) реалізують автоматичне диференціювання у зворотному режимі — узагальнення зворотного поширення на довільні обчислювальні графи.

Кожна операція над тензором записує зворотну функцію у стрічку/граф. Під час зворотного проходу рушій обходить цей граф і накопичує градієнти за ланцюговим правилом, цілком автоматично. Ви пишете прямі обчислення; градієнти отримуєте безкоштовно.

Приклад PyTorch (концептуально) x = torch.tensor([2.0], requires_grad=True) y = x ** 3 + 2 * x // y = 12 y.backward() // dy/dx = 3x² + 2 = 14 print(x.grad) // tensor([14.])

Автодиференціювання у прямому режимі (де ви поширюєте дотичну, а не градієнт) ефективне, коли розмірність входу << розмірності виходу. Зворотний режим ефективний, коли розмірність виходу << входу (тобто обчислення градієнта скалярних втрат за мільйонами вагів). Навчання нейромереж завжди використовує зворотний режим.

Контрольні точки градієнта: для дуже глибоких моделей або моделей з обмеженою пам'яттю не зберігайте всі проміжні активації. Переобчислюйте їх під час зворотного проходу зі значень у контрольних точках. Це обмінює обчислення на пам'ять (корисно для навчання великих мовних моделей).