Pytorch 发电机';优化器是否也训练鉴别器?
在学习GANs时,我注意到代码示例展示了以下模式: 鉴别器的训练如下:Pytorch 发电机';优化器是否也训练鉴别器?,pytorch,Pytorch,在学习GANs时,我注意到代码示例展示了以下模式: 鉴别器的训练如下: d_optim.zero_grad() real_pred = d(real_batch) d_loss = d_loss_fn(real_pred, torch.ones(real_batch_size, 1)) d_loss.backward() fake_pred = d(g(noise_batch).detach()) d_loss = d_loss_fn(fake_pred, torch.zeros(noise
d_optim.zero_grad()
real_pred = d(real_batch)
d_loss = d_loss_fn(real_pred, torch.ones(real_batch_size, 1))
d_loss.backward()
fake_pred = d(g(noise_batch).detach())
d_loss = d_loss_fn(fake_pred, torch.zeros(noise_batch_size, 1))
d_loss.backward()
d_optim.step()
g_optim.zero_grad()
fake_pred = d(g(noise_batch))
g_loss = g_loss_fn(fake_pred, torch.ones(noise_batch_size, 1))
g_loss.backward()
g_optim.step()
发电机的培训如下:
d_optim.zero_grad()
real_pred = d(real_batch)
d_loss = d_loss_fn(real_pred, torch.ones(real_batch_size, 1))
d_loss.backward()
fake_pred = d(g(noise_batch).detach())
d_loss = d_loss_fn(fake_pred, torch.zeros(noise_batch_size, 1))
d_loss.backward()
d_optim.step()
g_optim.zero_grad()
fake_pred = d(g(noise_batch))
g_loss = g_loss_fn(fake_pred, torch.ones(noise_batch_size, 1))
g_loss.backward()
g_optim.step()
提到为鉴别器编写了d(g(noise\u batch).detach())
,而不是d(g(noise\u batch))
,以防止d\u optim.step()
训练g
,但没有提到发电机的d(noise\u batch))
;g_optim.step()
是否也训练d
事实上,例如,如果
d\u optim=torch.optim.SGD(d.parameters(),lr=0.001),我们为什么要d(g(noise\u batch).detach())
?这是否没有指定要更新d.parameters()
和g.parameters()
?TLDR:optimizer
将只更新指定给它的参数,而backward()
调用将计算计算图中所有变量的梯度。因此,detach()
此时不需要梯度计算的变量非常有用
我相信答案在于PyTorch内部的实现方式
tensor.detach()
创建一个与不需要梯度的tensor
共享存储的张量。因此,有效地,你切断了计算图。也就是说,执行false\u pred=d(g(noise\u batch).detach())
将分离(切断)生成器的计算图李>
- 在loss上调用
backward()
时,将为整个计算图计算梯度(无论优化器是否使用它)。因此,切断发电机部件将避免发电机重量的梯度计算(因为不需要梯度计算)
- 此外,调用
optimizer.step()
时,仅更新传递给特定优化器的参数。因此,g_optim
只会优化传递给它的参数(您没有明确提到哪些参数传递给g_optim
)。类似地,d\u optim
将只更新d.parameters()
,因为您明确指定了它
我理解:detach
用于避免不必要的计算,而不是避免训练g
的参数。