-1

I have a few variables listed below. How come I receive the error message at the bottom when I try to run this block of code? Ind_var[i,:] should be of shape (1,2) so by matrix multiplication (1,2) * (2,2) is (1,2)? Sorry I'm new to python.

import numpy as np

spread_len = 10
n_param = 2
Q = np.zeros((spread_len,1))
ind_var = np.zeros((spread_len,2))
R = np.zeros((n_param,n_param))
Ve = 0.001

for i in range(spread_len):
     Q[i]=ind_var[i,:]*R*ind_var[i,:]+Ve

Error message:

ValueError: could not broadcast input array from shape (2,2) into shape (1)

A1122
  • 1,324
  • 3
  • 15
  • 35
  • You might be confusing `*` with the matrix-multiplication in MATLAB, as opposed to in NumPy that goes as elementwise multiplication? – Divakar Jun 29 '16 at 08:27

2 Answers2

0

You need to transpose the second ind_var[i,:] to get a (2,1) shape, otherwise you're spanning a new (2,2) matrix which doesn't fit into Q[i] which is shape (1).

Also R and ind_var need to be matrices, not arrays, for matrix math:

import numpy as np

spread_len = 10
n_param = 2
Q = np.zeros((spread_len,1))
ind_var = np.asmatrix(np.zeros((spread_len,2)))
R = np.asmatrix(np.zeros((n_param,n_param)))
Ve = 0.001

for i in range(spread_len):
    Q[i]=ind_var[i,:]*R*ind_var[i,:].T+Ve

Maybe not a beautiful solution, but you can go from here and use matlib to create matrices.

import numpy as np
import numpy.matlib as ml

spread_len = 10
n_param = 2
Q = np.zeros((spread_len,1))
ind_var = ml.zeros((spread_len,2))
R = ml.zeros((n_param,n_param))
Ve = 0.001

for i in range(spread_len):
    Q[i]=ind_var[i,:]*R*ind_var[i,:].T+Ve
CodeMonkey
  • 4,067
  • 1
  • 31
  • 43
  • So I tried `np.transpose` the second `ind_var[i,:]`, as `Q[i] = ind_var[i,:]*R*np.transpose(ind_var[i,:])+Ve` but I still get the same error message **ValueError: could not broadcast input array from shape (2,2) into shape (1)** – A1122 Jun 29 '16 at 08:10
  • You can use `np.matrix` directly, without importing the `ml` module. – hpaulj Jun 29 '16 at 18:51
0

In your example:

In [970]: ind_var.shape
Out[970]: (10, 2)

In [971]: R.shape
Out[971]: (2, 2)

In [972]: ind_var[0,:]*R*ind_var[0,:]+Ve
Out[972]: 
array([[ 0.001,  0.001],
       [ 0.001,  0.001]])

For arrays, the * multiplication is element by element, like MATLAB .*. So the result is shape of R, and the wrong size to put in a cell of Q.

There is an array matrix multiplication, np.dot:

In [973]: np.dot(ind_var[0,:], np.dot(R, ind_var[0,:]))+Ve
Out[973]: 0.001

There is an array subclass, np.matrix that is constrained to be 2d (like old MATLAB) and uses * for matrix product

In [981]: Rm=np.matrix(R)  
In [982]: ind_m=np.matrix(ind_var)
In [983]: ind_m[0,:]*R*ind_m[0,:].T+Ve
Out[983]: matrix([[ 0.001]])

np.einsum is a generalization of np.dot that can perform all calculations in one step

In [985]: np.einsum('ij,jk,ik->i', ind_var, R, ind_var)+Ve
Out[985]: 
array([ 0.001,  0.001,  0.001,  0.001,  0.001,  0.001,  0.001,  0.001,
        0.001,  0.001])

R and ind_var values are all 0 in this example, so the results aren't diagnositic - except for shape.

I was going to suggest the new matmul operator, @ but ind_var@R@ind_var.T produces a 10x10 array, which is not what we want. The iterative ind_var[0,:]@R@ind_var[0,:] is ok.

(I really should test things with nontrivial values).

hpaulj
  • 221,503
  • 14
  • 230
  • 353