it there any way to convert 3D numpy array to 2D - python

I got a 3d NumPy array:
array([[[ 12., 0., 0.],
[ 15., 0., 0.],
[ 13., 0., 0.]],
[[ 12., 0., 0.],
[ 11., 0., 0.],
[ 13., 0., 0.]]])
Is there any way to convert to a 2d and only get
[12., 15., 13.]
[12., 11., 13.]

x = np.array(
[[[ 12., 0., 0.],
[ 15., 0., 0.],
[ 13., 0., 0.]],
[[ 12., 0., 0.],
[ 11., 0., 0.],
[ 13., 0., 0.]]]
)
x_2d = x[:, :, 0]
>> x_2d
>> array([[12., 15., 13.],
[12., 11., 13.]])

Related

Python array: Take two and skip two

I have a case where I have input array like this below
array([[[ 1., 0., 2., 0., 3., 0., 4., 0., 5.],
[ 6., 0., 7., 0., 8., 0., 9., 0., 10.],
[11., 0., 12., 0., 13., 0., 14., 0., 15.]],
[[16., 0., 17., 0., 18., 0., 19., 0., 20.],
[21., 0., 22., 0., 23., 0., 24., 0., 25.],
[26., 0., 27., 0., 28., 0., 29., 0., 30.]]])
and I would like to get an output like the one below.
array([[[ 1., 0., 3., 0., 5.],
[ 6., 0., 8., 0., 10.],
[11., 0., 13., 0., 15.]],
[[16., 0., 18., 0., 20.],
[21., 0., 23., 0., 25.],
[26., 0., 28., 0., 30.]]])
I would love if the solution can be generic not just to this example.
Since the length of the last dimension cannot be guaranteed to be even, here I choose to build the bool indices:
>>> mask = np.arange(ar.shape[-1]) // 2 % 2 == 0 # np.arange() & 2 == 0 is faster
>>> mask
array([ True, True, False, False, True, True, False, False, True])
>>> ar[:, :, mask] # or ar[..., mask]
array([[[ 1., 0., 3., 0., 5.],
[ 6., 0., 8., 0., 10.],
[11., 0., 13., 0., 15.]],
[[16., 0., 18., 0., 20.],
[21., 0., 23., 0., 25.],
[26., 0., 28., 0., 30.]]])
If the length of the last dimension can be guaranteed to be even, reshape with slicing is another technique:
>>> ar
array([[[ 1., 0., 2., 0., 3., 0., 4., 0.],
[ 6., 0., 7., 0., 8., 0., 9., 0.],
[11., 0., 12., 0., 13., 0., 14., 0.]],
[[16., 0., 17., 0., 18., 0., 19., 0.],
[21., 0., 22., 0., 23., 0., 24., 0.],
[26., 0., 27., 0., 28., 0., 29., 0.]]])
>>> shape = ar.shape[:-1]
>>> ar.reshape(*shape, -1, 2)[..., ::2, :].reshape(*shape, -1)
array([[[ 1., 0., 3., 0.],
[ 6., 0., 8., 0.],
[11., 0., 13., 0.]],
[[16., 0., 18., 0.],
[21., 0., 23., 0.],
[26., 0., 28., 0.]]])

fold/col2im for convolutions in numpy

