Ответ 1
Вы можете оценить самый большой размер партии, используя:
Максимальный размер партии = доступные байты памяти GPU/4/(размер тензоров + обучаемые параметры)
Иногда я сталкиваюсь с проблемой:
ООМ при выделении тензора с формой
e.q.
ООМ при выделении тензора с формой (1024, 100, 160)
Где 1024 - размер моей партии, а я не знаю, что остальные. Если я уменьшу размер партии или количество нейронов в модели, она будет работать нормально.
Существует ли общий способ расчета оптимального размера пакета на основе модели и памяти графического процессора, чтобы программа не вылетала?
Короче говоря: я хочу максимально возможный размер пакета с точки зрения моей модели, который поместится в моей памяти GPU и не приведет к сбою программы.
Вы можете оценить самый большой размер партии, используя:
Максимальный размер партии = доступные байты памяти GPU/4/(размер тензоров + обучаемые параметры)
Из недавней книги Deep Learning от Goodfellow et al., Глава 8:
Размеры микросхемы обычно определяются следующими факторами:
- Более крупные партии обеспечивают более точную оценку градиента, но с меньшей линейной отдачей.
- Многоядерные архитектуры обычно недоиспользуются чрезвычайно маленькими партиями. Это мотивирует использование некоторого абсолютного минимального размера партии, ниже которого нет сокращения времени обработки мини-бара.
- Если все примеры в пакете должны обрабатываться параллельно (как это обычно бывает), тогда объем памяти масштабируется с размером партии. Для многих аппаратных настроек это ограничивающий фактор в размере партии.
- Некоторые виды аппаратных средств обеспечивают лучшее время работы с конкретными размерами массивов. Особенно при использовании графических процессоров для питания 2-х серийных размеров обычно требуется лучшее время исполнения. Типичная мощность в 2 размера партии варьируется от 32 до 256, при этом иногда используется 16 для больших моделей.
- Небольшие партии могут предложить эффект регуляризации (Wilson and Martinez, 2003), возможно, из-за шума, который они добавляют к процессу обучения. Ошибка обобщения часто лучше всего подходит для размера партии 1. Обучение с таким небольшим размером партии может потребовать небольшой скорости обучения для поддержания стабильности из-за большого отклонения в оценке градиента. Общее время выполнения может быть очень высоким в результате необходимости делать больше шагов, как из-за снижения скорости обучения, так и потому, что для выполнения всего набора упражнений требуется больше шагов.
Что на практике обычно означает "по силам 2, и тем лучше, при условии, что пакет вписывается в вашу память (GPU)".
Вы также можете ознакомиться с несколькими хорошими сообщениями в Stack Exchange:
Просто имейте в виду, что статья Keskar et al. " Об широкомасштабном обучении для глубокого обучения: разрыв обобщения и резкие минимумы ", цитируемый несколькими из вышеперечисленных сообщений, получил некоторые возражения других уважаемых исследователей сообщества глубокого обучения.
Надеюсь это поможет...
ОБНОВЛЕНИЕ (декабрь 2017 г.): В Yoshua Bengio & team появилась новая статья, Три фактора, влияющие на минимумы в SGD (ноябрь 2017 г.); это стоит прочитать в том смысле, что он сообщает о новых теоретических и экспериментальных результатах о взаимодействии между скоростью обучения и размером партии.
Я столкнулся с аналогичной ошибкой памяти GPU, которая была решена путем настройки сеанса tensorflow со следующим:
# See https://www.tensorflow.org/tutorials/using_gpu#allowing_gpu_memory_growth
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
см.: google colaboratory 'ResourceExhaustedError' с графическим процессором
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
#####################################################################################################
#####################################################################################################