Tf 2.0 DC Gan example in tensorflow 2.0 guide では、2つの勾配テープがあります。以下を参照してください。
@tf.function
def train_step(images):
noise = tf.random.normal([BATCH_SIZE, noise_dim])
with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape:
generated_images = generator(noise, training=True)
real_output = discriminator(images, training=True)
fake_output = discriminator(generated_images, training=True)
gen_loss = generator_loss(fake_output)
disc_loss = discriminator_loss(real_output, fake_output)
gradients_of_generator = gen_tape.gradient(gen_loss, generator.trainable_variables)
gradients_of_discriminator = disc_tape.gradient(disc_loss, discriminator.trainable_variables)
generator_optimizer.apply_gradients(Zip(gradients_of_generator, generator.trainable_variables))
discriminator_optimizer.apply_gradients(Zip(gradients_of_discriminator, discriminator.trainable_variables))
2つのグラデーションテープがあることがはっきりとわかります。単一のテープメイクを使用してどのような違いがあるのだろうと思っていて、次のように変更しました
@tf.function
def train_step(images):
noise = tf.random.normal([BATCH_SIZE, noise_dim])
with tf.GradientTape() as tape:
generated_images = generator(noise, training=True)
real_output = discriminator(images, training=True)
fake_output = discriminator(generated_images, training=True)
gen_loss = generator_loss(fake_output)
disc_loss = discriminator_loss(real_output, fake_output)
gradients_of_generator = tape.gradient(gen_loss, generator.trainable_variables)
gradients_of_discriminator = tape.gradient(disc_loss, discriminator.trainable_variables)
generator_optimizer.apply_gradients(Zip(gradients_of_generator, generator.trainable_variables))
discriminator_optimizer.apply_gradients(Zip(gradients_of_discriminator, discriminator.trainable_variables))
これは私に次のエラーを与えます:
RuntimeError: GradientTape.gradient can only be called once on non-persistent tapes.
なぜ2本のテープが必要なのか知りたいのですが。現在のところ、tf2.0 APIに関するドキュメントは不十分です。誰かが私に正しいドキュメント/チュートリアルを説明したり教えたりできますか?
GradientTape
の- documentation から:
デフォルトでは、GradientTape.gradient()メソッドが呼び出されるとすぐに、GradientTapeによって保持されているリソースが解放されます。同じ計算で複数の勾配を計算するには、永続的な勾配テープを作成します。これにより、tapeオブジェクトがガベージコレクションされるときにリソースが解放されるため、gradient()メソッドを複数回呼び出すことができます。
技術的な理由は、gradient
が2回呼び出されるためです(これは(非永続的)テープでは許可されていません)。
ただし、現在のケースでは、根本的な理由は、一般的にGANSのトレーニングがジェネレーターとディスクリミネーターの最適化を交互に行うことによって行われることです。各最適化には独自のオプティマイザーがあり、通常はさまざまな変数で動作し、現在では最小化された損失でさえも異なります(gen_loss
およびdisc_loss
(コード内)。
つまり、GANのトレーニングは基本的に2つの異なる(敵対的な)問題を交互に最適化しているため、2つの勾配になってしまいます。