shape of Vector in numpy - python

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

Related

Numpy docs: How to multiply 2 arrays of different sizes together?

Numpy docs claims you can multiply arrays of different lengths together, however it is not working. I'm definitely misinterpreting what its saying but there's no example to go with their text. From the docs here:
Therefore, I created some code to try it out but I'm getting an error that says ValueError: operands could not be broadcast together with shapes (4,1) (3,1). Same error if I try this with shapes (4,) and (3,).
a = np.array([[1.0],
[1.0],
[1.0],
[1.0]])
print(a.shape)
b = np.array([[2.0],
[2.0],
[2.0]])
print(b.shape)
a*b
You can multiply arrays together if every dimenssion has the same length or one of the arrays has dimension 1 in the current axis.
in your example the arrays has sizes 4x1 and 3x1. So if you want to multiply them together you need to transpose one:
a = np.array([[1.0],
[1.0],
[1.0],
[1.0]])
print(a.shape)
b = np.array([[2.0],
[2.0],
[2.0]])
print(b.shape)
a*b.T
So its dimensions are shared with 1 in the other array 4x1 and 1x3 now and the result will have size 4x3
Copying and pasting the immediately previous text, in the same document, with my own emphasis:
When operating on two arrays, NumPy compares their shapes element-wise. It starts with the trailing (i.e. rightmost) dimensions and works its way left. Two dimensions are compatible when
they are equal, or
one of them is 1
If these conditions are not met, a ValueError: operands could not be broadcast together exception is thrown, indicating that the arrays have incompatible shapes. The size of the resulting array is the size that is not 1 along each axis of the inputs.
Arrays do not need to have the same number of dimensions. For example, if you have a 256x256x3 array of RGB values, and you want to scale each color in the image by a different value, you can multiply the image by a one-dimensional array with 3 values. Lining up the sizes of the trailing axes of these arrays according to the broadcast rules, shows that they are compatible:
Image (3d array): 256 x 256 x 3
Scale (1d array): 3
Result (3d array): 256 x 256 x 3
When either of the dimensions compared is one, the other is used. In other words, dimensions with size 1 are stretched or “copied” to match the other.
Now, let's try applying this logic to the example data.
A (2d array): 4 x 1
B (2d array): 3 x 1
Look at the first dimension: the lengths are 4 and 3. Is 4 equal to 3? No. Is either of those equal to 1? No. Therefore, the conditions are not met. We cannot broadcast along the first dimension of the array because there is not a rule that tells us how to match up 4 values against 3. If it were 4 values against 4, or 3 against 3, we could pair them up directly. If it were 4 against 1, or 1 against 3, we could "broadcast" by repeating the single value. Neither case applies here.
We could, however, multiply if either of the arrays were transposed:
A.T (2d array): 1 x 4
B (2d array): 3 x 1
A (2d array): 4 x 1
B.T (2d array): 1 x 3
Verifying this is left as an exercise for the reader.

numpy .dot using lists and arrays, whats the difference

When multiplication of two similar matrices 1*2 like [1,2], [3,5] is carried out using numpy.dot, it gives a result, when in fact it should be giving a shape and dimension error like while multiplying two similar arrays. What is going on under the hood?
a=[1,2]
b=[6,3]
result=[np.dot(b, a)]
print(result)
O/P= 12
But,
a=[[1,2]]
b=[[6,3]]
result=[np.dot(b, a)]
print(result)
Error:
O/P= ValueError: shapes (1,2) and (1,2) not aligned: 2 (dim 1) != 1
(dim 0)
As per the documentation here,
If both a and b are 1-D arrays, it is inner product of vectors (without complex conjugation).
If both a and b are 2-D arrays, it is matrix multiplication, but using matmul or a # b is preferred.
Case 1: a and b are 1-D arrays, so result is 1*6+2*3=12.
Case 2: a and b are 2-D arrays, so we will do matrix product of these two. It raises ValueError since the last dimension of a is not the same size as the second-to-last dimension of b.
Adding on to Anubhav Singh's correct answer, note that a matrix product of a row vector with a column vector returns a 1-by-1 matrix whose sole entry is the dot product of the two vectors, so in this case,
In [32]: a = np.array([[1,2]])
In [33]: b = np.array([[6,3]])
In [34]: a # b.T
Out[34]: array([[12]])
In [35]: np.dot(a, b.T)
Out[35]: array([[12]])
In [36]: np.dot(a[0], b[0])
Out[36]: 12
This is why np.dot behaves the way it does.

Numpy inner product of 2 column vectors

