Говоря о глубоком обучении: как рассчитать объем памяти модели и промежуточные переменные

искусственный интеллект глубокое обучение

предисловие

Уважаемые, видеопамять вздулась, а ваша видеокарта дымит!

torch.FatalError: cuda runtime error (2) : out of memory at /opt/conda/conda-bld/pytorch_1524590031827/work/aten/src/THC/generic/THCStorage.cu:58

Предположительно, это последняя ошибка, которую хотят видеть все алхимики, но никто.

OUT OF MEMORY, очевидно, что видеопамять не может вместить столько весов модели и промежуточных переменных, сколько у вас, и тогда программа вылетает. Что делать, на самом деле способов много, своевременная очистка промежуточных переменных, оптимизация кода, уменьшение батча и т.д., позволяют снизить риск переполнения памяти.

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

Как рассчитать

Прежде всего, мы должны понять основную информацию об объеме данных:

  • 1 G = 1000 MB
  • 1 M = 1000 KB
  • 1 K = 1000 Byte
  • 1 B = 8 bit

Что ж, некоторые обязательно спросят, почему именно 1000, а не 1024. Я не буду здесь слишком много обсуждать, можно лишь сказать, что оба утверждения верны, но сценарии применения немного отличаются. Здесь расчет выполняется единообразно по вышеуказанным нормам.

Затем давайте поговорим о пространстве, занимаемом векторами, которые мы обычно используем, взяв в качестве примера официальный формат данных Pytorch (все форматы данных фреймворка глубокого обучения следуют одному стандарту):

TIM截图20180606094724

Нам нужно только посмотреть на информацию слева.В обычном обучении мы часто используем эти два типа:

  • float32 с плавающей запятой одинарной точности
  • целое число int32

Как правило, пространство, занимаемое 8-битной целочисленной переменной, равно1Bэто8bit. 32-битное число с плавающей запятой составляет4Bэто32bit. А числа двойной точности с плавающей запятой double и long integer long обычно не используются в обычном обучении.

p.s. Видеокарты потребительского класса оптимизированы для вычислений с одинарной точностью, а видеокарты серверного класса оптимизированы для вычислений с двойной точностью.

То есть, если предположить, что имеется трехканальное изображение RGB с истинным цветом, длина и ширина которого составляют 500 x 500, а тип данных — с плавающей запятой одинарной точности, то размер видеопамяти, занимаемой этим изображением составляет: 500 х 500 х 3 х 4В = 3М.

А (256,3,100,100)-(N,C,H,W) FloatTensor занимает 256 x 3 x 100 x 100 x 4B = 31M

Не так много, это не имеет значения, шоу только началось.

где память

Вроде место занимаемое картинкой (3х256х256) и свёрточным слоем (256х100х100) не большое, так почему мы всё же используем больше видеопамяти, причина очень проста, это не наше входное изображение занимает больше места в видеопамять, но промежуточные переменные в нейронной сети и огромное количество промежуточных параметров, генерируемых при использовании алгоритма оптимизатора.

Давайте сначала просто посчитаем видеопамять, которую Vgg16 net должен занимать:

Обычно занимаемая моделью видеопамять состоит из двух частей:

  • Параметры самой модели (params)
  • Промежуточные переменные (память), созданные расчетами модели

TIM截图20180607101031

Изображение взято из cs231n, типичной последовательной сети, которая очень гладкая сверху вниз Мы видим, что мы вводим трехканальное изображение 224x224x3, и мы видим, что одно изображение занимает только150x4k, но это выше150k, это связано с тем, что формат данных по умолчанию — 8-битный, а не 32-битный при расчете, поэтому окончательный результат необходимо умножить на 4.

Мы видим, что значение памяти слева представляет собой: входное изображение, пространство, занимаемое изображением, и результирующий промежуточный сверточный слой. Все мы знаем, что эти различные глубокие сверточные слои также являются процессом «мышления» глубоких нейронных сетей:

TIM截图20180607101604

Изображение изменилось с 3 каналов на 64 --> 128 --> 256 --> 512.... Это сверточные слои, и ими в основном занята наша видеопамять.

