I am trying to repeat a tensor in torch in two ways. For example repeating the tensor {1,2,3,4} 3 times both ways to yield;
{1,2,3,4,1,2,3,4,1,2,3,4}
{1,1,1,2,2,2,3,3,3,4,4,4}
There is a built in torch:repeatTensor function which will generate the first of the two (like numpy.tile()) but I can't find one for the latter (like numpy.repeat()). I'm sure that I could call sort on the first to give the second but I think this might be computationally expensive for larger arrays?
Thanks.
6 Answers
Try torch.repeat_interleave() method:
>>> x = torch.tensor([1, 2, 3])
>>> x.repeat_interleave(2)
tensor([1, 1, 2, 2, 3, 3])
Quoting -
z = torch.FloatTensor([[1,2,3],[4,5,6],[7,8,9]]) 1 2 3 4 5 6 7 8 9 z.transpose(0,1).repeat(1,3).view(-1, 3).transpose(0,1) 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6 7 7 7 8 8 8 9 9 9
This will give you a intuitive feel of how it works.
a = torch.Tensor([1,2,3,4])
To get [1., 2., 3., 4., 1., 2., 3., 4., 1., 2., 3., 4.] we repeat the tensor thrice in the 1st dimension:
a.repeat(3)
To get [1,1,1,2,2,2,3,3,3,4,4,4] we add a dimension to the tensor and repeat it thrice in the 2nd dimension to get a 4 x 3 tensor, which we can flatten.
b = a.reshape(4,1).repeat(1,3).flatten()
or
b = a.reshape(4,1).repeat(1,3).view(-1)
Here's a generic function that repeats elements in tensors.
def repeat(tensor, dims):
if len(dims) != len(tensor.shape):
raise ValueError("The length of the second argument must equal the number of dimensions of the first.")
for index, dim in enumerate(dims):
repetition_vector = [1]*(len(dims)+1)
repetition_vector[index+1] = dim
new_tensor_shape = list(tensor.shape)
new_tensor_shape[index] *= dim
tensor = tensor.unsqueeze(index+1).repeat(repetition_vector).reshape(new_tensor_shape)
return tensor
If you have
foo = tensor([[1, 2],
[3, 4]])
By calling repeat(foo, [2,1]) you get
tensor([[1, 2],
[1, 2],
[3, 4],
[3, 4]])
So you duplicated every element along dimension 0 and left elements as they are on dimension 1.
Use einops:
from einops import repeat
repeat(x, 'i -> (repeat i)', repeat=3)
# like {1,2,3,4,1,2,3,4,1,2,3,4}
repeat(x, 'i -> (i repeat)', repeat=3)
# like {1,1,1,2,2,2,3,3,3,4,4,4}
This code works identically for any framework (numpy, torch, tf, etc.)
Can you try something like:
import torch as pt
#1 work as numpy tile
b = pt.arange(10)
print(b.repeat(3))
#2 work as numpy tile
b = pt.tensor(1).repeat(10).reshape(2,-1)
print(b)
#3 work as numpy repeat
t = pt.tensor([1,2,3])
t.repeat(2).reshape(2,-1).transpose(1,0).reshape(-1)