Почему в этом примере необходимо вызвать команду 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 ответа:
Вы правы,
optimizerDтолько обновляетnetDи градиенты наnetGне используются до вызоваnetG.zero_grad(), поэтому отсоединение не нужно, это просто экономит время, потому что вы не вычисляете градиенты для генератора.Вы в основном также отвечаете на свой другой вопрос самостоятельно, вы не отсоединяете
fakeво втором блоке, потому что вы специально хотите вычислить градиенты наnetG, чтобы иметь возможность обновить его параметры.Обратите внимание, как во втором блоке
real_labelиспользуется в качестве соответствующая метка дляfake, так что если дискриминатор находит поддельный вход реальным, конечная потеря невелика, и наоборот, что именно то, что вы хотите для генератора. Не уверен, что это то, что смутило вас, но это действительно единственная разница по сравнению с обучением дискриминатора на поддельных входах.
Потому что поддельная переменная теперь является частью графа генератора [1], но ты этого не хочешь. Поэтому вы должны "отделить" его от него, прежде чем поместить его в дискриминатор.