Я пытаюсь вычислить объем памяти, необходимый графическому процессору для обучения моей модели, на основе этих заметок от Андрея Карфати: 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 изображений / мини-пакет.
Можете ли вы помочь мне понять особенности памяти для обучения моей модели глубокого обучения? Правильны ли вышеуказанные соображения?
источник
Ответы:
Я думаю, что вы на правильном пути.
Да, вам нужно будет хранить производные активаций и параметров для обратного распространения.
Кроме того, ваш выбор оптимизации может иметь значение. Вы тренируетесь, используя SGD, или Адама, или Адаграда? Все они будут иметь разные требования к памяти. Например, вам нужно будет сохранить кэш размера шага для метода, основанного на импульсе, хотя это должно быть вторично по сравнению с другими упомянутыми вами соображениями, касающимися памяти.
В общем, вы, похоже, рассчитали требования к памяти для прямого прохода. Андрей Карпати упоминает, что обратный проход может в 3 раза увеличить память о прямом проходе, поэтому, возможно, именно поэтому вы видите такую разницу (прокрутите вниз до раздела «Практические примеры» на веб-сайте, чтобы увидеть пример для VGGNet).
источник
@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 выше )
Я хотел бы указать вам на эту статью и соответствующее видео . Они помогли мне понять, что происходит намного лучше.
ПРИМЕЧАНИЕ . Память, необходимая для использования сети для прогнозов, намного меньше, чем для обучения, по двум причинам:
Процесс (память на тренировку)
( ПОМНИТЕ: мини-пакетирование говорит, что мы берем подмножество наших данных, вычисляем градиенты и ошибки для каждого изображения в подмножестве, затем усредняем их и делаем шаг вперед в направлении среднего. Для коннетов весовые коэффициенты и уклоны являются общими, но количество активаций умножается на количество изображений в пакете. )
ШАГ 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 (если предыдущий уровень не является полностью подключенным уровнем, количество входов равно размеру сплющенного слоя).
ПРИМЕЧАНИЕ . Память только для весов и смещений плюс память для активаций для одного изображения (см. Ниже) - это общий объем памяти, необходимый для предсказаний (исключая некоторые накладные расходы на память для сверток и некоторые другие вещи).
(Я использую термины здесь, терпите меня)
Каждая свертка в слое свертки производит активации « количество пикселей в изображении » (т.е. вы пропускаете изображение через одну свертку, вы получаете одну карту объектов, состоящую из активаций « 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, чтобы получить ответ в ГБ.
источник
В качестве альтернативы, я думаю, вы можете использовать любую библиотеку профилировщика для анализа использования памяти и процессора вашей программой. Существует множество библиотек python, которые могут дать вам снимок памяти и использования процессора конкретным потоком или процессом с интервалом в миллисекунды.
Вы можете запустить ту часть вашей программы, которую хотите отслеживать, в другом подпроцессе, используя popen, и отслеживать использование памяти и процессора, используя его PID.
Псутил я нахожу хороших для такой работы. Хотя есть много других.
Я надеюсь, это поможет.
источник