Тренировочный дискриминатор и генератор одновременно (Tensorflow) - PullRequest
0 голосов
/ 09 декабря 2018

Обычно в кодах GAN с использованием TensorFlow мы имеем следующую форму:

 _, 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).Однако что если мы сделаем следующее:

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

Значит ли это, что D и G проходят параллельную подготовку?Или, по сравнению с прошлым, G сейчас «устаревает» D?

1 Ответ

0 голосов
/ 17 декабря 2018

Дискриминатор D и генератор G не будут обучаться параллельно при передаче списка [D_solver, D_loss, clip_D, G_solver, G_loss] в функцию sess.run().Все операции этого списка будут выполнены, но функция Session.run() не может гарантировать какой-либо порядок выполнения этих операций.Может случиться, что G выполняется перед D или наоборот.

Такое поведение Session.run () обсуждалось в предыдущих выпусках тензорного потока: # 13133 и # 10860 .

Редактировать: добавить ответ на перефразированный вопрос

Если вы дважды наберете sess.run, как в вашем примере, вы сначала обучите дискриминатор D, а затем генератор G. Если вывызовите sess.run только один раз, со всеми операциями для D и G в списке fetches, все операции в этом списке будут выполнены в некотором порядке.Но нет никакой гарантии, в каком порядке это будет.При каждом вызове сначала можно обучить 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 и т. Д. На второй итерации мы можем фактически получить, что сначала выполняется D_loss, затемD_solver, затем G_solver и т. Д.

Пример с порядком выполнения, выполняемым sess.run на каждой итерации (без clip_D): Итерация 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 ...

При таком подходе выне будет шаблона в вашей подготовке.Например, на первой итерации мы обучаем G перед обучением D. На второй итерации мы обучаем D без какого-либо недавнего обновления в G, т. Е. G не обучался между обучением D на итерации 1 и 2.

С другой стороны, при рассмотрении первого сценария, в котором мы последовательно обучаем D и G, мы гарантируем, что на каждой итерации нашего обучения D обучается до G, а метрики для D рассчитываются до обучения G, иметрики для G рассчитываются после обучения D.

...