2

I have a tensor t

1 2
3 4
5 6
7 8

And I would like to make it

0 0 0 0
0 1 2 0
0 3 4 0
0 5 6 0
0 7 8 0
0 0 0 0 

I tried stacking with new=torch.tensor([0. 0. 0. 0.]) tensor four times but that did not work.

t = torch.arange(8).reshape(1,4,2).float()
print(t)
new=torch.tensor([[0., 0., 0.,0.]])
print(new)
r = torch.stack([t,new])  # invalid argument 0: Tensors must have same number of dimensions: got 4 and 3
new=torch.tensor([[[0., 0., 0.,0.]]])
print(new)
r = torch.stack([t,new])  # invalid argument 0: Sizes of tensors must match except in dimension 0.

I also tried cat, that did not work either.

kmario23
  • 57,311
  • 13
  • 161
  • 150
Dex
  • 137
  • 2
  • 10

2 Answers2

3

It is probably better to initialize an array of the desired shape first, and then add the data at the appropriate indices.

import torch

t = torch.arange(8).reshape(1,4,2).float()
x = torch.zeros((1, t.shape[1]+2, t.shape[2]+2))
x[:, 1:-1, 1:-1] = t

print(x)

On the other hand, if you just want to pad your tensor with zeroes (and not just add extra zeroes somewhere), you can use torch.nn.functional.pad:

import torch

t = torch.arange(8).reshape(1, 4, 2).float()
x = torch.nn.functional.pad(t, (1, 1, 1, 1))

print(x)
amdex
  • 761
  • 3
  • 10
  • This is much better than stack operation. Anyway do you know where I was wrong with the stack operation? – Dex Sep 19 '19 at 09:30
  • Yes, your tensor is `(1, 4, 2)`-shaped, so you can't just stack it with a tensor that is, essentially, `(1, 4)`-shaped. First off, you need to use `cat`, and remove the first dimension of your `t`. You could solve it with a complicated series of `cat`: `x = torch.cat([torch.zeros(1, 4), torch.cat([torch.zeros(4, 1), t[0], torch.zeros(4, 1)], 1), torch.zeros(1, 4)])[None, :, :]` – amdex Sep 19 '19 at 09:36
  • You nailed it! Fantastic. – Dex Sep 19 '19 at 10:39
  • The second approach (`F.pad`) is better when gradients have to flow through. Torch gives an error saying in-place modification of a tensor for the first approach. – Nagabhushan S N May 18 '21 at 17:34
1

It is possible to use torch.cat to concatenate the tensors and get the desired tensor. Here is a complete example:

# input tensor
In [98]: at = torch.arange(1, 9).reshape(-1, 2).float()
In [99]: at 
Out[99]: 
tensor([[1., 2.],
        [3., 4.],
        [5., 6.],
        [7., 8.]])

# columns to be padded
In [100]: col_zeros = torch.zeros(at.shape[0]).reshape(-1, 1)      
In [101]: col_zeros   
Out[101]: 
tensor([[0.],
        [0.],
        [0.],
        [0.]])

# rows to be padded
In [102]: row_zeros = torch.zeros(at.shape[1]+2).reshape(1, -1)   
In [103]: row_zeros 
Out[103]: tensor([[0., 0., 0., 0.]])

Let's first pad for the columns:

# the order in the list of tensors matter.
# since we want a zero column on both sides, we place the input tensor in the middle
# and pad the `col_zeros` on both sides (i.e. along dimension=1)
In [104]: col_padded = torch.cat([col_zeros, at, col_zeros], dim=1) 
In [105]: col_padded     
Out[105]: 
tensor([[0., 1., 2., 0.],
        [0., 3., 4., 0.],
        [0., 5., 6., 0.],
        [0., 7., 8., 0.]])

Next, let's pad for the rows:

# here we pad the `row_zeros` on the upper and lower sides (i.e. along dimension=0)
# placing the already `col_padded` tensor in the middle of the list of tensors
In [106]: final_padded = torch.cat([row_zeros, col_padded, row_zeros], dim=0)  
In [107]: final_padded      
Out[107]: 
tensor([[0., 0., 0., 0.],
        [0., 1., 2., 0.],
        [0., 3., 4., 0.],
        [0., 5., 6., 0.],
        [0., 7., 8., 0.],
        [0., 0., 0., 0.]])
kmario23
  • 57,311
  • 13
  • 161
  • 150