Numpy Subtract two arrays of equal ndim but different shape - python

So I have two ndarrays:
A with shape (N,a,a), a stack of N arrays of shape (a,a) basically
B with shape (8,M,a,a), a matrix of 8 x M arrays of shape (a,a)
I need to subtract B from A (A-B) such that the resulting array is of shape (8,M*N,a,a).
More verbosely each (M total) of the 8 arrays of B needs to be subtracted from each array in A, resulting in 8*M*N subtractions between (a,a) shape arrays.
How can I do this in a vectorized manner without loops?
This thread does something similar but in lower dimensions and I can't figure out how to extend it.

A = np.arange(8).reshape(2,2,2)
B = np.ones(shape=(8,4,2,2))
General broadcasting works if dimensions are the same or if one dimension is 1, so we do this;
a = A[np.newaxis, :, np.newaxis, :, :]
b = B[:, np.newaxis, :, :, :]
a.shape # <- (1,2,1,2,2)
b.shape # <- (8,1,4,2,2)
Now when you can do broadcasting
c = a - b
c.shape # <- (8,2,4,2,2)
And when you reshape the (2x4=8) components get aligned.
c.reshape(8,-1,2,2)
The ordering of the new axes dictates the reshaping, so be careful with that.

Related

Sort 3D array using sort indices of a 2D array

I have 2D and a 3D numpy array. The 2d array A has shape (N, 3) and the 3d array B has shape (N, 3, 3). I want to sort A along axis=1 and then apply that same sorting to array B sorting along axis=2.
I know I can do
sort_idxs = np.argsort(A, axis=1)
but then I don't know how to apply sort_idxs in the way I need to array B. sort_idxs has a shape of (N, 3) like A. Somehow I need to map the first dimension of sort_idxs to the first dimension of B, map the second dimension of sort_idxs to the 3rd dimension of B, and ignore the second dimension of B. How can I do this?
This can be solved using
sort_idxs = np.argsort(A, axis=1)
B_sorted = np.take_along_axis(B, sort_idxs[:, np.newaxis, :], axis=2)

mask first k elements in a 3D tensor in PyTorch (different k for each row)

I have a tensor M of dimensions [NxQxD] and a 1d tensor of indices idx (of size N). I want to efficiently create a tensor mask of dimensions [NxQxD] such that mask[i,j,k] = 1 iff j <= idx[i], i.e. I want to keep only the idx[i] first dimensions out of Q in the second dimension (dim=1) of M, for every row i.
Thanks!
It turns out this can be done via a broadcasting trick:
mask_2d = torch.arange(Q)[None, :] < idx[:, None] #(N,Q)
mask_3d = mask[..., None] #(N,Q,1)
masked = mask.float() * data

Convert NumPy vector to 2D array / matrix

What is the best way to convert a vector to a 2-dimensional array?
For example, a vector b of size (10, )
a = rand(10,10)
b = a[1, :]
b.shape
Out: (10L,)
can be converted to array of size (10,1) as
b = b.reshape(len(b), 1)
Is there a more concise way to do it?
Since you lose a dimension when indexing with a[1, :], the lost dimension needs to be replaced to maintain a 2D shape. With this in mind, you can make the selection using the syntax:
b = a[1, :, None]
Then b has the required shape of (10, 1). Note that None is the same as np.newaxis and inserts a new axis of length 1.
(This is the same thing as writing b = a[1, :][:, None] but uses only one indexing operation, hence saves a few microseconds.)
If you want to continue using reshape (which is also fine for this purpose), it's worth remembering that you can use -1 for (at most) one axis to have NumPy figure out what the correct length should be instead:
b.reshape(-1, 1)
Use np.newaxis:
In [139]: b.shape
Out[139]: (10,)
In [140]: b=b[:,np.newaxis]
In [142]: b.shape
Out[142]: (10, 1)
I think clearest way of doing this is by using np.expand_dims, which basically adds an axis to the array. If you use axis=-1, a new axis will be added as the last dimension.
b = np.expand_dims(b, axis=-1)
or if you want to me more concise:
b = np.expand_dims(b, -1)
Although the question is old, still it is worth to answer I think.
Use this style:
b = a[1:2, :]
you can use np.asmatrix(b) as well
a.shape #--> (12,)
np.asmatrix(a).shape #--> (1, 12)
np.asmatrix(a).T.shape #--> (12, 1)

What is the meaning of the following operation in numpy?

I'm digging out a piece of numpy code and there's a line I don't understand at all:
W[:, :, None] * h[None, :, :] * diff[:, None, :]
where W, h and diff are 784x20, 20x100 and 784x100 matrices. Multiplication result is 784x20x100 array, but I have no idea what does this computation actually do and what is the meaning of the result.
For what it's worth, the line is from machine learning related code, W corresponds to the weights array of of neural network's layer, h is layer activation, and diff is the difference between network's target and hypothesis (from Sida Wang's thesis on transforming autoencoder).
For NumPy arrays, * corresponds to element-wise multiplication. In order for this to work, the two arrays have to be either:
the same shape as each other
such that one array can be broadcast to the other
One array can be broadcast to another if, when pairing the trailing dimensions of each array, either the lengths in each pair are equal or one of the lengths is 1.
For example, the following arrays A and B have shapes which are compatible for broadcasting:
A.shape == (20, 1, 3)
B.shape == (4, 3)
(3 is equal to 3 and then the next length in A is 1 which can be paired with any length. It doesn't matter that B has fewer dimensions than A.)
To make two incompatible arrays broadcastable with each other, extra dimensions can be inserted into one or both arrays. Indexing a dimension with None or np.newaxis inserts an extra dimension of length one into an array.
Let's look at the example in the question. Python evaluates repeated multiplications left to right:
W[:, :, None] has shape (784, 20, 1)
h[None, :, :] has shape ( 1, 20, 100)
These shapes are broadcastable according to the explanation above and the multiplication returns an array with shape (784, 20, 100).
Array shape from last multiplication, (784, 20, 100)
diff[:, None, :] has a shape of (784, 1, 100)
These shapes of these two arrays are compatible so the second multiplication succeeds. An array with the shape (784, 20, 100) is returned.

shape of Vector in numpy

I am confused by the fact that
a = np.array([1,2])
a.T == a # True
and also
I = np.array([[1,0],[0,1]])
np.dot(a, I) = np.dot(I, a) # both sides work
Is the shape of vector (or array) in this case 1*2 or 2*1 ?
The vector a has shape 2, not 1 × 2 nor 2 × 1 (it is neither a column nor row vector), which is why transposition doesn't have any effect, as transposition by default reverses the ordering of the axes.
Numpy is very lenient about what kinds of arrays can be multiplied using dot:
it is a sum product over the last axis of a and the second-to-last of b

Categories