Как рассчитать влияние мини-партии памяти на тренировку моделей глубокого обучения?

17

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

Моя сеть имеет 532 752 активаций и 19 072 984 параметров (весов и смещений). Все это 32-битные значения с плавающей запятой, поэтому каждое занимает 4 байта в памяти.

Мое входное изображение 180x50x1 (ширина x высота x глубина) = 9 000 значений с плавающей запятой 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 изображений / мини-пакет.

Можете ли вы помочь мне понять особенности памяти для обучения моей модели глубокого обучения? Правильны ли вышеуказанные соображения?

barbolo
источник
Пожалуйста, смотрите мой (предлагаемый) ответ на ваш вопрос здесь .
Адам Хендри

Ответы:

5

Я думаю, что вы на правильном пути.

Да, вам нужно будет хранить производные активаций и параметров для обратного распространения.

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

В общем, вы, похоже, рассчитали требования к памяти для прямого прохода. Андрей Карпати упоминает, что обратный проход может в 3 раза увеличить память о прямом проходе, поэтому, возможно, именно поэтому вы видите такую ​​разницу (прокрутите вниз до раздела «Практические примеры» на веб-сайте, чтобы увидеть пример для VGGNet).

StatsSorceress
источник
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 МБ

( Кто-то, пожалуйста, поправьте меня, если я ошибаюсь. К вашему сведению, вы уже умножили разное на 128, поэтому я не умножил его на 128 выше )


Я хотел бы указать вам на эту статью и соответствующее видео . Они помогли мне понять, что происходит намного лучше.

ПРИМЕЧАНИЕ . Память, необходимая для использования сети для прогнозов, намного меньше, чем для обучения, по двум причинам:

  • При прогнозировании мы отправляем изображение только через сеть, а не назад (поэтому мы не умножаем память X 3; см. Ниже)
  • Для каждого изображения существует один прогноз (поэтому нам не нужно умножать объем памяти, требуемый для одного изображения, на размер пакета, потому что мы не используем пакеты в прогнозе).

Процесс (память на тренировку)

  1. Рассчитать память, необходимую для тренировки на одном изображении
  2. Умножьте это число на количество изображений в вашей партии

( ПОМНИТЕ: мини-пакетирование говорит, что мы берем подмножество наших данных, вычисляем градиенты и ошибки для каждого изображения в подмножестве, затем усредняем их и делаем шаг вперед в направлении среднего. Для коннетов весовые коэффициенты и уклоны являются общими, но количество активаций умножается на количество изображений в пакете. )

ШАГ 1: Память на 1 изображение

Чтобы обучить одно изображение, вы должны зарезервировать память для:

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

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

    Чтобы приблизить для этого объем памяти, рассчитайте объем памяти, необходимый для хранения весов и смещений, и умножьте ее на 3 (т. Е. «На 3», поскольку мы говорим, что объем памяти, необходимый для хранения весов и смещений, (приблизительно) равен что нужно для градиентов и для переменных импульса)

    УРАВНЕНИЯ:

    сверток:

    весовые коэффициенты (n) = глубина (n) * (kernel_width * kernel_height) * глубина (n-1)

    уклоны (n) = глубина (n)

    Полностью связанные (плотные) слои:

    веса (n) = выходы (n) * входы (n)

    смещения (n) = выходы (n)

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

ПРИМЕЧАНИЕ . Память только для весов и смещений плюс память для активаций для одного изображения (см. Ниже) - это общий объем памяти, необходимый для предсказаний (исключая некоторые накладные расходы на память для сверток и некоторые другие вещи).

  • Активации (это «Blobs» в Caffe):

(Я использую термины здесь, терпите меня)

Каждая свертка в слое свертки производит активации « количество пикселей в изображении » (т.е. вы пропускаете изображение через одну свертку, вы получаете одну карту объектов, состоящую из активаций « m », где « m » - это количество пикселей от вашего изображение / вход).

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

сверток:

активаций (n) = ширина изображения * высота изображения * изображение_канала

Полностью связанные (плотные) слои:

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

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

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

ШАГ 2: Память для обучения партии

Суммируйте количество весов и смещений (3 раза) и количество активаций (2 раза больше размера партии). Умножьте это на 4, и вы получите количество байтов, необходимое для обучения пакета. Вы можете разделить на 1024 ^ 2, чтобы получить ответ в ГБ.

Адам Хендри
источник
Почему вы говорите «мы не используем партии в прогнозировании»? Если пользователю необходимо делать прогнозы для большого количества изображений, тогда имеет смысл использовать пакеты в прогнозах.
user3731622
1

В качестве альтернативы, я думаю, вы можете использовать любую библиотеку профилировщика для анализа использования памяти и процессора вашей программой. Существует множество библиотек python, которые могут дать вам снимок памяти и использования процессора конкретным потоком или процессом с интервалом в миллисекунды.

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

Псутил я нахожу хороших для такой работы. Хотя есть много других.

Я надеюсь, это поможет.

EngineeredBrain
источник
3
Спасибо за ответ, @Anwar. Я ищу аналитический расчет, а не эмпирическое наблюдение.
Барболо