Від похідних до зворотного поширення: теорія, на якій ґрунтується Micrograd

Процес навчання нейронної мережі передбачає пошук ваг і зміщень, які роблять прогнози точнішими. Ми порівнюємо ці прогнози з очікуваними відповідями за допомогою функції втрат — формули, яка перетворює їхню невідповідність у число, де нижче значення вказує на кращу відповідність. Щоб вибрати оновлення, нам потрібно знати, як зміна кожного параметра вплине на цю втрату. Ми могли випадковим чином підштовхнути параметр, знову обчислити втрати та порівняти результати. Але перевірка мільйонів параметрів по одному таким чином вимагала б мільйонів додаткових оцінок.

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

Математично це проблема оптимізації, зокрема мінімізації: ми шукаємо значення параметрів моделі, які роблять втрати якомога меншими. Хоча методи нульового порядку, такі як MeZO, можуть керувати оновленнями, випадково змінюючи багато параметрів одночасно та оцінюючи втрати, стандартним підходом є використання похідної інформації для керування пошуком. Сьогодні нейронні мережі переважно навчаються за допомогою градієнтів, обчислених за алгоритмом, відомим як зворотне поширення — підхід, який ми розробимо тут.

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

Далі ми простежимо зміни через пов’язані операції: ланцюгове правило перемножує похідні вздовж шляху й додає внески, коли один вхід впливає на вихід кількома шляхами. Головна ідея полягає в тому, що знання похідних невеликого набору базових операцій дозволяє диференціювати побудовані з них функції. Навіть похідну квадрата можна отримати лише з множення. Ми пов’яжемо цю ідею із символьним диференціюванням, а потім простежимо прямий і зворотний проходи, щоб побачити, як автоматичне диференціювання у зворотному режимі повторно використовує проміжні результати для обчислення градієнтів за багатьма входами. Саме на цьому ґрунтується зворотне поширення.

Ця стаття закладає теоретичні основи для розуміння Micrograd Андрея Карпаті — невеликого рушія автоматичного диференціювання з API, схожим на PyTorch. У своєму відеорозборі він створює цей рушій і використовує його для навчання нейронної мережі. Ті самі принципи лежать в основі функції PyTorch torch.autograd.backward, яка обчислює градієнти за ланцюговим правилом.

Від швидкості зміни до похідних

Давайте почнемо з простого лінійного співвідношення z=3xz=3x і знайдемо його похідну, вивчивши нахил його графіка. Похідна вказує нам, як швидко змінюється вихід функції, коли ми змінюємо її вхід при певному вхідному значенні. Тут будь-яке збільшення xx призводить до збільшення zz утричі. Використовуючи Δ\Delta для представлення зміни, ми можемо написати:

Δz=3 Δx.\Delta z=3\,\Delta x.

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

slope=ΔzΔx=riserun\text{slope}=\frac{\Delta z}{\Delta x}=\frac{\text{rise}}{\text{run}}

На графіку нижче ми можемо побачити, як синя лінія z=3xz=3x піднімається на 33 для циклу 11, даючи нахил 3/1=33/1=3.

Compare slopes of 3, 1, and 0.5 on the same axesThe solid blue line z = 3x passes through (0, 0), (1, 3), and (2, 6). A green horizontal segment shows a run of 1, and an orange vertical segment shows a rise of 3. The dashed purple line z = x and dotted gray line z = 0.5x rise by 1 and 0.5 per unit of x. All three use the same axes: the larger slope gives the steeper line.1326390xzz = xz = 0.5xrun = 1rise = 3z = 3x

Пунктирна сіра лінія z=0.5xz=0.5x і пунктирна фіолетова лінія z=xz=x підвищуються лише на 0.50.5 і 11 для того самого циклу 11. При однакових масштабах осі більший абсолютний нахил означає крутішу лінію. Усі три нахили додатні, тому лінії підвищуються, коли ми рухаємось праворуч; від’ємний нахил спричинить падіння лінії.

Ми виявили, що синя лінія має нахил 33, тому похідною від z=3xz=3x є 33. Ми пишемо це як dzdx\frac{dz}{dx} і читаємо як «похідну від zz відносно xx». Фраза «щодо xx» визначає вхідні дані, які ми змінюємо: похідна вимірює, наскільки швидко змінюється вихідний сигнал zz, коли змінюється xx. Наша функція має лише один вхід, xx, тому немає інших вхідних даних, які потрібно фіксувати. Для нашої синьої лінії ми отримуємо:

dzdx=3\frac{dz}{dx}=3

Символи dd вказують на похідну, тоді як Δz/Δx\Delta z/\Delta x описує середню швидкість зміни протягом кінцевого інтервалу. Для z=3xz=3x швидкість зміни постійна і не залежить від xx, тому похідною є 33, де б ми її не оцінювали.

Ми використали нахил прямої, щоб знайти похідну. Ми також можемо обчислити його за допомогою правил диференціювання. Оскільки z=3xz=3x, ми можемо замінити zz його виразом і написати:

dzdx=ddx(3x)\frac{dz}{dx}=\frac{d}{dx}(3x)

Тут диференціальний оператор ddx\frac{d}{dx} означає «продиференціювати наступний вираз за xx». У ddx(3x)\frac{d}{dx}(3x) таким виразом є 3x3x, який ми розглядаємо як функцію xx. Це позначення особливо корисне, коли ми розглядаємо окремі доданки складнішого виразу як функції та диференціюємо їх окремо.

Використовуючи правило сталого множника, ми зберігаємо множник 33 і диференціюємо xx. Похідна від xx по відношенню до xx дорівнює 11, тому що збільшення вхідних даних на будь-яку величину збільшує вихідні дані xx точно на таку ж величину:

ddx(3x)=3ddx(x)=3×1=3.\frac{d}{dx}(3x)=3\frac{d}{dx}(x)=3\times1=3.

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

Похідна, що залежить від вхідного значення

Давайте тепер розглянемо функцію, швидкість зміни якої залежить від її вхідних даних. Це робить локальну природу похідної більш зрозумілою: вона описує, як вихід змінюється поблизу конкретного вхідного значення, де ми його оцінюємо. Щоб продемонструвати це, ми використаємо функцію з одним входом xx під назвою LL:

L(x)=x2+3.L(x)=x^2+3.

Ми можемо записати цю похідну як dL/dxdL/dx, використовуючи ту саму нотацію, яку ми ввели вище, яка називається , нотація Лейбніца. Інший спосіб запису — L′(x)L'(x), що читається як «L просте число x», що називається нотацією Лагранжа або простою нотацією. Обидва означають похідну від LL відносно xx.

Щоб знайти похідну від L(x)=x2+3L(x)=x^2+3, ми розділимо її два члени окремо, а потім додамо результати. Тут використовуються три правила:

ПравилоЯк ми це використовуємо
Силове правилоДиференціювати x2x^2
Постійне правилоПродиференціюйте постійний доданок 33
Правило сумиДодайте похідні двох доданків

Давайте спочатку застосуємо правило похідної степеневої функції до x2x^2: помножте на експоненту, потім зменшіть експоненту на одиницю. загалом,

ddx(xn)=nxn−1\frac{d}{dx}(x^n)=nx^{n-1}

Для x2x^2 це дає 2x2x. Потім ми застосовуємо правило константи до 33. Його похідна по відношенню до xx дорівнює нулю, оскільки вона не змінюється зі зміною xx. І, нарешті, ми використовуємо sum правило, щоб додати ці похідні. Отже, для нашої функції похідна:

L′(x)=2x+0=2xL'(x)=2x+0=2x

Щоб побачити, що говорить нам ця формула, давайте обчислимо результат функції та її похідну за трьома значеннями xx:

Вхід xxВихід L(x)=x2+3L(x)=x^2+3Похідна L′(x)=2xL'(x)=2x
−5-5(−5)2+3=28(-5)^2+3=282×(−5)=−102\times(-5)=-10
0002+3=30^2+3=32×0=02\times0=0
5552+3=285^2+3=282×5=102\times5=10

На відміну від постійної ставки 33 у z=3xz=3x, ця ставка залежить від поточного значення xx. Вихідні дані функції однакові для x=−5x=-5 і x=5x=5, але похідні мають протилежні знаки. У x=5x=5 позитивна похідна означає, що вихід зростає, оскільки xx трохи збільшується. У x=−5x=-5 негативна похідна означає, що вихід падає, коли xx трохи збільшується.

На графіку нижче зосереджено напрямок: дві точки мають однакову висоту, але зелені стрілки показують різні способи переміщення вздовж кривої для зменшення результату.

