PyTorch在训练过程中将两组梯度归一化

时间:2019-09-14 02:13:18

标签: pytorch normalization

在此GAN tutorial中,如果您向下滚动到训练循环,则可以看到它们结合了渐变  errD = errD_real + errD_fake这样。其中errD_real = criterion(output, label)errD_fake = criterion(output, label)criterion = nn.BCELoss()。我想做同样的事情,但是在执行向后传递之前,我想将两个梯度标准化为两者的较低欧几里德范数。我该怎么办?

我知道我可以通过打印出netD.weight.grad来分别在netD上访问每个权重的梯度,但是有什么方法可以将它们批量归一化为两者中较低的欧几里得范数?

这是我正在谈论的训练循环的一部分:

for epoch in range(num_epochs):
    # For each batch in the dataloader
    for i, data in enumerate(dataloader, 0):

        ############################
        # (1) Update D network: maximize log(D(x)) + log(1 - D(G(z)))
        ###########################
        ## Train with all-real batch
        netD.zero_grad()
        # Format batch
        real_cpu = data[0].to(device)
        b_size = real_cpu.size(0)
        label = torch.full((b_size,), real_label, device=device)
        # Forward pass real batch through D
        output = netD(real_cpu).view(-1)
        # Calculate loss on all-real batch
        errD_real = criterion(output, label)
        # Calculate gradients for D in backward pass
        errD_real.backward()
        D_x = output.mean().item()

        ## Train with all-fake batch
        # Generate batch of latent vectors
        noise = torch.randn(b_size, nz, 1, 1, device=device)
        # Generate fake image batch with G
        fake = netG(noise)
        label.fill_(fake_label)
        # Classify all fake batch with D
        output = netD(fake.detach()).view(-1)
        # Calculate D's loss on the all-fake batch
        errD_fake = criterion(output, label)
        # Calculate the gradients for this batch
        errD_fake.backward()
        D_G_z1 = output.mean().item()
        # Add the gradients from the all-real and all-fake batches
        errD = errD_real + errD_fake
        # Update D
        optimizerD.step()
        ...

2 个答案:

答案 0 :(得分:2)

您提到了不正确的两件事。

  1. errD = errD_real + errD_fake基本结合了两个目标函数,而不是梯度。
  2. 您需要在向后通过之后而不是在之前更改渐变。通过向后传递,将计算梯度,然后您可以在调用optimizer.step()之前修改梯度,以更新模型参数。

回答您的问题:

我相信PyTorch不会直接提供API支持来实现您的目标。但是,向后传递后,您可以轻松地自己修改渐变。要计算欧几里得范数,可以使用norm函数。然后,您可以简单地divide(就地)渐变。

答案 1 :(得分:0)

您最好保持渐变不变,并优化程序,使其能够计算出所需的效果。

在大多数情况下,无论如何都将删除渐变,然后再进行新的转发。

Lamb等一些较新的算法可以按您的计划进行参数级(逐层)梯度归一化(在这种情况下为MSE)的技巧。

还请检查SAGAN论文,以及自从您提到GAN以来他们为什么使用nn.utils.spectral_norm的原因。