How can I take an inner product of 2 column vectors in python's numpy
Below code does not work
import numpy as np
x = np.array([[1], [2]])
np.inner(x, x)
It returned
array([[1, 2],
[2, 4]])`
instead of 5
The inner product of a vector with dimensions 2x1 (2 rows, 1 column) with another vector of dimension 2x1 (2 rows, 1 column) is a matrix with dimensions 2x2 (2 rows, 2 columns). When you take the inner product of any tensor the inner most dimensions must match (which is 1 in this case) and the result is a tensor with the dimensions matching the outter, i.e.; a 2x1 * 1x2 = 2x2.
What you want to do is transpose both such that when you multiply the dimensions are 1x2 * 2x1 = 1x1.
More generally, multiplying anything with dimensions NxM by something with dimensionsMxK, yields something with dimensions NxK. Note the inner dimensions must both be M. For more, review your matrix multiplication rules
The np.inner function will automatically transpose the second argument, thus when you pass in two 2x1, you get a 2x2, but if you pass in two 1x2 you will get a 1x1.
Try this:
import numpy as np
x = np.array([[1], [2]])
np.inner(np.transpose(x), np.transpose(x))
or simply define your x as row vectors initially.
import numpy as np
x = np.array([1,2])
np.inner(x, x)
i think you mean to have:
x= np.array([1,2])
in order to get 5 as output, your vector needs to be 1xN not Nx1 if you want to apply np.inner on it
Try the following it will work
np.dot(np.transpose(a),a))
make sure col_vector has shape (N,1) where N is the number of elements
then simply sum one to one multiplication result
np.sum(col_vector*col_vector)

Numpy operation for euclidean distance between multidimensional arrays

I have two numpy arrays. 'A' of size w,h,2 and 'B' with n,2.
In other words, A is a 2-dimensional array of 2D vectors while B is a 1D array of 2D vectors.
What i want as a result is an array of size w,h,n. The last dimension is an n-dimensional vector where each of the components is the euclidean distance between the corresponding vector from A (denoted by the first two dimensions w and h) and the nth vector of B.
I know that i can just loop through w, h and n in python manually and calculate the distance for each element, but i like to know if there is a smart way to do that with numpy operations to increase performance.
I found some similar questions but unfortunately all of those use input arrays of the same dimensionality.
Approach #1
You could reshape A to 2D, use Scipy's cdist that expects 2D arrays as inputs, get those euclidean distances and finally reshape back to 3D.
Thus, an implementation would be -
from scipy.spatial.distance import cdist
out = cdist(A.reshape(-1,2),B).reshape(w,h,-1)
Approach #2
Since, the axis of reduction is of length 2 only, we can just slice the input arrays to save memory on intermediate arrays, like so -
np.sqrt((A[...,0,None] - B[:,0])**2 + (A[...,1,None] - B[:,1])**2)
Explanation on A[...,0,None] and A[...,1,None] :
With that None we are just introducing a new axis at the end of sliced A. Well, let's take a small example -
In [54]: A = np.random.randint(0,9,(4,5,2))
In [55]: A[...,0].shape
Out[55]: (4, 5)
In [56]: A[...,0,None].shape
Out[56]: (4, 5, 1)
In [57]: B = np.random.randint(0,9,(3,2))
In [58]: B[:,0].shape
Out[58]: (3,)
So, we have :
A[...,0,None] : 4 x 5 x 1
B[:,0] : 3
That is essentially :
A[...,0,None] : 4 x 5 x 1
B[:,0] : 1 x 1 x 3
When the subtraction is performed, the singleton dims are broadcasted corresponding to the dimensions of the other participating arrays -
A[...,0,None] - B : 4 x 5 x 3
We repeat this for the second index along the last axis. We add these two arrays after squaring and finally a square-root to get the final eucl. distances.

Stacking and adding up numpy arrays

I have an array g.
g = np.array([])
I have some loops through which I need to build it with the following structure in python:
[
[1 4
2 5
3 6]
[7 10
8 11
9 12]
]
...
i.e. any number of rows (let's say 10), but with each entry consisting of a 3x2 array.
After initializing g at the top, I'm doing this:
curr_g = np.array([])
for y, w in zip(z.T, weights.T):
temp_g = sm.WLS(y, X, w).fit()
# temp_g.params produces a (3L,) array
# curr_g is where I plan to end up with a 3x2 array
curr_g = np.hstack((temp_g.params, curr_g))
g = np.hstack((temp_g.params, g))
I thought that when I use hstack with two 3x1 arrays, then I'll end up with one single 3x2 array. But what's happening is that after the stacking, curr_g just goes from (3L,) to (6L,)...
Also, once I've got a 3x2 array, how do I stack 3x2 arrays on top of each other?
You are correct saying that "when I use hstack with two 3x1 arrays, then I'll end up with one single 3x2 array":
params =array([1,2,3]).reshape(3,1)
curr_g =array([4,5,6]).reshape(3,1)
print hstack((params, curr_g)).shape # == (3,2)
Likely, you get an array with shape (6,) because temp_g.params and g have both shape (3,), not (3,1). If this is the case, you're better of with column_stack((temp_g.params, curr_g)).
To the last point, you first initialize your big array g to the right size:
g=array((N,3,2))
and then you fill it in the for loop:
for j, (y, w) in enumerate(zip(z.T, weights.T)):
#calculate temp_g and curr_g
g[j]=column_stack((temp_g.params, curr_g))

Categories