L(x) = x² + 3 against Parameter xThe function curve is U-shaped with a minimum at x = 0, where the output is 3. At x = −5 and x = 5, the output is 28. Arrows follow the curve downward toward zero: increase x from −5, but decrease x from 5.-60-310020330640L(x) = x² + 3Parameter x(−5, 28)(5, 28)Increase x →← Decrease xMinimum (0, 3)

Цей графік показує, що якщо наша мета — зменшити результат функції, знак похідної вказує нам, у який бік рухатися від кожної початкової точки. Зелені стрілки показують ці напрямки, які ми можемо визначити, не намагаючись як збільшити, так і зменшити xx і перерахувати вихідні дані функції. Обидві стрілки ведуть до x=0x=0, де ця функція досягає свого мінімуму, а похідна дорівнює нулю, хоча нульова похідна не завжди вказує на мінімум.

Поширеним способом візуалізації похідної є нахил дотичної до графіка у вибраній точці. У x=5x=5 похідною є 1010, тому дотична має нахил 1010. Змініть Параметр x нижче, щоб побачити, як змінюється нахил фіолетової дотичної уздовж синьої кривої.

Output L(x) against Parameter xAt x=5, the output is 28 and the tangent slope is 10. -60-310.75021.5332.25643Output L(x)Parameter x
Exact derivative10L′(x) = 2x

Тангенс також допомагає нам оцінити, наскільки вихід функції змінюється поблизу. У x=5x=5, де результатом є 2828, а похідною є 1010, a невелика зміна в xx викликає зміну у вихідному сигналі приблизно в 1010 разів більше:

ΔL≈10 Δx.\Delta L\approx10\,\Delta x.

Ми використовуємо ≈\approx у наведеному вище виразі, оскільки ми оцінюємо зміну випуску за невеликий крок. У x=5x=5 похідна точно дорівнює 1010, але нахил змінюється, коли ми рухаємося вздовж кривої. Встановлення Параметр x на 4.94.9 у віджеті дає нахил 9.89.8; менший перехід до 4.994.99 дасть 9.989.98. Чим менший крок, тим менше змінюється нахил, тому розгляд його як постійного в 1010 дає точнішу оцінку зміни у виході.

Оцінювання похідної за допомогою скінченних різниць

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

Оцінка прямої різниці ділить вихідну зміну на невелику, відмінну від нуля зміну вхідної величини hh:

L(x+h)−L(x)h\frac{L(x+h)-L(x)}{h}

Давайте обчислимо кінцево-різницеву оцінку за допомогою L(x)=x2+3L(x)=x^2+3. Починаючи з x=5x=5, крок h=0.001h=0.001 приведе нас до 5.0015.001:

L(5.001)−L(5)0.001=28.010001−280.001=10.001\frac{L(5.001)-L(5)}{0.001} =\frac{28.010001-28}{0.001} =10.001

Це середня швидкість зміни між двома вхідними даними. Геометрично, це нахил прямої лінії, що з’єднує їхні точки на кривій, називається secant. Похідна дає нахил дотичної у початковій точці.

У наведеному нижче віджеті встановіть для Параметр x значення 55, де фіолетовий дотичний має нахил 1010. З Мала зміна h на 0.0010.001 помаранчевий секанс має нахил 10.00110.001. Це кінцево-різнична оцінка. Коли ми зменшуємо hh, помаранчевий нахил наближається до 1010, точної похідної.

L(x) = x² + 3 against Parameter xAt x=2, the output is 7 and the tangent slope is 4. With h=0.8, the secant slope is 4.8.-60-310.75021.5332.25643L(x) = x² + 3Parameter x
Tangent: exact derivativeSecant: finite difference
Exact derivative4L′(x) = 2x
Finite difference4.8(L(x + h) − L(x)) / h

Ми називаємо це середнім, тому що ділимо загальну зміну випуску на загальну зміну входу за інтервал. Скінченно-різницеве ​​наближення використовує лише два значення кінцевих точок, тому воно не повідомляє нам, як функція поводиться між ними. Його вихід може змінюватися повільніше в одній частині інтервалу і швидше в іншій.

Оскільки ми знаємо формулу, ми можемо побудувати криву між кінцевими точками та побачити цю різницю. На графіку нижче використовується ширший інтервал від x=1x=1 до x=5x=5, щоб зробити різницю видимою. Пунктирна лінія, що з’єднує кінцеві точки, має середній нахил; зелена крива показує, як фактично змінюється вихід. Заштрихований трикутник показує загальну вхідну зміну Δx=4\Delta x=4 і вихідну зміну ΔL=24\Delta L=24, тому середній нахил дорівнює 24/4=624/4=6.

The average slope uses only the endpoints
Average slope as change in output divided by change in parameterA dashed blue secant passes through (1, 4) and (5, 28). A shaded right triangle shows the parameter change Δx = 4 and output change ΔL = 24, giving an average slope of 6. The midpoint is (3, 12). An orange secant joins (1, 4) to (3, 12), with average slope 4. A purple secant joins (3, 12) to (5, 28), with average slope 8. The green curve is L(x) = x² + 3.Outputx(3, 12)3Δx = 4ΔL = 24(1, 4)1(5, 28)5
Whole intervalFirst halfSecond halfFunction curve

Ми можемо порівняти середню швидкість за весь інтервал з показниками за дві його половини. Розщеплення на x=3x=3, де вихід є 1212, дає:

ІнтервалВведення змінВихідні зміниСередній курс
Весь інтервал1→51 \to 54→284 \to 28(28−4)/(5−1)=6(28-4)/(5-1)=6
Перша половина1→31 \to 34→124 \to 12(12−4)/(3−1)=4(12-4)/(3-1)=4
Друга половина3→53 \to 512→2812 \to 28(28−12)/(5−3)=8(28-12)/(5-3)=8

Визначення межі уточнює ідею швидкості зміни в одній точці: це значення, до якого наближається середня швидкість зміни, коли інтервал скорочується до нуля:

L′(x)=lim⁡h→0L(x+h)−L(x)hL'(x)=\lim_{h\to0}\frac{L(x+h)-L(x)}{h}

Ми дозволяємо hh наближатися до нуля, а не замінюємо h=0h=0, що дасть 0/00/0. Використовуючи це обмеження, ми отримуємо правило L′(x)=2xL'(x)=2x. Для нашої функції спочатку спростіть співвідношення, залишаючи hh ненульовим:

L(x+h)−L(x)h=(x+h)2+3−(x2+3)h=2xh+h2h=2x+h\begin{aligned} \frac{L(x+h)-L(x)}{h} &=\frac{(x+h)^2+3-(x^2+3)}{h}\\ &=\frac{2xh+h^2}{h}\\ &=2x+h \end{aligned}

Це робить різницю чіткою: обчислення кінцевої різниці на вибраному кроці дає 2x+h2x+h. Взяття обмеження, коли hh наближається до нуля, видаляє зайвий hh, даючи нам правило похідної:

L′(x)=2x,L′(5)=10L'(x)=2x,\qquad L'(5)=10

Це пояснює правило, яке ми символічно застосували раніше. Отримавши формулу 2x2x, ми можемо обчислити її безпосередньо на будь-якому вході, не обчислюючи функцію на сусідньому вході.

Пряма різниця порівнює xx із x+hx+h. Вибірка позаду xx дає оцінку зворотної різниці, тоді як вибірка однаково з обох сторін дає оцінку центральної різниці. Це інші типи скінченно-різницевої апроксимації. Для тієї самої функції L(x)=x2+3L(x)=x^2+3 ми тепер використаємо більший крок h=0.1h=0.1:

МетодФормулаОцінити в x=5x=5, h=0.1h=0.1
ВпередL(x+h)−L(x)h\dfrac{L(x+h)-L(x)}{h}10.110.1
НазадL(x)−L(x−h)h\dfrac{L(x)-L(x-h)}{h}9.99.9
ЦентральнаL(x+h)−L(x−h)2h\dfrac{L(x+h)-L(x-h)}{2h}10.010.0

У точній арифметиці, коли ми зменшуємо крок hh, оцінки прямої, зворотної та центральної різниці збігаються до точної похідної — для нашої функції на x=5x=5 це значення дорівнює 1010. Центральна різниця є точною для цього квадрата в точній арифметиці, але загалом залишається наближенням.

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

Ці методи корисні для перевірки похідних, але їхні додаткові оцінки функцій роблять їх дорогими, якщо застосовувати їх окремо до мільйонів параметрів.

Кілька входів і частинні похідні

Досі ми використовували функції z=3xz=3x і L(x)=x2+3L(x)=x^2+3 лише з одним параметром xx. Давайте тепер розглянемо z=x+yz=x+y і z=xyz=xy з двома параметрами xx і yy, які ми можемо змінювати окремо. Щоб зрозуміти вплив кожного параметра на zz, ми змінюємо один, утримуючи інший фіксованим. Зміна обох одночасно призвела б до змішування їх ефектів.

