Concatenate torch tensor at a certain index - python-3.x

I am looking to Concatenate 2 torch tensors at a certain index. As an example, I want to add b after a[1].
a = torch.Tensor([1, 2, 3, 4, 5])
b = torch.Tensor([6, 7, 8, 9, 10])
The desired output is
torch.Tensor([1, 2, 6, 7, 8, 9, 10, 3, 4, 5])
I tried torch.cat, but I can only have
tensor([ 6., 7., 8., 9., 10., 1., 2., 3., 4., 5.])
tensor([ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.])

you will need to split the first tensor and concatenate the second in between
torch.cat([a[:2], b, a[2:]])
output will be like
tensor([ 1., 2., 6., 7., 8., 9., 10., 3., 4., 5.])

Related

How to remove specific value in tensor?

If I have the tensor like this,
tensor([[2, 5, 4, 2, 1, 1, 1, 1, 5],
[4, 0, 1, 5, 0, 3, 5, 1, 4],
[1, 1, 7, 2, 1, 5, 1, 1, 1],
[5, 5, 5, 3, 0, 4, 3, 1, 1],
[1, 1, 1, 1, 5, 3, 2, 7, 3],
[6, 6, 1, 1, 1, 1, 1, 1, 1]])
I wanted to remove value '1' as many as i can
so desired tensor is like this
tensor([[2., 5., 4., 2., 5., 1., 1.],
[4., 0., 5., 0., 3., 5., 4.],
[7., 2., 5., 1., 1., 1., 1.],
[5., 5., 5., 3., 0., 4., 3.],
[5., 3., 2., 7., 3., 1., 1.],
[6., 6., 1., 1., 1., 1., 1.]])
how to make original tensor to desired tensor effectively?
I tried like this way,
>>> not_one = torch.sum(t!=1, dim=-1)
>>> max_l = not_one.max()
>>> not_one
tensor([5, 7, 3, 7, 5, 2])
>>> max_l
tensor(7)
>>> desired_tensor = torch.ones(t.size(0), max_l)
>>> for i, tt in enumerate(t):
... desired_tensor[i, :not_one[i]] = tt[tt != 1]
...
>>> desired_tensor
tensor([[2., 5., 4., 2., 5., 1., 1.],
[4., 0., 5., 0., 3., 5., 4.],
[7., 2., 5., 1., 1., 1., 1.],
[5., 5., 5., 3., 0., 4., 3.],
[5., 3., 2., 7., 3., 1., 1.],
[6., 6., 1., 1., 1., 1., 1.]])

Broadcasting in PyTorch

