web-dev-qa-db-ja.com

この例では、なぜdetachを変数で呼び出す必要があるのですか?

私はこの例を実行していました- https://github.com/pytorch/examples/blob/master/dcgan/main.py そして私は基本的な質問があります。

_fake = netG(noise)
label = Variable(label.fill_(fake_label))
output = netD(fake.detach()) # detach to avoid training G on these labels
errD_fake = criterion(output, label)
errD_fake.backward()
D_G_z1 = output.data.mean()
errD = errD_real + errD_fake
optimizerD.step()
_

変数fakedetach()を呼び出す理由を理解しているので、ジェネレーターパラメーターの勾配は計算されません。私の質問は、optimizerD.step()がDiscriminatorに関連付けられたパラメーターのみを更新するので、それは重要ですか?

OptimizerDは次のように定義されます:optimizerD = optim.Adam(netD.parameters(), lr=opt.lr, betas=(opt.beta1, 0.999))

さらに、Generatorのパラメーターを更新する次のステップでは、その前にnetG.zero_grad()を呼び出します。これにより、以前に計算されたすべての勾配が最終的に削除されます。さらに、Gネットワ​​ークのパラメーターを更新するときは、これを行います--output = netD(fake)。ここでは、デタッチを使用していません。どうして?

では、なぜ上記のコードで変数(3行目)を切り離す必要があるのでしょうか?

11
Wasi Ahmad

そうです、optimizerDnetDのみを更新し、netG.zero_grad()が呼び出される前に、netGのグラデーションは使用されないため、デタッチする必要はありません。ジェネレーターの勾配を計算していないため、時間を節約できます。

基本的には、他の質問にも自分で答えています。パラメータを更新できるようにfakeの勾配を計算する必要があるため、2番目のブロックでnetGを切り離さないでください。

2番目のブロックreal_labelfakeの対応するラベルとして使用されるため、ディスクリミネーターが偽の入力が本物であると判断した場合、最終的な損失は小さく、その逆も同様です。これはまさにジェネレーターに必要なものです。 。それがあなたを混乱させたものであるかどうかはわかりませんが、偽の入力で弁別器を訓練することと比較して、それは本当に唯一の違いです。

10
Jens Petersen

言っておくけど。デタッチの役割は、グラジエントドロップをフリーズすることです。ネットワークの識別用であれ、ネットワークの生成用であれ、logD(G(z))に関するすべてを更新します。判別ネットワークの場合、Gの凍結は全体的な勾配の更新に影響しません(つまり、内部関数は定数と見なされ、勾配を見つけるための外部関数には影響しません)が、逆に、Dが凍結されている場合はグラデーションの更新を完了する方法はありません。したがって、発電機を訓練する際に凍結Dの勾配を使用しませんでした。したがって、ジェネレーターについては、Dの勾配を計算しましたが、Dの重みを更新しなかったため(optimizer_g.stepのみが書き込まれました)、ジェネレーターのトレーニング時にディスクリミネーターは変更されません。あなたは尋ねるかもしれません、それであなたが弁別器を訓練するとき、あなたはデタッチを加える必要があります。これは余分な動きではありませんか?グラデーションをフリーズするので、トレーニングをスピードアップでき、使用できる場所で使用できます。それは余分な仕事ではありません。次に、ジェネレーターをトレーニングするとき、logD(G(z))のため、Dの勾配をフリーズする方法がないため、ここではデタッチを記述しません。

0
einstellung

上位投票の回答は、不正確/不完全です。

これを確認してください: https://github.com/pytorch/examples/issues/116 そして@plopdの答えを見てください:

本当じゃない。グラフからfakeをデタッチすることは、実際にジェネレーターを更新するときにノイズがGを順方向に通過するのを防ぐために必要です。デタッチしない場合、Dの勾配更新にfakeは必要ありませんが、それでも計算グラフに追加され、すべての変数をクリアするbackwardパスの結果として追加されます。グラフ内(retain_graph=Falseデフォルト)、Gが更新されるとfakeは使用できなくなります。

この投稿はまた多くを明らかにします: https://zhuanlan.zhihu.com/p/43843694 (中国語)。

0
FatPanda

偽の変数がジェネレータグラフの一部になっているため [1] ですが、これは望ましくありません。したがって、ディスクリミネーターに入れる前に、彼から「切り離す」必要があります。

0
loose11