This question already has answers here:
Matrix multiply two 1-D numpy arrays
(3 answers)
Closed 4 months ago.
I have for example two arrays, a and b. Array a has a length of 3. Array b an arbitrary length.
I would like to do the following with a numpy approach:
temp_res = 0
for i in range(3):
tem_res += a[i] * b
a can be treated as a vector of scalar values for multiplication. Basically I want to have a Matrix with 3 rows which has the same length as b and are multiplied with a's value at the corresponding index. However, because of the different shapes, I do not say any how to this without any loop (or list comprehension).
How can the example above implemented with purely numpy (and without any python loop)? I already checked out the documentation, but same shape is always a condition.
you need to read about numpy broadcasting, putting 1 in the first dimension of b will force broadcasting on it, a reshape only changes the stride but doesn't make a copy of the data.
tem_res = a * b.reshape([1,-1])
this can also be written this way in case b was larger than 2D
tem_res = a * b[None,:]
Example:
import numpy as np
a = np.ones([3,4]) # 3x4 array of ones
b = np.zeros([4]) # 1D array 4 elements of zeros
c = a * b.reshape([1,-1]) # b.reshape is now 1x4, it can be multipled by 3x4
print(c) # confirm it is 3x4 array
[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]
I know it is possible to create numpy arrays using the Linspace function. For example, given a range [x,y] I can make a vector of z elements equally distanced in [x,y]
v = np.linspace(x, y, z, retstep=True)
What if one needs more dimensions? Is it possible to use the same function to generate a 3x4 array? I tried by creating simple arrays and then merge them, but I don't think that is an efficient way to do that
You can use arrays for start and stop point of linspace:
x=np.linspace((0,0,0), (3,5,14), 4, axis=1)
print(x)
This will give the output:
[[ 0. 1. 2. 3. ]
[ 0. 1.66666667 3.33333333 5. ]
[ 0. 4.66666667 9.33333333 14. ]]
I have two multidimensional arrays, which I want to multiply with each other. One has the shape N,N,3 and the other has the shape N,N.
Let me set the stage:
I have an array of atom positions of the shape N,3:
atom_positions = [[x1,y1,z1],
[x2,y2,z2],
[x3,y3,z3],
...
]
From these I calculate an upper triangular matrix of distance vectors so that the resulting N,N,3 matrix contains all unique pair distance vectors r_ij of the vectors inside atom_positions:
pair_distance_vectors = [[[0,0,0],[x2-x1,y2-y1,z2-z1],[x3-x1,y3-y1,z3-z1],...],
[[0,0,0],[0,0,0] ,[x3-x2,y3-y2,z3-z2],...],
...
]
Now I want to normalize each of these pair distance vectors. For that I want to use my N,N pair_distances array, which contains the length of every vector inside pair_distance_vectors.
The formula for a single vector is:
r_ij/|r_ij|
I want to do that by doing a matrix multiplication, where every entry in the N,N array becomes a scalar by which a vector inside the N,N,3 array is multiplied. I'm pretty sure that this can be achieved somehow with numpy by using numpy.dot() or a different function, but I just can't find the answer myself. Also, I'm afraid if I do find a transformation which allows for this, that my maths will be faulty.
Here's some demonstration code, which achieves what I want in a very inefficient fashion:
import numpy as np
pair_distance_vectors = np.ones(shape=(2,2,3))
pair_distances = np.array(((1,2),(3,4)))
normalized_pair_distance_vectors = np.zeros(shape=(2,2,3))
for i,vec_list in enumerate(pair_distance_vectors):
for j,vec in enumerate(vec_list):
normalized_pair_distance_vectors[i,j] = vec*pair_distances[i,j]
print(normalized_pair_distance_vectors)
Thanks in advance.
EDIT: Maybe this is clearer:
distance_vectors = [[[x11,y11,z11],[x12,y12,z12],[x13,y13,z13],...],
[[x21,y21,z21],[x22,y22,z22],[x23,y23,z23],...],
... ]
distance_matrix = [[r_11,r_12,r_13,...],
[r_21,r_22,r_23,...],
... ]
norm_distance_vectors = some_operation(distance_vectors,distance_matrix)
norm_distance_vectors = [[r_11*[x11,y11,z11],r_12*[x12,y12,z12],r_13*[x13,y13,z13],...],
[r_21*[x21,y21,z21],r_22*[x22,y22,z22],r_23*[x23,y23,z23],...],
... ]
You won't need a loop. Trick is to expand your pair_distance in the 3rd dimension by repeating it m times (m being the dimension of your vectors, here 3D) and then divide two arrays element wise (works for any m-dimensional vectors, replace 3 with m):
pair_distances = np.repeat(pair_distances[:,:,None], 3, axis=2)
normalized_pair_distance_vectors = np.nan_to_num(pair_distance_vectors/ pair_distances)
Output for your example inputs:
[[[1. 1. 1. ]
[0.5 0.5 0.5 ]]
[[0.33333333 0.33333333 0.33333333]
[0.25 0.25 0.25 ]]]
While generating a linspace array in Numpy we get an array of the form (len(array), ), i.e. it doesn't have any 2nd dimension. How do I generate a similar array and initialize it using Numpy zeros? Because it takes a 2nd argument, like 1, so I get (len(array), 1) while initializing, which I wanted to avoid if possible.
Eg. np.linspace(0,10,5) = [0, 2.5, 5, 7.5, 10] ;
It's array dimension is (5, ).
On the other hand, a zeros array is defined as np.zeros((5,1)) and our output is a vector [0 0 0 0 0] ^ (Transpose). I wanted to be a flat array not like a vector.
Is there a way?
your first argument (5,1) is defining the shape of the array as a 5x1 explicitly 2d shape. Just pass (5,), or more explicitly as follows:
import numpy as np
z = np.zeros(shape=(5,), dtype=float)
print(z)
print(z.shape)
output is:
[ 0. 0. 0. 0. 0.]
(5,)
I have a problem to understand the matrix multiplication in numpy.
For example I have the following matrix (2d numpy array):
a = [ [ 1. 1. ]
[ 1. 2. ]
[ 1. 3. ] ]
And the following row vector theta:
theta = [ 1. 1. ]
The only way to multiply a with theta would be to transform
theta in a column vector first and then I would get the result:
result = [ [ 2. ]
[ 3. ]
[ 4. ] ]
When I multiply the matrix and the row vector (without transforming)
result = np.dot(a,theta)
I get this:
result = [ 2. 3. 4. ]
How is this even possible? I mean, I didn't transform the matrix.
Can you please tell me how this numpy multiplication works?
Thank you for your attention.
No, you're multiplying numpy array with another numpy array (not a matrix with a vector), although it looks like that. This is because, in essence, numpy arrays are not the same as matrices. And the dot product treats it that way as well.
If you write out the array and multiply, then you will see why. It's just the dot product (element-wise multiplication) of each row in the array 'a' with the vector 'theta'.
PS: (matrices are 2-D while arrays are not limited to any dimension)
Also, please take a look at this answer and this excellent answer