Add a vector to array - python

A really stupid question, but I could not figure the right way..
A is a 2 by 2 matrix, and B is a 2 by 1 matrix.
In a 10 iterations loop, B_new=A*B. B_new is 2 by 1.
Save B_new to an output matrix B_final after each iteration. So in the end, B_final is 2 by 10.
However, I have problem of adding B to B_new in a loop. Below is my code, can anyone give me some suggestions?
import numpy as np
a=np.ones(shape=(2,2))
b=np.ones(shape=(2,1))
c_final=np.zeros(shape=(2,10))
for i in range(0,10):
c=np.dot(a,b)
b=c
c_final[:,i]=c
Here is the error message:
c_final[:,i]=c
ValueError: output operand requires a reduction, but reduction is not enabled

The error you're seeing is because when numpy broadcasts c_final[:,i] and np.dot(a,b) together it produces an array with shape (2,2), which then can't be assigned to c_final[:,i] since it has a shape of (2,1). I think it's much clearer if you just play around with it in the interpreter:
>>> import numpy as np
>>> a = np.ones((2,2))
>>> b = np.ones((2,1))
>>> c_final = np.zeros((2,10))
>>> np.dot(a,b)
array([[ 2.],
[ 2.]])
>>> np.dot(a,b).shape
(2, 1)
>>> c_final[:,0]
array([ 0., 0.])
>>> c_final[:,0].shape
(2,)
>>> np.broadcast(c_final[:,0],np.dot(a,b)).shape
(2, 2)
The way around this is to flatten np.dot(a,b) by using np.squeeze or something similar so that when they are broadcast together they produce a 2 element array. For example:
>>> c_final[:,0] = np.dot(a,b).squeeze()
You're not alone in finding the error message unhelpful. Someone filed a ticket about this about a year ago.

Related

Add a level to Numpy array

I have a problem with a numpy array.
In particular, suppose to have a matrix
x = np.array([[1., 2., 3.], [4., 5., 6.]])
with shape (2,3), I want to convert the float numbers into list so to obtain the array [[[1.], [2.], [3.]], [[4.], [5.], [6.]]] with shape (2,3,1).
I tried to convert each float number to a list (i.e., x[0][0] = [x[0][0]]) but it does not work.
Can anyone help me? Thanks
What you want is adding another dimension to your numpy array. One way of doing it is using reshape:
x = x.reshape(2,3,1)
output:
[[[1.]
[2.]
[3.]]
[[4.]
[5.]
[6.]]]
There is a function in Numpy to perform exactly what #Valdi_Bo mentions. You can use np.expand_dims and add a new dimension along axis 2, as follows:
x = np.expand_dims(x, axis=2)
Refer:
np.expand_dims
Actually, you want to add a dimension (not level).
To do it, run:
result = x[...,np.newaxis]
Its shape is just (2, 3, 1).
Or save the result back under x.
You are trying to add a new dimension to the numpy array. There are multiple ways of doing this as other answers mentioned np.expand_dims, np.new_axis, np.reshape etc. But I usually use the following as I find it the most readable, especially when you are working with vectorizing multiple tensors and complex operations involving broadcasting (check this Bounty question that I solved with this method).
x[:,:,None].shape
(2,3,1)
x[None,:,None,:,None].shape
(1,2,1,3,1)
Well, maybe this is an overkill for the array you have, but definitely the most efficient solution is to use np.lib.stride_tricks.as_strided. This way no data is copied.
import numpy as np
x = np.array([[1., 2., 3.], [4., 5., 6.]])
newshape = x.shape[:-1] + (x.shape[-1], 1)
newstrides = x.strides + x.strides[-1:]
a = np.lib.stride_tricks.as_strided(x, shape=newshape, strides=newstrides)
results in:
array([[[1.],
[2.],
[3.]],
[[4.],
[5.],
[6.]]])
>>> a.shape
(2, 3, 1)

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?
(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.])
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.
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.

How can I initialize an empty Numpy array with a given number of dimensions?

I basically want to initialize an empty 6-tensor, like this:
a = np.array([[[[[[]]]]]])
Is there a better way than writing the brackets explicitly?
You can use empty or zeros.
For example, to create a new array of 2x3, filled with zeros, use: numpy.zeros(shape=(2,3))
You can do something like np.empty(shape = [1] * (dimensions - 1) + [0]).
Example:
>>> a = np.array([[[[[[]]]]]])
>>> b = np.empty(shape = [1] * 5 + [0])
>>> a.shape == b.shape
True
Iteratively adding rows of that rank-1 using np.concatenate(a,b,axis=0)
Don't. Creating an array iteratively is slow, since it has to create a new array at each step. Plus a and b have to match in all dimensions except the concatenation one.
np.concatenate((np.array([[[]]]),np.array([1,2,3])), axis=0)
will give you dimensions error.
The only thing you can concatenate to such an array is an array with size 0 dimenions
In [348]: np.concatenate((np.array([[]]),np.array([[]])),axis=0)
Out[348]: array([], shape=(2, 0), dtype=float64)
In [349]: np.concatenate((np.array([[]]),np.array([[1,2]])),axis=0)
------
ValueError: all the input array dimensions except for the concatenation axis must match exactly
In [354]: np.array([[]])
Out[354]: array([], shape=(1, 0), dtype=float64)
In [355]: np.concatenate((np.zeros((1,0)),np.zeros((3,0))),axis=0)
Out[355]: array([], shape=(4, 0), dtype=float64)
To work iteratively, start with a empty list, and append to it; then make the array at the end.
a = np.zeros((1,1,1,1,1,0)) could be concatenated on the last axis with another np.ones((1,1,1,1,1,n)) array.
In [363]: np.concatenate((a,np.array([[[[[[1,2,3]]]]]])),axis=-1)
Out[363]: array([[[[[[ 1., 2., 3.]]]]]])
You could directly use the ndarray constructor:
numpy.ndarray(shape=(1,) * 6)
Or the empty variant, since it seems to be more popular:
numpy.empty(shape=(1,) * 6)
This should do it:
x = np.array([])

