if the tensor is of shape [20, 5] then I need to take 10 at a time and sum them, so result is [2,5].
eg:
shape[20,5] -> shape[2, 5] (sum 10 at a time)
shape[100, 20] -> shape[10,20] (sum 10 at a time)
Is there any faster/optimal way to do this?
eg:
[[1, 1], [1, 2], [3, 4], [1,2]] i want [[2, 3], [4, 6]] by taking sum of 2 rows.
It is not completely clear, but I cannot use a comment for this, so.
For the first case you have:
t1 = torch.tensor([[1., 1.], [1., 2.], [3., 4.], [1.,2.]])
t1.shape #=> torch.Size([4, 2])
t1
tensor([[1., 1.],
[1., 2.],
[3., 4.],
[1., 2.]])
To get the desired output you should reshape:
tr1 = t1.reshape([2, 2, 2])
res1 = torch.sum(tr1, axis = 1)
res1.shape #=> torch.Size([2, 2])
res1
tensor([[2., 3.],
[4., 6.]])
Let's take a tensor with all one elements (torch.ones) for the second case.
t2 = torch.ones((20, 5))
t2.shape #=> torch.Size([20, 5])
t2
tensor([[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]])
So, reshaping to get the required (?) result:
tr2 = tensor.reshape((10, 2, 5))
res2 = torch.sum(tr2, axis = 0)
res2.shape #=> torch.Size([2, 5])
res2
tensor([[10., 10., 10., 10., 10.],
[10., 10., 10., 10., 10.]])
Is this what you are looking for?
I am not aware of any off the shelf solution for that.
If having the average is enough you can use nn.AvgPool1d https://pytorch.org/docs/stable/generated/torch.nn.AvgPool1d.html#avgpool1d:
import torch, torch.nn as nn
x = torch.rand(batch_size, channels, lenght)
pool = nn.AvgPool1D(kernel_size=10, stride=10)
avg = pool(x)
With this solution, just make sure you are averaging the correct dimension.
EDIT
I just realized you can get the sum by modifying the last line with avg = pool(x) * kernel_size!
You can also just write your own function that does the summing for you:
import torch
def SumWindow(x, window_size, dim):
input_split = torch.split(x, window_size, dim)
input_sum = [v.sum(dim=dim), for v in input_split] # may be expensive if there are too many tensors
out = torch.cat(inptu_sum, dim=dim)
return dim
Related
I am using the GTZAN dataset (containing 1000 songs with 10 genres) to make a music genre classification project.
I tried to convert a dataset of images, which are spectrograms of the songs, into tensors but it only returns a tensor of ones.
This is how I tried to do it:
transform = T.Compose([
T.Resize(image_size),
T.ToTensor()
])
data = torchvision.datasets.ImageFolder(root = root, transform = transform)
train_loader = DataLoader(train_dataset,
batch_size=batch_size,
shuffle=True)
test_loader = DataLoader(test_dataset,
batch_size*2)
dataiter = iter(train_loader)
images, labels = dataiter.next()
When I return images it gives a tensor of pure ones, e.g.
images[1]
tensor([[[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
...,
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.]],
[[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
...,
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.]],
[[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
...,
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.],
[1., 1., 1., ..., 1., 1., 1.]]])
Are you sure it is all ones? Try to compute maximum/minimum/mean.
If that's the case, maybe you are reading the files assuming the wrong format.
This notebook could be of help https://www.kaggle.com/code/mireiaboneta/cnnmodel
I tried to find the difference between two vectors on python colab. It returns a square matrix with the dimension being the number of rows of the vectors. As in np.subtract(y,X#genet).shape where y.shape returns (60,) and X#genet returns (60,). It is expected that np.subtract(y,X#genet).shape should return (60,) but it returned (60,60).
You sure your shapes are correct? if they are the same size then the resulting size would be the same.
>>> import numpy as np
>>> y = np.ones(60)
>>> y
array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.,
1., 1., 1., 1., 1., 1., 1., 1., 1.])
>>> y.shape
(60,)
>>> x = np.ones(60)
>>> x.shape
(60,)
>>> np.subtract(y, x).shape
(60,)
compute
It appears one of your arrays are the wrong shape (ie)
>>> y = np.ones(60)
>>> x = np.ones((60,1))
>>> np.subtract(y, x).shape
(60, 60)
I am trying to use conv2d function on these two tensors:
Z = np.random.choice([0,1],size=(100,100))
Z = torch.from_numpy(Z).type(torch.FloatTensor)
print(Z)
tensor([[0., 0., 1., ..., 1., 0., 0.],
[1., 0., 1., ..., 1., 1., 1.],
[0., 0., 0., ..., 0., 1., 1.],
...,
[1., 0., 1., ..., 1., 1., 1.],
[1., 0., 1., ..., 0., 0., 0.],
[0., 1., 1., ..., 1., 0., 0.]
and
filters = torch.tensor(np.array([[1,1,1],
[1,0,1],
[1,1,1]]), dtype=torch.float32)
print(filters)
tensor([[1., 1., 1.],
[1., 0., 1.],
[1., 1., 1.]])
But when I try to do torch.nn.functional.conv2d(Z,filters) this error returns:
RuntimeError: weight should have at least three dimensions
I really don't understand what is the problem here. How to fix it?
The input to torch.nn.functional.conv2d(input, weight) should be
You can use unsqueeze() to add fake batch and channel dimensions thus having sizes: input: (1, 1, 100, 100) and weight: (1, 1, 3, 3).
torch.nn.functional.conv2d(Z.unsqueeze(0).unsqueeze(0), filters.unsqueeze(0).unsqueeze(0))
I'm observing some odd behaviour using numpy broadcasting. The problem is illustrated below, where running the first piece of code produces an error:
A = np.ones((10))
B = np.ones((10, 4))
C = np.ones((10))
np.asarray([A, B, C])
ValueError: could not broadcast input array from shape (10,4) into shape (10)
If I instead expand the dimensions of B, using B = np.expand_dims(B, axis=0), it will successfully create the array, but it now has (not surprisingly) the wrong dimensions:
array([array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]),
array([[[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]]]),
array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])], dtype=float32)
Why does it fail to broadcast the first example, and how can I end up with an array like below (notice only double brackets around the second array)? Any feedback is much appreciated.
array([array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]),
array([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]]),
array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])], dtype=object)
Including, say, None prevents the broadcasting, so this workaround is an option:
np.asarray([A, B, C, None])[:-1]
Here the outcome:
array([array([ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]),
array([[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.]]),
array([ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])], dtype=object)
Whats the most pythonic way of writing a function that returns a nxn boundary mask for convolotion, e.g for 3x3 it will return [[1,1,1],[1,0,1],[1,1,1]], for 5x5 it will return [[1,1,1,1,1],[1,0,0,0,1],[1,0,0,0,1],[1,0,0,0,1],[1,1,1,1,1]] and so on.
this works (but isnt so pythonic):
def boundaryMask(size):
mask=np.zeros((size,size))
for i in range(size):
mask[0][i]=1
mask[i][0]=1
mask[i][size-1]=1
mask[size-1][i]=1
return mask
One option would be to create an array of ones, and then assign zeros to the center of the array using slicing:
N = 4
x = np.ones((N, N))
x[1:-1, 1:-1] = 0
x
#array([[ 1., 1., 1., 1.],
# [ 1., 0., 0., 1.],
# [ 1., 0., 0., 1.],
# [ 1., 1., 1., 1.]])
Put in a function and test on various sizes:
def boundaryMask(size):
mask=np.ones((size,size))
mask[1:-1,1:-1] = 0
return mask
boundaryMask(1)
# array([[ 1.]])
boundaryMask(2)
#array([[ 1., 1.],
# [ 1., 1.]])
boundaryMask(3)
#array([[ 1., 1., 1.],
# [ 1., 0., 1.],
# [ 1., 1., 1.]])
boundaryMask(4)
#array([[ 1., 1., 1., 1.],
# [ 1., 0., 0., 1.],
# [ 1., 0., 0., 1.],
# [ 1., 1., 1., 1.]])