У сучасному світі нейронні мережі знаходять собі все більше застосувань у різних галузях науки і бізнесу. Причому чим складніше завдання, тим більш складною виходить нейромережа.
Навчання складних нейронних мереж іноді може займати дні і тижні тільки для однієї конфігурації. А щоб підібрати оптимальну конфігурацію для конкретного завдання, потрібно запустити навчання кілька разів - це може зайняти місяці обчислень навіть на дійсно потужній машині.
У якийсь момент, знайомлячись з представленим в 2015 році методом Batch Normalization від компанії Google мені, для вирішення завдання пов'язаної з розпізнаванням осіб, вдалося істотно поліпшити швидкість роботи нейромережі.
За подробицями прошу під кат.
У даній статті я постараюся поєднати два актуальні на сьогоднішній день завдання - це завдання комп'ютерного зору і машинного навчання. Як проектування архітектури нейронної мережі, як я вже і вказував, буде використовуватися Batch Normalization для прискорення навчання нейронної мережі. Навчання ж нейронної мережі (написаної з використанням популярної в рамках computer vision бібліотеки Caffe) проводилося на базі з 3 мільйонів осіб 14 тисяч різних людей.
У моєму завданні була необхідна класифікація на 14700 класів. База розбита на дві частини: тренувальна і тестова вибірки. Відома точність класифікації на тестовій вибірці: 94,5%. При цьому для цього знадобилося 420 тисяч ітерацій навчання - а це майже 4 діб (95 годин) на відеокарті NVidia Titan X.
Спочатку для даної нейромережі використовувалися деякі стандартні способи прискорення навчання:
- Збільшення learning rate
- Зменшення кількості параметрів мережі
- Зміна learning rate у процесі навчання особливим способом
Всі ці методи були застосовані до даної мережі але потім можливість їх застосовувати зійшла нанівець, тому що стала зменшуватися точність класифікації.
У цей момент я відкрив для себе новий метод прискорення нейронних мереж - Batch Normalization. Автори даного методу тестували його на стандартній мережі Inception на базі LSVRC2012 і отримали хороші результати:
З графіка і таблиці видно що мережа навчилася в 15 разів швидше і навіть досягла більш високої точності в кінцевому підсумку.
Що ж з себе представляє Batch Normalization?
Розгляньмо класичну нейронну мережу з кількома шарами. Кожен шар має безліч входів і безліч виходів. Мережа навчається методом зворотного поширення помилки, по батчах, тобто помилка вважається за якимось підмножиною навчальної вибірки.
Стандартний спосіб нормування - для кожного k розглянемо розподіл елементів батча. Віднімемо середнє і поділимо на дисперсію вибірки, отримавши розподіл з центром в 0 і дисперсією 1. Такий розподіл дозволить мережі швидше навчаться, тому що всі числа отримаються одного порядку. Але ще краще ввести дві змінні для кожної ознаки, узагальнивши нормалізацію наступним чином:
Отримаємо середнє, дисперсію. Ці параметри будуть входити в алгоритм зворотного поширення помилки.
Тим самим отримуємо batch normalization шар з 2 * k параметрами, який і будемо додавати в архітектуру запропонованої мережі для розпізнавання облич.
На вхід в моєму завданні подається чорно-біле зображення обличчя людини розміром 50x50 пікселів. На виході маємо 14000 ймовірностей класів. Клас з максимальною ймовірністю вважається результатом передбачення.
Оригінальна мережа при цьому виглядає наступним чином:
Використовується 8 згорткових шарів, кожен розмір 3x3. Після кожної згортки використовується ReLU: max(x, 0). Після блоку з двох згорток йде max-pooling з розміром комірки 2x2 (без перекриття комірок). Останній pooling шар має розмір комірки 7x7, який усереднює значення, а не бере максимум. У результаті отримується масив 1x1x320, який і подається на повносв'язний шар.
Мережа ж з Batch Normalization виглядає дещо складніше:
У новій архітектурі кожен блок з двох згорток містить шар Batch Normalization між ними. Також довелося видалити один згортковий шар з другого блоку, оскільки додавання нових шарів збільшило витрату пам'яті графічної карти.
При цьому я прибраний Dropout відповідно до рекомендацій щодо застосування BN авторів оригінальної статті.
Експериментальна оцінка
Основна метрика - точність, ділимо кількість правильно класифікованих зображень на кількість всіх зображень у тестовій вибірці.
Основна складність в оптимізації нейромережі за допомогою шару Batch Normalization - підібрати learning rate і правильно його змінювати в процесі навчання мережі. Щоб мережа сходилася швидше, початковий learning rate повинен бути більше, а потім знижуватися, щоб результат був точніше.
Було протестовано кілька варіантів зміни learning rate:
[x] - ціла частина
# iter - номер ітерації
Nsteps - кроки вказані вручну на ітераціях: 14000, 28000, 42000, 120000(x4),160000(x4), 175000, 190000, 210000.
Графік, що демонструє процес навчання: точність на тестовій вибірці залежно від кількості виконаних ітерацій навчання нейронної мережі:
Оригінальна мережа сходиться за 420000 ітерацій, при цьому learning rate за весь час змінюється тільки 2 рази на 150000-ій ітерації і на 300000-ій. Такий підхід був запропонований автором оригінальної мережі, і мої експерименти з цією мережею показали, що цей підхід оптимальний.
Але якщо присутній шар Batch Normalization, такий підхід дає погані результати - графік long_step. Тому моєю ідеєю було - на початковій стадії міняти learning rate плавно, а потім зробити кілька стрибків (графік multistep_no_dropout). Графік short_step показує, що просто плавна зміна learing rate працює гірше. По суті тут я спираюся на рекомендації статті і намагаюся їх застосувати до оригінального підходу.
У результаті експериментів я прийшов до висновку, що прискорити навчання можна, але точність у будь-якому випадку буде трохи гірше. Можна порівняти завдання розпізнавання облич із завданням розглянутим у статтях Inception (Inception-v3, Inception-v4): автори статті порівнювали результати класифікації для різних архітектур і з'ясувалося, що все-таки Inception-BN поступається новим версіям Inception без використання Batch Normalization. У нашому завданні виходить така ж проблема. Але все-таки якщо стоїть завдання якомога швидше отримати прийнятну точність, то BN якраз може допомогти: щоб досягти точності 80% потрібно в 1,4 рази менше часу порівняно з оригінальною мережею (45000 ітерацій проти 64000). Це можна використовувати, наприклад, для проектування нових мереж і підбору параметрів.
Програмна реалізація
Як я вже писав, у моїй роботі використовується Caffe - зручний інструмент для глибинного навчання. Все реалізовано на C++ і CUDA, що забезпечує оптимальне використання ресурсів комп'ютера. Для даного завдання це особливо актуально, оскільки якби програма була написана не оптимально не було б сенсу прискорювати навчання за допомогою зміни архітектури мережі.
Caffe має модульність - є можливість підключити будь-який нейросетевий шар. Для шару Batch Normalization вдалося знайти 3 реалізації:
- BatchNorm в оригінальному caffe (від 25 лютого 2015)
- BN в caffe windows (від 31 березня 2015)
- BatchNorm в CUDNN (від 24 листопада 2015)
Для швидкого порівняння цих реалізацій я взяв стандартну базу Cifar10 і тестував все під операційною системою Linux x64, використовуючи відеокарту NVidia GeForce 740M (2GB), процесор (4 ядра) Intel^ Core (TM) i5-4200U CPU @ 1.60GHz і 4GB RAM.
Реалізацію від caffe windows вбудував у стандартний caffe, оскільки тестував під Linux.
На графіку видно, що 1-а реалізація поступається 2-ій і 3-ій за точністю, крім цього в 1-му і 2-му випадках точність передбачення змінюється стрибками від ітерації до ітерації (у першому випадку стрибки набагато сильніші). Тому для завдання розпізнавання облич обрана саме 3-я реалізація (від NVidia) як більш стабільна і більш нова.
Дані модифікації нейромережі за допомогою додавання шарів Batch Normalization показують, що для досягнення прийнятної точності (80%) буде потрібно в 1,4 рази менше часу.