Я подумав, що відповім на автономний пост для всіх, хто цікавиться. Для цього буде використано описані тут позначення .
Вступ
Ідея заднього розмноження полягає в тому, щоб мати набір "прикладів навчання", які ми використовуємо для тренування нашої мережі. Кожен із них має відому відповідь, тому ми можемо підключити їх до нейронної мережі та виявити, наскільки це було неправильно.
Наприклад, з розпізнаванням рукописного тексту у вас було б багато рукописних символів поряд із тим, якими вони були насправді. Тоді нейронну мережу можна навчити за допомогою зворотного розповсюдження, щоб "навчитися" розпізнавати кожен символ, і тоді, коли він пізніше буде представлений невідомим рукописним символом, він зможе визначити, що це правильно.
Зокрема, ми вводимо якийсь зразок тренінгу в нейронну мережу, бачимо, наскільки це було добре, потім "прокручуємося назад", щоб знайти, наскільки ми можемо змінити ваги та зміщення кожного вузла для отримання кращого результату, а потім відрегулювати їх відповідно. Поки ми продовжуємо це робити, мережа "вчиться".
Існують також інші кроки, які можуть бути включені в навчальний процес (наприклад, випадання), але я зосередитимусь переважно на зворотному розповсюдженні, оскільки саме в цьому питанні йшлося.
Часткові похідні
Часткова похідна є похідною відносно деякої змінної .∂f∂xfx
Наприклад, якщо , , тому що просто константа щодо . Так само , тому що - просто константа відносно .∂ ff(x,y)=x2+y2y2x∂f∂f∂x=2xy2xx2y∂f∂y=2yx2y
Градієнт функції, позначений , - це функція, що містить часткову похідну для кожної змінної у f. Конкретно:∇f
∇f(v1,v2,...,vn)=∂f∂v1e1+⋯+∂f∂vnen
,
де - одиничний вектор, що вказує у напрямку змінної .eiv1
Тепер, коли ми обчислили для деякої функції , якщо ми знаходимось у положенні , ми можемо "ковзати вниз" , рухаючись у напрямку .F ( v 1 , v 2 , . . . , V п ) е - ∇ F ( V 1 , V 2 , . . . , V п )∇ff(v1,v2,...,vn)f−∇f(v1,v2,...,vn)
З нашим прикладом , одиничними векторами є і , тому що і , і ті вектори вказують у напрямку осей і . Таким чином, .e 1 = ( 1 , 0 ) e 2 = ( 0 , 1 ) v 1 = x v 2 = y x y ∇ f ( x , y ) = 2 x ( 1 , 0 ) + 2 у ( 0 , 1 )f(x,y)=x2+y2e1=(1,0)e2=(0,1)v1=xv2=yxy∇f(x,y)=2x(1,0)+2y(0,1)
Тепер, щоб "ковзати вниз" нашу функцію , скажімо, ми знаходимося в точці . Тоді нам потрібно би рухатись у напрямку .( - 2 , 4 ) - ∇ f ( - 2 , - 4 ) = - ( 2 ⋅ - 2 ⋅ ( 1 , 0 ) + 2 ⋅ 4 ⋅ ( 0 , 1 ) ) = - ( ( - 4 , 0 ) + ( 0 , 8 ) ) = ( 4 ,f(−2,4)−∇f(−2,−4)=−(2⋅−2⋅(1,0)+2⋅4⋅(0,1))=−((−4,0)+(0,8))=(4,−8)
Величина цього вектора дасть нам наскільки крутий пагорб (більші значення означають, що пагорб крутіший). У цьому випадку маємо .42+(−8)2−−−−−−−−−√≈8.944
Продукт Адамара
Добуток Адамара з двох матриць подібно до додавання матриць, за винятком того, що замість того, щоб додати матриці елементарно, ми помножимо їх на елементи.A,B∈Rn×m
Формально, в той час як додавання матриць - , де такий, щоC ∈ R n × mA+B=CC∈Rn×m
Cij=Aij+Bij
,
Продукт Адамара , де такий, щоC ∈ R n × mA⊙B=CC∈Rn×m
Cij=Aij⋅Bij
Обчислення градієнтів
(більша частина цього розділу - з книги Нілсена ).
У нас є набір навчальних зразків , де є єдиним вхідним навчальним зразком, а - очікуваним вихідним значенням цього навчального зразка. Ми також маємо нашу нейронну мережу, що складається з пристрастей і ваги . використовується для запобігання плутанини з , та використовується у визначенні мережі подачі.(S,E)SrErWBrijk
Далі ми визначаємо функцію витрат яка бере нашу нейронну мережу і єдиний приклад навчання, і виводить, як добре це зробило.C(W,B,Sr,Er)
Зазвичай застосовується квадратична вартість, яка визначається
C(W,B,Sr,Er)=0.5∑j(aLj−Erj)2
де - вихід на нашу нейронну мережу, заданий вхідний зразокaLSr
Тоді ми хочемо знайти і для кожного вузла в нашій нейронній мережі подачі.∂C∂wij∂C∂bij
Ми можемо назвати це градієнтом на кожному нейроні, оскільки вважаємо і константами, оскільки ми не можемо їх змінити, коли ми намагаємося навчитися. І це має сенс - ми хочемо рухатись у напрямку відносно і що мінімізує витрати, і переміщення в негативному напрямку градієнта щодо і зробить це.CSrErWBWB
Для цього ми визначаємо як помилку нейрона у шарі .δij=∂C∂zijji
Почнемо з обчислення , включивши у нашу нейронну мережу.aLSr
Тоді ми обчислюємо помилку нашого вихідного шару черезδL
δLj=∂C∂aLjσ′(zLj)
.
Що також можна записати як
δL=∇aC⊙σ′(zL)
.
Далі ми знаходимо помилку з точки зору помилки в наступному шарі , черезδiδi+1
δi=((Wi+1)Tδi+1)⊙σ′(zi)
Тепер, коли ми маємо помилку кожного вузла в нашій нейронній мережі, обчислити градієнт по відношенню до наших ваг і ухилів легко:
∂C∂wijk=δijai−1k=δi(ai−1)T
∂C∂bij=δij
Зауважимо, що рівняння помилки вихідного шару є єдиним рівнянням, яке залежить від функції витрат, тому незалежно від функції витрат останні три рівняння однакові.
Як приклад, з квадратичною вартістю, ми отримуємо
δL=(aL−Er)⊙σ′(zL)
для помилки вихідного шару. а потім це рівняння можна підключити до другого рівняння, щоб отримати помилку шару :L−1th
δL−1=((WL)TδL)⊙σ′(zL−1)
=((WL)T((aL−Er)⊙σ′(zL)))⊙σ′(zL−1)
які ми можемо повторити цей процес , щоб знайти помилку будь-якого шару щодо , який потім дозволяє обчислювати градієнт ваг і зсуву будь-якого вузла по відношенню до .CC
Я міг би писати пояснення і доказ цих рівнянь , при бажанні, хоча можна також знайти докази їх тут . Я б закликав усіх, хто це читає, довести це самі, хоча, починаючи з визначення і застосовуючи правило ланцюга вільно.δij=∂C∂zij
Для ще кілька прикладів, я зробив список деяких функцій витрат поряд з їх градієнтів тут .
Спуск градієнта
Тепер, коли у нас є ці градієнти, нам потрібно використовувати їх для вивчення. У попередньому розділі ми з'ясували, як рухатись до "ковзання" кривої відносно деякої точки. У цьому випадку, оскільки це градієнт деякого вузла щодо ваг та зміщення цього вузла, наша "координата" - це поточні ваги та зміщення цього вузла. Оскільки ми вже знайшли градієнти щодо цих координат, ці значення вже є тим, скільки нам потрібно змінити.
Ми не хочемо ковзати по схилу з дуже швидкою швидкістю, інакше ризикуємо ковзати повз мінімум. Щоб цього не допустити, ми хочемо мати деякий "крок розміру" .η
Тоді знайдіть, наскільки нам слід змінити кожну вагу і зміщення на, тому що ми вже обчислили градієнт відносно струму, який маємо
Δwijk=−η∂C∂wijk
Δbij=−η∂C∂bij
Таким чином, наші нові ваги та ухили є
wijk=wijk+Δwijk
bij=bij+Δbij
Використання цього процесу в нейронній мережі з лише вхідним шаром і вихідним шаром називається правилом Delta .
Стохастичний градієнт спуск
Тепер, коли ми знаємо, як виконати розмноження для одного зразка, нам потрібен певний спосіб використання цього процесу, щоб "вивчити" весь наш навчальний набір.
Один із варіантів - просто виконати розмноження для кожного зразка в наших навчальних даних, по одному. Однак це досить неефективно.
Кращим підходом є стохастичний градієнтний спуск . Замість того, щоб проводити зворотне розмноження для кожного зразка, ми вибираємо невеликий випадковий зразок (який називається партією ) нашого навчального набору, а потім виконуємо зворотне розмноження для кожного зразка в цій партії. Сподіваємося, що, виконуючи це, ми фіксуємо "наміри" набору даних, не вичисляючи градієнта кожного зразка.
Наприклад, якщо у нас було 1000 зразків, ми могли вибрати партію розміром 50, а потім запустити зворотне розмноження для кожного зразка цієї партії. Сподіваємось, що нам було надано достатньо великий навчальний набір, що він відображає розподіл фактичних даних, які ми намагаємось засвоїти досить добре, що вибір невеликої випадкової вибірки є достатнім для збору цієї інформації.
Однак робити зворотне розповсюдження для кожного прикладу тренувань у нашій міні-партії не ідеально, тому що ми можемо в кінцевому підсумку "хитатися навколо", коли зразки тренувань змінюють ваги та зміщення таким чином, що вони скасовують один одного і не дають їм потрапити на мінімум, до якого ми намагаємося досягти.
Щоб цього не допустити, ми хочемо перейти до «середнього мінімуму», оскільки сподіваємось, що в середньому градієнти зразків спрямовані вниз по схилу. Отже, вибираючи нашу партію випадковим чином, ми створюємо міні-партію, яка є невеликою випадковою вибіркою нашої партії. Потім, даючи міні-партію з навчальних зразків, і оновлюйте ваги і зміщення лише після усереднення градієнтів кожного зразка в міні-партії.n
Формально ми це робимо
Δwijk=1n∑rΔwrijk
і
Δbij=1n∑rΔbrij
де - обчислена зміна ваги для зразка , а - обчислена зміна зміщення зразка .ΔwrijkrΔbrijr
Тоді, як і раніше, ми можемо оновлювати ваги та ухили за допомогою:
wijk=wijk+Δwijk
bij=bij+Δbij
Це дає нам деяку гнучкість у тому, як ми хочемо виконувати спуск градієнта. Якщо у нас є функція, яку ми намагаємося навчитися з великою кількістю місцевих мінімумів, це поведінка "хитання навколо" насправді бажана, оскільки це означає, що ми набагато рідше "застряємо" в одному локальному мінімумі, і, швидше за все, "вискочити" з одного локального мінімуму і, сподіваємось, потрапити в інший, який ближче до глобальних мінімумів. Таким чином ми хочемо невеликі міні-партії.
З іншого боку, якщо ми знаємо, що місцевих мінімумів дуже мало, і в основному спуск градієнта йде в напрямку глобальних мінімумів, ми хочемо великих міні-партій, тому що така поведінка «хитання навколо» заважатиме нам так швидко спускатися зі схилу як хотілося б. Дивіться тут .
Один із варіантів - вибрати найбільшу можливу міні-партію, розглядаючи всю партію як одну міні-партію. Це називається Batch Gradient Descent , оскільки ми просто усереднюємо градієнти партії. Однак це практично ніколи не застосовується на практиці, оскільки це дуже неефективно.