0

最近我了解了生成对抗网络

为了训练生成器,我对它的学习方式感到困惑。下面是 GAN 的实现:

`# train generator
            z = Variable(xp.random.uniform(-1, 1, (batchsize, nz), dtype=np.float32))
            x = gen(z)
            yl = dis(x)
            L_gen = F.softmax_cross_entropy(yl, Variable(xp.zeros(batchsize, dtype=np.int32)))
            L_dis = F.softmax_cross_entropy(yl, Variable(xp.ones(batchsize, dtype=np.int32)))

        # train discriminator

        x2 = Variable(cuda.to_gpu(x2))
        yl2 = dis(x2)
        L_dis += F.softmax_cross_entropy(yl2, Variable(xp.zeros(batchsize, dtype=np.int32)))

        #print "forward done"

        o_gen.zero_grads()
        L_gen.backward()
        o_gen.update()

        o_dis.zero_grads()
        L_dis.backward()
        o_dis.update()`

因此,它会计算论文中提到的生成器的损失。但是,它会根据鉴别器输出调用生成器后向函数。鉴别器输出只是一个数字(不是数组)。

但我们知道,一般来说,为了训练网络,我们在最后一层计算损失函数(最后一层输出和实际输出之间的损失),然后计算梯度。例如,如果输出是 64*64,那么我们将其与 64*64 图像进行比较,然后计算损失并进行反向传播。

但是,在我在生成对抗网络中看到的代码中,我看到它们从鉴别器输出(只是一个数字)计算生成器的损失,然后调用生成器的反向传播。生成器的最后一层是例如 64*64 像素,但鉴别器损失是 1*1(这与通常的网络不同)所以我不明白它是如何导致生成器被学习和训练的?

我想如果我们附加两个网络(附加生成器和鉴别器)然后调用反向传播但只更新生成器参数,它是有意义的并且应该可以工作。但是我在代码中看到的完全不同。

所以我问怎么可能?

谢谢

4

1 回答 1

0

你说'但是,它会根据鉴别器输出调用生成器后向函数。鉴别器输出只是一个数字(不是数组)',而损失始终是一个标量值。当我们计算两个图像的均方误差时,它也是一个标量值。

L_adversarial = E[log(D(x))]+E[log(1−D(G(z))]

x 来自真实数据分布

z 是由生成器转换的潜在数据分布

回到您的实际问题,判别器网络在最后一层有一个 sigmoid 激活函数,这意味着它的输出范围为 [0,1]。鉴别器试图通过最大化损失函数中添加的两个项来最大化这种损失。第一项的最大值为 0,当 D(x) 为 1 时发生,第二项的最大值也为 0,当 1-D(G(z)) 为 1 时发生,这意味着 D(G(z)) 为 0 . 所以鉴别器试图做一个二进制分类,我最大化这个损失函数,当它被输入 x(真实数据)时它试图输出 1,当它被输入 G(z)(生成的假数据)时输出 0。但是生成器试图最小化这种损失,换句话说,它试图通过生成与真实样本相似的假样本来欺骗判别器。随着时间的推移,生成器和鉴别器都变得越来越好。

代码在pytorch

bce_loss = nn.BCELoss() #bce_loss = -ylog(y_hat)-(1-y)log(1-y_hat)[similar to L_adversarial]

Discriminator = ..... #some network   
Generator = ..... #some network

optimizer_generator = ....... #some optimizer for generator network    
optimizer_discriminator = ....... #some optimizer for discriminator network       

z = ...... #some latent data distribution that is transformed by the generator
real = ..... #real data distribution

#####################
#Update Discriminator
#####################
fake = Generator(z)
fake_prediction = Discriminator(fake)
real_prediction = Discriminator(real)
discriminator_loss = bce_loss(fake_prediction,torch.zeros(batch_size))+bce_loss(real_prediction,torch.ones(batch_size))
discriminator_loss.backward()
optimizer_discriminator.step()

#################
#Update Generator
#################
fake = Generator(z)
fake_prediction = Discriminator(fake)
generator_loss = bce_loss(fake_prediction,torch.ones(batch_size))
generator_loss.backward()
optimizer_generator.step()
于 2018-12-25T10:09:21.527 回答