Suppose I have an input matrix of shape (batch_size ,channels ,h ,w)
in this case (1 ,2 ,3 ,3)
[[[[ 0., 1., 2.],
[ 3., 4., 5.],
[ 6., 7., 8.]],
[[ 9., 10., 11.],
[12., 13., 14.],
[15., 16., 17.]]]])
to do a convolution with it i unroll it to the shape of
(batch_size ,channels * kernel_size * kernel_size ,out_h * out_w)
which is:
[[[ 0., 1., 3., 4.],
[ 1., 2., 4., 5.],
[ 3., 4., 6., 7.],
[ 4., 5., 7., 8.],
[ 9., 10., 12., 13.],
[10., 11., 13., 14.],
[12., 13., 15., 16.],
[13., 14., 16., 17.]]]
now i want to get the unrolled matrix back to its original form
which looks like this:
# for demonstration only the first and second column of the unrolled matrix
# the output should be the same shape as the initial matrix -> initialized to zeros
# current column -> [ 0., 1., 3., 4., 9., 10., 12., 13.]
[[[[0+0, 0+1, 0],
[0+3, 0+4, 0],
[0 , 0 , 0]],
[[0+9 , 0+10, 0],
[0+12, 0+13, 0],
[0 , 0 , 0]]]]
# for the next column it would be
# current column -> [ 1., 2., 4., 5., 10., 11., 13., 14.]
[[[[0 , 1+1, 0+2],
[3 , 4+4, 0+5],
[0 , 0 , 0 ]],
[[9 , 10+10, 0+11],
[12 , 13+13, 0+14],
[0 , 0 , 0 ]]]])
you basically put your unrolled elements back to its original place and sum the overlapping parts together.
But now to my question:
How could one implement this as fast as possible using numpy and
as less loops as possible. I already just looped through it kernel by kernel but this aproach isnt feasible with larger inputs. I think this could be parallelized quite a bit but my numpy indexing and overall knowledge isnt good enough to figure out a good solution by myself.
thanks for reading and have a nice day :)
With numpy, I expect this can be done using numpy.lib.stride_tricks.as_strided. However, I'd suggest that you look at pytorch, which interoperates easily with numpy and has quite efficient primitives for this operation. In your case, the code would look like:
kernel_size = 2
x = torch.arange(18).reshape(1, 2, 3, 3).to(torch.float32)
unfold = torch.nn.Unfold(kernel_size=kernel_size)
fold = torch.nn.Fold(kernel_size=kernel_size, output_size=(3, 3))
unfolded = unfold(x)
cols = torch.arange(kernel_size ** 2)
for col in range(kernel_size ** 2):
# col = 0
unfolded_masked = torch.where(col == cols, unfolded, torch.tensor(0.0, dtype=torch.float32))
refolded = fold(unfolded_masked)
print(refolded)
tensor([[[[ 0., 1., 0.],
[ 3., 4., 0.],
[ 0., 0., 0.]],
[[ 9., 10., 0.],
[12., 13., 0.],
[ 0., 0., 0.]]]])
tensor([[[[ 0., 1., 2.],
[ 0., 4., 5.],
[ 0., 0., 0.]],
[[ 0., 10., 11.],
[ 0., 13., 14.],
[ 0., 0., 0.]]]])
tensor([[[[ 0., 0., 0.],
[ 3., 4., 0.],
[ 6., 7., 0.]],
[[ 0., 0., 0.],
[12., 13., 0.],
[15., 16., 0.]]]])
tensor([[[[ 0., 0., 0.],
[ 0., 4., 5.],
[ 0., 7., 8.]],
[[ 0., 0., 0.],
[ 0., 13., 14.],
[ 0., 16., 17.]]]])

target, image[0] in datasets sklearn

what is the use of targetand image[0] method in digits datasets ?
from sklearn import datasets
digits = datasets.load_digits()
digits.target
digits.images[0]
prints
array([0, 1, 2, ..., 8, 9, 8])
array([[ 0., 0., 5., 13., 9., 1., 0., 0.],
[ 0., 0., 13., 15., 10., 15., 5., 0.],
[ 0., 3., 15., 2., 0., 11., 8., 0.],
[ 0., 4., 12., 0., 0., 8., 8., 0.],
[ 0., 5., 8., 0., 0., 9., 8., 0.],
[ 0., 4., 11., 0., 1., 12., 7., 0.],
[ 0., 2., 14., 5., 10., 12., 0., 0.],
[ 0., 0., 6., 13., 10., 0., 0., 0.]])
target return a vector where each value corresponds to the label of each image of the data set: digit between 0 to 9.
image[0] corresponds to the first image encoded as a matrix of size (8,8).

Make 3D array with 1D arrays with zero padding depending on index of 1D array numpythonically