Раніше ми писали dz/dxdz/dx, щоб описати, як вихідний сигнал zz змінюється з одним входом xx. Для наших функцій з двома входами нам потрібно вказати, який вхід ми змінюємо. Щоб виміряти, як змінюється zz, коли ми змінюємо xx, утримуючи yy фіксованим, ми використовуємо частинну похідну, записану як ∂z/∂x\partial z/\partial x. Ми читаємо це як ' частинну похідну від zz відносно xx'. Порядок позначень означає те саме, що й раніше; символ ∂\partial вказує на те, що ми змінюємо один вхід, утримуючи інші фіксованими.

Геометрично два входи визначають точку на поверхні z=f(x,y)z=f(x,y). Часткова похідна вимірює нахил у цій точці в одному напрямку входу, тоді як інший вхід залишається фіксованим. Тому нам потрібні обидва вхідні значення, щоб визначити, де ми вимірюємо нахил, навіть якщо ми досліджуємо зміни лише в одному напрямку.

Під час обчислення частинної похідної ми застосовуємо правила диференціювання, розглядаючи інші вхідні дані як константи.

Почнемо з додавання, z=x+yz=x+y. Утримуючи yy фіксованим, збільшення xx на 11 збільшує zz на 11, отже, ∂z/∂x=1\partial z/\partial x=1. Зміна ролей дає ∂z/∂y=1\partial z/\partial y=1.

Для множення, z=xyz=xy, швидкість залежить від вхідних даних, які ми фіксуємо. У наведеній нижче таблиці показано, як змінюється zz, коли ми збільшуємо xx, утримуючи yy на постійному значенні 55:

x\boldsymbol{x}y\boldsymbol{y}z=xy\boldsymbol{z=xy}
33551515
44552020
55552525
66553030

Ми бачимо, що кожного разу, коли xx збільшується на 11, zz збільшується на 55. Оскільки yy утримується на рівні 55, швидкість зміни по відношенню до xx дорівнює 55:

∂z∂x=y=5\frac{\partial z}{\partial x}=y=5

Як бачите, швидкість зміни дорівнює постійному значенню yy. Тут використовується те саме правило кратності констант, яке ми застосували до z=3xz=3x. Множник у z=3xz=3x був 33. У z=xyz=xy множник дорівнює yy, який ми залишаємо постійним, диференціюючи xx. Отже, коли ми залишаємо одну змінну постійною, вона все ще бере участь у обчисленні та впливає на те, як результат реагує на зміни в іншій змінній.

Диференціювання відносно yy працює так само: ми тримаємо xx постійним і застосовуємо правило кратних констант, отримуючи ∂z/∂y=x\partial z/\partial y=x. Два входи відіграють симетричні ролі, але їхні ефекти залежать від поточних значень xx і yy. На x=3x=3 і y=5y=5 вихідний сигнал – 1515, а частинні похідні – 55 і 33 відповідно.

Тепер ми можемо узагальнити локальні правила похідних для обох операцій:

Операція∂z/∂x\partial z/\partial x∂z/∂y\partial z/\partial y
z=x+yz=x+y1111
z=xyz=xyyyxx

Крім того, зміна будь-якого входу змінює вихід на ту саму величину. Для множення кожна частинна похідна дорівнює іншому входу. Ці правила називаються локальними, оскільки вони описують, як вихідні дані окремої операції реагують на вхідні дані. Пізніше ми з’єднаємо їх, щоб відстежувати зміни за допомогою кількох операцій.

Часткові похідні 55 і 33 описують чутливість, а не частину вихідного сигналу 1515. Для однакових невеликих змін лише зміна xx має у 5/35/3 разів більший ефект, ніж лише зміна yy. Щоб оцінити ефект зміни обох вхідних даних, нам потрібні як похідні, так і запропоновані зміни вхідних даних.

Для цього ми збираємо частинні похідні у вектор, який називається градієнтом. Позначаємо його символом ∇\nabla, тому для функції z=xyz=xy при x=3x=3 і y=5y=5 пишемо ∇z=(5,3)\nabla z=(5,3). Цей вектор має й геометричний зміст у площині входів: серед переміщень однакової малої евклідової довжини він указує напрям найбільшого зростання виходу в наближенні першого порядку. Протилежний вектор указує напрям найшвидшого локального спадання.

Графік нижче демонструє ці вказівки для z=xyz=xy. Ви можете побачити, як фіолетова стрілка веде вгору від (3,5)(3,5), де вихід 1515, тоді як зелена стрілка веде вниз. Вони відстежують шляхи поверхні, коли ми переміщуємо вхідні дані в напрямку градієнта або протилежному йому. Графік масштабує висоту окремо; градієнт визначає напрямок у вхідній площині.

The surface z = xy and gradient directions at (3, 5)The horizontal axes are inputs x and y; height is output z. The saddle surface has height 15 at (3, 5). The purple surface path follows input direction (5, 3), and the green surface path follows (-5, -3), the directions of steepest local increase and decrease in output per unit input distance.xyz-36036(3, 5, 15)
∇z = (5, 3): local increase−∇z = (−5, −3): local decrease
Drag to rotate, or focus the graph and use the arrow keys. Height is scaled separately; the gradient describes direction in the input plane.

Коли ми знаємо частинні похідні, ми можемо використовувати наближення Тейлора першого порядку, яке також називається лінійне наближення. Це дозволяє нам оцінити сукупний вплив невеликих вхідних змін на вихід: ми множимо кожну частинну похідну на відповідну вхідну зміну та додаємо результати.

Δz≈∂z∂xΔx+∂z∂yΔy\Delta z\approx\frac{\partial z}{\partial x}\Delta x+\frac{\partial z}{\partial y}\Delta y

Це скалярний добуток градієнта та вектора вхідних змін. Для нашої функції z=xyz=xy на (3,5)(3,5) це дає:

Δz≈5 Δx+3 Δy\Delta z\approx5\,\Delta x+3\,\Delta y

Наприклад, збільшення обох входів на 0.10.1 дає:

Δz≈5(0.1)+3(0.1)=0.8\Delta z\approx5(0.1)+3(0.1)=0.8

Збільшення xx на 0.10.1 вносить 0.50.5 у прогнозовану зміну, тоді як збільшення yy на 0.10.1 сприяє 0.30.3. Кожен внесок є частковою похідною, помноженою на відповідну зміну вхідних даних. Похідні описують чутливість; вибрані зміни визначають, яка частина цієї чутливості входить до прогнозу.

Оцінка функції на нових входах дає фактичну зміну 3.1×5.1−15=0.813.1\times5.1-15=0.81. Залишок 0.010.01 є членом взаємодії Δx Δy\Delta x\,\Delta y, який лінійне наближення виключає. Таким чином, терміни 0.50.5 і 0.30.3 описують внесок у прогнозовану зміну, а не частки вихідного результату 1515. Така ж різниця стосується зворотного поширення: воно обчислює чутливість втрати до кожної ваги. Множення цих похідних на запропоновані зміни ваги оцінює їхній внесок у зміну втрат.

Поєднання правил диференціювання для складнішої функції

У попередньому розділі ми обчислили частинні похідні для додавання та множення. Тепер ми об’єднаємо правила диференціювання у виразі з кількома термінами та ступенями:

f(x,y)=xy2+x3f(x,y)=xy^2+x^3

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

Спочатку диференціюємо, потім підставляємо значення

Ми зберігаємо xx і yy як символи, знаходячи частинну похідну для кожного входу, розглядаючи інший як константу. Потім ми оцінимо обидва похідні за (x,y)=(3,2)(x,y)=(3,2).

По-перше, ми диференціюємо відносно xx, фіксуючи yy і диференціюючи кожен термін. Фактор y2y^2 діє як постійний множник xx:

∂f∂x=y2∂∂x(x)+∂∂x(x3)=y2⋅1+3x2=y2+3x2\begin{aligned} \frac{\partial f}{\partial x} &=y^2\frac{\partial}{\partial x}(x) +\frac{\partial}{\partial x}(x^3)\\ &=y^2\cdot1+3x^2\\ &=y^2+3x^2 \end{aligned}

Утримання yy фіксованим не видаляє його з обчислення: його значення визначає множник y2y^2. Ми диференціюємо x3x^3 за допомогою правила похідної степеневої функції.

Потім ми диференціюємо відносно yy, змінюючи ролі та залишаючи xx фіксованим. Тепер xx є постійним множником y2y^2, а весь член x3x^3 є постійним:

