Saya ingin menjalankan perhitungan yang berbeda berdasarkan nilai global step. Berikut adalah contoh minimal dari apa yang saya coba lakukan:

import tensorflow as tf

global_step = tf.train.get_or_create_global_step()
incr_global_step = global_step.assign(global_step + 1)

w = tf.cond(tf.equal(tf.mod(global_step, 2), 0),
            lambda : tf.get_variable('w1', initializer=tf.zeros([], dtype=tf.int32)),
            lambda : tf.get_variable('w2', initializer=tf.ones([], dtype=tf.int32)))

with tf.Session() as sess:
  sess.run(tf.global_variables_initializer())
  for _ in range(4):
    print(sess.run([w, incr_global_step]))

Saya mendapatkan kesalahan berikut:

FailedPreconditionError (see above for traceback): Attempting to use uninitialized value global_step
 [[Node: global_step/read = Identity[T=DT_INT64, _class=["loc:@global_step"], _device="/job:localhost/replica:0/task:0/cpu:0"](global_step)]]

Apakah ini perilaku yang diharapkan? Jika demikian, apa yang saya lakukan salah?

Saya menggunakan tensorflow 1.2

3
GeertH 7 Agustus 2017, 17:41

2 jawaban

Jawaban Terbaik

Jadi ya ini memang cukup aneh. Saya dapat menjalankan kode Anda dengan modifikasi berikut:

import tensorflow as tf

global_step = tf.train.get_or_create_global_step()
incr_global_step = global_step.assign(global_step + 1)

w = tf.cond(tf.equal(tf.mod(global_step.initialized_value(), 2), 0),
            lambda : tf.get_variable('w1', initializer=tf.zeros([], dtype=tf.int32)),
            lambda : tf.get_variable('w2', initializer=tf.ones([], dtype=tf.int32)).initialized_value())

with tf.Session() as sess:
  sess.run(tf.global_variables_initializer())
  for _ in range(4):
    print(sess.run([w, incr_global_step]))

Perhatikan bahwa saya harus menambahkan initialized_value ke global_step dan variabel 'w2' di tf.cond, tetapi entah bagaimana tidak ke 'w1' (Anda dapat meletakkannya juga dan itu akan berfungsi, tetapi tidak akan mengajukan jika Anda tidak, tampaknya). Metode ini, seperti yang disebutkan dalam dokumentasi, umumnya tidak diperlukan, dan hanya memberikan "tampilan" dari variabel yang dijamin akan digunakan setelah diinisialisasi. Mengapa tf.cond mengharuskan Anda untuk menggunakannya, dan mengapa dengan cara yang tidak konsisten, saya tidak tahu.

Selain itu, perhatikan bahwa cara Anda menjalankan kode sebenarnya tidak deterministik. Secara umum Anda akan mendapatkan ini:

[1, 1]
[0, 2]
[1, 3]
[0, 4]

Tapi tidak selalu. Ini adalah output yang baru saja saya dapatkan:

[0, 1]
[0, 2]
[1, 3]
[0, 4]

Hal ini karena urutan kenaikan dan kondisi yang dijalankan tidak deterministik. Lebih baik eksplisit tentang dependensi, jadi jika Anda ingin w menjalankan setelah kenaikan, Anda akan melakukan:

import tensorflow as tf

global_step = tf.train.get_or_create_global_step()
incr_global_step = global_step.assign(global_step + 1)

with tf.control_dependencies([incr_global_step]):
    w = tf.cond(tf.equal(tf.mod(global_step.initialized_value(), 2), 0),
                lambda : tf.get_variable('w1', initializer=tf.zeros([], dtype=tf.int32)).initialized_value(),
                lambda : tf.get_variable('w2', initializer=tf.ones([], dtype=tf.int32)).initialized_value())

with tf.Session() as sess:
  sess.run(tf.global_variables_initializer())
  for _ in range(4):
    print(sess.run([w, incr_global_step]))

Yang luar biasa mengharuskan saya untuk menambahkan initialized_value untuk 'w1' juga. Ini benar-benar tidak konsisten. Juga, output dalam hal ini adalah:

[0, 2]
[1, 3]
[0, 4]
[1, 5]

Sekarang, itu mengganggu saya bahwa hasil kenaikan dimulai pada dua. Sepertinya kenaikan dijalankan sekali lebih dari yang diharapkan. Jadi saya merasa tf.cond entah bagaimana memaksakan satu putaran pertama tambahan, yang akan menjadi penyebab perilakunya yang aneh.

Jika Anda menginginkan yang sebaliknya, jalankan w sebelum kenaikan, Anda dapat melakukan:

import tensorflow as tf

w = tf.cond(tf.equal(tf.mod(global_step.initialized_value(), 2), 0),
            lambda : tf.get_variable('w1', initializer=tf.zeros([], dtype=tf.int32)),
            lambda : tf.get_variable('w2', initializer=tf.ones([], dtype=tf.int32)).initialized_value())

with tf.control_dependencies([w]):
    incr_global_step = global_step.assign(global_step + 1)

with tf.Session() as sess:
  sess.run(tf.global_variables_initializer())
  for _ in range(4):
    print(sess.run([w, incr_global_step]))

Ya, saya tidak membutuhkan 'w1' initialized_value lagi. Ini menghasilkan:

[0, 1]
[1, 2]
[0, 3]
[1, 4]

Di sini kenaikannya, menurut saya, masuk akal.

3
jdehesa 7 Agustus 2017, 16:27

Anda harus menggunakan placeholder_with_default.

global_step = tf.placeholder_with_default(1, shape=[], name='global_step')
0
Ishant Mrinal 7 Agustus 2017, 15:24