Почему в этом примере необходимо вызвать команду detach для переменной?


Я проходил через этот пример - https://github.com/pytorch/examples/blob/master/dcgan/main.py и у меня есть основной вопрос.

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

Я понимаю, почему мы вызываем detach() переменную fake, чтобы не вычислялись градиенты для параметров генератора. Мой вопрос в том, имеет ли это значение, так как optimizerD.step() собирается обновить параметры, связанные только с дискриминатором?

Кроме того, на следующем шаге, когда мы будем обновлять параметры для генератора, перед этим мы будем вызов netG.zero_grad(), который в конечном итоге удаляет все ранее вычисленные градиенты. Более того, когда мы обновляем параметры для сети G, мы делаем это - output = netD(fake). Здесь мы не используем detach. Почему?

Итак, почему в приведенном выше коде необходимо отсоединить переменную (строка 3)?

2 6

2 ответа:

Вы правы, optimizerD только обновляет netD и градиенты на netG не используются до вызова netG.zero_grad(), поэтому отсоединение не нужно, это просто экономит время, потому что вы не вычисляете градиенты для генератора.

Вы в основном также отвечаете на свой другой вопрос самостоятельно, вы не отсоединяете fake во втором блоке, потому что вы специально хотите вычислить градиенты на netG, чтобы иметь возможность обновить его параметры.

Обратите внимание, как во втором блоке real_label используется в качестве соответствующая метка для fake, так что если дискриминатор находит поддельный вход реальным, конечная потеря невелика, и наоборот, что именно то, что вы хотите для генератора. Не уверен, что это то, что смутило вас, но это действительно единственная разница по сравнению с обучением дискриминатора на поддельных входах.

Потому что поддельная переменная теперь является частью графа генератора [1], но ты этого не хочешь. Поэтому вы должны "отделить" его от него, прежде чем поместить его в дискриминатор.