∂f∂y=x∂∂y(y2)+∂∂y(x3)=x⋅2y+0=2xy\begin{aligned} \frac{\partial f}{\partial y} &=x\frac{\partial}{\partial y}(y^2) +\frac{\partial}{\partial y}(x^3)\\ &=x\cdot2y+0\\ &=2xy \end{aligned}

Термін x3x^3 дає нульовий внесок, оскільки зміна yy, утримуючи xx фіксованим, не може змінити його значення.

Це дає нам наступні частинні похідні при вибраних вхідних даних:

Введення змінюємоВведення фіксованоЧасткова похідна в (3,2)(3,2)Прогнозована зміна випуску
xxy=2y=222+3(32)=312^2+3(3^2)=31Δf≈31 Δx\Delta f\approx31\,\Delta x
yyx=3x=32(3)(2)=122(3)(2)=12Δf≈12 Δy\Delta f\approx12\,\Delta y

Спочатку фіксуємо один вхід, потім диференціюємо переріз

Тепер розгляньмо другий підхід: спочатку фіксуємо один вхід, а потім диференціюємо функцію перерізу. Підставляємо значення одного входу у f(x,y)=xy2+x3f(x,y)=xy^2+x^3 й отримуємо звичайну функцію іншого входу.

Спочатку ми встановлюємо y=2y=2 і залишаємо xx вільним варіювати:

f(x,2)=x(22)+x3=4x+x3f(x,2)=x(2^2)+x^3=4x+x^3

Це частина вихідної функції, а не похідна: ми замінили значення лише для одного вхідного параметра.

Для фрагмента з y=2y=2 ми більше не маємо yy як змінну у виразі, оскільки заміна 22 перетворила y2y^2 на постійний множник 44. Ефект yy, однак, все ще переноситься через множник 44. Тепер, коли лише xx залишається як змінна, ми беремо звичайну похідну відносно xx:

ddx(4x+x3)=4+3x2⟹4+3(32)=31at x=3\frac{d}{dx}(4x+x^3)=4+3x^2 \quad\Longrightarrow\quad 4+3(3^2)=31\quad\text{at }x=3

Потім, повертаючись до початкової функції, ми встановлюємо x=3x=3 і залишаємо yy вільною для змін:

f(3,y)=3y2+33=3y2+27f(3,y)=3y^2+3^3=3y^2+27

А для фрагмента з x=3x=3 ми диференціюємо по відношенню до yy:

ddy(3y2+27)=6y⟹6(2)=12at y=2\frac{d}{dy}(3y^2+27)=6y \quad\Longrightarrow\quad 6(2)=12\quad\text{at }y=2

Обидва зрізи проходять через одну вибрану точку, де f(3,2)=3(22)+33=39f(3,2)=3(2^2)+3^3=39. Диференціація кожного зрізу дає ті самі частинні похідні, які ми обчислили вище:

∂f∂x(3,2)=31,∂f∂y(3,2)=12\frac{\partial f}{\partial x}(3,2)=31,\qquad \frac{\partial f}{\partial y}(3,2)=12

Обидва підходи залишають інший вхід сталим, тому його значення можна підставити до диференціювання або залишити його символом і підставити значення пізніше. Перший підхід дає загальні формули похідних, y2+3x2y^2+3x^2 і 2xy2xy, які можна обчислити для будь-якої пари входів. Другий дає формули для конкретних перерізів: 4+3x24+3x^2, коли y=2y=2, та 6y6y, коли x=3x=3. Наприклад, підстановка x=3x=3 у 2xy2xy дає 6y6y, як і диференціювання функції перерізу 3y2+273y^2+27. Кожен переріз отримуємо окремою підстановкою в початкову функцію.

Ці похідні вимірюють чутливість, а не частки поточного виходу. Як і раніше, ми збираємо частинні похідні у вектор градієнта. У (3,2)(3,2) це дає ∇f=(31,12)\nabla f=(31,12). Запропоновані вхідні зміни утворюють вектор (Δx,Δy)(\Delta x,\Delta y). Їх скалярний добуток оцінює сукупну зміну випуску:

Δf≈∇f(3,2)⋅(Δx,Δy)=31Δx+12Δy\Delta f\approx\nabla f(3,2)\cdot(\Delta x,\Delta y) =31\Delta x+12\Delta y

У (x,y)=(3,2)(x,y)=(3,2) обидві координати визначають точку, де ми вимірюємо нахили. Переміщення в напрямку xx, утримуючи y=2y=2, дає дотичний нахил 3131; рух у напрямку yy, утримуючи x=3x=3, дає нахил 1212. Це два напрямки через одну точку поверхні. Кожна швидкість є частковою похідною початкової функції з двома входами та звичайною похідною її відповідного зрізу з одним входом. Градієнт поєднує ці швидкості в напрямку найкрутішого локального збільшення у вхідній площині.

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

Surface and both fixed-input slicesBoth slices pass through (3, 2, 39). One varies x with y fixed at 2; the other varies y with x fixed at 3. Their tangent slopes are 31 and 12. Drag or use arrow keys to rotate.x varies; y stays fixedy varies; x stays fixedSurface path along the gradient direction at the selected point
f(x, 2) = 4x + x³-505-1450145xf

∂f/∂x = 31

f(3, y) = 3y² + 27-5052764.5102yf

∂f/∂y = 12

Починаючи з (3,2)(3,2), переміщення повзунка xx по-різному впливає на два графіки. Зліва xx є змінним входом, тому вибрана точка рухається вздовж тієї самої кривої f(x,2)=4x+x3f(x,2)=4x+x^3, а y=2y=2 залишається фіксованою. Праворуч xx — це фіксований вхід, який визначає зріз, тому зміна його з 33 на 44 змінює формулу з f(3,y)=3y2+27f(3,y)=3y^2+27 на f(4,y)=4y2+64f(4,y)=4y^2+64. Іншими словами, переміщення xx переміщує точку вздовж лівого зрізу та змінює, який зріз буде показано праворуч. Переміщення yy робить навпаки.

Похідні через послідовність пов’язаних операцій

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

У наступній таблиці наведено правила додавання, множення та вкладення. Ми будемо використовувати g(x)g(x) і h(x)h(x) як загальні назви для двох диференційованих функцій xx:

ПравилоЯк поєднуються функціїПохідна щодо xx
Правило сумиg(x)+h(x)g(x)+h(x)g′(x)+h′(x)g'(x)+h'(x)
Правило продуктуg(x)h(x)g(x)h(x)g′(x)h(x)+g(x)h′(x)g'(x)h(x)+g(x)h'(x)
Правило ланцюжкаg(h(x))g(h(x))g′(h(x))h′(x)g'(h(x))h'(x)

Правило добутку узагальнює правило постійних кратних, яке ми використовували раніше, на випадки, коли обидва фактори змінюються. Множення двох функцій не означає множення їх похідних. Щоб продиференціювати окремі функції, ми можемо використовувати таке правило, як правило похідної степеневої функції, або розбити функції на простіші операції, похідні яких ми вже знаємо. Ланцюгове правило поєднує їх локальні похідні, щоб визначити, як вихідний вхід впливає на кінцевий вихід, роблячи його центральним у зворотному поширенні.

У попередньому розділі ми диференціювали терміни, розглядаючи інші вхідні дані як постійні. Тепер ми розглянемо ці терміни: кожну арифметичну операцію можна розглядати як функцію її вхідних даних.

Давайте спочатку розділимо нашу функцію f(x,y)=xy2+x3f(x,y)=xy^2+x^3 на окремі операції з іменованими проміжними результатами:

u=y2,v=xu,w=x3,f=v+wu=y^2,\qquad v=xu,\qquad w=x^3,\qquad f=v+w

Наприклад, зведення у квадрат відображає yy на u=y2u=y^2, а множення – xx і uu на v=xuv=xu. Вихід квадрата стає входом для множення. Коли вихідні дані однієї функції стають вхідними даними іншої, функції складаються — зв’язок, який називається композицією функції, показаний як g(h(x))g(h(x)) у таблиці вище. Операція має власні негайні входи; операції підключення роблять її результат також залежним від попередніх вхідних даних.

Розділення відповідає залежностям виразу: u=y2u=y^2 має бути доступним перед v=xuv=xu, а vv і ww мають бути доступними перед f=v+wf=v+w. Оскільки w=x3w=x^3 не залежить від uu або vv, ми можемо обчислити його до або після цієї гілки. Розбиття не є унікальним: ми можемо виразити зведення в квадрат і куб як множення. Тут ми розглядаємо їх як окремі операції та використовуємо правило похідної степеневої функції для їх локальних похідних.