why do we need np.squeeze()?

Very often, arrays are squeezed with np.squeeze(). In the documentation, it says
Remove single-dimensional entries from the shape of a.
However I'm still wondering: Why are zero and nondimensional entries in the shape of a? Or to put it differently: Why do both a.shape = (2,1) and (2,) exist?
Besides the mathematical differences between the two things, there is the issue of predictability. If your suggestion was followed, you could at no point rely on the dimension of your array. So any expression of the form my_array[x,y] would need to be replaced by something that first checks if my_array is actually two-dimensional and did not have an implicit squeeze at some point. This would probably obfuscate code far more than the occasional squeeze, which does a clearly specified thing.
Actually, it might even be very hard to tell, which axis has been removed, leading to a whole host of new problems.
In the spirit of The Zen of Python, also Explicit is better than implicit, we can also say that we should prefer explicit squeeze to implicit array conversion.
This helps you get rid of useless one dimension arrays like using
[7,8,9] instead of [[[7,8,9]]]
or [[1,2,3],[4,5,6]] instead of [[[[1,2,3],[4,5,6]]]].
Check this link from tutorials point for example.
One example of the importance is when multiplying arrays. Two 2-dimensional arrays will multiply each value at a time
e.g.
>>> x = np.ones((2, 1))*2
>>> y = np.ones((2, 1))*3
>>> x.shape
(2,1)
>>> x*y
array([[ 6.],
[ 6.]])
If you multiply a 1d array by a 2d array then the behaviour is different
>>> z = np.ones((2,))*3
>>> x*z
array([[ 6., 6.],
[ 6., 6.]])
Secondly, you also might want to squeeze the earlier dimensions e.g. a.shape = (1,2,2) to a.shape = (2,2)
When you squeeze a (2,1) array, you get (2,) which works as both (2,1) and (1,2):
>>> a = np.ones(2)
>>> a.shape
(2,)
>>> a.T.shape
(2,)
>>> X = np.ones((2,2))*2
>>> np.dot(a,X)
[4. 4.]
>>> np.dot(X,a)
[4. 4.]
This cannot happen with a (2,1) array:
>>> b = np.ones((2,1))
>>> np.dot(b,X)
Traceback (most recent call last):
ValueError: shapes (2,1) and (2,2) not aligned: 1 (dim 1) != 2 (dim 0)

About NumPy array in Python [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
What is the difference between:
import numpy as np
A = np.zeros((3,))
and
import numpy as np
B = np.zeros((1,3))
Thanks for your answer!
Hope these illustrate the difference in practice.
>>> A = np.zeros((3,))
>>> B = np.zeros((1,3))
>>> A #no column, just 1D
array([ 0., 0., 0.])
>>> B #has one column
array([[ 0., 0., 0.]])
>>> A.shape
(3,)
>>> B.shape
(1, 3)
>>> A[1]
0.0
>>> B[1] #can't do this, it will take the 2nd column, but there is only one column.
Traceback (most recent call last):
File "<pyshell#89>", line 1, in <module>
B[1]
IndexError: index 1 is out of bounds for axis 0 with size 1
>>> B[0] #But you can take the 1st column
array([ 0., 0., 0.])
>>> B[:,1] #take the 2nd cell, for each column
array([ 0.])
>>> B[0,1] #how to get the same result as A[1]? take the 2nd cell of the 1st col.
0.0
The first one creates a 1D numpy.array of zeros:
>>> import numpy as np
>>> A = np.zeros((3,))
>>> A
array([ 0., 0., 0.])
>>> A[0]
0.0
>>>
The second creates a 2D numpy.array of 1 row and 3 columns, filled with zeros:
>>> import numpy as np
>>> B = np.zeros((1,3))
>>> B
array([[ 0., 0., 0.]])
>>> B[0]
array([ 0., 0., 0.])
>>>
Here is a reference on numpy.zeros and one on numpy.array if you want further details.
A is a one-dimensional array with three elements.
B is a two-dimensional array with one row and three columns.
You could also use C = np.zeros((3,1)) which would create a two-dimensional array with three rows and one column.
A, B, and C have the same elements -- the difference is in how they will be interpreted by later calls. For instance some numpy calls operate on specific dimensions, or can be told to operate on a specific dimensions. For instance sum:
>> np.sum(A, 0)
3.0
>> np.sum(B, 0)
array([ 1., 1., 1.])
They also have different behavior with matrix/tensor operations like dot, and also operations like hstack and vstack.
If all you are going to use is vectors, form A will usually do what you want. The extra 'singleton' dimension (i.e., a dimension of size 1) is just extra cruft you have to keep track of. However, if you need to interact with 2d arrays it is likely that you will have to distinguish between row vectors and column vectors. In that case forms B and C will be useful.

Categories