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?

                              革兰氏阴性菌

                              How should I tell a customer about typographic mistakes?