To better understand how nn.BatchNorm2d works, I wanted to recreate the following lines of code:
input = torch.randint(1, 5, size=(2, 2, 3, 3)).float()
batch_norm = nn.BatchNorm2d(2)
output = (batch_norm(input))
print(input)
print(output)
tensor([[[[3., 3., 2.],
[3., 2., 2.],
[4., 2., 1.]],
[[1., 1., 2.],
[3., 2., 1.],
[1., 1., 1.]]],
[[[4., 3., 3.],
[4., 1., 4.],
[1., 3., 2.]],
[[2., 1., 4.],
[4., 2., 1.],
[4., 1., 3.]]]])
tensor([[[[ 0.3859, 0.3859, -0.6064],
[ 0.3859, -0.6064, -0.6064],
[ 1.3783, -0.6064, -1.5988]],
[[-0.8365, -0.8365, 0.0492],
[ 0.9349, 0.0492, -0.8365],
[-0.8365, -0.8365, -0.8365]]],
[[[ 1.3783, 0.3859, 0.3859],
[ 1.3783, -1.5988, 1.3783],
[-1.5988, 0.3859, -0.6064]],
[[ 0.0492, -0.8365, 1.8206],
[ 1.8206, 0.0492, -0.8365],
[ 1.8206, -0.8365, 0.9349]]]]
To achieve, I first calculated the mean and variance for each channel:
my_mean = (torch.mean(input, dim=[0, 2, 3]))
my_var = (torch.var(input, dim=[0, 2, 3]))
print(my_mean, my_var)
tensor([2.8333, 2.5556])
tensor([1.3235, 1.3203])
This seems reasonable, I have the mean and variance for each channel across the whole batch. Then I wanted to simply extract the mean from the input and divide by the variance. This is where problems arise, since I do not know to properly set up the mean and variance. PyTorch does not seem to broadcast properly:
my_output = (input - my_mean) / my_var
RuntimeError: The size of tensor a (3) must match the size of tensor b (2) at non-singleton dimension 3
I then wanted to reshape the mean and variance in the appropriate shape, such that each value is repeated 25 times in a 5x5 shape
First try:
my_mean.repeat(25).reshape(3, 5, 5)
But this also results in an error. What is the best way to achieve my goal?

Best way to cut a pytorch tensor into overlapping chunks?

If for instance I have:
eg6 = torch.tensor([
[ 1., 7., 13., 19.],
[ 2., 8., 14., 20.],
[ 3., 9., 15., 21.],
[ 4., 10., 16., 22.],
[ 5., 11., 17., 23.],
[ 6., 12., 18., 24.]])
batch1 = eg6
batch2 = -eg6
x = torch.cat((batch1,batch2)).view(2,6,4)
And then I want to slice it up into overlapping chunks, like a sliding window function, and have the chunks be batch-processable. For example, and just looking at the first dimension, I want 1,2,3, 3,4,5, 5,6 (or 5,6,0).
It seems unfold() kind of does what I want. It transposes the last two dimensions for some reason, but that is easy enough to repair. Changing it from shape [2,3,3,4] to [6,3,4] requires a memory copy, but I believe that is unavoidable?
SZ=3
x2 = x.unfold(1,SZ,2).transpose(2,3).reshape(-1,SZ,4)
This works perfectly when x is of shape [2,7,4]. But with only 6 rows, it throws away the final row.
Is there a version of unfold() that can be told to use all data, ideally taking a pad character?
Or do I need to pad x before calling unfold()? What is the best way to do that? I'm wondering if "pad" is the wrong word, as I'm only finding functions that want to put padding characters at both ends, with convolutions in mind.
Aside: Looking at the source of unfold, it seems the strange transpose is there deliberately and explicitly?! For that reason, and the undesired chop behaviour, it made me think the correct answer to my question might be write a new low-level function. But that is too much effort for me, at least for today... (I think a second function for the backwards pass also needs to be written.)
The operation performed here is similar to what a 1D convolution would behave like. With kernel_size=SZ and stride=2. As you noticed if you don't provide sufficient padding (you're correct on the wording) the last element won't be used.
A general approach (for any SZ and any input shape x.size(1)) is to figure out if padding is necessary, and if so what amount is needed.
The size of the output is given by out = floor((x.size(1) - SZ)/2 + 1).
The number of unused elements is x.size(1) - out*(SZ-1) - 1.
If the number of unused elements is non zero, you need to add a padding of (out+1)*(SZ-1) + 1 - x.size(1)
This example won't need padding:
>>> x = torch.stack((torch.tensor([
[ 1., 7., 13., 19.],
[ 2., 8., 14., 20.],
[ 3., 9., 15., 21.],
[ 4., 10., 16., 22.],
[ 5., 11., 17., 23.]]),)*2)
>>> x.shape
torch.Size([2, 5, 4])
>>> out = floor((x.size(1) - SZ)/2 + 1)
2
>>> unused = x.size(1) - out*(SZ-1) - 1
0
While this one will:
>>> x = torch.stack((torch.tensor([
[ 1., 7., 13., 19.],
[ 2., 8., 14., 20.],
[ 3., 9., 15., 21.],
[ 4., 10., 16., 22.],
[ 5., 11., 17., 23.],
[ 6., 12., 18., 24.]]),)*2)
>>> x.shape
torch.Size([2, 6, 4])
>>> out = floor((x.size(1) - SZ)/2 + 1)
2
>>> unused = x.size(1) - out*(SZ-1) - 1
1
>>> p = (out+1)*(SZ-1) + 1 - x.size(1)
1
Now, to actually add padding you could just use torch.cat. Although I am the built-in, nn.functional.pad, would work...
>>> torch.cat((x, torch.zeros(x.size(0), p, x.size(2))), dim=1)
tensor([[[ 1., 7., 13., 19.],
[ 2., 8., 14., 20.],
[ 3., 9., 15., 21.],
[ 4., 10., 16., 22.],
[ 5., 11., 17., 23.],
[ 6., 12., 18., 24.],
[ 0., 0., 0., 0.]],
[[ 1., 7., 13., 19.],
[ 2., 8., 14., 20.],
[ 3., 9., 15., 21.],
[ 4., 10., 16., 22.],
[ 5., 11., 17., 23.],
[ 6., 12., 18., 24.],
[ 0., 0., 0., 0.]]])

How to multiply torch[N,1] and torch[1,N]?

