1

I am trying to use scatter_update to update a slice of a tensor. My first code snippet to get familiar with the function works out perfectly fine.

import tensorflow as tf
import numpy as np

with tf.Session() as sess:
    init_val = tf.Variable(tf.zeros((3, 2)))
    indices = tf.constant([0, 1])
    update = tf.scatter_update(init_val, indices, tf.ones((2, 2)))

    init = tf.global_variables_initializer()
    sess.run(init)
    print(sess.run(update))

But when I try to feed the initial value into the graph like

with tf.Session() as sess:
    x = tf.placeholder(tf.float32, shape=(3, 2))
    init_val = x
    indices = tf.constant([0, 1])
    update = tf.scatter_update(init_val, indices, tf.ones((2, 2)))

    init = tf.global_variables_initializer()
    sess.run(init)
    print(sess.run(update, feed_dict={x: np.zeros((3, 2))}))

I get the strange error

InvalidArgumentError: You must feed a value for placeholder tensor 'Placeholder_1' with dtype float and shape [3,2]
 [[{{node Placeholder_1}} = Placeholder[dtype=DT_FLOAT, shape=[3,2], _device="/job:localhost/replica:0/task:0/device:CPU:0"]()]]

Dropping the tf.Variable around x when assigning it to init_val also does not help since I am getting the error

AttributeError: 'Tensor' object has no attribute '_lazy_read'

(see this entry on Github). Has anyone an idea? Thanks in advance!

I am using Tensorflow 1.12 on CPU.

  • 1
    You can only apply `tf.scatter_update` to variables, not to tensors in general. Replacing slices or individual values in tensors is a frequent issue, as there is no really good way of doing it. I initiated [this issue in GitHub](https://github.com/tensorflow/tensorflow/issues/18383) and posted a half-solution that should work for many cases, but proper TF support would be the ideal thing. – jdehesa Jan 09 '19 at 12:40
  • 1
    Btw, in your [other related question](https://stackoverflow.com/q/54107678) you use a variable. Unless you really need a variable, you should avoid using it just to be able to replace values in it. It is a very common workaround for the issue, but variables are not supposed to be used for that and it brings other issues later (e.g. no gradients). – jdehesa Jan 09 '19 at 12:43
  • About this question (updating a tensor through scatter), does [TensorFlow assign Tensor to Tensor with array indexing](https://stackoverflow.com/q/53632837) solve it? – jdehesa Jan 09 '19 at 12:45
  • No, if I try calling `scatter_nd` I get the same error as before while it works if I do not feed the data. Any other ideas? – Vincent Stimper Jan 09 '19 at 13:09

1 Answers1

1

You can replace in a tensor through scattering by building and update tensor and a mask tensor:

import tensorflow as tf
import numpy as np

with tf.Session() as sess:
    x = tf.placeholder(tf.float32, shape=(3, 2))
    init_val = x
    indices = tf.constant([0, 1])
    x_shape = tf.shape(x)
    indices = tf.expand_dims(indices, 1)
    replacement = tf.ones((2, 2))
    update = tf.scatter_nd(indices, replacement, x_shape)
    mask = tf.scatter_nd(indices, tf.ones_like(replacement, dtype=tf.bool), x_shape)
    result = tf.where(mask, update, x)
    print(sess.run(result, feed_dict={x: np.arange(6).reshape((3, 2))}))

Output:

[[1. 1.]
 [1. 1.]
 [4. 5.]]
jdehesa
  • 58,456
  • 7
  • 77
  • 121
  • Thank you very much! Another possible workaround I found is to concatenate the tensor manually. But your approach is more general. – Vincent Stimper Jan 09 '19 at 14:01
  • @VincentStimper Yes, there is usually a number of approaches depending on the case. I used scattering since it was in the question, but you are right that concatenating is much simpler here, and surely faster, so you may want to stick to it if you don't need anything more complex. – jdehesa Jan 09 '19 at 15:04