numpy
has an old subclass np.matrix
that makes sure everything has exactly 2 dimensions. But it is no longer recommended.
numpy
tries to work equally well with 0,1,2, and more dimensions.
In [69]: A = np.array([[1,2,3],[4,5,6]])
In [70]: x = np.array([1,2,3])
In [71]: y = np.array([[1,2,3]])
In [72]: A.shape
Out[72]: (2, 3)
Matrix product of a (2,3) with (3,) resulting a (2,). It's docs say it expands the (3,) to (3,1), getting a (2,1) result, and then squeezing out that 1:
In [73]: A@x
Out[73]: array([14, 32])
The (2,3) with (1,3) transposed produces (2,1):
In [74]: [email protected]
Out[74]:
array([[14],
[32]])
(3,) with (3,2) => (2,):
In [78]: [email protected]
Out[78]: array([14, 32])
(1,3) with (3,2) => (1,3):
In [79]: [email protected]
Out[79]: array([[14, 32]])
How does your math intuition handle 3d or higher arrays? matmul/@
handles them nicely. np.einsum
does even better.
While you can create a (1,n) arrays, if it makes you more comfortable. But beware that you'll still end up with 1 or even 0d results.
For example with indexing:
In [80]: A
Out[80]:
array([[1, 2, 3],
[4, 5, 6]])
In [81]: A[1,:]
Out[81]: array([4, 5, 6])
In [82]: A[:,1]
Out[82]: array([2, 5])
In [83]: A[1,1]
Out[83]: 5
In [84]: A[1,1].shape
Out[84]: ()
In [85]: A[1,1].ndim
Out[85]: 0
or reduction along an axis:
In [86]: A.sum(axis=1)
Out[86]: array([ 6, 15])
though it's possible to retain dimensions:
In [87]: A.sum(axis=1, keepdims=True)
Out[87]:
array([[ 6],
[15]])
In [88]: A[[1],:]
Out[88]: array([[4, 5, 6]])
In [89]: A[:,[1]]
Out[89]:
array([[2],
[5]])
Another to keep in mind is that numpy operators most operation element-wise. The main exception being @
. Where as in MATLAB A*B
is matrix multiplication, and A.*B
is element-wise. Add to that broadcasting
, which allows us to add a (2,3) and (3,) array:
In [90]: A+x
Out[90]:
array([[2, 4, 6],
[5, 7, 9]])
Here (2,3) + (3,) => (2,3) + (1,3) => (2,3). The (3,) 1d array often behaves as a (1,3) or even (1,1,3) if needed. But expansion in the other direction has to be explicit.
In [92]: A / A.sum(axis=1) # (2,3) with (2,) error
Traceback (most recent call last):
File "<ipython-input-92-fec3395556f9>", line 1, in <module>
A / A.sum(axis=1)
ValueError: operands could not be broadcast together with shapes (2,3) (2,)
In [93]: A / A.sum(axis=1, keepdims=True) # (2,3) with (2,1) ok
Out[93]:
array([[0.16666667, 0.33333333, 0.5 ],
[0.26666667, 0.33333333, 0.4 ]])
In [94]: A / A.sum(axis=1)[:,None]
Out[94]:
array([[0.16666667, 0.33333333, 0.5 ],
[0.26666667, 0.33333333, 0.4 ]])