Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to replace a value within a tensor by indices?

The below code add something to a specific location within a tensor by indices (thanks to @mrry's answer here).

indices = [[1, 1]]  # A list of coordinates to update.
values = [1.0]  # A list of values corresponding to the respective
            # coordinate in indices.
shape = [3, 3]  # The shape of the corresponding dense tensor, same as `c`.
delta = tf.SparseTensor(indices, values, shape)

For example, given this -

c = tf.constant([[0.0, 0.0, 0.0],
             [0.0, 0.0, 0.0],
             [0.0, 0.0, 0.0]])

It'll add 1 at [1, 1], resulting in

[[0.0, 0.0, 0.0],
[0.0, 1.0, 0.0],
[0.0, 0.0, 0.0]])

Question - Is it possible to replace the value at a specific location instead of adding at that location? If it's not possible in tensorflow, is it possible in any other similar libraries?

For example,

Given this -

[[4.0, 43.1.0, 45.0],
[2.0, 22.0, 6664.0],
[-4543.0, 0.0, 43.0]])

Is there a way to replace the 22 at [1, 1] with (say) 45, resulting in the below?

[[4.0, 43.1.0, 45.0],
[2.0, 45.0, 6664.0],
[-4543.0, 0.0, 43.0]])
like image 559
Achilles Avatar asked Mar 19 '17 05:03

Achilles


People also ask

Can we change the content of a tensor?

If you're familiar with NumPy, tensors are (kind of) like np. arrays . All tensors are immutable like Python numbers and strings: you can never update the contents of a tensor, only create a new one.

What is TF Where?

The tf. where() function is used to returns the elements, either of first tensor or second tensor depending on the specified condition. If the given condition is true, it select from the first tensor else select form the second tensor. Syntax: tf.where (condition, a, b)


1 Answers

This is clunky, but it does replace values in a tensor. It's based on this answer that you mentioned.

# inputs
inputs = tf.placeholder(shape = [None, None], dtype = tf.float32)  # tensor with values to replace
indices = tf.placeholder(shape = [None, 2], dtype = tf.int64)  # coordinates to be updated
values = tf.placeholder(shape = [None], dtype = tf.float32)  # values corresponding to respective coordinates in "indices"

# set elements in "indices" to 0's
maskValues = tf.tile([0.0], [tf.shape(indices)[0]])  # one 0 for each element in "indices"
mask = tf.SparseTensor(indices, maskValues, tf.shape(inputs, out_type = tf.int64))
maskedInput = tf.multiply(inputs, tf.sparse_tensor_to_dense(mask, default_value = 1.0))  # set values in coordinates in "indices" to 0's, leave everything else intact

# replace elements in "indices" with "values"
delta = tf.SparseTensor(indices, values, tf.shape(inputs, out_type = tf.int64))
outputs = tf.add(maskedInput, tf.sparse_tensor_to_dense(delta))  # add "values" to elements in "indices" (which are 0's so far)

What it does:

  1. Set input elements in positions that need to be replaced to 0's.
  2. Add desired values to these 0's (this is straight from here).

Check by running:

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    ins = np.array([[4.0, 43.0, 45.0], [2.0, 22.0, 6664.0], [-4543.0, 0.0, 43.0]])
    ind = [[1, 1]]
    vals = [45]
    outs = sess.run(outputs, feed_dict = { inputs: ins, indices: ind, values: vals })
    print(outs)

Output:

[[ 4.000e+00  4.300e+01  4.500e+01]
 [ 2.000e+00  4.500e+01  6.664e+03]
 [-4.543e+03  0.000e+00  4.300e+01]]

Unlike many otherwise great answers out there, this one works beyond tf.Variable()s.

like image 188
Nico Avatar answered Oct 09 '22 00:10

Nico