Покроковий приклад автоматичної диференціації у зворотному режимі


27

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

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

Пару питань, з якими у мене найбільше труднощів:

  • насіння - навіщо вони взагалі потрібні?
  • правила зворотної диференціації - я знаю, як зробити диференціацію вперед, але як ми рухаємось назад? Наприклад, у прикладі з цього розділу , як ми можемо знати, що ?w2¯=w3¯w1
  • чи працюємо ми лише з символами чи передаємо фактичні значення ? Наприклад, у тому ж прикладі є та \ bar {w_i} ?¯ w iwiwi¯

"Ручне машинне навчання за допомогою Scikit-Learn & TensorFlow" Додаток D дає дуже гарне пояснення на мою думку. Рекомендую.
Агустін Баррачина

Відповіді:


37

Скажімо, у нас є вираз z=х1х2+гріх(х1) і хочемо знайти похідні гzгх1 та гzгх2 . AD в зворотному режимі розбиває це завдання на 2 частини, а саме передні вперед і назад.

Вперед пропуск

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

ш1=х1
ш2=х2
ш3=ш1ш2
ш4=гріх(ш1)
ш5=ш3+ш4
z=ш5

Перевага цього подання полягає в тому, що правила диференціювання для кожного окремого виразу вже відомі. Наприклад, ми знаємо, що похідна від - , і тому . Ми будемо використовувати цей факт у зворотному проході нижче.гріхcosгш4гш1=cos(ш1)

По суті, передача вперед складається з оцінки кожного з цих виразів і збереження результатів. Скажімо, наші вхідні дані: і . Тоді ми маємо:х1=2х2=3

ш1=х1=2
ш2=х2=3
ш3=ш1ш2=6
ш4=гріх(ш1) =0,9
ш5=ш3+ш4=6.9
z=ш5=6.9

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

Це були магічні старти, і це починається з правила ланцюга . У своїй основній формі ланцюгове правило зазначає, що якщо у вас є змінна яка залежить від яка, у свою чергу, залежить від , то:т(у(v))уv

гтгv=гтгугугv

або, якщо залежить від через декілька шляхів / змінних , наприклад:тvуi

у1=f(v)
у2=г(v)
т=год(у1,у2)

тоді (див. доказ тут ):

гтгv=iгтгуiгуiгv

З точки зору графіка вираження, якщо у нас є кінцевий вузол та вузли введення , а шлях від до проходить через проміжні вузли (тобто де ), ми можемо знайти похідну якzшizшiшpz=г(шp)шp=f(шi)гzгшi

гzгшi=ppаrентс(i)гzгшpгшpгшi

Іншими словами, щоб обчислити похідну змінної виведення wrt будь-яку проміжну або вхідну змінну , нам потрібно лише знати похідні її батьків і формулу для обчислення похідної від примітивного виразу .zшiшp=f(шi)

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

гzгz=1

Це може сприйматися як "зміна призводить до абсолютно такої ж зміни в ", що цілком очевидно.zz

Тоді ми знаємо, що і так:z=ш5

гzгш5=1

ш5 лінійно залежить від та , тому і . Використовуючи правило ланцюга, ми знаходимо:ш3ш4гш5гш3=1гш5гш4=1

гzгш3=гzгш5гш5гш3=1×1=1
гzгш4=гzгш5гш5гш4=1×1=1

З визначення та правил часткових похідних ми знаходимо, що . Таким чином:ш3=ш1ш2гш3гш2=ш1

dzdw2=dzdw3dw3dw2=1×w1=w1

Що, як ми вже знаємо з прямого проходу, це:

dzdw2=w1=2

Нарешті, робить внесок у через та . Ще раз з правил часткових похідних ми знаємо, що і . Таким чином:w1zw3w4гш3гш1=ш2гш4гш1=cos(ш1)

гzгш1=гzгш3гш3гш1+гzгш4гш4гш1=ш2+cos(ш1)

І знову, з огляду на відомі входи, ми можемо обчислити це:

гzгш1=ш2+cos(ш1)=3+cos(2) =2,58

Оскільки і - лише псевдоніми для та , ми отримуємо свою відповідь:ш1ш2х1х2

гzгх1=2,58
гzгх2=2

І це все!


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

  1. Похідні можуть мати набагато більшу розмірність, ніж входи або вихідні дані, наприклад, похідне від вектору wrt - це матриця, а похідне від матриці wrt - матриця - 4-мірний масив (іноді його називають тензором). У багатьох випадках такі похідні є дуже рідкими.
  2. Кожен компонент у вихідному масиві є незалежною функцією від 1 або більше компонентів вхідних масивів. Наприклад, якщо і обидва і є векторами, ніколи не залежить від , а лише від підмножини . Зокрема, це означає, що знаходження похідної зводиться до відстеження того, як залежить від .у=f(х)хууiуjхкгуiгхjуiхj

Сила автоматичної диференціації полягає в тому, що вона може мати справу зі складними структурами з мов програмування, таких як умови та цикли. Однак якщо все, що вам потрібно, це алгебраїчні вирази, і у вас є достатньо хороший фреймворк для роботи з символічними уявленнями, можливо побудувати повністю символічні вирази. Насправді, у цьому прикладі ми могли б створити вираз та обчислити цю похідну за будь-якими вхідними .гzгш1=ш2+cos(ш1)=х2+cos(х1)


1
Дуже корисне питання / відповідь. Спасибі. Просто кричуча критика: ти, здається, рухаєшся по деревній структурі, не пояснюючи це (коли ти починаєш говорити про батьків тощо)
MadHatter

1
Також не завадить з’ясувати, навіщо нам потрібно насіння.
MadHatter

@MadHatter дякую за коментар. Я спробував перефразувати пару абзаців (ці стосуються батьків), щоб підкреслити структуру графіка. Я також додав "насіння" до тексту, хоча саме це ім'я, на мою думку, може ввести в оману: у насінні AD завжди є фіксований вираз - , а не те, що ви можете вибрати чи створити. гzгz=1
подруга

Спасибі! Я помітив, коли вам потрібно встановити більше одного "насіння", як правило, один вибирає 1 і 0. Я хотів би знати чому. Я маю на увазі, один приймає "коефіцієнт" диференціальної WT, тому "1" принаймні інтуїтивно виправданий .. Але як щодо 0? А що робити, якщо треба зібрати більше 2-х насінин?
MadHatter

1
Наскільки я розумію, більше одного насіння використовується тільки в передньому режимі AD. У цьому випадку ви встановлюєте насіннєве значення 1 для вхідної змінної, яку ви хочете диференціювати, і встановлюєте насіньку 0 на всі інші вхідні змінні, щоб вони не сприяли вихідному значенню. У зворотному режимі ви встановлюєте початкову змінну виводу , і зазвичай у вас є лише одна вихідна змінна. Я здогадуюсь, ви можете побудувати конвеєр AD в зворотному режимі з кількох вихідних змінних і встановити всі вони, окрім одного до 0, щоб отримати такий же ефект, як у режимі прямого перегляду, але я ніколи не досліджував цей варіант.
подруга
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.