numpy matrix vector multiplication
Simplest solution
Use numpy.dot
or a.dot(b)
. See the documentation here.
>>> a = np.array([[ 5, 1 ,3],
[ 1, 1 ,1],
[ 1, 2 ,1]])
>>> b = np.array([1, 2, 3])
>>> print a.dot(b)
array([16, 6, 8])
This occurs because numpy arrays are not matrices, and the standard operations *, +, -, /
work element-wise on arrays.
Note that while you can use numpy.matrix
(as of early 2021) where *
will be treated like standard matrix multiplication, numpy.matrix
is deprecated and may be removed in future releases.. See the note in its documentation (reproduced below):
It is no longer recommended to use this class, even for linear algebra. Instead use regular arrays. The class may be removed in the future.
Thanks @HopeKing.
Other Solutions
Also know there are other options:
As noted below, if using python3.5+ and numpy v1.10+, the
@
operator works as you'd expect:>>> print(a @ b)
array([16, 6, 8])If you want overkill, you can use
numpy.einsum
. The documentation will give you a flavor for how it works, but honestly, I didn't fully understand how to use it until reading this answer and just playing around with it on my own.>>> np.einsum('ji,i->j', a, b)
array([16, 6, 8])As of mid 2016 (numpy 1.10.1), you can try the experimental
numpy.matmul
, which works likenumpy.dot
with two major exceptions: no scalar multiplication but it works with stacks of matrices.>>> np.matmul(a, b)
array([16, 6, 8])numpy.inner
functions the same way asnumpy.dot
for matrix-vector multiplication but behaves differently for matrix-matrix and tensor multiplication (see Wikipedia regarding the differences between the inner product and dot product in general or see this SO answer regarding numpy's implementations).>>> np.inner(a, b)
array([16, 6, 8])
# Beware using for matrix-matrix multiplication though!
>>> b = a.T
>>> np.dot(a, b)
array([[35, 9, 10],
[ 9, 3, 4],
[10, 4, 6]])
>>> np.inner(a, b)
array([[29, 12, 19],
[ 7, 4, 5],
[ 8, 5, 6]])If you have multiple 2D arrays to
dot
together, you may consider thenp.linalg.multi_dot
function, which simplifies the syntax of many nestednp.dot
s. Note that this only works with 2D arrays (i.e. not for matrix-vector multiplication).>>> np.dot(np.dot(a, a.T), a).dot(a.T)
array([[1406, 382, 446],
[ 382, 106, 126],
[ 446, 126, 152]])
>>> np.linalg.multi_dot((a, a.T, a, a.T))
array([[1406, 382, 446],
[ 382, 106, 126],
[ 446, 126, 152]])
Rarer options for edge cases
If you have tensors (arrays of dimension greater than or equal to one), you can use
numpy.tensordot
with the optional argumentaxes=1
:>>> np.tensordot(a, b, axes=1)
array([16, 6, 8])Don't use
numpy.vdot
if you have a matrix of complex numbers, as the matrix will be flattened to a 1D array, then it will try to find the complex conjugate dot product between your flattened matrix and vector (which will fail due to a size mismatchn*m
vsn
).
Numpy Matrix Multiplication with Vectors
The reason why you are getting a scalar because you are multiplying two 1D vectors in numpy, which produces the inner product of 2 vectors. You need to reshape your vector to the shape (3,1), which turns them into a 2D shape and then you get the expected result upon performing the vector multiplication. Check the snippet below
>>> import numpy as np
>>> A = np.array([1,2,3])
>>> B = np.array([4,5,6])
>>> A.shape
(3,)
>>> B.shape
(3,)
>>> AA = A.reshape(3, 1)
>>> BB = B.reshape(3, 1)
>>> AA.shape
(3, 1)
>>> BB.shape
(3, 1)
>>> np.matmul(AA, np.transpose(BB))
array([[ 4, 5, 6],
[ 8, 10, 12],
[12, 15, 18]])
Multiplying a matrix with array of vectors in NumPy
There are a few different ways to solve this problem.
Option 1:
The most straightforward is to reshape the array vectors
so that it has shape (3, 128 * 128)
, then call the builtin np.dot
function, and reshape the result back to your desired shape.
(Note that the (128, 128)
part of the array's shape is not really relevant to the rotation; it's an interpretation that you probably want to make your problem clearer, but makes no difference to the linear transformation you want to apply. Said another way, you are rotating 3-vectors. There are 128 * 128 == 16384
of them, they just happen to be organized into a 3D array like above.)
This approach would look like:
>>> v = vectors.reshape(-1, 3).T
>>> np.dot(rotation_matrix, v).shape
(3, 16384)
>>> rotated = np.dot(rotation_matrix, v).T.reshape(vectors.shape)
>>> rotated.shape == vectors.shape
True
Option 2:
Another method that does not involve any reshaping is to use NumPy's Einstein summation. Einstein summation is very flexible, and takes a while to understand, but its power justifies its complexity. In its simplest form, you "label" the axes that you want to multiply together. Axes that are omitted are "contracted", meaning a sum across that axis is computed. For your case, it would be:
>>> np.einsum('ij,klj->kli', rotation_matrix, vectors).shape
(128, 128, 3)
>>> np.allclose(rotated, np.einsum('ij,klj->kli', rotation_matrix_vectors))
True
Here's a quick explanation of the indexing. We are labeling the axes of the rotation matrix i
and j
, and the axes of the vectors k
, l
, and j
. The repeated j
means those are the axes multiplied together. This is equivalent to right-multiplying the reshaped array above with the rotation matrix (i.e., it's a rotation).
The output axes are labeled kli
. This means we're preserving the k
and l
axes of the vectors. Since j
is not in the output labels, there is a summation across that axis. Instead we have the axis i
, hence the final shape of (128, 128, 3)
. You can see above that the dot-product method and the einsum
method agree.
It can take a while to wrap your head around Einstein summation, but it is super awesome and powerful. I highly recommend learning more about it, especially if this sort of linear algebra is a common problem for you.
matrix - vector multiplication in python (numpy)
Remember that for a matrix multiplication, the second dimension of the first matrix must be equal to the first dimension of the second one. Therefore, performing a matrix multiplication of a 4x1 vector and a 4x4 matrix is not possible.
What you can do is transpose the vector (using myvector.T
) so you get a 1x4 vector and multiply that with your 4x4 matrix.
Alternatively, you could multiply the vector on the right side.
Matrix by Vector multiplication using numpy dot product
The multiplication is possible because v
has only one dimension. Numpy considers it as a vector, so as this vector has 2 components, the matrix vector multiplication is allowed.
However, if you force v
shape to be 1 row and 2 columns (so 2 dimensions), you will get an (expected) error:
>>> v.reshape(1,2).shape
(1, 2)
>>> np.dot(m, v.reshape(1,2))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<__array_function__ internals>", line 5, in dot
ValueError: shapes (3,2) and (1,2) not aligned: 2 (dim 1) != 1 (dim 0)
In order to have a valid multiplication, you need v
to be 2 rows and 1 column (so you need to transpose it):
>>> np.dot(m, v.reshape(1,2).T)
array([[11],
[17],
[17]])
And you can see that the shape of the result is (2,1)
, so 2 rows and one column.
Vectorized Matrix-Vector multiplication along specified axis of multidimensional array
This is where np.einsum
shines:
np.einsum('mnij,mnj->mni', A,B)
Check with
np.allclose(np.einsum('mnij,mnj->mni', A,x), b)
returns True
Numpy matrix multiplication between a 2D array and each vector in 3D array
You could use the @
operator:
A @ H.T
array([[[ 14, 32, 50],
[ 32, 77, 122],
[ 50, 122, 194]],
[[ 68, 167, 266],
[ 86, 212, 338],
[104, 257, 410]]])
How to multiply two vector and get a matrix?
Normal matrix multiplication works as long as the vectors have the right shape. Remember that *
in Numpy is elementwise multiplication, and matrix multiplication is available with numpy.dot()
(or with the @
operator, in Python 3.5)
>>> numpy.dot(numpy.array([[1], [2]]), numpy.array([[3, 4]]))
array([[3, 4],
[6, 8]])
This is called an "outer product." You can get it using plain vectors using numpy.outer()
:
>>> numpy.outer(numpy.array([1, 2]), numpy.array([3, 4]))
array([[3, 4],
[6, 8]])
Numpy matrix-vector multiplication with complex elements
Borrowing A_p
and u_p
from @Ivan I'd like to advertise the following much simpler approach that makes use of __matmul__
's inbuilt broadcasting. All we need to do is reverse the order of dimensions:
(u_p.T@A_p.T).T
This gives the same result as Ivan's einsum
but is a bit more flexible giving us full broadcasting without us having to figure out the corresponding format string every time.
np.allclose(np.einsum('ijmn,jkmn->ikmn', A_p, u_p),(u_p.T@A_p.T).T)
# True
Related Topics
Why Is Python Setup.Py Saying Invalid Command 'Bdist_Wheel' on Travis Ci
How to Build Multiple Submit Buttons Django Form
Python - Extracting and Saving Video Frames
How to Disable Log Messages from the Requests Library
How to Connect to MySQL in Python 3 on Windows
Iterating Through Directories with Python
In Python, Differencebetween ".Append()" and "+= []"
How to Switch Position of Two Items in a Python List
Read File Data Without Saving It in Flask
When to Use "While" or "For" in Python
How to Transform an Xml File Using Xslt in Python
Pandas Groupby, Then Sort Within Groups
How to Set Max_Retries for Requests.Request