Consider the following 1D arrays
a=np.arange(3)+9
b=np.arange(3)+5
currently I am initializing the new 3d array by using
n=4
cols=3
k=np.vstack((a,b,a*b,np.zeros((n,cols)),a,b,a,a,b**2,np.zeros((n,cols)),a*2,a)).T.reshape(-1,2,n+5)
where a and b will always be the same shape
which results in
array([[[ 9., 5., 45., 0., 0., 0., 0., 9., 5.],
[ 9., 9., 25., 0., 0., 0., 0., 18., 9.]],
[[ 10., 6., 60., 0., 0., 0., 0., 10., 6.],
[ 10., 10., 36., 0., 0., 0., 0., 20., 10.]],
[[ 11., 7., 77., 0., 0., 0., 0., 11., 7.],
[ 11., 11., 49., 0., 0., 0., 0., 22., 11.]]])
How would i use a similar technique, also without a for loop, to change the zero padding to the following:
array([[[ 9., 5., 45., 9., 5., 0., 0., 0., 0.],
[ 9., 9., 25., 18., 9., 0., 0., 0., 0.]],
[[ 10., 6., 60., 0., 0., 10., 6., 0., 0.],
[ 10., 10., 36., 0., 0., 20., 10., 0., 0.]],
[[ 11., 7., 77., 0., 0., 0., 0., 11., 7.],
[ 11., 11., 49., 0., 0., 0., 0., 22., 11.]]])
One can use advanced-indexing to assign those array values into a zeros initialized array given the column indices -
out = np.zeros((3,2,9),dtype=bool)
vals = np.array([[a,b,a*b,a,b],[a,a,b**2,2*a,a]])
out[np.arange(3)[:,None],:, idx] = vals.T
Sample run -
In [448]: a
Out[448]: array([ 9, 10, 11])
In [449]: b
Out[449]: array([5, 6, 7])
In [450]: out
Out[450]:
array([[[ 9., 5., 45., 9., 5., 0., 0., 0., 0.],
[ 9., 9., 25., 18., 9., 0., 0., 0., 0.]],
[[ 10., 6., 60., 0., 0., 10., 6., 0., 0.],
[ 10., 10., 36., 0., 0., 20., 10., 0., 0.]],
[[ 11., 7., 77., 0., 0., 0., 0., 11., 7.],
[ 11., 11., 49., 0., 0., 0., 0., 22., 11.]]])

numpy array to triangle (matrix)

I have an array that I want split int a matrix (10x10).
after a several tries i did this.
a=np.arange(1,56)
tri = np.zeros((10, 10))
tri[np.triu_indices_from(tri,0)]=a
tri
array([[ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.],
[ 0., 11., 12., 13., 14., 15., 16., 17., 18., 19.],
[ 0., 0., 20., 21., 22., 23., 24., 25., 26., 27.],
[ 0., 0., 0., 28., 29., 30., 31., 32., 33., 34.],
[ 0., 0., 0., 0., 35., 36., 37., 38., 39., 40.],
[ 0., 0., 0., 0., 0., 41., 42., 43., 44., 45.],
[ 0., 0., 0., 0., 0., 0., 46., 47., 48., 49.],
[ 0., 0., 0., 0., 0., 0., 0., 50., 51., 52.],
[ 0., 0., 0., 0., 0., 0., 0., 0., 53., 54.],
[ 0., 0., 0., 0., 0., 0., 0., 0., 0., 55.]])
and the result I wish:
array([[ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.],
[ 11., 12., 13., 14., 15., 16., 17., 18., 19., 0.],
[ 20., 21., 22., 23., 24., 25., 26., 27., 0., 0.],
[ 28., 29., 30., 31., 32., 33., 34., 0., 0., 0.],
[ 35., 36., 37., 38., 39., 40., 0., 0., 0., 0.],
[ 41., 42., 43., 44., 45., 0., 0., 0., 0., 0.],
[ 46., 47., 48., 49., 0., 0., 0., 0., 0., 0.],
[ 50., 51., 52., 0., 0., 0., 0., 0., 0., 0.],
[ 53., 54., 0., 0., 0., 0., 0., 0., 0., 0.],
[ 55., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])
I did several ties like try.T, np.triu, np.tril ...etc.
thanks
If this is what you mean, you can rotate an upper triangular index matrix by 90 degree using rot90() method and then use it as index to fill the values in the array:
import numpy as np
a=np.arange(1,56)
tri = np.zeros((10, 10))
tri[np.rot90(np.triu(np.ones((10,10), dtype=bool)))] = a
tri
# array([[ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.],
# [ 11., 12., 13., 14., 15., 16., 17., 18., 19., 0.],
# [ 20., 21., 22., 23., 24., 25., 26., 27., 0., 0.],
# [ 28., 29., 30., 31., 32., 33., 34., 0., 0., 0.],
# [ 35., 36., 37., 38., 39., 40., 0., 0., 0., 0.],
# [ 41., 42., 43., 44., 45., 0., 0., 0., 0., 0.],
# [ 46., 47., 48., 49., 0., 0., 0., 0., 0., 0.],
# [ 50., 51., 52., 0., 0., 0., 0., 0., 0., 0.],
# [ 53., 54., 0., 0., 0., 0., 0., 0., 0., 0.],
# [ 55., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])

Categories