Тепер ми використаємо ланцюгове правило для обчислення похідних через окремі операції, множачи локальні похідні вздовж кожного шляху та додаючи внески від різних шляхів. Спочатку ми підемо одним шляхом, а потім перевіримо вхід, який досягає виходу двома шляхами.

Ланцюгове правило: один шлях

Ми почнемо з диференціації щодо yy, утримуючи xx фіксованим. Розподіл показує, чому yy є корисною відправною точкою: його зміна впливає на u=y2u=y^2, потім на v=xuv=xu, тоді як w=x3w=x^3 залишається постійним. Після цього ми розглянемо xx, який впливає як на vv, так і на ww. Наразі існує лише один шлях від yy до кінцевого результату:

y ⟶ u=y2 ⟶ v=xu ⟶ f=v+wy\ \longrightarrow\ u=y^2\ \longrightarrow\ v=xu\ \longrightarrow\ f=v+w

Щоб побачити різницю між локальною похідною та ланцюговим правилом, зосередьтеся лише на двох вузлах операції: квадраті u=y2u=y^2 і множенні v=xuv=xu, з’єднаних u→vu\to v.

Якщо розглядати окремо, множення приймає xx і uu як вхідні дані. Його локальні частинні похідні:

∂v∂x=u,∂v∂u=x\frac{\partial v}{\partial x}=u, \qquad \frac{\partial v}{\partial u}=x

Щоб отримати кожну локальну похідну, нам потрібен лише вираз операції та вхідні дані, за якими ми диференціюємо. Для v=xuv=xu обробка xx як константи дає ∂v/∂u=x\partial v/\partial u=x, незалежно від того, як було обчислено uu або де використовується vv. Нам не потрібна решта графіка для цього кроку. Квадрат окремо постачає du/dy=2ydu/dy=2y.

Зверніть увагу, як ланцюгове правило включає похідну вузла u=y2u=y^2, du/dy=2ydu/dy=2y окремо, навіть якщо вузол v=xuv=xu уже використовує значення uu. Місцева похідна ∂v/∂u=x\partial v/\partial u=x лише повідомляє нам, як vv реагує на зміни в uu. Він не включає, як uu змінюється на yy. Ця ставка дорівнює du/dy=2ydu/dy=2y, тому нам потрібні обидва фактори:

∂v∂y=∂v∂u⏟how v responds to u⋅dudy⏟how u responds to y=x⋅2y\frac{\partial v}{\partial y} =\underbrace{\frac{\partial v}{\partial u}}_{\text{how v responds to u}} \cdot\underbrace{\frac{du}{dy}}_{\text{how u responds to y}} =x\cdot2y

Якщо xx виправлено, множення є зовнішньою функцією, а зведення у квадрат — внутрішньою. Зовнішня похідна сама по собі не може сказати нам, як змінюється внутрішня функція: множення приймає значення uu, не знаючи, чи воно надійшло з y2y^2, 2y2y чи іншого обчислення. У y=2y=2 і y2y^2, і 2y2y виробляють u=4u=4, але їх похідними є 44 і 22 відповідно. Тому те саме значення не означає однакову реакцію на зміну в yy. Ця відмінність застосовується щоразу, коли ми диференціюємо композицію.

Якщо ми замінимо u=y2u=y^2 на v=xuv=xu, повний вираз v=xy2v=xy^2 містить цю внутрішню залежність. Диференціація безпосередньо дає 2xy2xy, враховуючи обидві ставки. На графіку чітко показано ці два фактори.

У таблиці нижче наведено лише ефект зміни yy, де xx залишається виправленим. Він зосереджений на двох операціях u=y2u=y^2 і v=xuv=xu, зупиняючись на vv для обчислення ∂v/∂y\partial v/\partial y:

КрокСимволічна форма
Визначити операціїu=y2u=y^2, потім v=xuv=xu
Виведіть локальні похідні формулdu/dy=2ydu/dy=2y, ∂v/∂u=x\partial v/\partial u=x
Об’єднайте формули за допомогою ланцюжкового правила∂v/∂y=(∂v/∂u)(du/dy)=x⋅2y\partial v/\partial y=(\partial v/\partial u)(du/dy)=x\cdot2y

Зв’язки мають значення, коли ми комбінуємо локальні похідні: шлях y→u→vy\to u\to v каже нам помножити ∂v/∂u\partial v/\partial u на du/dydu/dy, щоб знайти ∂v/∂y\partial v/\partial y. Операція постачає локальне правило; графік показує, як зв’язати його з іншими правилами.

Тепер перейдіть до останнього додавання. Оригінальна функція приймає xx і yy, але кожна операція має власні входи. Для останнього додавання f=v+wf=v+w ці вхідні дані: vv і ww. Його локальна похідна ∂f/∂v\partial f/\partial v запитує, як змінюється вихід додавання, коли vv змінюється, а ww залишається фіксованим. Це дорівнює 11, оскільки додавання невеликої кількості до vv додає ту саму кількість до ff. Потім ланцюгове правило з’єднує ці локальні відповіді з початковим введенням yy.

У наведеній нижче таблиці наведено локальні похідні уздовж повного шляху:

ОпераціяМісцева похідна
Згладьте yy, щоб отримати uudu/dy=2ydu/dy=2y
Помножте uu на фіксоване значення xx, щоб отримати vv∂v/∂u=x\partial v/\partial u=x
Додайте фіксоване значення ww, щоб отримати ff∂f/∂v=1\partial f/\partial v=1

Щоб отримати похідну остаточного результату щодо yy, , тепер ми можемо застосувати ланцюгове правило, помноживши локальні похідні на y→u→v→fy\rightarrow u\rightarrow v\rightarrow f:

∂f∂y=∂f∂v⋅∂v∂u⋅dudy=1⋅x⋅2y=2xy\frac{\partial f}{\partial y} =\frac{\partial f}{\partial v}\cdot\frac{\partial v}{\partial u}\cdot\frac{du}{dy} =1\cdot x\cdot2y =2xy

Це відповідає формулі, яку ми отримали шляхом прямого диференціювання xy2+x3xy^2+x^3. Тут ∂f/∂y\partial f/\partial y дорівнює ∂v/∂y\partial v/\partial y, оскільки остання операція множить швидкість на 11.

Віджет нижче відображає графік цих пов’язаних обчислень. Починається з xx і yy, входів, від яких залежить функція. Вирази всередині вузлів, наприклад u=y2u=y^2 і v=xuv=xu, визначають операції. Суцільні стрілки вказують від результату операції до операції, яка його використовує. Таким чином, u→vu\to v означає, що v=xuv=xu використовує результат u=y2u=y^2, роблячи їхню композицію видимою. Множення використовує uu, а не його похідну du/dydu/dy; мітки похідних і пунктирні стрілки до поля ланцюгового правила показують, як ми диференціюємо обчислення. Дотримуйтесь помаранчевого шляху та помножте локальні похідні, щоб отримати 2y⋅x⋅1=2xy2y\cdot x\cdot1=2xy.

One path from y through u and v to fHolding x constant, the derivative for y receives a contribution through one path: y → u → v → f. Multiply along this path: ∂f/∂y = 2y × x × 1 = 2xy.yu = y²du/dy = 2yxv = xu∂v/∂u = xw = x³f = v + w∂f/∂v = 1Chain rule∂f/∂y = 2y × x × 1 = 2xy

Scroll the graph sideways to see the chain-rule box.

Коли ми тепер беремо формулу похідної 2xy2xy і замінюємо x=3x=3 і y=2y=2, ми отримуємо 2(3)(2)=122(3)(2)=12, що відповідає частковій похідній, яку ми обчислили раніше. Ми можемо обчислити цю формулу на будь-якій вхідній парі без попереднього обчислення значень проміжної функції.

У x=3x=3 і y=2y=2 невелика зміна hh у yy створює приблизно 4h4h зміну в uu. Шкали множення, які змінюються на 33, даючи приблизно 12h12h зміну vv. Додавання незмінного ww залишає ці зміни недоторканими.

Кілька шляхів: додавання внесків у похідну

Ми простежили, як yy впливає на вихід через один шлях. Давайте тепер знайдемо частинну похідну f(x,y)=xy2+x3f(x,y)=xy^2+x^3 відносно xx, залишаючи yy фіксованим. Ми використовуємо ті самі проміжні результати:

u=y2,v=xu,w=x3,f=v+wu=y^2,\qquad v=xu,\qquad w=x^3,\qquad f=v+w

Значення u=y2u=y^2 залишається постійним, але і v=xuv=xu, і w=x3w=x^3 змінюються на xx. Це дає нам два шляхи від xx до кінцевого результату:

x⟶v=xu⟶f=v+wandx⟶w=x3⟶f=v+wx\longrightarrow v=xu\longrightarrow f=v+w \qquad\text{and}\qquad x\longrightarrow w=x^3\longrightarrow f=v+w

