Рецепт навчання нейронних мереж

Кілька тижнів тому я опублікував твіт на тему "Найпоширеніші помилки нейронних мереж", перерахувавши кілька загальних припущень, пов'язаних з тренуванням нейронних мереж. Твіт отримав трохи більше залучення, ніж я передбачав (включаючи веб-семінар:)). Зрозуміло, що багато людей особисто стикалися з великим розривом між "ось як працює згортковий шар" і "наш конвент досягає найсучасніших результатів".

нейронних

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

1) Тренування нейронних мереж - це дірява абстракція

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

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

Круто! Сміливий розробник взяв на себе тягар розуміння рядків запитів, URL-адрес, запитів GET/POST, HTTP-з'єднань тощо, і багато в чому приховав складність за кількома рядками коду. Це те, що ми знайомі і очікуємо. На жаль, нейронні мережі не є нічим подібним. Вони не є “готовою” технологією, коли ви трохи відхиляєтесь від навчання класифікатора ImageNet. Я намагався зробити це в своєму дописі "Так, ви повинні розуміти зворотний зв’язок", вибравши зворотне розмноження і назвавши його "дірявою абстракцією", але, на жаль, ситуація набагато важча. Backprop + SGD магічно не змушує вашу мережу працювати. Норма партії магічним чином не змушує її сходитися швидше. RNN магічним чином не дозволяють "підключати" текст. І те, що ви можете сформулювати свою проблему так, як RL, не означає, що ви повинні це робити. Якщо ви наполягаєте на використанні технології, не розуміючи, як вона працює, ви, ймовірно, зазнаєте невдачі. Що призводить мене до ...

2) Тренування нейронних мереж не вдається безшумно

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

Це лише початок, коли справа стосується тренування нейронних мереж. Усе може бути синтаксично правильним, але все це не впорядковано належним чином, і це насправді важко сказати. „Можлива поверхня помилки” велика, логічна (на відміну від синтаксичної) і дуже складна для модульного тесту. Наприклад, можливо, ви забули перевернути ярлики, коли перегортали зображення вліво-вправо під час збільшення даних. Ваша мережа все ще може (шокуюче) працювати досить добре, тому що ваша мережа може внутрішньо навчитися виявляти перевернуті зображення, а потім перевертає свої прогнози вліво-вправо. Або, можливо, ваша авторегресивна модель випадково сприймає те, що вона намагається передбачити, як вхідну інформацію через непомітну помилку. Або ви намагалися обрізати свої градієнти, але замість цього перерізали втрату, спричиняючи ігнорування прикладів, що відкидаються, під час навчання. Або ви ініціалізували свої ваги з попередньо підготовленого контрольно-пропускного пункту, але не використовували початкове значення. Або ви просто зіпсували налаштування для потужностей регуляризації, швидкості навчання, швидкості затухання, розміру моделі тощо. Тому ваша неправильно налаштована нейронна мережа видасть винятки, лише якщо вам пощастить; Здебільшого він тренується, але мовчки працює трохи гірше.

Як результат, (а це надто важко переоцінити) «швидкий і лютий» підхід до навчання нейронних мереж не працює і призводить лише до страждань. Зараз страждання є цілком природною частиною того, щоб нейронна мережа працювала добре, але її можна пом'якшити, якщо бути ретельною, захисною, параноїчною та одержимою візуалізацією практично всіх можливих речей. Якість, яка на моєму досвіді найбільше корелює з успіхом у глибокому навчанні, - це терпіння та увага до деталей.

Рецепт

У світлі вищезазначених двох фактів, я розробив для себе конкретний процес, якого я дотримуюсь, застосовуючи нейронну мережу до нової проблеми, який я спробую описати. Ви побачите, що ці два принципи сприймаються дуже серйозно. Зокрема, він будується від простого до складного і на кожному кроці ми висуваємо конкретні гіпотези про те, що станеться, а потім або перевіряємо їх експериментом, або досліджуємо, поки не знайдемо певної проблеми. Що ми намагаємось запобігти дуже важко - це введення багато «неперевіреної» складності відразу, що обов’язково приведе до помилок/неправильних конфігурацій, які знадобляться назавжди (якщо коли-небудь). Якщо написання коду нейронної мережі було подібним до тренувального, ви хочете використовувати дуже малу швидкість навчання і вгадувати, а потім оцінювати повний набір тестів після кожної ітерації.