Select tensor slice along a dimension based on index - python

I have a PyTorch tensor of the following shape: (100, 5, 100). I need to convert it into a tensor of shape (100, 100) by selecting from each row only one item in the second dimension, meaning that of those 5 elements I only need one, with its corresponding 100 elements.
To do this operation I have a second tensor of shape (100,) with the indices that specify which of those 5 items should be selected in each row.
Is there a simple way to perform this selection without having to mess with the dimensions too much?

Suppose tensor with indicies called idx and have shape (100,). Tensor with values called source. Then to select:
result = source[torch.arange(100), idx]

Related

Sample rows from tensor in every 3 rows in Python

How to sample the tensor in Python?
I want to sample a frame every 3 frames from videos, and the tensor shape will be [color, frames, height, width].
Thus, the sampling tensor shape will be [color, frames / 3, height, width]
Assume there is a tensor.size([3,300,10,10]).
After sampling rows every 3 rows in the second dimension, the tensor will be tensor.size([3,100,10,10])
Another example,
A tensor = [[1,2,3,4,5,6,7,8,9,10],[1,2,3,4,5,6,7,8,9,10],[1,2,3,4,5,6,7,8,9,10]].
After sampling rows every 3 rows in the second dimension, the tensor will be [[1,4,7,10],[1,4,7,10],[1,4,7,10]]
Let N be the size of dimension you want to sample and you want to sample every kth row.
You can do (assuming you want to sample from the 1st dimension, and there are 4 dimensions),
new_tensor = tensor[:, torch.arange(0, N, k), : ,: ]
You may skip slicing the last two dimensions and the result won't change.
new_tensor = tensor[:, torch.arange(0, N, k)]
More specifically for the 2D tensor in question, you can use this code.
tensor=torch.tensor([
[1,2,3,4,5,6,7,8,9,10],
[1,2,3,4,5,6,7,8,9,10],
[1,2,3,4,5,6,7,8,9,10]
])
new_tensor=tensor[:, torch.arange(0,10,3)]

How to modify a single value of a 2D tensor programatically by index

I have a 2D tensor my_tensor size [50,50] and dtype int32 and I need to increment the value at one specific location. The indices of the location to be updated is given by 2 integer tensors, which give the location in axis 0 and axis 1, respectively:
idx_0 is:
tf.Tensor([27], shape=(1,), dtype=int32)
idx_1 is:
tf.Tensor([26], shape=(1,), dtype=int32)
Tensorflow's tensor_scatter_nd_add seems to be the solution. The code works if I define the indexes manually, but if I try to use idx_0 and idx_1, every implementation gives some index/dimension mis-match error.
This works, incrementing location (27,26):
tf.tensor_scatter_nd_add(reversals_count, [[27, 26]], [1])
but this raises an error:
tf.tensor_scatter_nd_add(reversals_count, [[idx_0, idx_1]], [1])
with the error message
{InvalidArgumentError}Outer dimensions of indices and update must match. Indices shape: [1,2,1], updates shape:[1] [Op:TensorScatterAdd]
How can I use the idx_0 and idx_1 tensors in place of [[27, 26]]? Other syntaxes I've tried similarly do not produce the correct dimensions:
[[idx_0], [idx_1]]
tf.concat([idx_0, idx_1], axis=0)
I have created an (5x5) unit matrix for sake of simplicity and updating them at indices (0,0) ,(1,1),(2,2),(3,3) (i.e at the first four diagonal elements) . First define the indices as tensors ,then values as tensors that will add up those at respective indices then update using "tf.tensor_scatter_nd_add" command . You can do similarly for a (50X50) matrix.Thanks!
import tensorflow as tf
indices = tf.constant([[0,0], [1,1], [2,2],[3,3]]) # updating at diagonal index elements, you can see the change
updates = tf.constant([9, 10, 11, 12])# values that will add up at respective indexes
print("original tensor is ")
tensor = tf.ones([5,5], dtype=tf.int32)
print(tensor)
print("updated tensor is ")
updated = tf.tensor_scatter_nd_add(tensor, indices, updates)
print(updated)

Reshaping array of shape x into an array of shape (x,y)