Ми вже розрахували ∂f/∂x=y2+3x2\partial f/\partial x=y^2+3x^2 шляхом диференціювання xy2+x3xy^2+x^3 відносно xx, утримуючи yy постійним. Правило ланцюга дає ту саму відповідь, використовуючи локальні похідні вздовж обох шляхів:

ОпераціяМісцева похідна
Помножте xx на фіксоване значення uu, щоб отримати vv∂v/∂x=u=y2\partial v/\partial x=u=y^2
Куб xx, щоб отримати wwdw/dx=3x2dw/dx=3x^2
Додайте vv і ww, щоб отримати ff, враховуючи ефект vv∂f/∂v=1\partial f/\partial v=1
Додайте vv і ww, щоб отримати ff, враховуючи ефект ww∂f/∂w=1\partial f/\partial w=1

Кожна локальна похідна додавання зберігає свій інший вхід фіксованим. Both inputs change when xx changes, so we need both contributions.

Тепер ми застосовуємо ланцюгове правило багатьох змінних: множимо локальні похідні вздовж кожного шляху, а потім додаємо два внески, щоб отримати похідну кінцевого результату щодо xx:

∂f∂x=∂f∂v⋅∂v∂x+∂f∂w⋅dwdx=1⋅y2+1⋅3x2=y2+3x2\frac{\partial f}{\partial x} =\frac{\partial f}{\partial v}\cdot\frac{\partial v}{\partial x} +\frac{\partial f}{\partial w}\cdot\frac{dw}{dx} =1\cdot y^2+1\cdot3x^2 =y^2+3x^2

Діаграма нижче показує два шляхи від xx до кінцевого результату: x→v→fx\to v\to f і x→w→fx\to w\to f. Обидва відстежують вплив зміни xx, коли yy залишається сталим. Вузли yy та uu сірі, бо ця гілка не змінюється; вона все одно надає значення u=y2u=y^2 для множення. Помаранчевий шлях дає внесок 1⋅y21\cdot y^2, а фіолетовий — 1⋅3x21\cdot3x^2. Блоки активних операцій показують їхні локальні похідні. Блок угорі перемножує похідні вздовж кожного шляху, а потім додає внески, отримуючи y2+3x2y^2+3x^2.

The chain rule through two paths from x to fHolding y constant, the derivative for x receives contributions through two paths: x → v → f and x → w → f. Multiply along each path, then add: ∂f/∂x = 1 × y² + 1 × 3x² = y² + 3x².yu = y²xv = xu∂v/∂x = u = y²w = x³dw/dx = 3x²f = v + w∂f/∂v = 1∂f/∂w = 1Chain ruleMultiply along paths, then add(∂f/∂v) × (∂v/∂x)+(∂f/∂w) × (dw/dx)1 × y²+1 × 3x²∂f/∂x = y² + 3x²

Scroll the graph sideways to follow the paths.

Тепер підставимо x=3x=3 і y=2y=2 у формулу похідної y2+3x2y^2+3x^2: отримуємо 22+3(32)=4+27=312^2+3(3^2)=4+27=31. Це збігається з частинною похідною, яку ми обчислили раніше, хоча проміжні значення функції ми спочатку не обчислювали.

Обчислення похідних: символьне й автоматичне диференціювання

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

Похідна квадрата лише з множення

Припустімо, наш рушій підтримує множення, але не має операції піднесення до степеня. Ми все одно можемо обчислити s=x2s=x^2 як s=x⋅xs=x\cdot x. Для множення s=abs=ab локальні похідні такі:

∂s∂a=b,∂s∂b=a.\frac{\partial s}{\partial a}=b,\qquad \frac{\partial s}{\partial b}=a.

Тут обидві вхідні позиції посилаються на ту саму змінну: a=xa=x і b=xb=x. Зміна xx впливає на результат через обидві позиції, тому ми додаємо їхні внески:

dsdx=∂s∂adadx+∂s∂bdbdx=x⋅1+x⋅1=2x.\frac{ds}{dx} =\frac{\partial s}{\partial a}\frac{da}{dx} +\frac{\partial s}{\partial b}\frac{db}{dx} =x\cdot1+x\cdot1 =2x.

Похідна квадрата випливає з множення та ланцюгового правила; окреме правило для квадрата нам не знадобилося. У зворотному проході починаємо з градієнта ss, рівного 11. Кожна вхідна позиція додає значення іншого операнда до градієнта xx. При x=3x=3 ці два внески дають 3+3=63+3=6. Хоча вузол xx лише один, потрібно врахувати обидва його використання.

Те саме працює для куба. Запишемо t=x⋅xt=x\cdot x, а потім c=t⋅xc=t\cdot x. Поєднуючи похідні, отримуємо:

dcdx=xdtdx+tdxdx=x(x+x)+x2=3x2.\frac{dc}{dx} =x\frac{dt}{dx}+t\frac{dx}{dx} =x(x+x)+x^2 =3x^2.

Отже, рушій може диференціювати степені з додатними цілими показниками, записані як послідовні множення, без реалізації правила похідної степеневої функції. Інші функції потребують відповідних додаткових базових операцій: наприклад, лише множенням не можна виразити sin⁡(x)\sin(x) або довільні дробові степені. Загальний принцип — задати правила диференціювання базових операцій, а потім поєднувати ці правила для диференціювання побудованих із них функцій.

Ті самі правила можуть будувати вирази або обчислювати числа

У прикладі з квадратом ми залишили xx символом, побудували x⋅1+x⋅1x\cdot1+x\cdot1 і спростили вираз до 2x2x. Таке створення виразів для похідних називається символьним диференціюванням. Програма може автоматично будувати ці вирази, використовуючи ті самі локальні правила й залежності.

Micrograd застосовує ці правила до числових значень. При x=3x=3 початкове множення дає s=9s=9, а його зворотне правило накопичує 3+3=63+3=6 у градієнті xx. Це автоматичне диференціювання: обчислення математично еквівалентне підстановці x=3x=3 у 2x2x, хоча сама символьна формула не будується. Зворотне поширення використовує автоматичне диференціювання у зворотному режимі для обчислення градієнтів втрат, потрібних для навчання.

Обидва методи поєднують ті самі правила диференціального числення. У цьому порівнянні відрізняється те, чи будуємо ми вирази для похідних, чи виконуємо обчислення похідних над числами:

МетодІз чим працюєЩо дає
Символьне диференціюванняСимвольні вирази, зокрема іменовані проміжні виразиФормули похідних, які можна обчислити для вибраних вхідних значень
Автоматичне диференціюванняОперації програми та їхні значення для вибраних входівЧислові значення похідних, отримані поєднанням локальних похідних

Від формул похідних до виконуваних правил

У попередньому одношляховому символічному графі ми написали du/dy=2ydu/dy=2y поруч із операцією u=y2u=y^2. Ця формула також говорить нам, як обчислити похідну за допомогою арифметики: візьміть вхідне значення та помножте його на 22. У y=2y=2 результатом є 44. Це числова локальна похідна: локальна похідна, обчислена за конкретними вхідними значеннями.

Autodiff не виводить правила похідних базових операцій із самих значень і не відкриває їх символьно під час виконання. Розробник рушія задає правило для кожної базової операції, перетворюючи відому формулу похідної на код. Якщо вибрати піднесення до квадрата як базову операцію, 2y2y стає 2 * input_value. Формула пояснює правило математично, а код виконує його над числами. Для входу 2 отримуємо 4. Якщо ж реалізувати квадрат як y * y, два внески від множення дадуть той самий результат: 2 + 2 = 4.

Рушій використовує граф і ланцюгове правило для диференціювання комбінацій цих операцій. Кожне локальне правило реалізується один раз і повторно використовується щоразу, коли з’являється відповідна операція:

Робота програмиВідоме правило локальної похідноїЧисловий розрахунок
u = y ** 2du/dy=2ydu/dy=2y2 * y.data
v = x * u∂v/∂x=u\partial v/\partial x=u, ∂v/∂u=x\partial v/\partial u=xu.data, x.data
w = x ** 3dw/dx=3x2dw/dx=3x^23 * x.data ** 2
f = v + w∂f/∂v=1\partial f/\partial v=1, ∂f/∂w=1\partial f/\partial w=11, 1

Тут .data містить числове значення вузла. Похідну множення щодо uu отримують шляхом читання значення іншого операнда, xx. Двигуну не потрібно знати, як цей операнд був обчислений, щоб застосувати це локальне правило.

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

