Can you modify the value of a Tensor in TensorFlow? - tensorflow

Can you modify the value of a specific tensor?
For example:
x = tf.zeros((2, 2))
x[0, 0] = 1 # pseudo-code
print(x) # <Tensor ... numpy=[[1, 0], [0, 0]]>

You can but you need to set the tensor to be a Variable and not a constant.
import tensorflow as tf
import numpy as np
x = np.zeros((2,2))
x_var = tf.Variable(x)
x[0,0]=1
tf.assign(x_var ,x)

Related

shuffling two tensors in the same order

As above. I tried those to no avail:
tf.random.shuffle( (a,b) )
tf.random.shuffle( zip(a,b) )
I used to concatenate them and do the shuffling, then unconcatenate / unpack. But now I'm in a situation where (a) is 4D rank tensor while (b) is 1D, so, no way to concatenate.
I also tried to give the seed argument to the shuffle method so it reproduces the same shuffling and I use it twice => Failed. Also tried to do the shuffling myself with randomly shuffled range of numbers, but TF is not as flexible as numpy in fancy indexing and stuff ==> failed.
What I'm doing now is, convert everything back to numpy then use shuffle from sklearn then go back to tensors by recasting. It is sheer stupid way. This is supposed to happen inside a graph.
You could just shuffle the indices and then use tf.gather() to extract values corresponding to those shuffled indices:
TF2.x (UPDATE)
import tensorflow as tf
import numpy as np
x = tf.convert_to_tensor(np.arange(5))
y = tf.convert_to_tensor(['a', 'b', 'c', 'd', 'e'])
indices = tf.range(start=0, limit=tf.shape(x)[0], dtype=tf.int32)
shuffled_indices = tf.random.shuffle(indices)
shuffled_x = tf.gather(x, shuffled_indices)
shuffled_y = tf.gather(y, shuffled_indices)
print('before')
print('x', x.numpy())
print('y', y.numpy())
print('after')
print('x', shuffled_x.numpy())
print('y', shuffled_y.numpy())
# before
# x [0 1 2 3 4]
# y [b'a' b'b' b'c' b'd' b'e']
# after
# x [4 0 1 2 3]
# y [b'e' b'a' b'b' b'c' b'd']
TF1.x
import tensorflow as tf
import numpy as np
x = tf.placeholder(tf.float32, (None, 1, 1, 1))
y = tf.placeholder(tf.int32, (None))
indices = tf.range(start=0, limit=tf.shape(x)[0], dtype=tf.int32)
shuffled_indices = tf.random.shuffle(indices)
shuffled_x = tf.gather(x, shuffled_indices)
shuffled_y = tf.gather(y, shuffled_indices)
Make sure that you compute shuffled_x, shuffled_y in the same session run. Otherwise they might get different index orderings.
# Testing
x_data = np.concatenate([np.zeros((1, 1, 1, 1)),
np.ones((1, 1, 1, 1)),
2*np.ones((1, 1, 1, 1))]).astype('float32')
y_data = np.arange(4, 7, 1)
print('Before shuffling:')
print('x:')
print(x_data.squeeze())
print('y:')
print(y_data)
with tf.Session() as sess:
x_res, y_res = sess.run([shuffled_x, shuffled_y],
feed_dict={x: x_data, y: y_data})
print('After shuffling:')
print('x:')
print(x_res.squeeze())
print('y:')
print(y_res)
Before shuffling:
x:
[0. 1. 2.]
y:
[4 5 6]
After shuffling:
x:
[1. 2. 0.]
y:
[5 6 4]

Efficient method for finding index of first occurrence of a number in batched data other than for loop

