Reputation: 788
Is there analogue for numpy.take
?
I want to form N+1
-dimensional array from N
-dimensional array, more precisely from array with shape (B, H, W, C)
I want to make (B, H, W, X, C)
array.
I suppose that for my case there is solution even without such general operation. But I'm really unsure that if I will write code with multiple intermediate operations and tensors (shifting, repeating and so on) TF will be able to optimize it and remove unnecessary operations. Moreover I suppose that such code will be unclean and just awful.
I want to add dimension with shifted values. I.e. for (H,W)->(H,W,3) dimensions case indices must be
[
[[0,0], #[0,-1], may be padding with zeros but for now pad with edge value
[0,0],
[0,1]],
[[0,0],
[0,1]
[0,2]]
...
[[1,0],
[1,0],
[1,1]],
[[1,0],
[1,1],
[1,2]],
...
]
I thought about tf.scatter_nd
(https://www.tensorflow.org/api_docs/python/tf/scatter_nd) but for now I don't understand how to use it. If I understand correctly, I can't use indices
with shapes larger than shapes of update
array (i.e. I can't use indices
with shape (3,4,5,3)
and update
with shape (3,4,3)
or even (3,4,1,3)
. If it's so then this operation seems useless until I make intermediate array with shape that I need to form in result.
UPD: may be I'm wrong and tensors operations (shifting, tiling and so on) is more appropriate and efficient solution.
But in any case I think that analogue for np.take
will be useful.
Upvotes: 0
Views: 2581
Reputation: 1627
Exemplary code for tf.gather
replacing np.take
:
import numpy as np
a = np.array([5, 7, 42])
b = np.random.randint(0, 3, (2, 3, 4))
c = a[b]
result_numpy = np.take(a, b)
print(a, b, c, result_numpy)
import tensorflow as tf
a = tf.convert_to_tensor(a)
b = tf.convert_to_tensor(b)
# c = a[b] # does not work
result_tf = tf.gather(a, b)
print(a, b, result_tf)
assert(np.array_equal(result_numpy, result_tf.numpy()))
Upvotes: 0
Reputation: 24591
The closest function in tensorflow to np.take
are tf.gather
and tf.gather_nd
.
tf.gather_nd
is more general than tf.gather
(and np.take
) as it can slices through several dimensions at once.
A noticeable restriction of tf.gather[_nd]
compared to np.take
is that they slice through the first dimensions of the tensor only -- you can't slice through inner dimensions. When you want to slice through an arbitrary dimension (as in your case), you need to transpose the array to put the slice dimensions first, gather, then transpose back.
Upvotes: 4