Для графа в нашому прикладі ми вибираємо окрему базову операцію піднесення до степеня, тож кожне піднесення до квадрата чи куба залишається однією операцією. Їх можна реалізувати як y.pow(2) і x.pow(3). Це вибір реалізації: послідовне множення також підходить для цих степенів. Метод pow(exponent) застосовує загальне правило похідної степеневої функції:

ddy(yn)=nyn−1\frac{d}{dy}(y^n)=ny^{n-1}

Для цілих додатних чисел, які використовуються тут, його розрахунок:

pow(exponent) {
  return new Value(
    this.data ** exponent,                         // function value
    [[this, exponent * this.data ** (exponent - 1)]] // input and local derivative
  );
}

Тут this є вхідним вузлом. Операція обчислює його вихідне значення та записує зв’язок із цим входом разом із його числовою локальною похідною. Зворотний перехід використовуватиме цю збережену похідну для поширення внеску градієнта на вхід.

Виклик y.pow(2) передає показник 22, тому локальна похідна дорівнює 2y2−1=2y2y^{2-1}=2y. Виклик x.pow(3) дає 3x3−1=3x23x^{3-1}=3x^2. Рушій отримує показник з аргументу операції, а програміст задає загальне правило диференціювання. Рушій не відкриває це правило під час виконання. Спеціалізований метод square() може використовувати те саме обчислення з показником, зафіксованим на 22.

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

Тепер ми можемо переглянути таблицю з символічного прикладу, знову дотримуючись лише y→u→vy\to u\to v із фіксованим xx, щоб обчислити ∂v/∂y\partial v/\partial y. Autodiff виконує ті самі операції з вибраними входами, тому він також обчислює їхні числові вихідні значення. Йому все ще потрібні локальні похідні, але він оцінює правила, які вже реалізовані для кожної операції, а не отримує нові формули під час виконання:

КрокНа x=3x=3, y=2y=2, з xx утримується фіксованим
Використовуйте ті самі операціїu=y2u=y^2, потім v=xuv=xu
Розрахувати значення операціїu=22=4u=2^2=4, потім v=3⋅4=12v=3\cdot4=12
Оцініть правила локальних похіднихdu/dy=2y=4du/dy=2y=4, ∂v/∂u=x=3\partial v/\partial u=x=3
Об’єднайте числові похідні за ланцюговим правилом∂v/∂y=(∂v/∂u)(du/dy)=3⋅4=12\partial v/\partial y=(\partial v/\partial u)(du/dy)=3\cdot4=12

Продовжуючи останнє додавання, ви отримаєте ∂f/∂y=1⋅12=12\partial f/\partial y=1\cdot12=12. У цій таблиці для пояснення виділено вплив одного введення. Наш символічний розрахунок поєднав 1⋅x⋅2y1\cdot x\cdot2y у формулу 2xy2xy. Autodiff оцінює окремі правила на поточних входах і натомість комбінує 1⋅3⋅41\cdot3\cdot4. Він використовує відомі правила похідної як числові інструкції, не створюючи символічну формулу похідної для всієї функції.

У наведеному нижче віджеті використовується той самий графік, що й у прикладі з одним шляхом. Перемикайтеся між Символьне диференціювання і Автоматичне диференціювання, щоб порівняти поєднання похідних виразів із поєднанням їхніх числових значень у x=3x=3 і y=2y=2.

One path from y through u and v to fHolding x constant, the derivative for y receives a contribution through one path: y → u → v → f. Multiply along this path: ∂f/∂y = 2y × x × 1 = 2xy.yu = y²du/dy = 2yxv = xu∂v/∂u = xw = x³f = v + w∂f/∂v = 1Chain rule∂f/∂y = 2y × x × 1 = 2xy

Scroll the graph sideways to see the chain-rule box.

У символьному режимі суцільні стрілки показують, як складаються функції: кожен проміжний результат стає входом для іншої операції. У режимі автоматичного диференціювання ті самі стрілки також описують прямий потік числових значень: зведення у квадрат дає u=4u=4, яке множення використовує з x=3x=3 для отримання v=12v=12. Залежності залишаються незмінними; тепер ми оцінюємо операції на конкретних входах. Цей віджет порівняння не анімує цей потік. Наведена нижче покрокова інструкція покаже ці прямі значення та зворотне поширення похідних внесків.

Обчислення операційних значень відрізняється від обчислення локальних похідних. Кожне правило похідної використовує будь-які значення, які йому потрібні: на цьому шляху правило квадрата потребує yy, а похідна множення щодо uu потребує xx. Рядки в таблиці числових обчислень описують різні завдання, а не окремі проходи: реалізація може оцінювати локальні похідні правила під час прямого або зворотного проходу. У цьому покроковому керівництві ми оцінюємо та зберігаємо їх під час проходу вперед.

Віджет порівняння відображає оцінені похідні; наступні кроки також відображатимуть передні значення. Вихід квадрата u=y2u=y^2 і його локальна похідна du/dy=2ydu/dy=2y дорівнюють 44 у y=2y=2, але це різні величини: у y=3y=3 вони будуть 99 і 66.

Обчислення формули комбінованої похідної дає той самий результат, що й оцінка локальних похідних, а потім їх об’єднання за допомогою ланцюгового правила. У (3,2)(3,2) обчислення 2xy2xy дає 1212, як і множення 4×3×14\times3\times1. Операції та їхні залежності залишаються незмінними; змінюється те, чи ми комбінуємо вирази для похідних чи числові значення.

Важливо уникати розширеної формули, оскільки багаторазова заміна проміжних виразів може зробити похідну формулу набагато більшою за вихідний вираз — проблема називається expression swell. Розгорнута формула може містити багато копій одного підвиразу, займаючи більше місця та повторюючи роботу, якщо кожна копія оцінюється окремо. Зберігання іменованих проміжних результатів дозволяє повторно використовувати ці обчислення. Символьна диференціація також може зберегти та поділитися цими виразами, тому збільшення виразу не є неминучим обмеженням методу.

Прямий і зворотний режими

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

Починаючи з одного вибраного входу, прямий режим може обчислити, як усі виходи реагують на цей вхід за один проход похідної. Починаючи з одного вибраного виходу, реверсивний режим може обчислити, як цей вихід реагує на всі вхідні дані за один зворотний прохід. Ми зосередимося на зворотному режимі, підході, який використовує зворотне поширення. Повний зворотний перехід обчислить як ∂f/∂x\partial f/\partial x, так і ∂f/∂y\partial f/\partial y, накопичуючи внески від обох шляхів до xx.

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

  • прямий перехід оцінює функцію. У цьому покроковому керівництві кожна операція обчислює своє значення та зберігає свої вхідні з’єднання та численні локальні похідні.
  • зворотний перехід починається з похідної виходу відносно самого себе, ∂f/∂f=1\partial f/\partial f=1, і використовує збережені локальні похідні для поширення числових вкладів у зворотному напрямку за допомогою ланцюгового правила. Внески на той самий вхід накопичуються.

У таблиці нижче показано, що наша передача обчислює та зберігає в x=3x=3 і y=2y=2. Тип операції визначає, яке похідне правило виконується; збережені ребра поєднують свої входи з оціненими локальними похідними:

РозрахунокВихідне значення на (x,y)=(3,2)(x,y)=(3,2)Збережені вхідні з’єднання та локальні похідні
u=y2u=y^244Вхід yy із du/dy=4du/dy=4
v=xuv=xu1212Вхід xx, з ∂v/∂x=4\partial v/\partial x=4; вхід uu, з ∂v/∂u=3\partial v/\partial u=3
w=x3w=x^32727Вхід xx із dw/dx=27dw/dx=27
f=v+wf=v+w3939Вхід vv, з ∂f/∂v=1\partial f/\partial v=1; вхід ww, з ∂f/∂w=1\partial f/\partial w=1

Вихідні значення та локальні похідні мають різні ролі. Наприклад, множення використовує u=4u=4 для обчислення результату v=12v=12, і те саме значення операнда постачає його локальну похідну щодо xx. Назад поєднує збережені локальні похідні з накопиченою чутливістю до кінцевого результату.

Модель — це програма, тому autodiff має доступ до операцій, які створили її результат; Скінченна таблиця спостережень входу-виходу сама по собі не може надати цю інформацію або визначити точні похідні. Для фіксованого навчального пакета розрахунок прогнозування та втрат моделі має багато параметрів і одне значення втрат. Зворотний режим повторно використовує проміжні результати для обчислення всіх похідних параметрів за один зворотний прохід замість повторного повного обчислення для кожного параметра.

Ми встановили, що записує механізм і як він використовує локальні похідні правила. Далі ми простежимо те саме обчислення в інтерактивному проході вперед і назад, спостерігаючи за тим, як записуються значення та накопичуються похідні внески.

