web-dev-qa-db-de.com

Wie berechnet man die optimale Losgröße?

Manchmal stoße ich auf ein Problem: 

OOM bei der Zuordnung des Tensors mit der Form

e.q.

OOM bei der Zuordnung von Tensor mit Form (1024, 100, 160)

Wo ist 1024 meine Losgröße und ich weiß nicht, was der Rest ist. Wenn ich die Stapelgröße oder die Anzahl der Neuronen im Modell reduziere, läuft es einwandfrei.

Gibt es eine generische Methode zum Berechnen der optimalen Stapelgröße basierend auf dem Modell- und GPU-Speicher, sodass das Programm nicht abstürzt?

EDIT

Da meine Frage unklar erscheint, lassen Sie mich es so formulieren: Ich möchte die größtmögliche Stapelgröße meines Modells, die in meinen GPU-Speicher passt und das Programm nicht zum Absturz bringt.

EDIT 2

Wem auch immer gestimmt hat, die Frage zu schließen, weil er zu breit ist: Wie in aller Welt ist die Frage zu breit? Es gibt einen Algorithmus, der einen Teil der Daten auswählt, um ihn in den GPU-Speicher zu speichern. Dies ist eindeutig unvollständig, da die Daten manchmal den GPU-Speicher überschreiten. Die Frage, wie der Algorithmus funktioniert, um zufällige Abstürze zu vermeiden, erscheint mir durchaus sinnvoll.

6
Andrzej Gis

Sie können die größte Chargengröße schätzen, indem Sie

Max. Stapelgröße = verfügbare GPU-Speicherbytes/4/(Größe der Tensoren + trainierbare Parameter)

5
ilan

Aus dem jüngsten Deep Learning-Buch von Goodfellow ua, Kapitel 8 :

Minibatch-Größen werden im Allgemeinen von den folgenden Faktoren bestimmt:

  • Größere Chargen liefern eine genauere Abschätzung des Gradienten, aber mit weniger als linearen Renditen. 
  • Multicore-Architekturen sind normalerweise von extrem kleinen Chargen zu wenig genutzt. Dies motiviert, einige absolute minimale Losgröße, unterhalb derer keine Reduzierung von .__ erfolgt. Zeit, um ein Minibatch zu verarbeiten. 
  • Wenn alle Beispiele im Stapel sein sollen parallel verarbeitet (wie es normalerweise der Fall ist), dann die Menge von Speicher skaliert mit der Stapelgröße. Für viele Hardware-Setups ist dies der limitierende Faktor bei der Losgröße. 
  • Einige Arten von Hardware erreichen bessere Laufzeit mit spezi fi schen Arrays. Besonders bei der Verwendung von Bei GPUs bieten 2 Batch-Größen normalerweise eine bessere Laufzeit . Eine typische Leistung von 2 Chargengrößen liegt zwischen 32 und 256, manchmal mit 16 versucht für große Modelle.
  • Kleine Chargen können ein .__ anbieten. Regularisierungseffekt (Wilson und Martinez, 2003), möglicherweise aufgrund der Geräusche tragen zum Lernprozess bei. Generalisierungsfehler ist oft am besten für eine Losgröße 1. Training mit einer so kleinen Losgröße Möglicherweise ist eine geringe Lernrate erforderlich, um die Stabilität wegen aufrechtzuerhalten. die hohe Varianz in der Abschätzung des Gradienten. Die Gesamtlaufzeit kann sehr hoch sein, da mehr Schritte erforderlich sind, beide wegen der reduzierten Lernrate und weil es mehr Schritte erfordert den gesamten Trainingssatz beobachten.

Was in der Praxis normalerweise bedeutet "in Potenzen von 2 und je größer desto besser, vorausgesetzt der Stapel passt in Ihren (GPU) Speicher".

In Stack Exchange sollten Sie auch einige gute Beiträge lesen:

Denken Sie daran, dass die Arbeit von Keskar et al. " Über das großvolumige Training für Deep Learning: Generalization Gap und Sharp Minima ', zitiert in mehreren der obigen Beiträge, hat einige Einwände von anderen angesehenen Forschern der Deep Learning-Community erhalten.

Hoffe das hilft...

UPDATE (Dezember 2017): Es gibt eine neue Arbeit von Yoshua Bengio & Team, Drei Faktoren, die die Minima in SGD beeinflussen (November 2017); Es lohnt sich, in dem Sinne zu lesen, dass neue theoretische und experimentelle Ergebnisse über das Zusammenspiel von Lernrate und Stapelgröße gemeldet werden.

10
desertnaut

Ich bin auf einen ähnlichen GPU-Mem-Fehler gestoßen, der durch Konfigurieren der Tensorflow-Sitzung mit den folgenden Problemen behoben wurde:

# See https://www.tensorflow.org/tutorials/using_gpu#allowing_gpu_memory_growth
config = tf.ConfigProto()
config.gpu_options.allow_growth = True

siehe: google colaboratory `ResourceExhaustedError` mit GPU

1
michael

definieren der Funktion zum Ermitteln der Chargengröße zum Trainieren des Modells

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



#####################################################################################################
#####################################################################################################
0
Anurag Gupta