Luca
Luca

Reputation: 1810

Numpy matrix multiplication fails ("shapes not aligned") when second element is a vector/array

When I multiply a NxN numpy matrix by a N elements numpy array I get an error saying that the shapes are not aligned.

from numpy import matrix,ones,eye
A = matrix(eye(3))
b = ones(3)
A*b

ValueError: shapes (3,3) and (1,3) not aligned: 3 (dim 1) != 1 (dim 0)

Also trasposing the vector does not solve the issue.

A*b.T

ValueError: shapes (3,3) and (1,3) not aligned: 3 (dim 1) != 1 (dim 0)

This make sense as numpy does not distinguish between column and row vectors so b.T is equal to b.

How can I perform a simple matrix-vector multiplication?

Upvotes: 1

Views: 4178

Answers (3)

Jgd10
Jgd10

Reputation: 537

The problem arises from the fact that the operator '*' is performing element-wise multiplication and NOT matrix multiplication as you intend. In python 3 this can be done using the '@' operator, as suggested by w-m. In python 2, however, you must use.

import numpy as np
result = np.dot(A,b)

The '*' operator will try to multiple every element of A with the corresponding element of b. If these are not the same shape you will get an error, which is what you see.

EDIT: I misunderstood OP's question. '*' will work for matrix multiplication if both objects are matrices. However, np.ones(3) produces a numpy array, which is not a numpy matrix object, so it doesn't work and tries to do element-wise multiplication.

if b becomes:

b = np.matrix((1,1,1)).T

then the code will work. It should also be noted that np.dot(A,b) will work even if both A and b are matrix objects, numpy arrays, or a mix of the two, making it the most general solution.

Upvotes: 0

Warren Weckesser
Warren Weckesser

Reputation: 114841

Because A is a matrix, Python calls A's __mul__ method to compute A*b, with b as its argument. That is, it calls A.__mul__(b). A numpy matrix insists on making everything a 2-d matrix, so it converts b to a matrix before performing the matrix multiplication. When b is converted to a numpy matrix, the result has shape (1, 3):

In [248]: b
Out[248]: array([1., 1., 1.])

In [249]: np.matrix(b).shape
Out[249]: (1, 3)

Then __mul__ complains that the shapes are not aligned, because A has shape (3, 3) and the converted b has shape (1, 3).

One way to fix this is to ensure that b is 2-d with shape (3, 1) before doing the multiplication:

In [250]: b = ones((3, 1))

In [251]: A * b
Out[251]: 
matrix([[1.],
        [1.],
        [1.]])

In the long term, though, it would be better to modify your code to not use matrix at all, as mentioned by @w-m.

Upvotes: 0

w-m
w-m

Reputation: 11232

(Don't use np.matrix, it's deprecated. Instead just use 2D arrays for linear algebra.)

Use the matrix multiplication operator @:

In [177]: from numpy import ones,eye
     ...: A = eye(3)
     ...: b = ones(3)
     ...: A @ b
Out[177]: array([1., 1., 1.])

Upvotes: 2

Related Questions