Автоматичне диференціювання у зворотному режимі крок за кроком

Давайте тепер простежимо за повним обчисленням автовідмінності у зворотному режимі, використовуючи ту саму функцію f(x,y)=xy2+x3f(x,y)=xy^2+x^3 у (x,y)=(3,2)(x,y)=(3,2). Ми оцінимо чотири операції з таблиці вище, а потім прослідкуємо за їхніми похідними у зворотному напрямку, щоб отримати градієнт (31,12)(31,12):

x = Value(3)
y = Value(2)

u = y ** 2
v = x * u
w = x ** 3
f = v + w

f.backward()

Прямий прохід дає u=4u=4, v=12v=12, w=27w=27 і остаточний вихід f=39f=39. Кожен результат зберігає зв’язки з вхідними даними, які його створили, а також інформацію, необхідну для локального правила похідної. Зворотний перехід обчислює, як кінцевий результат реагує на кожен вузол; це не змінює ці передові значення.

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

Перед зворотним проходом кожен .grad починається з нуля. Ми насаджуємо f.grad = 1, тому що ∂f/∂f=1\partial f/\partial f=1.

.grad кожного скалярного вузла зберігає похідну остаточного результату щодо цього вузла. Разом x.grad і y.grad утворюють вектор градієнта (31,12)(31,12). Покрокове керівництво зберігає численні локальні похідні для з’єднань і використовує їх під час зворотного зв’язку: parent.grad += node.grad * local_derivative.

Попередній віджет порівняння дотримувався лише шляху від yy до обчислення ∂f/∂y\partial f/\partial y. Наведений нижче віджет обробляє весь графік за один зворотний прохід, обчислюючи похідні щодо xx і yy. Ці кроки відбуваються послідовно в межах одного проходу. У кожному полі окремо показано вихідне значення, чисельні локальні похідні та накопичений градієнт.

Вхідні дані фіксуються на x=3x=3 і y=2y=2, що еквівалентно створенню x = Value(3) і y = Value(2). Виберіть Обчислити прямий прохід, щоб побачити результати чотирьох операцій. Потім виберіть Задати градієнт виходу і виконайте зворотні кроки додавання, кубування, множення та зведення в квадрат. Кожен крок назад виділяє операцію та її вхідні дані, а потім з’єднує символічний вираз ланцюгового правила з його числовою заміною та відповідним оновленням .grad під графіком. Подивіться, як два внески накопичуються на xx.

The same operations, forward and backwardf(x, y) = xy² + x³
Computation graph of f = xy² + x³Start with x = 3 and y = 2, then evaluate u = y², v = xu, w = x³, and f = v + w. Local derivatives describe each operation. Each grad describes the final output’s derivative with respect to that node.yvalue 2grad —u = y²value ——grad —xvalue 3grad —v = xuvalue ———grad —w = x³value ——grad —f = v + wvalue ———grad —Chain rule∂f/∂x = —∂f/∂y = —
Stage 0 of 6. Start with x = 3 and y = 2, then evaluate u = y², v = xu, w = x³, and f = v + w.

У наведеній нижче таблиці наведено зворотні кроки, які ви можете виконувати у віджеті. Форвардні значення залишаються незмінними; змінюються лише накопичені градієнти.

Крок назадОновлення градієнта
Насінняf.grad=1\mathtt{f.grad}=1
Доповненняv.grad=f.grad⋅1=1\mathtt{v.grad}=\mathtt{f.grad}\cdot1=1, w.grad=f.grad⋅1=1\mathtt{w.grad}=\mathtt{f.grad}\cdot1=1
Кубx.grad=w.grad⋅3x2=1⋅27=27\mathtt{x.grad}=\mathtt{w.grad}\cdot3x^2=1\cdot27=27
Множення, внесок у xxДодайте v.grad⋅u=1⋅4=4\mathtt{v.grad}\cdot u=1\cdot4=4, даючи x.grad=27+4=31\mathtt{x.grad}=27+4=31
Множення, внесок у uuu.grad=v.grad⋅x=1⋅3=3\mathtt{u.grad}=\mathtt{v.grad}\cdot x=1\cdot3=3
Квадратy.grad=u.grad⋅2y=3⋅4=12\mathtt{y.grad}=\mathtt{u.grad}\cdot2y=3\cdot4=12

Два шляхи від xx вносять свій внесок окремо, а yy отримує свій внесок через uu і vv:

∂f∂x=1×27⏟through w+1×4⏟through v=31,∂f∂y=1×3×4=12\frac{\partial f}{\partial x}=\underbrace{1\times27}_{\text{through }w}+\underbrace{1\times4}_{\text{through }v}=31, \qquad \frac{\partial f}{\partial y}=1\times3\times4=12

Цей порядок обробляє гілку куба перед гілкою множення. Інші дійсні зворотні порядки дають той самий результат, за умови, що вузол отримує всі внески вниз за течією, перш ніж він передає свою накопичену похідну на свої входи.

Віджет показує повний прохід назад. Давайте тепер підключимо його кроки множення v=xuv=xu і квадрат u=y2u=y^2 до коду. Зворотний крок множення множить дві різні похідні:

∂f∂v⏟stored in v.grad×∂v∂x⏟u.data, the other operand’s value=1×4\underbrace{\frac{\partial f}{\partial v}}_{\text{stored in v.grad}} \times \underbrace{\frac{\partial v}{\partial x}}_{\text{u.data, the other operand's value}} =1\times4

Перший фактор говорить нам, як кінцевий результат ff відповідає vv. Другий показує нам, як vv реагує на xx, утримуючи uu фіксованим. Їх множення є ланцюговим правилом: воно дає внесок цього шляху в похідну відносно xx.

Покрокове керівництво зберігає численні локальні похідні під час проходу вперед. Інша реалізація може зберігати значення операндів і оцінювати ті самі локальні правила під час зворотного руху. У цій формі метод множення __mul__(self, other) створює вузол результату під назвою out, а його зворотне правило можна записати так:

self.grad += out.grad * other.data  # contribution to the left operand
other.grad += out.grad * self.data  # contribution to the right operand

Для v = x * u out — це vv, self — xx, а other — uu. Написані з цими назвами оновлення множення супроводжуються оновленням квадрата:

# Multiplication: v = x * u
x.grad += v.grad * u.data       # add 1 × 4 to the existing 27 → 31
u.grad += v.grad * x.data       # add 1 × 3 → 3

# Square: u = y ** 2
y.grad += u.grad * (2 * y.data) # add 3 × 4 → 12

Передній перехід постачає u=4u=4, x=3x=3 і y=2y=2. Множення використовує значення іншого операнда для кожної локальної похідної. Квадрат використовує 2y=42y=4 і множить його на накопичений u.grad = 3.

КодЗначення
out.gradПохідна кінцевого результату щодо результату цієї операції
other.dataЗначення іншого операнда, яке дорівнює локальній похідній для множення
+=Додайте внесок цього шляху до накопиченої похідної

other.data зберігає значення, а не похідну. Правило множення говорить, що це значення дорівнює потрібній локальній похідній. Для додавання локальна похідна дорівнює 11, тож відповідне оновлення — self.grad += out.grad * 1. Для степеня обчислюємо правило похідної степеневої функції при заданому вході: локальна похідна куба — 3x23x^2, а квадрата — 2y2y.

У символьному віджеті ми об’єднали локальні вирази для похідних вздовж шляху від yy:

∂f∂y=∂f∂v⋅∂v∂u⋅dudy=1⋅x⋅2y=2xy\frac{\partial f}{\partial y} =\frac{\partial f}{\partial v}\cdot\frac{\partial v}{\partial u}\cdot\frac{du}{dy} =1\cdot x\cdot2y =2xy

Код має ті самі з’єднання, але поєднує числа. Додавання дає v.grad = 1; множення дає u.grad = 1 × 3 = 3; квадрат дає y.grad = 3 × 4 = 12. Таким чином, u.grad вже містить перші два фактори символічного вираження. Autodiff отримує ту саму похідну без побудови комбінованої формули 2xy2xy.

Ці кроки обчислюють похідні на (3,2)(3,2); вони не оновлюють входи, щоб мінімізувати функцію. Клас Value автоматизує зворотні кроки в одному виклику f.backward().

Від обчислень до рушія

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

Щоб побачити ці ідеї, реалізовані в Python, перейдіть Покрокове керівництво до Мікрограду Андрія Карпати. Локальні похідні правила, накопичення градієнта та зворотний обхід, які ми досліджували тут, забезпечують основу для розуміння його реалізації.

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

Перегляд зображення

Змінюйте масштаб жестом щипка або клавішами + / −. Переміщуйте зображення перетягуванням або стрілками. Esc — закрити.