Как рассчитать оптимальный размер партии
Иногда я сталкиваюсь с проблемой:
ООМ при выделении тензора с формой
уравнение
ООМ при выделении тензора с формой (1024, 100, 160)
Где 1024 - размер моей партии, а я не знаю, что остальное. Если я уменьшу размер партии или количество нейронов в модели, она будет работать нормально.
Существует ли общий способ расчета оптимального размера пакета на основе модели и памяти графического процессора, чтобы программа не вылетала?
РЕДАКТИРОВАТЬ
Поскольку мой вопрос может показаться неясным, позвольте мне сказать по-своему: я хочу максимально возможный размер пакета с точки зрения моей модели, который поместится в моей памяти GPU и не приведет к сбою программы.
РЕДАКТИРОВАТЬ 2
Тем, кто голосовал за закрытие вопроса за его слишком широкость: Насколько этот вопрос слишком широк? Существует некоторый алгоритм, который выбирает часть данных для помещения в память графического процессора. Это явно несовершенно, поскольку данные иногда превышают объем памяти графического процессора. Вопрос о том, как работает алгоритм для предотвращения случайных сбоев, кажется мне вполне разумным.
3 ответа
Вы можете оценить самый большой размер партии, используя:
Максимальный размер пакета = доступные байты памяти GPU / 4 / (размер тензоров + обучаемые параметры)
Из недавней книги Глубокого обучения Гудфеллоу и др., Глава 8:
Размеры мини-партии обычно определяются следующими факторами:
- Большие партии обеспечивают более точную оценку градиента, но с менее чем линейной отдачей.
- Многоядерные архитектуры обычно недостаточно используются очень маленькими партиями. Это мотивирует использование некоторого абсолютного минимального размера партии, ниже которого не происходит сокращения времени на обработку мини-партии.
- Если все примеры в пакете должны обрабатываться параллельно (как это обычно бывает), то объем памяти масштабируется в зависимости от размера пакета. Для многих аппаратных установок это является ограничивающим фактором в размере пакета.
- Некоторые виды аппаратного обеспечения достигают лучшего времени выполнения с определенными размерами массивов. Особенно при использовании графических процессоров, как правило, для мощности 2-х размеров пакетов предлагается лучшее время выполнения. Типичная мощность двух размеров пакета варьируется от 32 до 256, при этом иногда пытаются использовать 16 для больших моделей.
- Небольшие партии могут предлагать регуляризирующий эффект (Wilson and Martinez, 2003), возможно, из-за шума, который они добавляют к процессу обучения. Ошибка обобщения часто лучше всего подходит для размера партии 1. Для обучения с таким небольшим размером партии может потребоваться небольшая скорость обучения для поддержания стабильности из-за высокой дисперсии в оценке градиента. Общее время выполнения может быть очень высоким из-за необходимости делать больше шагов, как из-за уменьшенной скорости обучения, так и из-за того, что требуется больше шагов для наблюдения всего учебного набора.
Что на практике обычно означает "в степени 2 и больше, тем лучше, при условии, что партия помещается в вашу (GPU) память".
Вы также можете обратиться к нескольким хорошим сообщениям здесь, в Stack Exchange:
- Размер пакета в зависимости от количества итераций для обучения нейронной сети
- Выбор размера мини-пакета для регрессии нейронной сети
- Насколько большим должен быть размер партии для стохастического градиентного спуска?
Просто имейте в виду, что статья Keskar et al. " О крупномасштабном обучении для глубокого обучения: разрыв в обобщении и острые минимумы", цитируемое несколькими постами выше, получило некоторые возражения от других уважаемых исследователей из сообщества глубокого обучения.
Надеюсь это поможет...
ОБНОВЛЕНИЕ (декабрь 2017 г.): есть новый документ Йошуа Бенжио и команды, " Три фактора, влияющие на минимумы в SGD" (ноябрь 2017 г.); Стоит прочитать в том смысле, что в нем сообщаются новые теоретические и экспериментальные результаты о взаимодействии между скоростью обучения и размером партии.
Используйте сводки, предоставленные pytorchsummary (установка pip) или keras (встроенный).
Например
from torchsummary import summary
summary(model)
.....
.....
================================================================
Total params: 1,127,495
Trainable params: 1,127,495
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.02
Forward/backward pass size (MB): 13.93
Params size (MB): 4.30
Estimated Total Size (MB): 18.25
----------------------------------------------------------------
Каждый экземпляр, который вы помещаете в пакет, потребует полного прямого / обратного прохода в памяти, ваша модель вам понадобится только один раз. Кажется, что люди предпочитают размер пакета, равный степени двойки, вероятно, из-за автоматической оптимизации макета на графическом процессоре.
Не забывайте линейно увеличивать скорость обучения при увеличении размера пакета.
Предположим, у нас есть Tesla P100 с 16 ГБ памяти.
(16000 - model_size) / (forward_back_ward_size)
(16000 - 4.3) / 18.25 = 1148.29
rounded to powers of 2 results in batch size 1024
определить функцию, чтобы найти размер партии для обучения модели
def FindBatchSize(model):
"""#model: model architecture, that is yet to be trained"""
import os, sys, psutil, gc, tensorflow, keras
import numpy as np
from keras import backend as K
BatchFound= 16
try:
total_params= int(model.count_params()); GCPU= "CPU"
#find whether gpu is available
try:
if K.tensorflow_backend._get_available_gpus()== []:
GCPU= "CPU"; #CPU and Cuda9GPU
else:
GCPU= "GPU"
except:
from tensorflow.python.client import device_lib; #Cuda8GPU
def get_available_gpus():
local_device_protos= device_lib.list_local_devices()
return [x.name for x in local_device_protos if x.device_type == 'GPU']
if "gpu" not in str(get_available_gpus()).lower():
GCPU= "CPU"
else:
GCPU= "GPU"
#decide batch size on the basis of GPU availability and model complexity
if (GCPU== "GPU") and (os.cpu_count() >15) and (total_params <1000000):
BatchFound= 64
if (os.cpu_count() <16) and (total_params <500000):
BatchFound= 64
if (GCPU== "GPU") and (os.cpu_count() >15) and (total_params <2000000) and (total_params >=1000000):
BatchFound= 32
if (GCPU== "GPU") and (os.cpu_count() >15) and (total_params >=2000000) and (total_params <10000000):
BatchFound= 16
if (GCPU== "GPU") and (os.cpu_count() >15) and (total_params >=10000000):
BatchFound= 8
if (os.cpu_count() <16) and (total_params >5000000):
BatchFound= 8
if total_params >100000000:
BatchFound= 1
except:
pass
try:
#find percentage of memory used
memoryused= psutil.virtual_memory()
memoryused= float(str(memoryused).replace(" ", "").split("percent=")[1].split(",")[0])
if memoryused >75.0:
BatchFound= 8
if memoryused >85.0:
BatchFound= 4
if memoryused >90.0:
BatchFound= 2
if total_params >100000000:
BatchFound= 1
print("Batch Size: "+ str(BatchFound)); gc.collect()
except:
pass
memoryused= []; total_params= []; GCPU= "";
del memoryused, total_params, GCPU; gc.collect()
return BatchFound
#####################################################################################################
#####################################################################################################
Я столкнулся с подобной ошибкой памяти графического процессора, которая была решена путем настройки сеанса tenorflow со следующим:
# See https://www.tensorflow.org/tutorials/using_gpu#allowing_gpu_memory_growth
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
см.: Google Colab Laboratory "ResourceExhaustedError" с графическим процессором