web-dev-qa-db-ja.com

最適なバッチサイズの計算方法

時々問題に遭遇します:

形状を持つテンソルを割り当てるときのOOM

等式.

形状(1024、100、160)のテンソルを割り当てるときのOOM

ここで、1024は私のバッチサイズで、残りは何なのかわかりません。モデルのバッチサイズまたはニューロンの数を減らすと、正常に実行されます。

モデルとGPUメモリに基づいて最適なバッチサイズを計算する一般的な方法はありますか?プログラムはクラッシュしませんか?

要するに、モデルの観点から可能な限り最大のバッチサイズが必要です。これは、GPUメモリに収まり、プログラムをクラッシュさせません。

16
Andrzej Gis

以下を使用して、最大バッチサイズを推定できます。

最大バッチサイズ=利用可能なGPUメモリバイト/ 4 /(テンソルのサイズ+トレーニング可能なパラメーター)

10
ilan

Goodfellowらによる最近のディープラーニングの本、 chapter 8 から:

ミニバッチのサイズは通常、次の要因によって決まります。

  • バッチが大きいほど、勾配のより正確な推定値が得られますが、線形リターンは少なくなります。
  • マルチコアアーキテクチャは通常、非常に小さなバッチで十分に活用されていません。これは、絶対最小バッチサイズを使用する動機となります。これを下回ると、ミニバッチを処理する時間が短縮されません。
  • バッチ内のすべての例が並行して処理される場合(通常の場合)、メモリの量はバッチサイズに比例します。多くのハードウェアセットアップでは、これがバッチサイズの制限要因です。
  • ある種のハードウェアは、特定のサイズのアレイでより良いランタイムを実現します。特にGPUを使用している場合、2のべき乗のバッチサイズが実行時間を改善するのが一般的です。 2つのバッチサイズの一般的な能力は32から256の範囲で、大規模なモデルでは16が試行されることがあります。
  • おそらく、学習プロセスにノイズが加わるため、小さなバッチは正則化効果をもたらします(Wilson and Martinez、2003)。一般化エラーは、多くの場合、バッチサイズ1に最適です。このような小さなバッチサイズでのトレーニングでは、勾配の推定値の変動が大きいため、安定性を維持するために小さな学習率が必要になる場合があります。合計学習時間は、学習率の低下とトレーニングセット全体の観察により多くのステップが必要なため、より多くのステップを実行する必要があるため、非常に高くなる可能性があります。

実際には、これは通常「2のべき乗以上の大きさで、バッチが(GPU)メモリに収まる場合」を意味します。

Stack Exchangeのいくつかの優れた投稿も参照してください。

Keskar et al。による論文は覚えておいてください。 「 ディープラーニングのための大規模バッチトレーニング:一般化ギャップとシャープミニマム 」は、上記のいくつかの投稿で引用され、 いくつかの異論 ディープラーニングコミュニティの他の立派な研究者による。

お役に立てれば...

[〜#〜] update [〜#〜](2017年12月):Yoshua Bengio&teamによる新しい論文があります、 SGD の最小値に影響する3つの要因(2017年11月);学習率とバッチサイズの相互作用に関する新しい理論的および実験的結果を報告するという意味で読む価値があります。

13
desertnaut

同様の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` with GP

1
michael

モデルを訓練するためのバッチサイズを見つける関数を定義する

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