I'd like to calculate a matrix (shape[N,N]) by multiplying 2 torch vectors A(shape[N,1]) and B=A'(shape[1,N]).
When I use torch.matmul or torch.mm, I got errors or A'A(shape[1,1]).
If A is denoted as
A = [a_1, a_2, ..., a_N]', I want to calculate a matrix C whose (i,j)element is
for i in range(N):
for j in range(N):
C(i,j) = a_i * a_j
I'd like to calculate this quickly. Do you have any ideas?
thank you for your help!
If I understood you correctly you can do something like this :
A = torch.randint(0,5,(5,))
C = (A.view(1, -1) * A.view(-1, 1)).to(torch.float)
it produces :
tensor([[ 1., 4., 3., 3., 0.],
[ 4., 16., 12., 12., 0.],
[ 3., 12., 9., 9., 0.],
[ 3., 12., 9., 9., 0.],
[ 0., 0., 0., 0., 0.]])
which is equivalent to writting :
D = torch.zeros((5,5))
for i in range(5):
for j in range(5):
D[i][j] = A[i] * A[j]
which results in :
tensor([[ 1., 4., 3., 3., 0.],
[ 4., 16., 12., 12., 0.],
[ 3., 12., 9., 9., 0.],
[ 3., 12., 9., 9., 0.],
[ 0., 0., 0., 0., 0.]])
You could simply do the following:
import torch
A = torch.randint(0, 5, (3, 2))
B = torch.randint(0, 5, (2, 3))
A:
tensor([[1, 3],
[2, 1],
[1, 3]])
B:
tensor([[1, 0, 3],
[3, 4, 1]])
C = A # B # python 3.5+
C:
tensor([[10, 12, 6],
[ 5, 4, 7],
[10, 12, 6]])

Image composition based on "pattern matrix"

I want to stitch together c rgb images in numpy resulting into a larger image. Images are represented as numpy arrays. I however, do have the following constraints:
I do want to stitch together c rgb images in shape n * m = c, stored in a dictionary, here an example of a dictionary containing 21 images:
c_images = { 5:numpy.array[[x,y,3]], 1:numpy.array[[x,y,3]], ... 21:numpy.array[[x,y,3]]}
I have a "pattern" matrix of size n * m = c, in which each the indexes of the images 0...c are scattered randomly. A randomly generated "pattern matrix" of size n = 3, m = 7, c = 21looks like the following
P_matrix = [[14, 3, 19, 5, 16, 18, 0],
[17, 1, 13, 7, 6, 15, 11],
[4, 9, 10, 12, 8, 20, 2 ]]
What would be the best way to use the pattern matrix, to compose a larger numpy array, based on c images ?
Maybe np.block can help you. Not all the images have to be the same size but they need to fit together. First some example data:
import numpy as np
n, m = 3, 4
img_size = np.array([3, 3])
img_list = [np.zeros(img_size)+i for i in range(n*m)]
# [array([[1., 1., 1.], array([[2., 2., 2.], ...array([[12., 12., 12.],
# [1., 1., 1.], [2., 2., 2.], [12., 12., 12.],
# [1., 1., 1.]]), [2., 2., 2.]]),, [12., 12., 12.]])
rnd_idx = np.random.permutation(range(n*m)).reshape((n, m))
# array([[ 9, 10, 0, 4],
# [ 3, 11, 6, 5],
# [ 2, 8, 7, 1]])
Than you need to create a nested list of your images based on the given pattern, np.block does the rest for you:
img_list_nested = [[img_list[col] for col in rows] for rows in rnd_idx]
img = np.block(img_list_nested)
# array([[ 9., 9., 9., 10., 10., 10., 0., 0., 0., 4., 4., 4.],
# [ 9., 9., 9., 10., 10., 10., 0., 0., 0., 4., 4., 4.],
# [ 9., 9., 9., 10., 10., 10., 0., 0., 0., 4., 4., 4.],
# [ 3., 3., 3., 11., 11., 11., 6., 6., 6., 5., 5., 5.],
# [ 3., 3., 3., 11., 11., 11., 6., 6., 6., 5., 5., 5.],
# [ 3., 3., 3., 11., 11., 11., 6., 6., 6., 5., 5., 5.],
# [ 2., 2., 2., 8., 8., 8., 7., 7., 7., 1., 1., 1.],
# [ 2., 2., 2., 8., 8., 8., 7., 7., 7., 1., 1., 1.],
# [ 2., 2., 2., 8., 8., 8., 7., 7., 7., 1., 1., 1.]])

Resources