2017-05-06 28 views
2

私はケラス(テンソルフローバックエンド)のデータ並列性を模索していますが、モデルの並列性は求めていません。 私はビデオファイルでビデオ分類を実行しているため、GPUにサイズ2のバッチにしか収まらなかった。だから、バッチサイズを増やして見積もりやトレーニングを速くするために、複数のGPUを使用する方法が不思議でした。 私にこれを行う効果的な方法を提案できますか?Kerasのデータ並列化

私は12gb TitanXと6gb Titan Blackを使用しています。

おかげ

答えて

1

これはそれを行う1つの方法である:

取得to_multi_gpuこの方法をmodel(シングルGPU上Keras 2.0を使用して定義された)、及び上同じモデル(共有パラメータを使用して)複製することを返し複数のGPU。新しいモデルへの入力は均等にスライスされ、各スライスは複製されたモデルの1つに渡されます。複製されたすべてのモデルからの出力は、最後に連結されます。

from keras import backend as K 
from keras.models import Model 
from keras.layers import Input 
from keras.layers.core import Lambda 
from keras.layers.merge import Concatenate 

def slice_batch(x, n_gpus, part): 
    """ 
    Divide the input batch into [n_gpus] slices, and obtain slice number [part]. 
    i.e. if len(x)=10, then slice_batch(x, 2, 1) will return x[5:]. 
    """ 
    sh = K.shape(x) 
    L = sh[0] // n_gpus 
    if part == n_gpus - 1: 
     return x[part*L:] 
    return x[part*L:(part+1)*L] 


def to_multi_gpu(model, n_gpus=2): 
    """ 
    Given a keras [model], return an equivalent model which parallelizes 
    the computation over [n_gpus] GPUs. 

    Each GPU gets a slice of the input batch, applies the model on that slice 
    and later the outputs of the models are concatenated to a single tensor, 
    hence the user sees a model that behaves the same as the original. 
    """ 
    with tf.device('/cpu:0'): 
     x = Input(model.input_shape[1:], name=model.input_names[0]) 

    towers = [] 
    for g in range(n_gpus): 
     with tf.device('/gpu:' + str(g)): 
      slice_g = Lambda(slice_batch, 
          lambda shape: shape, 
          arguments={'n_gpus':n_gpus, 'part':g})(x) 
      towers.append(model(slice_g)) 

    with tf.device('/cpu:0'): 
     merged = Concatenate(axis=0)(towers) 

    return Model(inputs=[x], outputs=[merged])