I am doing a task in which i have data in form of frames stored in batches. Dimension of a batch is like (batch_size,400), i want to find index of first occurrence of number 1 in each 400 length frame.
currently i m using for loop over batch size but since data is very larger it is very time consuming
Any other Efficient method using some matrix operation in tensorflow or numpy would
In TensorFlow:
import tensorflow as tf
def index_of_first_tf(batch, value):
eq = tf.equal(batch, value)
has_value = tf.reduce_any(eq, axis=-1)
_, idx = tf.math.top_k(tf.cast(eq, tf.int8))
idx = tf.squeeze(idx, -1)
return tf.where(has_value, idx, -tf.ones_like(idx))
In NumPy:
import numpy as np
def index_of_first_np(batch, value):
eq = np.equal(batch, value)
has_value = np.any(eq, axis=-1)
idx = np.argmax(eq, axis=-1)
idx[~has_value] = -1
return idx
Tests:
import tensorflow as tf
batch = [[0, 1, 2, 3],
[1, 2, 1, 0],
[0, 2, 3, 4]]
value = 1
print(index_of_first_np(batch, value))
# [ 1 0 -1]
with tf.Graph().as_default(), tf.Session() as sess:
print(sess.run(index_of_first_tf(batch, value)))
# [ 1 0 -1]

Manipulate indices in a SparseTensor

I would like to shift the indices of a SparseTensor in Tensorflow. Is there a way to alter a SparseTensor's indices?
import numpy as np
import tensorflow as tf
# build graph
x = tf.sparse_placeholder(tf.float32, [None, 10], name='x')
sparse_indices = x.indices
# This line does not work:
sparse_indices[:, 1] = sparse_indices[:, 1] + 1
shifted_x = tf.SparseTensor(indices=sparse_indices,
values=x.values,
dense_shape=[2,20])
# start session
session = tf.InteractiveSession()
indices = np.array([[1, 0], [2, 1]], dtype=np.int64)
values = np.array([1, 1], dtype=np.float32)
shape = np.array([2, 10], dtype=np.int64)
shifted = session.run(shifted_x,
{x:tf.SparseTensorValue(indices, values, shape)})

One dimensional sparse tensor

I am trying to pass in a one-dimensional sparse vector to Tensorflow:
import tensorflow as tf
import numpy as np
x = tf.sparse_placeholder(tf.float32)
y = tf.sparse_reduce_sum(x)
with tf.Session() as sess:
indices = np.array([0, 1], dtype=np.int64)
values = np.array([1.5, 3.0], dtype=np.float32)
shape = np.array([2], dtype=np.int64)
print(sess.run(y, feed_dict={
x: tf.SparseTensorValue(indices, values, shape)}))
This code throws the following error:
ValueError: Cannot feed value of shape (2,) for Tensor u'Placeholder_2:0', which has shape '(?, ?)'
Am I passing the shape wrong?
The indices should be of size (2,1). So change the indices to: indices = np.array([[0], [1]], dtype=np.int64). The below code works:
x = tf.sparse_placeholder(tf.float32)
y = tf.sparse_reduce_sum(x)
with tf.Session() as sess:
indices = np.array([[0], [1]], dtype=np.int64)
values = np.array([1.5, 3.0], dtype=np.float32)
shape = np.array([2], dtype=np.int64)
print(sess.run(y, feed_dict={
x: tf.SparseTensorValue(indices, values, shape)}))
#Output
#4.5

Tensorflow: Access index of variable containing an array

I need to save some values to specific places in a tensorflow array:
import tensorflow as tf
import numpy as np
AVG = tf.Variable([0, 0, 0, 0, 0], name='data')
for i in range(5):
data = np.random.randint(1000, size=10000)
AVG += np.average(data)
I need to make it average each iteration in different places of the AVG variable. Is this doable ?
You can use tf.scatter_add. Here is a complete working program :
import tensorflow as tf
import numpy as np
AVG = tf.Variable([0, 0, 0, 0, 0], name='data')
for i in range(5):
data = np.random.randint(1000, size=10000)
AVG = tf.scatter_add(AVG, [i], [np.average(data).astype('int')])
sess = tf.InteractiveSession()
sess.run(tf.initialize_all_variables())
print(AVG.eval())