の部分にMultiGPUトレーニングのすべてのコードは、私たちが面白い損失関数を持つGANアルゴリズムに取り組んでいるTensorflow 1.3とPython 3.xのTensorflow:グラフ
を想定しています。
Stage 1 - Compute only the completion/generator loss portion of the network
Iterates over the completion portion of the GAN for X iterations.
Stage 2 - Compute only the discriminator loss portion of the network
Iterates over the discriminator portion for Y iterations (but
don't train on Stage 1)
Stage 3 - Compute the full loss on the network
Iterate over both completion and discriminator for Z iterations
(training on the entire network).
私たちはこの単一GPUを持っています。トレーニング時間が長いため、マルチGPUにしたいと考えています。
タワーの損失、タワーの平均化、GPUでのグラデーションの計算、CPUへの適用について説明しているTensorflow/models/tutorials/Images/cifar10/cifar10_multi_gpu_train.pyを見てきました。これは素晴らしいスタートです。しかし、私たちの損失はより複雑なので、私たちのためにすべてを少し複雑にしています。
コードは非常に複雑ですが、これに似ていますが、https://github.com/timsainb/Tensorflow-MultiGPU-VAE-GAN(Tensorflow 0.1の周りに書かれているので実行されないため、動作していないという奇妙な点があります。
に)あなたに私たちがやっているかのアイデアを与える、我々は勾配を計算するとき、それはこのようなもの(重要な部分を強調しようとする擬似コード)になります。私たちは「compute_gradients(のみ呼び出す場合
for i in range(num_gpus):
with tf.device('/gpu:%d' % gpus[i]):
with tf.name_scope('Tower_%d' % gpus[i]) as scope:
with tf.variable_scope("generator")
generator = build_generator()
with tf.variable_scope("discriminator"):
with tf.variable_scope("real_discriminator") :
real_discriminator = build_discriminator(x)
with tf.variable_scope("fake_discriminator", reuse = True):
fake_discriminator = build_discriminator(generator)
gen_only_loss, discm_only_loss, full_loss = build_loss(generator,
real_discriminator, fake_discriminator)
tf.get_variable_scope().reuse_variables()
gen_only_grads = gen_only_opt.compute_gradients(gen_only_loss)
tower_gen_only_grads.append(gen_only_grads)
discm_only_train_vars= tf.get_collection(
tf.GraphKeys.TRAINABLE_VARIABLES, "discriminator")
discm_only_train_vars= discm_only_train_vars+ tf.get_collection(
tf.GraphKeys.TRAINABLE_RESOURCE_VARIABLES, "discriminator")
discm_only_grads = discm_only_opt.compute_gradients(discm_only_loss,
var_list = discm_only_train_vars)
tower_discm_only_grads.append(discm_only_grads)
full_grads = full_opt.compute_gradients(full_loss)
tower_full_grads.append(full_grads)
# average_gradients is the same code from the cifar10_multi_gpu_train.py.
We haven't changed it. Just iterates over gradients and averages
them...this is part of the problem...
gen_only_grads = average_gradients(tower_gen_only_grads)
gen_only_train = gen_only_opt.apply_gradients(gen_only_grads,
global_step=global_step)
discm_only_grads = average_gradients(tower_discm_only_grads)
discm_only_train = discm_only_opt.apply_gradients(discm_only_grads,
global_step=global_step)
full_grads = average_gradients(tower_full_grads)
full_train = full_opt.apply_gradients(full_grads, global_step=global_step)
をfull_loss) "であれば、アルゴリズムは複数のGPUで正常に動作します。これは、cifar10_multi_gpu_train.pyのコードのコードとかなり同じです。複雑な部分は、ステージ1または2でネットワークを制限する必要がある場合に発生します。
Compute_gradients(full_loss)は、デフォルト値Noneのvar_listパラメータを持ちます。つまり、すべての変数を訓練します。 Tower_1のときにTower_0変数を訓練しないことは、どのように知っていますか? compute_gradients(discm_only_loss、var_list = discm_only_train_vars)を扱うとき、ネットワークのその部分へのトレーニングを制限する正しい変数を集める方法を知る必要があるからです。私はこれについて話しているスレッドを見つけましたが、それが不正確/不完全であることがわかりました - "freeze" some variables/scopes in tensorflow: stop_gradient vs passing variables to minimize。
なぜなら、compute_gradientsのコードを見れば、var_listは、Noneが渡されたときに訓練可能な変数と学習可能なリソース変数の組み合わせだからです。これは、複数のGPUに分割しようとしないと正しく動作します。
質問1: 私はタワーでネットワークを分割したので、私は現在のタワーも集めていますか?このような行を追加する必要はありますか? (?と私は、これらの変数のトレーニングを逃してはいけないことを確認)、塔のための適切な変数を養成するために
discm_only_train_vars= tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, "Tower_{}/discriminator".format(i))
discm_only_train_vars= discm_only_train_vars + tf.get_collection(tf.GraphKeys.TRAINABLE_RESOURCE_VARIABLES, "Tower_{}/discriminator".format(i))
質問2: おそらく同じ答え質問1.「compute_gradientsを取得すると(gen_only_loss)はもう少し難しいです... gen_only_lossは弁別されていないバージョンでは弁別者に決して触れなかったので、必要なグラフ内のテンソルを活性化し、すべて正常でした。しかし、私が "compute_gradients"を呼び出すと、タワー型のバージョンでは、まだアクティブ化されていないテンソルの勾配が返されるので、エントリのいくつかは[(None、tf.Variable)、(None、tf.Variable)]です。これにより、None値をTensorに変換できないため、average_gradientsがクラッシュします。これは、私もこれらを制限する必要があると私に思います。
シフルの例と私のfull_lossの例は特定の塔の訓練を気にしませんが、私がvar_listを指定したら、compute_gradientsがどの魔法を使っていたかを知っていますどの塔が消えるかを訓練するための変数?私は他の変数をつかむことについて心配する必要がありますか?