通常在使用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?
答案 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的指标。