1

When I updated to the most recent version of numpy, a lot of my code broke because now every time I call np.dot() on a matrix and an array, it returns a 1xn matrix rather than simply an array. This causes me an error when I try to multiply the new vector/array by a matrix

example

A = np.matrix( [ [4, 1, 0, 0], [1, 5, 1, 0], [0, 1, 6, 1], [1, 0, 1, 4] ] )

x = np.array([0, 0, 0, 0])
print(x)

x1 = np.dot(A, x)
print(x1)

x2 = np.dot(A, x1)
print(x2)

output:
[0 0 0 0]
[[0 0 0 0]]
Traceback (most recent call last):
  File "review.py", line 13, in <module>
    x2 = np.dot(A, x1)
ValueError: shapes (4,4) and (1,4) not aligned: 4 (dim 1) != 1 (dim 0)

I would expect that either dot of a matrix and vector would return a vector, or dot of a matrix and 1xn matrix would work as expected.

Using the transpose of x doesn't fix this, nor does using A @ x, or A.dot(x) or any variation of np.matmul(A, x)

Jackson
  • 47
  • 7
  • 1
    Annoying as it probably is this may be a good moment to [get rid of `matrix`](https://stackoverflow.com/q/53254738/7207392) for good. – Paul Panzer May 22 '19 at 02:43

1 Answers1

1

Your arrays:

In [24]: A = np.matrix( [ [4, 1, 0, 0], [1, 5, 1, 0], [0, 1, 6, 1], [1, 0, 1, 4] ] )   
    ...: x = np.array([0, 0, 0, 0])                                                                      
In [25]: A.shape                                                                                         
Out[25]: (4, 4)
In [26]: x.shape                                                                                         
Out[26]: (4,)

The dot:

In [27]: np.dot(A,x)                                                                                     
Out[27]: matrix([[0, 0, 0, 0]])     # (1,4) shape

Let's try the same, but with a ndarray version of A:

In [30]: A.A                                                                                             
Out[30]: 
array([[4, 1, 0, 0],
       [1, 5, 1, 0],
       [0, 1, 6, 1],
       [1, 0, 1, 4]])
In [31]: np.dot(A.A, x)                                                                                  
Out[31]: array([0, 0, 0, 0])

The result is (4,) shape. That makes sense: (4,4) dot (4,) => (4,)

np.dot(A,x) is doing the same calculation, but returning a np.matrix. That by definition is a 2d array, so the (4,) is expanded to (1,4).

I don't have an older version to test this on, and am not aware of any changes.

If x is a (4,1) matrix, then the result (4,4)dot(4,1)=>(4,1):

In [33]: np.matrix(x)                                                                                    
Out[33]: matrix([[0, 0, 0, 0]])
In [34]: np.dot(A, np.matrix(x).T)                                                                       
Out[34]: 
matrix([[0],
        [0],
        [0],
        [0]])
hpaulj
  • 221,503
  • 14
  • 230
  • 353
  • Thanks for the quick reply! Your solution works. It seems inconsistent to be able to dot a matrix by a row vector if its an array but not if it's a matrix. I'm just going to use the np.array class instead of np.matrix – Jackson May 22 '19 at 02:53
  • 1
    Your `x` with shape (4,) is a 1d array. You may think of it as a vector or row-vector, but that doesn't change the dimensions or shape. `np.dot` describes how it handles 1d arrays, regardless of whether they are first or second. Some people (with MATLAB or linear algebra backgrounds) do have a problem conceiving of a 1d array that is neither row or column vector. – hpaulj May 22 '19 at 03:09