I am following a tutorial to implement the K-nearest Neighbor algorithm on a dataset.
I have an array of shape (6003,) and I want to do this:
data = data.reshape((data.shape[0], 3072))
However, I am getting this error:
cannot reshape array of size 6003 into shape (6003,3072)
Any help on this, please? Thanks!
when you reshape a numpy array the total number elements shouldn't change.
e.g. a =[2,3,4,5,1,7] if you want to reshape this to a 2Darray then the dimensions multiplied should be equal to the total number elements in the original array a.
this means you can reshape array a in to dimension of (1,6) (2,3),(6,1),(3,2).
the title of your question does give away the error by the way.
Reshaping array of shape (x,) into an array of shape (x,y)
is impossible because you are trying to add more elements into your original data.
an array of shape (x,) can only be reshaped into an array of shape (x/y,y)
I hope this helps.
You are trying to reshape into an incompatible shape. Now, what do I mean by that? Look at this example:
a = np.array([[1, 2, 3],
[4, 5, 6],
])
The shape of this array is:
a.shape
>> (2, 3)
Array a has 2 x 3 = 6 elements. Let's try to reshape it into a (2, 6) array
a.reshape(2, 6)
This raises
>> ValueError: cannot reshape array of size 6 into shape (2,6)
Notice that we were trying to make an array that has 2 x 3 = 6 elements into an array that would have 2 x 6 = 12 elements. But NumPy cannot add those extra elements into your original array and give that your desired shape. So it raises ValueError.
In your case, you are trying to make an array with 6003 elements into an array that will have 6003 x 3072 = 18441216 elements!

Tensor Reshape No-op in RNN example

What exactly is this code doing in the method zero_state for the RNNCell in the file rnn_cell.py? I'm not entirely sure what a shape of the form [-1, n] means...
The semantics of reshape are similar to the one from numpy:
http://docs.scipy.org/doc/numpy/reference/generated/numpy.reshape.html
It changes the tensor to have 2-dimensions and the second dimension should have self.state_size elements. E.g. if my tensor has 6 elements and I reshape it to [-1, 2], then the first dimension will have 6 / 2 = 3 elements.
Rafal's example is great. The way I remember -1 is that it sets the size of that dimension to whatever's necessary to fit all of the data from the original tensor. You can only have one -1 in a reshape.
If the original tensor is of size a, b, c (total elements = abc)
and you resize it to x, y, -1,
then the effect will be that the -1 will end up being abc/(y*z).
A 3,3,3 tensor (27 elements) reshaped to 9,3,-1 will actually have a size of 9,3,1 (27 elements)
Documentation vaguely suggests the behavior for -1.
If shape is the special value [-1], then tensor is flattened and the
operation outputs a 1-D tensor with all elements of tensor.
When the shape is an array, where one of the elements is -1, this value is just a convenient placeholder for some integer that might produce the same shape. Note that there might not be such an integer (for example if your starting matrix is [5x5] you can not reshape it with [7, -1]).
Also as you see there can not be two -1, because this make the shape ambiguous. As it was noted, the behavior is similar to numpy's reshape.

represent an index inside a list as x,y in python

I have a list which contains 1000 integers. The 1000 integers represent 20X50 elements of dimensional array which I read from a file into the list.
I need to walk through the list with an indicator in order to find close elements to each other. I want that my indicator will be represented not only by a simple index i, but as a two indices x,y so I can know where is my indicator along the list.
I tried to reshape the list like that:
data = np.array( l )
shape = ( 20, 50 )
data.reshape( shape )
but I don't know how to access the data array.
Update: Is there any way to find the indices of x, y for an integers that are smaller than NUM(let's say NUM=12)
According to documentation of numpy.reshape , it returns a new array object with the new shape specified by the parameters (given that, with the new shape, the amount of elements in the array remain unchanged) , without changing the shape of the original object, so when you are calling the data.reshape() function you should also assign it back to data for it to reflect in data.
Example -
data = data.reshape( shape ) # where shape = (20,50)
Also, another way to change the shape, is to directly assign the new shape to the data.shape property.
Example -
shape = (20,50)
data.shape = shape # where shape is the new shape

Categories

Resources