同时训练鉴别器和发生器(Tensorflow)

时间:2018-12-09 17:09:33

标签: tensorflow machine-learning neural-network generative-adversarial-network

通常在使用TensorFlow的GAN代码中,我们具有以下形式:

define input:default-graph-uri <http://localhost:8890/DAV/elec1> 

首先可以将其视为训练鉴别器(D),然后再训练生成器(G)。但是,如果执行以下操作怎么办:

 _, D_loss_curr, _ = sess.run(
            [D_solver, D_loss, clip_D],
            feed_dict={X: X_mb, z: sample_z(mb_size, z_dim)}
        )

 _, G_loss_curr = sess.run(
        [G_solver, G_loss],
        feed_dict={z: sample_z(mb_size, z_dim)}
    )

这是否意味着D和G正在并行训练?还是与以前相比,G现在“过时了” D?

1 个答案:

答案 0 :(得分:0)

将列表[D_solver, D_loss, clip_D, G_solver, G_loss]传递给功能sess.run()时,将不会并行训练鉴别器D和生成器G。该列表的所有操作都将被执行,但是函数Session.run()无法保证这些操作的执行顺序。 G可能在D之前执行,反之亦然。

在先前的张量流问题:Session.run()#13133中讨论了#10860的这种行为。

编辑:为已答题添加答案

如果您两次调用sess.run(如您的示例),则将首先训练鉴别器D,然后训练生成器G。 如果仅调用sess.run,并且列表fetches中D和G的所有操作都将以某种顺序执行。但是不能保证它将是哪个顺序。在每个呼叫中​​,可以首先训练D,然后训练G,或者可以首先训练G,然后训练D。 函数Session.run()遵循执行顺序,并且不会并行运行这些操作,即,图形操作不会同时执行。该执行顺序不一定是您在fetches=[D_solver, D_loss, clip_D, G_solver, G_loss]中传递的顺序。

例如,考虑第二种情况,在此情况下,我们只需一次调用sess.run()就可以传递所有操作。在您进行第一次训练时,可能会先执行G_loss,然后再执行G_solver,然后执行D_solver,依此类推。在第二次迭代中,我们实际上可能会得到{{ 1}}首先执行,然后执行D_loss,然后执行D_solver,等等。

示例由G_solver在每次迭代(无sess.run)下执行的顺序: 迭代1:G_loss,G_solver,D_solver,D_loss
迭代2:D_loss,D_solver,G_solver,G_loss
迭代3:G_solver,G_loss,D_loss,D_solver
迭代4:G_solver,G_loss,D_loss,D_solver ...

使用这种方法,您将不会在训练中有规律可循。例如,在第一次迭代中,我们训练D之前先训练G。在第二次迭代中,我们训练D时G中没有任何最近的更新,即,在迭代1和2中训练D之间没有训练G。

另一方面,考虑到我们依次训练D和G的第一种情况,我们保证在训练的每个迭代中,D在G之前进行训练,D的度量在G训练之前进行计算,并在训练D之后计算出G的指标。