A strange bug in tf.scatter_add when I implement unpool in tensorflow











up vote
2
down vote

favorite












I'm trying to implement unpool in tensorflow with tf.scatter_add, but I meet a strange bug, here is my code:



import tensorflow as tf
import numpy as np
import random

tf.reset_default_graph()

mat = list(range(64))
random.shuffle(mat)
mat = np.array(mat)
mat = np.reshape(mat, [1,8,8,1])
M = tf.constant(mat, dtype=tf.float32)
pool1, argmax1 = tf.nn.max_pool_with_argmax(M, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
pool2, argmax2 = tf.nn.max_pool_with_argmax(pool1, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
pool3, argmax3 = tf.nn.max_pool_with_argmax(pool2, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')


def unpool(x, argmax, strides, unpool_shape=None, batch_size=None, name='unpool'):
x_shape = x.get_shape().as_list()
argmax_shape = argmax.get_shape().as_list()
assert not(x_shape[0] is None and batch_size is None), "must input batch_size if number of batch is alterable"
if x_shape[0] is None:
x_shape[0] = batch_size
if argmax_shape[0] is None:
argmax_shape[0] = x_shape[0]
if unpool_shape is None:
unpool_shape = [x_shape[i] * strides[i] for i in range(4)]
x_unpool = tf.get_variable(name=name, shape=[np.prod(unpool_shape)], initializer=tf.zeros_initializer(), trainable=False)
argmax = tf.cast(argmax, tf.int32)
argmax = tf.reshape(argmax, [np.prod(argmax_shape)])
x = tf.reshape(x, [np.prod(argmax.get_shape().as_list())])
x_unpool = tf.scatter_add(x_unpool , argmax, x)
x_unpool = tf.reshape(x_unpool , unpool_shape)
return x_unpool


unpool2 = unpool(pool3, argmax3, strides=[1,2,2,1], name='unpool3')
unpool1 = unpool(unpool2, argmax2, strides=[1,2,2,1], name='unpool2')
unpool0 = unpool(unpool1, argmax1, strides=[1,2,2,1], name='unpool1')


with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
mat_out = mat[:,:,:,0]
pool1_out = sess.run(pool1)[0,:,:,0]
pool2_out = sess.run(pool2)[0,:,:,0]
pool3_out = sess.run(pool3)[0,:,:,0]
argmax1_out = sess.run(argmax1)[0,:,:,0]
argmax2_out = sess.run(argmax2)[0,:,:,0]
argmax3_out = sess.run(argmax3)[0,:,:,0]
unpool2_out = sess.run(unpool2)[0,:,:,0]
unpool1_out = sess.run(unpool1)[0,:,:,0]
unpool0_out = sess.run(unpool0)[0,:,:,0]
print(unpool2_out)
print(unpool1_out)
print(unpool0_out)


output:



[[ 0.  0.]
[ 0. 63.]]
[[ 0. 0. 0. 0.]
[ 0. 0. 0. 0.]
[ 0. 0. 126. 0.]
[ 0. 0. 0. 0.]]
[[ 0. 0. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 315. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0. 0. 0.]
[ 0. 0. 0. 0. 0. 0. 0. 0.]]


The location is right, but the value is wrong. unpool2 is right, unpool1 is double of expected value, and unpool2 is quintuple of expected value. I don't what't wrong, can anyone tell me how to fix this bug?



Great thanks in advance.










share|improve this question




























    up vote
    2
    down vote

    favorite












    I'm trying to implement unpool in tensorflow with tf.scatter_add, but I meet a strange bug, here is my code:



    import tensorflow as tf
    import numpy as np
    import random

    tf.reset_default_graph()

    mat = list(range(64))
    random.shuffle(mat)
    mat = np.array(mat)
    mat = np.reshape(mat, [1,8,8,1])
    M = tf.constant(mat, dtype=tf.float32)
    pool1, argmax1 = tf.nn.max_pool_with_argmax(M, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
    pool2, argmax2 = tf.nn.max_pool_with_argmax(pool1, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
    pool3, argmax3 = tf.nn.max_pool_with_argmax(pool2, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')


    def unpool(x, argmax, strides, unpool_shape=None, batch_size=None, name='unpool'):
    x_shape = x.get_shape().as_list()
    argmax_shape = argmax.get_shape().as_list()
    assert not(x_shape[0] is None and batch_size is None), "must input batch_size if number of batch is alterable"
    if x_shape[0] is None:
    x_shape[0] = batch_size
    if argmax_shape[0] is None:
    argmax_shape[0] = x_shape[0]
    if unpool_shape is None:
    unpool_shape = [x_shape[i] * strides[i] for i in range(4)]
    x_unpool = tf.get_variable(name=name, shape=[np.prod(unpool_shape)], initializer=tf.zeros_initializer(), trainable=False)
    argmax = tf.cast(argmax, tf.int32)
    argmax = tf.reshape(argmax, [np.prod(argmax_shape)])
    x = tf.reshape(x, [np.prod(argmax.get_shape().as_list())])
    x_unpool = tf.scatter_add(x_unpool , argmax, x)
    x_unpool = tf.reshape(x_unpool , unpool_shape)
    return x_unpool


    unpool2 = unpool(pool3, argmax3, strides=[1,2,2,1], name='unpool3')
    unpool1 = unpool(unpool2, argmax2, strides=[1,2,2,1], name='unpool2')
    unpool0 = unpool(unpool1, argmax1, strides=[1,2,2,1], name='unpool1')


    with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    mat_out = mat[:,:,:,0]
    pool1_out = sess.run(pool1)[0,:,:,0]
    pool2_out = sess.run(pool2)[0,:,:,0]
    pool3_out = sess.run(pool3)[0,:,:,0]
    argmax1_out = sess.run(argmax1)[0,:,:,0]
    argmax2_out = sess.run(argmax2)[0,:,:,0]
    argmax3_out = sess.run(argmax3)[0,:,:,0]
    unpool2_out = sess.run(unpool2)[0,:,:,0]
    unpool1_out = sess.run(unpool1)[0,:,:,0]
    unpool0_out = sess.run(unpool0)[0,:,:,0]
    print(unpool2_out)
    print(unpool1_out)
    print(unpool0_out)


    output:



    [[ 0.  0.]
    [ 0. 63.]]
    [[ 0. 0. 0. 0.]
    [ 0. 0. 0. 0.]
    [ 0. 0. 126. 0.]
    [ 0. 0. 0. 0.]]
    [[ 0. 0. 0. 0. 0. 0. 0. 0.]
    [ 0. 0. 0. 0. 0. 0. 0. 0.]
    [ 0. 0. 0. 0. 0. 0. 0. 0.]
    [ 0. 0. 0. 0. 0. 0. 0. 0.]
    [ 0. 0. 0. 0. 0. 0. 0. 0.]
    [ 0. 0. 0. 0. 315. 0. 0. 0.]
    [ 0. 0. 0. 0. 0. 0. 0. 0.]
    [ 0. 0. 0. 0. 0. 0. 0. 0.]]


    The location is right, but the value is wrong. unpool2 is right, unpool1 is double of expected value, and unpool2 is quintuple of expected value. I don't what't wrong, can anyone tell me how to fix this bug?



    Great thanks in advance.










    share|improve this question


























      up vote
      2
      down vote

      favorite









      up vote
      2
      down vote

      favorite











      I'm trying to implement unpool in tensorflow with tf.scatter_add, but I meet a strange bug, here is my code:



      import tensorflow as tf
      import numpy as np
      import random

      tf.reset_default_graph()

      mat = list(range(64))
      random.shuffle(mat)
      mat = np.array(mat)
      mat = np.reshape(mat, [1,8,8,1])
      M = tf.constant(mat, dtype=tf.float32)
      pool1, argmax1 = tf.nn.max_pool_with_argmax(M, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
      pool2, argmax2 = tf.nn.max_pool_with_argmax(pool1, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
      pool3, argmax3 = tf.nn.max_pool_with_argmax(pool2, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')


      def unpool(x, argmax, strides, unpool_shape=None, batch_size=None, name='unpool'):
      x_shape = x.get_shape().as_list()
      argmax_shape = argmax.get_shape().as_list()
      assert not(x_shape[0] is None and batch_size is None), "must input batch_size if number of batch is alterable"
      if x_shape[0] is None:
      x_shape[0] = batch_size
      if argmax_shape[0] is None:
      argmax_shape[0] = x_shape[0]
      if unpool_shape is None:
      unpool_shape = [x_shape[i] * strides[i] for i in range(4)]
      x_unpool = tf.get_variable(name=name, shape=[np.prod(unpool_shape)], initializer=tf.zeros_initializer(), trainable=False)
      argmax = tf.cast(argmax, tf.int32)
      argmax = tf.reshape(argmax, [np.prod(argmax_shape)])
      x = tf.reshape(x, [np.prod(argmax.get_shape().as_list())])
      x_unpool = tf.scatter_add(x_unpool , argmax, x)
      x_unpool = tf.reshape(x_unpool , unpool_shape)
      return x_unpool


      unpool2 = unpool(pool3, argmax3, strides=[1,2,2,1], name='unpool3')
      unpool1 = unpool(unpool2, argmax2, strides=[1,2,2,1], name='unpool2')
      unpool0 = unpool(unpool1, argmax1, strides=[1,2,2,1], name='unpool1')


      with tf.Session() as sess:
      sess.run(tf.global_variables_initializer())
      mat_out = mat[:,:,:,0]
      pool1_out = sess.run(pool1)[0,:,:,0]
      pool2_out = sess.run(pool2)[0,:,:,0]
      pool3_out = sess.run(pool3)[0,:,:,0]
      argmax1_out = sess.run(argmax1)[0,:,:,0]
      argmax2_out = sess.run(argmax2)[0,:,:,0]
      argmax3_out = sess.run(argmax3)[0,:,:,0]
      unpool2_out = sess.run(unpool2)[0,:,:,0]
      unpool1_out = sess.run(unpool1)[0,:,:,0]
      unpool0_out = sess.run(unpool0)[0,:,:,0]
      print(unpool2_out)
      print(unpool1_out)
      print(unpool0_out)


      output:



      [[ 0.  0.]
      [ 0. 63.]]
      [[ 0. 0. 0. 0.]
      [ 0. 0. 0. 0.]
      [ 0. 0. 126. 0.]
      [ 0. 0. 0. 0.]]
      [[ 0. 0. 0. 0. 0. 0. 0. 0.]
      [ 0. 0. 0. 0. 0. 0. 0. 0.]
      [ 0. 0. 0. 0. 0. 0. 0. 0.]
      [ 0. 0. 0. 0. 0. 0. 0. 0.]
      [ 0. 0. 0. 0. 0. 0. 0. 0.]
      [ 0. 0. 0. 0. 315. 0. 0. 0.]
      [ 0. 0. 0. 0. 0. 0. 0. 0.]
      [ 0. 0. 0. 0. 0. 0. 0. 0.]]


      The location is right, but the value is wrong. unpool2 is right, unpool1 is double of expected value, and unpool2 is quintuple of expected value. I don't what't wrong, can anyone tell me how to fix this bug?



      Great thanks in advance.










      share|improve this question















      I'm trying to implement unpool in tensorflow with tf.scatter_add, but I meet a strange bug, here is my code:



      import tensorflow as tf
      import numpy as np
      import random

      tf.reset_default_graph()

      mat = list(range(64))
      random.shuffle(mat)
      mat = np.array(mat)
      mat = np.reshape(mat, [1,8,8,1])
      M = tf.constant(mat, dtype=tf.float32)
      pool1, argmax1 = tf.nn.max_pool_with_argmax(M, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
      pool2, argmax2 = tf.nn.max_pool_with_argmax(pool1, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
      pool3, argmax3 = tf.nn.max_pool_with_argmax(pool2, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')


      def unpool(x, argmax, strides, unpool_shape=None, batch_size=None, name='unpool'):
      x_shape = x.get_shape().as_list()
      argmax_shape = argmax.get_shape().as_list()
      assert not(x_shape[0] is None and batch_size is None), "must input batch_size if number of batch is alterable"
      if x_shape[0] is None:
      x_shape[0] = batch_size
      if argmax_shape[0] is None:
      argmax_shape[0] = x_shape[0]
      if unpool_shape is None:
      unpool_shape = [x_shape[i] * strides[i] for i in range(4)]
      x_unpool = tf.get_variable(name=name, shape=[np.prod(unpool_shape)], initializer=tf.zeros_initializer(), trainable=False)
      argmax = tf.cast(argmax, tf.int32)
      argmax = tf.reshape(argmax, [np.prod(argmax_shape)])
      x = tf.reshape(x, [np.prod(argmax.get_shape().as_list())])
      x_unpool = tf.scatter_add(x_unpool , argmax, x)
      x_unpool = tf.reshape(x_unpool , unpool_shape)
      return x_unpool


      unpool2 = unpool(pool3, argmax3, strides=[1,2,2,1], name='unpool3')
      unpool1 = unpool(unpool2, argmax2, strides=[1,2,2,1], name='unpool2')
      unpool0 = unpool(unpool1, argmax1, strides=[1,2,2,1], name='unpool1')


      with tf.Session() as sess:
      sess.run(tf.global_variables_initializer())
      mat_out = mat[:,:,:,0]
      pool1_out = sess.run(pool1)[0,:,:,0]
      pool2_out = sess.run(pool2)[0,:,:,0]
      pool3_out = sess.run(pool3)[0,:,:,0]
      argmax1_out = sess.run(argmax1)[0,:,:,0]
      argmax2_out = sess.run(argmax2)[0,:,:,0]
      argmax3_out = sess.run(argmax3)[0,:,:,0]
      unpool2_out = sess.run(unpool2)[0,:,:,0]
      unpool1_out = sess.run(unpool1)[0,:,:,0]
      unpool0_out = sess.run(unpool0)[0,:,:,0]
      print(unpool2_out)
      print(unpool1_out)
      print(unpool0_out)


      output:



      [[ 0.  0.]
      [ 0. 63.]]
      [[ 0. 0. 0. 0.]
      [ 0. 0. 0. 0.]
      [ 0. 0. 126. 0.]
      [ 0. 0. 0. 0.]]
      [[ 0. 0. 0. 0. 0. 0. 0. 0.]
      [ 0. 0. 0. 0. 0. 0. 0. 0.]
      [ 0. 0. 0. 0. 0. 0. 0. 0.]
      [ 0. 0. 0. 0. 0. 0. 0. 0.]
      [ 0. 0. 0. 0. 0. 0. 0. 0.]
      [ 0. 0. 0. 0. 315. 0. 0. 0.]
      [ 0. 0. 0. 0. 0. 0. 0. 0.]
      [ 0. 0. 0. 0. 0. 0. 0. 0.]]


      The location is right, but the value is wrong. unpool2 is right, unpool1 is double of expected value, and unpool2 is quintuple of expected value. I don't what't wrong, can anyone tell me how to fix this bug?



      Great thanks in advance.







      python tensorflow






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited yesterday

























      asked Nov 8 at 9:27









      张庆昊

      1329




      1329
























          2 Answers
          2






          active

          oldest

          votes

















          up vote
          0
          down vote













          Use tf.scatter_update will avoid this bug, but I still want to konw what's the reason for this bug.



          import tensorflow as tf
          import numpy as np
          import random

          tf.reset_default_graph()

          mat = list(range(64))
          random.shuffle(mat)
          mat = np.array(mat)
          mat = np.reshape(mat, [1,8,8,1])
          M = tf.constant(mat, dtype=tf.float32)
          pool1, argmax1 = tf.nn.max_pool_with_argmax(M, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
          pool2, argmax2 = tf.nn.max_pool_with_argmax(pool1, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
          pool3, argmax3 = tf.nn.max_pool_with_argmax(pool2, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')


          def unpool(x, argmax, strides, unpool_shape=None, batch_size=None, name='unpool'):
          x_shape = x.get_shape().as_list()
          argmax_shape = argmax.get_shape().as_list()
          assert not(x_shape[0] is None and batch_size is None), "must input batch_size if number of batch is alterable"
          if x_shape[0] is None:
          x_shape[0] = batch_size
          if argmax_shape[0] is None:
          argmax_shape[0] = x_shape[0]
          if unpool_shape is None:
          unpool_shape = [x_shape[i] * strides[i] for i in range(4)]
          unpool = tf.get_variable(name=name, shape=[np.prod(unpool_shape)], initializer=tf.zeros_initializer(), trainable=False)
          argmax = tf.cast(argmax, tf.int32)
          argmax = tf.reshape(argmax, [np.prod(argmax_shape)])
          x = tf.reshape(x, [np.prod(argmax.get_shape().as_list())])
          unpool = tf.scatter_update(unpool, argmax, x)
          unpool = tf.reshape(unpool, unpool_shape)
          return unpool


          unpool2 = unpool(pool3, argmax3, strides=[1,2,2,1], name='unpool3')
          unpool1 = unpool(unpool2, argmax2, strides=[1,2,2,1], name='unpool2')
          unpool0 = unpool(unpool1, argmax1, strides=[1,2,2,1], name='unpool1')


          with tf.Session() as sess:
          sess.run(tf.global_variables_initializer())
          mat_out = mat[:,:,:,0]
          pool1_out = sess.run(pool1)[0,:,:,0]
          pool2_out = sess.run(pool2)[0,:,:,0]
          pool3_out = sess.run(pool3)[0,:,:,0]
          argmax1_out = sess.run(argmax1)[0,:,:,0]
          argmax2_out = sess.run(argmax2)[0,:,:,0]
          argmax3_out = sess.run(argmax3)[0,:,:,0]
          unpool2_out = sess.run(unpool2)[0,:,:,0]
          unpool1_out = sess.run(unpool1)[0,:,:,0]
          unpool0_out = sess.run(unpool0)[0,:,:,0]
          print(unpool2_out)
          print(unpool1_out)
          print(unpool0_out)


          output:



          [[ 0.  0.]
          [ 0. 63.]]
          [[ 0. 0. 0. 0.]
          [ 0. 0. 0. 0.]
          [ 0. 0. 0. 63.]
          [ 0. 0. 0. 0.]]
          [[ 0. 0. 0. 0. 0. 0. 0. 0.]
          [ 0. 0. 0. 0. 0. 0. 0. 0.]
          [ 0. 0. 0. 0. 0. 0. 0. 0.]
          [ 0. 0. 0. 0. 0. 0. 0. 0.]
          [ 0. 0. 0. 0. 0. 0. 0. 0.]
          [ 0. 0. 0. 0. 0. 0. 0. 63.]
          [ 0. 0. 0. 0. 0. 0. 0. 0.]
          [ 0. 0. 0. 0. 0. 0. 0. 0.]]





          share|improve this answer






























            up vote
            0
            down vote



            accepted










            In fact, the answer is simple. For convenience, I rename some variables, look this code:



            def unpool(x, argmax, strides, unpool_shape=None, batch_size=None, name='unpool'):
            x_shape = x.get_shape().as_list()
            argmax_shape = argmax.get_shape().as_list()
            assert not(x_shape[0] is None and batch_size is None), "must input batch_size if number of batch is alterable"
            if x_shape[0] is None:
            x_shape[0] = batch_size
            if argmax_shape[0] is None:
            argmax_shape[0] = x_shape[0]
            if unpool_shape is None:
            unpool_shape = [x_shape[i] * strides[i] for i in range(4)]
            x_unpool = tf.get_variable(name=name, shape=[np.prod(unpool_shape)], initializer=tf.zeros_initializer(), trainable=False)
            argmax = tf.cast(argmax, tf.int32)
            argmax = tf.reshape(argmax, [np.prod(argmax_shape)])
            x = tf.reshape(x, [np.prod(argmax.get_shape().as_list())])
            x_unpool_add = tf.scatter_add(x_unpool , argmax, x)
            x_unpool_reshape = tf.reshape(x_unpool_add , unpool_shape)
            return x_unpool_reshape


            x_unpool_add is a op of tf.scatter_add, everytime we compute x_unpool_reshape, x_unpool_add will be called. So x_unpool will add x twice if we compute unpool2 twice. In my origin code, I compute unpool0, unpool1, unpool2 in order, x_unpool_add of unpool1 is called firstly, then when we compute unpool2, because of we need compute unpool1, x_unpool_add will be called again, so it's equal to call x_unpool_add twice, the value is wrong. If we compute unpool2 directly, we will get right result. So replacling tf.scatter_add with tf.scatter_update can avoid this bug.



            This code can reproducible this intuitively:



            import tensorflow as tf

            t1 = tf.get_variable(name='t1', shape=[1], dtype=tf.float32, initializer=tf.zeros_initializer())
            t2 = tf.get_variable(name='t2', shape=[1], dtype=tf.float32, initializer=tf.zeros_initializer())
            d = tf.scatter_add(t1, [0], [1])
            e = tf.scatter_add(t2, [0], d)

            with tf.Session() as sess:
            sess.run(tf.global_variables_initializer())
            d_out1 = sess.run(d)
            d_out2 = sess.run(d)
            e_out = sess.run(e)
            print(d_out1)
            print(d_out2)
            print(e_out)


            output:



            [1.]
            [2.]
            [3.]





            share|improve this answer























              Your Answer






              StackExchange.ifUsing("editor", function () {
              StackExchange.using("externalEditor", function () {
              StackExchange.using("snippets", function () {
              StackExchange.snippets.init();
              });
              });
              }, "code-snippets");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "1"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














               

              draft saved


              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53204794%2fa-strange-bug-in-tf-scatter-add-when-i-implement-unpool-in-tensorflow%23new-answer', 'question_page');
              }
              );

              Post as a guest
































              2 Answers
              2






              active

              oldest

              votes








              2 Answers
              2






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes








              up vote
              0
              down vote













              Use tf.scatter_update will avoid this bug, but I still want to konw what's the reason for this bug.



              import tensorflow as tf
              import numpy as np
              import random

              tf.reset_default_graph()

              mat = list(range(64))
              random.shuffle(mat)
              mat = np.array(mat)
              mat = np.reshape(mat, [1,8,8,1])
              M = tf.constant(mat, dtype=tf.float32)
              pool1, argmax1 = tf.nn.max_pool_with_argmax(M, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
              pool2, argmax2 = tf.nn.max_pool_with_argmax(pool1, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
              pool3, argmax3 = tf.nn.max_pool_with_argmax(pool2, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')


              def unpool(x, argmax, strides, unpool_shape=None, batch_size=None, name='unpool'):
              x_shape = x.get_shape().as_list()
              argmax_shape = argmax.get_shape().as_list()
              assert not(x_shape[0] is None and batch_size is None), "must input batch_size if number of batch is alterable"
              if x_shape[0] is None:
              x_shape[0] = batch_size
              if argmax_shape[0] is None:
              argmax_shape[0] = x_shape[0]
              if unpool_shape is None:
              unpool_shape = [x_shape[i] * strides[i] for i in range(4)]
              unpool = tf.get_variable(name=name, shape=[np.prod(unpool_shape)], initializer=tf.zeros_initializer(), trainable=False)
              argmax = tf.cast(argmax, tf.int32)
              argmax = tf.reshape(argmax, [np.prod(argmax_shape)])
              x = tf.reshape(x, [np.prod(argmax.get_shape().as_list())])
              unpool = tf.scatter_update(unpool, argmax, x)
              unpool = tf.reshape(unpool, unpool_shape)
              return unpool


              unpool2 = unpool(pool3, argmax3, strides=[1,2,2,1], name='unpool3')
              unpool1 = unpool(unpool2, argmax2, strides=[1,2,2,1], name='unpool2')
              unpool0 = unpool(unpool1, argmax1, strides=[1,2,2,1], name='unpool1')


              with tf.Session() as sess:
              sess.run(tf.global_variables_initializer())
              mat_out = mat[:,:,:,0]
              pool1_out = sess.run(pool1)[0,:,:,0]
              pool2_out = sess.run(pool2)[0,:,:,0]
              pool3_out = sess.run(pool3)[0,:,:,0]
              argmax1_out = sess.run(argmax1)[0,:,:,0]
              argmax2_out = sess.run(argmax2)[0,:,:,0]
              argmax3_out = sess.run(argmax3)[0,:,:,0]
              unpool2_out = sess.run(unpool2)[0,:,:,0]
              unpool1_out = sess.run(unpool1)[0,:,:,0]
              unpool0_out = sess.run(unpool0)[0,:,:,0]
              print(unpool2_out)
              print(unpool1_out)
              print(unpool0_out)


              output:



              [[ 0.  0.]
              [ 0. 63.]]
              [[ 0. 0. 0. 0.]
              [ 0. 0. 0. 0.]
              [ 0. 0. 0. 63.]
              [ 0. 0. 0. 0.]]
              [[ 0. 0. 0. 0. 0. 0. 0. 0.]
              [ 0. 0. 0. 0. 0. 0. 0. 0.]
              [ 0. 0. 0. 0. 0. 0. 0. 0.]
              [ 0. 0. 0. 0. 0. 0. 0. 0.]
              [ 0. 0. 0. 0. 0. 0. 0. 0.]
              [ 0. 0. 0. 0. 0. 0. 0. 63.]
              [ 0. 0. 0. 0. 0. 0. 0. 0.]
              [ 0. 0. 0. 0. 0. 0. 0. 0.]]





              share|improve this answer



























                up vote
                0
                down vote













                Use tf.scatter_update will avoid this bug, but I still want to konw what's the reason for this bug.



                import tensorflow as tf
                import numpy as np
                import random

                tf.reset_default_graph()

                mat = list(range(64))
                random.shuffle(mat)
                mat = np.array(mat)
                mat = np.reshape(mat, [1,8,8,1])
                M = tf.constant(mat, dtype=tf.float32)
                pool1, argmax1 = tf.nn.max_pool_with_argmax(M, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
                pool2, argmax2 = tf.nn.max_pool_with_argmax(pool1, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
                pool3, argmax3 = tf.nn.max_pool_with_argmax(pool2, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')


                def unpool(x, argmax, strides, unpool_shape=None, batch_size=None, name='unpool'):
                x_shape = x.get_shape().as_list()
                argmax_shape = argmax.get_shape().as_list()
                assert not(x_shape[0] is None and batch_size is None), "must input batch_size if number of batch is alterable"
                if x_shape[0] is None:
                x_shape[0] = batch_size
                if argmax_shape[0] is None:
                argmax_shape[0] = x_shape[0]
                if unpool_shape is None:
                unpool_shape = [x_shape[i] * strides[i] for i in range(4)]
                unpool = tf.get_variable(name=name, shape=[np.prod(unpool_shape)], initializer=tf.zeros_initializer(), trainable=False)
                argmax = tf.cast(argmax, tf.int32)
                argmax = tf.reshape(argmax, [np.prod(argmax_shape)])
                x = tf.reshape(x, [np.prod(argmax.get_shape().as_list())])
                unpool = tf.scatter_update(unpool, argmax, x)
                unpool = tf.reshape(unpool, unpool_shape)
                return unpool


                unpool2 = unpool(pool3, argmax3, strides=[1,2,2,1], name='unpool3')
                unpool1 = unpool(unpool2, argmax2, strides=[1,2,2,1], name='unpool2')
                unpool0 = unpool(unpool1, argmax1, strides=[1,2,2,1], name='unpool1')


                with tf.Session() as sess:
                sess.run(tf.global_variables_initializer())
                mat_out = mat[:,:,:,0]
                pool1_out = sess.run(pool1)[0,:,:,0]
                pool2_out = sess.run(pool2)[0,:,:,0]
                pool3_out = sess.run(pool3)[0,:,:,0]
                argmax1_out = sess.run(argmax1)[0,:,:,0]
                argmax2_out = sess.run(argmax2)[0,:,:,0]
                argmax3_out = sess.run(argmax3)[0,:,:,0]
                unpool2_out = sess.run(unpool2)[0,:,:,0]
                unpool1_out = sess.run(unpool1)[0,:,:,0]
                unpool0_out = sess.run(unpool0)[0,:,:,0]
                print(unpool2_out)
                print(unpool1_out)
                print(unpool0_out)


                output:



                [[ 0.  0.]
                [ 0. 63.]]
                [[ 0. 0. 0. 0.]
                [ 0. 0. 0. 0.]
                [ 0. 0. 0. 63.]
                [ 0. 0. 0. 0.]]
                [[ 0. 0. 0. 0. 0. 0. 0. 0.]
                [ 0. 0. 0. 0. 0. 0. 0. 0.]
                [ 0. 0. 0. 0. 0. 0. 0. 0.]
                [ 0. 0. 0. 0. 0. 0. 0. 0.]
                [ 0. 0. 0. 0. 0. 0. 0. 0.]
                [ 0. 0. 0. 0. 0. 0. 0. 63.]
                [ 0. 0. 0. 0. 0. 0. 0. 0.]
                [ 0. 0. 0. 0. 0. 0. 0. 0.]]





                share|improve this answer

























                  up vote
                  0
                  down vote










                  up vote
                  0
                  down vote









                  Use tf.scatter_update will avoid this bug, but I still want to konw what's the reason for this bug.



                  import tensorflow as tf
                  import numpy as np
                  import random

                  tf.reset_default_graph()

                  mat = list(range(64))
                  random.shuffle(mat)
                  mat = np.array(mat)
                  mat = np.reshape(mat, [1,8,8,1])
                  M = tf.constant(mat, dtype=tf.float32)
                  pool1, argmax1 = tf.nn.max_pool_with_argmax(M, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
                  pool2, argmax2 = tf.nn.max_pool_with_argmax(pool1, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
                  pool3, argmax3 = tf.nn.max_pool_with_argmax(pool2, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')


                  def unpool(x, argmax, strides, unpool_shape=None, batch_size=None, name='unpool'):
                  x_shape = x.get_shape().as_list()
                  argmax_shape = argmax.get_shape().as_list()
                  assert not(x_shape[0] is None and batch_size is None), "must input batch_size if number of batch is alterable"
                  if x_shape[0] is None:
                  x_shape[0] = batch_size
                  if argmax_shape[0] is None:
                  argmax_shape[0] = x_shape[0]
                  if unpool_shape is None:
                  unpool_shape = [x_shape[i] * strides[i] for i in range(4)]
                  unpool = tf.get_variable(name=name, shape=[np.prod(unpool_shape)], initializer=tf.zeros_initializer(), trainable=False)
                  argmax = tf.cast(argmax, tf.int32)
                  argmax = tf.reshape(argmax, [np.prod(argmax_shape)])
                  x = tf.reshape(x, [np.prod(argmax.get_shape().as_list())])
                  unpool = tf.scatter_update(unpool, argmax, x)
                  unpool = tf.reshape(unpool, unpool_shape)
                  return unpool


                  unpool2 = unpool(pool3, argmax3, strides=[1,2,2,1], name='unpool3')
                  unpool1 = unpool(unpool2, argmax2, strides=[1,2,2,1], name='unpool2')
                  unpool0 = unpool(unpool1, argmax1, strides=[1,2,2,1], name='unpool1')


                  with tf.Session() as sess:
                  sess.run(tf.global_variables_initializer())
                  mat_out = mat[:,:,:,0]
                  pool1_out = sess.run(pool1)[0,:,:,0]
                  pool2_out = sess.run(pool2)[0,:,:,0]
                  pool3_out = sess.run(pool3)[0,:,:,0]
                  argmax1_out = sess.run(argmax1)[0,:,:,0]
                  argmax2_out = sess.run(argmax2)[0,:,:,0]
                  argmax3_out = sess.run(argmax3)[0,:,:,0]
                  unpool2_out = sess.run(unpool2)[0,:,:,0]
                  unpool1_out = sess.run(unpool1)[0,:,:,0]
                  unpool0_out = sess.run(unpool0)[0,:,:,0]
                  print(unpool2_out)
                  print(unpool1_out)
                  print(unpool0_out)


                  output:



                  [[ 0.  0.]
                  [ 0. 63.]]
                  [[ 0. 0. 0. 0.]
                  [ 0. 0. 0. 0.]
                  [ 0. 0. 0. 63.]
                  [ 0. 0. 0. 0.]]
                  [[ 0. 0. 0. 0. 0. 0. 0. 0.]
                  [ 0. 0. 0. 0. 0. 0. 0. 0.]
                  [ 0. 0. 0. 0. 0. 0. 0. 0.]
                  [ 0. 0. 0. 0. 0. 0. 0. 0.]
                  [ 0. 0. 0. 0. 0. 0. 0. 0.]
                  [ 0. 0. 0. 0. 0. 0. 0. 63.]
                  [ 0. 0. 0. 0. 0. 0. 0. 0.]
                  [ 0. 0. 0. 0. 0. 0. 0. 0.]]





                  share|improve this answer














                  Use tf.scatter_update will avoid this bug, but I still want to konw what's the reason for this bug.



                  import tensorflow as tf
                  import numpy as np
                  import random

                  tf.reset_default_graph()

                  mat = list(range(64))
                  random.shuffle(mat)
                  mat = np.array(mat)
                  mat = np.reshape(mat, [1,8,8,1])
                  M = tf.constant(mat, dtype=tf.float32)
                  pool1, argmax1 = tf.nn.max_pool_with_argmax(M, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
                  pool2, argmax2 = tf.nn.max_pool_with_argmax(pool1, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
                  pool3, argmax3 = tf.nn.max_pool_with_argmax(pool2, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')


                  def unpool(x, argmax, strides, unpool_shape=None, batch_size=None, name='unpool'):
                  x_shape = x.get_shape().as_list()
                  argmax_shape = argmax.get_shape().as_list()
                  assert not(x_shape[0] is None and batch_size is None), "must input batch_size if number of batch is alterable"
                  if x_shape[0] is None:
                  x_shape[0] = batch_size
                  if argmax_shape[0] is None:
                  argmax_shape[0] = x_shape[0]
                  if unpool_shape is None:
                  unpool_shape = [x_shape[i] * strides[i] for i in range(4)]
                  unpool = tf.get_variable(name=name, shape=[np.prod(unpool_shape)], initializer=tf.zeros_initializer(), trainable=False)
                  argmax = tf.cast(argmax, tf.int32)
                  argmax = tf.reshape(argmax, [np.prod(argmax_shape)])
                  x = tf.reshape(x, [np.prod(argmax.get_shape().as_list())])
                  unpool = tf.scatter_update(unpool, argmax, x)
                  unpool = tf.reshape(unpool, unpool_shape)
                  return unpool


                  unpool2 = unpool(pool3, argmax3, strides=[1,2,2,1], name='unpool3')
                  unpool1 = unpool(unpool2, argmax2, strides=[1,2,2,1], name='unpool2')
                  unpool0 = unpool(unpool1, argmax1, strides=[1,2,2,1], name='unpool1')


                  with tf.Session() as sess:
                  sess.run(tf.global_variables_initializer())
                  mat_out = mat[:,:,:,0]
                  pool1_out = sess.run(pool1)[0,:,:,0]
                  pool2_out = sess.run(pool2)[0,:,:,0]
                  pool3_out = sess.run(pool3)[0,:,:,0]
                  argmax1_out = sess.run(argmax1)[0,:,:,0]
                  argmax2_out = sess.run(argmax2)[0,:,:,0]
                  argmax3_out = sess.run(argmax3)[0,:,:,0]
                  unpool2_out = sess.run(unpool2)[0,:,:,0]
                  unpool1_out = sess.run(unpool1)[0,:,:,0]
                  unpool0_out = sess.run(unpool0)[0,:,:,0]
                  print(unpool2_out)
                  print(unpool1_out)
                  print(unpool0_out)


                  output:



                  [[ 0.  0.]
                  [ 0. 63.]]
                  [[ 0. 0. 0. 0.]
                  [ 0. 0. 0. 0.]
                  [ 0. 0. 0. 63.]
                  [ 0. 0. 0. 0.]]
                  [[ 0. 0. 0. 0. 0. 0. 0. 0.]
                  [ 0. 0. 0. 0. 0. 0. 0. 0.]
                  [ 0. 0. 0. 0. 0. 0. 0. 0.]
                  [ 0. 0. 0. 0. 0. 0. 0. 0.]
                  [ 0. 0. 0. 0. 0. 0. 0. 0.]
                  [ 0. 0. 0. 0. 0. 0. 0. 63.]
                  [ 0. 0. 0. 0. 0. 0. 0. 0.]
                  [ 0. 0. 0. 0. 0. 0. 0. 0.]]






                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Nov 9 at 1:25

























                  answered Nov 8 at 9:31









                  张庆昊

                  1329




                  1329
























                      up vote
                      0
                      down vote



                      accepted










                      In fact, the answer is simple. For convenience, I rename some variables, look this code:



                      def unpool(x, argmax, strides, unpool_shape=None, batch_size=None, name='unpool'):
                      x_shape = x.get_shape().as_list()
                      argmax_shape = argmax.get_shape().as_list()
                      assert not(x_shape[0] is None and batch_size is None), "must input batch_size if number of batch is alterable"
                      if x_shape[0] is None:
                      x_shape[0] = batch_size
                      if argmax_shape[0] is None:
                      argmax_shape[0] = x_shape[0]
                      if unpool_shape is None:
                      unpool_shape = [x_shape[i] * strides[i] for i in range(4)]
                      x_unpool = tf.get_variable(name=name, shape=[np.prod(unpool_shape)], initializer=tf.zeros_initializer(), trainable=False)
                      argmax = tf.cast(argmax, tf.int32)
                      argmax = tf.reshape(argmax, [np.prod(argmax_shape)])
                      x = tf.reshape(x, [np.prod(argmax.get_shape().as_list())])
                      x_unpool_add = tf.scatter_add(x_unpool , argmax, x)
                      x_unpool_reshape = tf.reshape(x_unpool_add , unpool_shape)
                      return x_unpool_reshape


                      x_unpool_add is a op of tf.scatter_add, everytime we compute x_unpool_reshape, x_unpool_add will be called. So x_unpool will add x twice if we compute unpool2 twice. In my origin code, I compute unpool0, unpool1, unpool2 in order, x_unpool_add of unpool1 is called firstly, then when we compute unpool2, because of we need compute unpool1, x_unpool_add will be called again, so it's equal to call x_unpool_add twice, the value is wrong. If we compute unpool2 directly, we will get right result. So replacling tf.scatter_add with tf.scatter_update can avoid this bug.



                      This code can reproducible this intuitively:



                      import tensorflow as tf

                      t1 = tf.get_variable(name='t1', shape=[1], dtype=tf.float32, initializer=tf.zeros_initializer())
                      t2 = tf.get_variable(name='t2', shape=[1], dtype=tf.float32, initializer=tf.zeros_initializer())
                      d = tf.scatter_add(t1, [0], [1])
                      e = tf.scatter_add(t2, [0], d)

                      with tf.Session() as sess:
                      sess.run(tf.global_variables_initializer())
                      d_out1 = sess.run(d)
                      d_out2 = sess.run(d)
                      e_out = sess.run(e)
                      print(d_out1)
                      print(d_out2)
                      print(e_out)


                      output:



                      [1.]
                      [2.]
                      [3.]





                      share|improve this answer



























                        up vote
                        0
                        down vote



                        accepted










                        In fact, the answer is simple. For convenience, I rename some variables, look this code:



                        def unpool(x, argmax, strides, unpool_shape=None, batch_size=None, name='unpool'):
                        x_shape = x.get_shape().as_list()
                        argmax_shape = argmax.get_shape().as_list()
                        assert not(x_shape[0] is None and batch_size is None), "must input batch_size if number of batch is alterable"
                        if x_shape[0] is None:
                        x_shape[0] = batch_size
                        if argmax_shape[0] is None:
                        argmax_shape[0] = x_shape[0]
                        if unpool_shape is None:
                        unpool_shape = [x_shape[i] * strides[i] for i in range(4)]
                        x_unpool = tf.get_variable(name=name, shape=[np.prod(unpool_shape)], initializer=tf.zeros_initializer(), trainable=False)
                        argmax = tf.cast(argmax, tf.int32)
                        argmax = tf.reshape(argmax, [np.prod(argmax_shape)])
                        x = tf.reshape(x, [np.prod(argmax.get_shape().as_list())])
                        x_unpool_add = tf.scatter_add(x_unpool , argmax, x)
                        x_unpool_reshape = tf.reshape(x_unpool_add , unpool_shape)
                        return x_unpool_reshape


                        x_unpool_add is a op of tf.scatter_add, everytime we compute x_unpool_reshape, x_unpool_add will be called. So x_unpool will add x twice if we compute unpool2 twice. In my origin code, I compute unpool0, unpool1, unpool2 in order, x_unpool_add of unpool1 is called firstly, then when we compute unpool2, because of we need compute unpool1, x_unpool_add will be called again, so it's equal to call x_unpool_add twice, the value is wrong. If we compute unpool2 directly, we will get right result. So replacling tf.scatter_add with tf.scatter_update can avoid this bug.



                        This code can reproducible this intuitively:



                        import tensorflow as tf

                        t1 = tf.get_variable(name='t1', shape=[1], dtype=tf.float32, initializer=tf.zeros_initializer())
                        t2 = tf.get_variable(name='t2', shape=[1], dtype=tf.float32, initializer=tf.zeros_initializer())
                        d = tf.scatter_add(t1, [0], [1])
                        e = tf.scatter_add(t2, [0], d)

                        with tf.Session() as sess:
                        sess.run(tf.global_variables_initializer())
                        d_out1 = sess.run(d)
                        d_out2 = sess.run(d)
                        e_out = sess.run(e)
                        print(d_out1)
                        print(d_out2)
                        print(e_out)


                        output:



                        [1.]
                        [2.]
                        [3.]





                        share|improve this answer

























                          up vote
                          0
                          down vote



                          accepted







                          up vote
                          0
                          down vote



                          accepted






                          In fact, the answer is simple. For convenience, I rename some variables, look this code:



                          def unpool(x, argmax, strides, unpool_shape=None, batch_size=None, name='unpool'):
                          x_shape = x.get_shape().as_list()
                          argmax_shape = argmax.get_shape().as_list()
                          assert not(x_shape[0] is None and batch_size is None), "must input batch_size if number of batch is alterable"
                          if x_shape[0] is None:
                          x_shape[0] = batch_size
                          if argmax_shape[0] is None:
                          argmax_shape[0] = x_shape[0]
                          if unpool_shape is None:
                          unpool_shape = [x_shape[i] * strides[i] for i in range(4)]
                          x_unpool = tf.get_variable(name=name, shape=[np.prod(unpool_shape)], initializer=tf.zeros_initializer(), trainable=False)
                          argmax = tf.cast(argmax, tf.int32)
                          argmax = tf.reshape(argmax, [np.prod(argmax_shape)])
                          x = tf.reshape(x, [np.prod(argmax.get_shape().as_list())])
                          x_unpool_add = tf.scatter_add(x_unpool , argmax, x)
                          x_unpool_reshape = tf.reshape(x_unpool_add , unpool_shape)
                          return x_unpool_reshape


                          x_unpool_add is a op of tf.scatter_add, everytime we compute x_unpool_reshape, x_unpool_add will be called. So x_unpool will add x twice if we compute unpool2 twice. In my origin code, I compute unpool0, unpool1, unpool2 in order, x_unpool_add of unpool1 is called firstly, then when we compute unpool2, because of we need compute unpool1, x_unpool_add will be called again, so it's equal to call x_unpool_add twice, the value is wrong. If we compute unpool2 directly, we will get right result. So replacling tf.scatter_add with tf.scatter_update can avoid this bug.



                          This code can reproducible this intuitively:



                          import tensorflow as tf

                          t1 = tf.get_variable(name='t1', shape=[1], dtype=tf.float32, initializer=tf.zeros_initializer())
                          t2 = tf.get_variable(name='t2', shape=[1], dtype=tf.float32, initializer=tf.zeros_initializer())
                          d = tf.scatter_add(t1, [0], [1])
                          e = tf.scatter_add(t2, [0], d)

                          with tf.Session() as sess:
                          sess.run(tf.global_variables_initializer())
                          d_out1 = sess.run(d)
                          d_out2 = sess.run(d)
                          e_out = sess.run(e)
                          print(d_out1)
                          print(d_out2)
                          print(e_out)


                          output:



                          [1.]
                          [2.]
                          [3.]





                          share|improve this answer














                          In fact, the answer is simple. For convenience, I rename some variables, look this code:



                          def unpool(x, argmax, strides, unpool_shape=None, batch_size=None, name='unpool'):
                          x_shape = x.get_shape().as_list()
                          argmax_shape = argmax.get_shape().as_list()
                          assert not(x_shape[0] is None and batch_size is None), "must input batch_size if number of batch is alterable"
                          if x_shape[0] is None:
                          x_shape[0] = batch_size
                          if argmax_shape[0] is None:
                          argmax_shape[0] = x_shape[0]
                          if unpool_shape is None:
                          unpool_shape = [x_shape[i] * strides[i] for i in range(4)]
                          x_unpool = tf.get_variable(name=name, shape=[np.prod(unpool_shape)], initializer=tf.zeros_initializer(), trainable=False)
                          argmax = tf.cast(argmax, tf.int32)
                          argmax = tf.reshape(argmax, [np.prod(argmax_shape)])
                          x = tf.reshape(x, [np.prod(argmax.get_shape().as_list())])
                          x_unpool_add = tf.scatter_add(x_unpool , argmax, x)
                          x_unpool_reshape = tf.reshape(x_unpool_add , unpool_shape)
                          return x_unpool_reshape


                          x_unpool_add is a op of tf.scatter_add, everytime we compute x_unpool_reshape, x_unpool_add will be called. So x_unpool will add x twice if we compute unpool2 twice. In my origin code, I compute unpool0, unpool1, unpool2 in order, x_unpool_add of unpool1 is called firstly, then when we compute unpool2, because of we need compute unpool1, x_unpool_add will be called again, so it's equal to call x_unpool_add twice, the value is wrong. If we compute unpool2 directly, we will get right result. So replacling tf.scatter_add with tf.scatter_update can avoid this bug.



                          This code can reproducible this intuitively:



                          import tensorflow as tf

                          t1 = tf.get_variable(name='t1', shape=[1], dtype=tf.float32, initializer=tf.zeros_initializer())
                          t2 = tf.get_variable(name='t2', shape=[1], dtype=tf.float32, initializer=tf.zeros_initializer())
                          d = tf.scatter_add(t1, [0], [1])
                          e = tf.scatter_add(t2, [0], d)

                          with tf.Session() as sess:
                          sess.run(tf.global_variables_initializer())
                          d_out1 = sess.run(d)
                          d_out2 = sess.run(d)
                          e_out = sess.run(e)
                          print(d_out1)
                          print(d_out2)
                          print(e_out)


                          output:



                          [1.]
                          [2.]
                          [3.]






                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited yesterday

























                          answered yesterday









                          张庆昊

                          1329




                          1329






























                               

                              draft saved


                              draft discarded



















































                               


                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53204794%2fa-strange-bug-in-tf-scatter-add-when-i-implement-unpool-in-tensorflow%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest




















































































                              Popular posts from this blog

                              How to pass form data using jquery Ajax to insert data in database?

                              National Museum of Racing and Hall of Fame

                              Guess what letter conforming each word