Как рассчитать оптимальный размер партии

Иногда я сталкиваюсь с проблемой:

ООМ при выделении тензора с формой

e.q.

ООМ при выделении тензора с формой (1024, 100, 160)

Где 1024 - размер моей партии, а я не знаю, что остальные. Если я уменьшу размер партии или количество нейронов в модели, она будет работать нормально.

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

Короче говоря: я хочу максимально возможный размер пакета с точки зрения моей модели, который поместится в моей памяти GPU и не приведет к сбою программы.

Ответ 1

Вы можете оценить самый большой размер партии, используя:

Максимальный размер партии = доступные байты памяти GPU/4/(размер тензоров + обучаемые параметры)

Ответ 2

Из недавней книги 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 г.); это стоит прочитать в том смысле, что он сообщает о новых теоретических и экспериментальных результатах о взаимодействии между скоростью обучения и размером партии.

Ответ 4

определить функцию для определения размера партии для обучения модели

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



#####################################################################################################
#####################################################################################################