Як обчислити вплив міні-пакетної пам'яті при навчанні моделей глибокого навчання?


17

Я намагаюся обчислити об'єм пам'яті, необхідний GPU для підготовки моєї моделі на основі цієї замітки Андрія Карфати: http://cs231n.github.io/convolutional-networks/#computational-considerations

Моя мережа має 532,752 активації та 19,072,984 параметрів (ваги та ухили). Це всі 32-бітні значення поплавків, тому кожен займає 4 байти в пам'яті.

Моє вхідне зображення - 180х50х1 (ширина х висота х глибина) = 9000 поплавків 32 значення. Я не використовую збільшення зображень, тому думаю, що інша пам'ять буде пов'язана лише з розміром міні-партії. Я використовую міні-серію розміром 128 зображень.

На основі рекомендації Андрія я отримую такі розміри пам'яті:

Активації: 532,752 * 4 / (1024 ^ 2) = 2,03 МБ

Параметри: 19,072,984 * 4 / (1024 ^ 2) * 3 = 218,27 Мб

Інше: 128 * 9000 * 4 / (1024 ^ 2) = 4,39 Мб

Тож загальна пам'ять для тренування цієї мережі склала б 224,69 Мб .

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

Якщо для кожного зображення в міні-партії TensorFlow зберігає їх градієнти, щоб він міг нормалізувати їх пізніше для одного кроку оновлення ваг / зміщення, то, я думаю, пам'ять повинна враховувати ще 532,752 * 128 значення (градієнти для кожного зображення в міні-партія). Якщо це так, то мені знадобиться більше 260,13 Мб для підготовки цієї моделі із 128 зображеннями / міні-партією.

Чи можете ви допомогти мені зрозуміти міркування щодо пам’яті для навчання моєї моделі глибокого навчання? Чи правильно вказані вище міркування?


Будь ласка, дивіться мою (запропоновану) відповідь на ваше запитання тут .
Адам Хендрі

Відповіді:


5

Я думаю, ти на правильному шляху.

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

Крім того, ваш вибір оптимізації може мати значення. Ви тренуєтесь за допомогою SGD, або Адама, або Адаграда? Всі вони матимуть різні вимоги до пам'яті. Наприклад, вам доведеться зберігати кеш розміру кроків для методу на основі імпульсу, хоча це має бути вторинним порівняно з іншими міркуваннями пам'яті, які ви згадуєте.

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


5

@StatsSorceress TL; DR:

Я проходжу цю діяльність, щоб побачити, чи можу я обчислити потрібну пам'ять:

Активації: 532,752 * 2 * 4 / (1024 ^ 2) = 4,06 МБ

Параметри: 19,072,984 * 4 / (1024 ^ 2) * 3 = 218,27 Мб

Інше: 128 * 9000 * 4 / (1024 ^ 2) = 4,39 Мб

Загальна пам'ять: (4,06 * 128 ) + 218,27 + 4,39 = 742,34 Мб

( Хтось, будь ласка, виправте мене з цього приводу, якщо я помиляюся. FYI, ви вже помножили різне на 128, тому я не помножив його на 128 вище )


Я хотів би вказати на цю статтю та відповідне відео . Вони допомогли мені зрозуміти, що відбувається набагато краще.

ПРИМІТКА . Пам'ять, необхідна для використання мережі для прогнозування, набагато менша, ніж потрібна для навчання з двох причин:

  • Під час прогнозування ми надсилаємо зображення лише вперед через мережу, а не назад (тому ми не примножуємо пам'ять X 3; див. Нижче)
  • Є одне передбачення на зображення (тому нам не потрібно примножувати пам'ять, необхідну для одного зображення, на розмір партії, оскільки ми не використовуємо партії для прогнозування).

Процес (пам'ять для поїзду)

  1. Обчисліть пам'ять, необхідну для тренування на одному зображенні
  2. Помножте це число на кількість зображень у вашій партії

( ПАМ'ЯТАЙТЕ: Міні-партія говорить, що ми беремо підмножину наших даних, обчислюємо градієнти та помилки для кожного зображення в підмножині, потім середнє значення і крокуємо вперед у напрямку середнього. Для конвентів, ваги та ухили поділяються, але кількість активацій змішується з кількістю зображень у партії. ).

КРОК 1: Пам'ять для 1 зображення

Для тренування одного зображення потрібно резервувати пам'ять для:

  • Параметри моделі:

    Ці ваги і зміщує на кожному шарі, а також їх градієнтів , і їх величини імпульсу (якщо Адам, Adagrad, RMSProp і т.д., оптимізатори використовуються)

    Щоб наблизити пам'ять до цього, обчисліть об'єм пам'яті, необхідної для зберігання ваг і ухилів, і помножте її на 3 (тобто "на 3", тому що ми говоримо, що об'єм пам'яті, необхідний для зберігання ваг і ухилів, приблизно (приблизно) дорівнює необхідні для градієнтів та змінних імпульсів)

    РІВНЯННЯ:

    Звитки:

    ваги (n) = глибина (n) * (ширина ядра * висота ядра) * глибина (n-1)

    зміщення (n) = глибина (n)

    Повністю з'єднані (щільні) шари:

    ваги (n) = виходи (n) * входи (n)

    зміщення (n) = виходи (n)

де n - поточний шар, а n-1 - попередній шар, а виходи - це кількість виходів із рівня FC, а входи - це кількість входів у рівень FC (якщо попередній шар не є повністю пов'язаним шаром, кількість входів дорівнює розміру цього шару, вирівняного).

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

  • Активації (це "краплі" в Caffe):

(Тут я вільно використовую терміни, майте на собі)

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

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

Звитки:

активації (n) = image_width * image_height * image_num_channels

Повністю з'єднані (щільні) шари:

активації (n) = виходи (n)

Зауважте, що ваш вхід - це лише зображення на початку мережі. Після згортків він перетворюється на щось інше (карти зображень). Тож дійсно замініть "image_width", "image_height" та "image_num_channels" на "input_width", "input_height" та "layer_depth", щоб бути точнішими. (Мені просто простіше думати про цю концепцію з точки зору зображень.)

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

КРОК 2: Пам'ять для тренування партії

Підсумовуйте кількість ваг і ухилів (3 рази) та кількість активацій (в 2 рази більший розмір партії). Помножте це на 4, і ви отримаєте кількість байтів, необхідних для тренування партії. Ви можете поділити на 1024 ^ 2, щоб отримати відповідь у ГБ.


Чому ви говорите "ми не використовуємо партії в передбаченні"? Якщо користувачеві потрібно робити прогнози на велику кількість зображень, то може мати сенс використовувати партії в прогнозах.
користувач3731622

1

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

Ви можете запустити частину програми, яку ви хочете контролювати, в іншому підпроцесі, використовуючи popen, і відслідковуйте її пам'ять та використання процесора, використовуючи PID.

psutil Я вважаю хорошим для такої роботи. Хоча є багато інших.

Сподіваюся, це допоможе.


3
Дякую за відповідь, @Anwar. Я шукаю аналітичний розрахунок, а не емпіричне спостереження.
barbolo
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.