Там же справа сверху есть параметры, это веса нейросети, вы можете видеть, что первый слой свертки 3х3, и канал входного изображения 3, а выходной канал 64, так что очевидно , вес первого сверточного слоя равен занимаемому пространству (3 x 3 x 3) x 64.

Еще одна вещь, которую следует отметить, это то, что промежуточная переменная будет удваиваться при обратном направлении!

Например, ниже приведен вычислительный граф, входx, после промежуточных результатовz, затем получите окончательную переменнуюL:

TIM截图20180607103553

Нам нужно сохранить промежуточное значение при переходе назад. выводL, затем введитеx, мы запрашиваем, когда назадLправильноxГрадиент , на этот раз нужно рассчитать цепочкуLиxСерединаz:

TIM截图20180607103417

dz/dxЭто промежуточное значение, конечно, зарезервировано для расчетов, поэтому грубая оценка,backwardКогда заполняемость промежуточной переменнойforwardдважды!

Оптимизатор и импульс

Обратите внимание, что оптимизатор также занимает нашу видеопамять!

Почему, посмотрите на эту формулу:

TIM截图20180607104151

Приведенная выше формула является общей формулой типичного метода стохастического спуска SGD, а весWПри обновлении он будет генерировать и сохранять промежуточные переменныеTIM截图20180607104328, то есть при оптимизации объем видеопамяти, занимаемый параметрами params в модели, удвоится.

Конечно, это только оптимизатор SGD, другие сложные оптимизаторы будут занимать больше памяти, если им потребуется много промежуточных переменных при расчете.

Какие слои в модели будут занимать видеопамять

Слой с параметрами будет занимать слой видеопамяти. Наши общие сверточные слои будут занимать видеопамять, а активационный слой Relu, который мы часто используем, не займет ее без параметров.

Слои, занимающие видеопамять, обычно следующие:

  • Сверточный слой, обычно conv2d
  • Полностью связанный слой, также известный как линейный слой.
  • Слой BatchNorm
  • Встраиваемый слой

Видеопамять не занимает:

  • Только что упомянутый уровень активации Relu и т. д.
  • объединяющий слой
  • выпадающий слой

Конкретный метод расчета:

  • Conv2d(Cin, Cout, K): Количество параметров: Cin × Cout × K × K
  • Линейный (M->N): Количество параметров: M×N
  • BatchNorm(N): Количество параметров: 2N
  • Embedding(N,W): Количество параметров: N × W

дополнительная видеопамять

Подводя итог, можно сказать, что в нашем общем обучении занятая видеопамять условно делится на следующие категории:

  • Параметры в модели (сверточные слои или другие слои с параметрами)
  • Промежуточные параметры, генерируемые моделью во время расчета (то есть входные и выходные данные, генерируемые каждым слоем входного изображения во время расчета)
  • Дополнительные промежуточные параметры, генерируемые при обратном направлении
  • Дополнительные параметры модели, генерируемые оптимизатором во время оптимизации

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

Как оптимизировать

Оптимизация Помимо оптимизации слоя алгоритма, самая основная оптимизация — это не что иное, как следующие пункты:

  • уменьшить размер входного изображения
  • Уменьшите пакет, каждый раз уменьшайте количество входных изображений
  • Больше использования понижающей дискретизации, слоя пула
  • Некоторые слои нейронной сети могут выполнять небольшие оптимизации, используя настройки слоя relu.inplace
  • Купите видеокарту с большим объемом памяти
  • Оптимизировано из фреймворков глубокого обучения

дразни меня

  • Если вы похожи на меня, Лао Пан очень хочет с вами общаться;
  • Если вам нравится контент Лао Пана, подпишитесь и поддержите его.
  • Если вам понравилась моя статья, надеюсь, она вам понравится? Избранное ? Комментарии ? Три в ряд~

Я хочу знать, как Лао Пан научился наступать на яму, и я хочу обменяться со мной вопросами ~ Пожалуйста, обратите внимание на публичный аккаунт "старый блог". Лао Пан также организует некоторые из своих частных коллекций, надеясь помочь всем, нажмитеТаинственный порталПолучать.