简体   繁体   中英

How can I create a new dimension when adding/multiplying vectors and matrices? (Python and NumPy)

I would like to compute:

matrix1 + vector * matrix2

where:

In: matrix1.shape
Out: (3, 3)

In: vector.shape
Out: (15,)

In: matrix2.shape
Out: (3, 3)

I did it this way:

answer = []
  for i in vector:
    answer_i = matrix1 + i * matrix2
    answer.append(answer_i)

So, I get a list of len(vector) in which each answer is shape (3,3). I wonder how to do the exact same thing, but without "for" loop and with NumPy arrays. The answer would be an array of shape (3, 3, 15). The answer may be simple but I don't have a lot of experience.

For example:

In: matrix1
Out: array([[1, 2, 3],
            [4, 5, 6],
            [7, 8, 9]])

In: vector
Out: array([-7., -6., -5., -4., -3., -2., -1.,  0.,  1.,  2.,  3.,  4., 5., 6.,  7.])

In: matrix2
Out: array([[ 5,  5,  5],
            [10, 10, 10],
            [20, 20, 20]])

My output (a list of len 15 for now):

[array([[ -34.,  -33.,  -32.],
        [ -66.,  -65.,  -64.],
        [-133., -132., -131.]]),
 array([[ -29.,  -28.,  -27.],
        [ -56.,  -55.,  -54.],
        [-113., -112., -111.]]),
 array([[-24., -23., -22.],
        [-46., -45., -44.],
        [-93., -92., -91.]]),
 array([[-19., -18., -17.],
        [-36., -35., -34.],
        [-73., -72., -71.]]),
 array([[-14., -13., -12.],
        [-26., -25., -24.],
        [-53., -52., -51.]]),
 array([[ -9.,  -8.,  -7.],
        [-16., -15., -14.],
        [-33., -32., -31.]]),
 array([[ -4.,  -3.,  -2.],
        [ -6.,  -5.,  -4.],
        [-13., -12., -11.]]),
 array([[1., 2., 3.],
        [4., 5., 6.],
        [7., 8., 9.]]),
 array([[ 6.,  7.,  8.],
        [14., 15., 16.],
        [27., 28., 29.]]),
 array([[11., 12., 13.],
        [24., 25., 26.],
        [47., 48., 49.]]),
 array([[16., 17., 18.],
        [34., 35., 36.],
        [67., 68., 69.]]),
 array([[21., 22., 23.],
        [44., 45., 46.],
        [87., 88., 89.]]),
 array([[ 26.,  27.,  28.],
        [ 54.,  55.,  56.],
        [107., 108., 109.]]),
 array([[ 31.,  32.,  33.],
        [ 64.,  65.,  66.],
        [127., 128., 129.]]),
 array([[ 36.,  37.,  38.],
        [ 74.,  75.,  76.],
        [147., 148., 149.]])]

I would like the output to be an array of shape (3, 3, 15).

您只需在矩阵中插入一个额外的维度,NumPy 广播将完成剩下的工作:

matrix1[..., None] + vector*matrix2[..., None]
In [1]: m1 = np.arange(1,10).reshape(3,3)
In [2]: vector = np.array([-7., -6., -5., -4., -3., -2., -1.,  0.,  1.,  2.,  3.
   ...: ,  4., 5., 6.,  7.])
In [4]: m2 = np.array([5,10,20])[:,None]+np.zeros(3,int)
In [5]: m2
Out[5]:
array([[ 5,  5,  5],
       [10, 10, 10],
       [20, 20, 20]])
In [6]: vector.shape
Out[6]: (15,)

np.array(answer) will produce a (15,3,3) array. With numpy broadcasting, we can get the same with:

In [12]: (m1+vector[:,None,None]*m2)
Out[12]:
array([[[ -34.,  -33.,  -32.],
        [ -66.,  -65.,  -64.],
        [-133., -132., -131.]],

       [[ -29.,  -28.,  -27.],
        [ -56.,  -55.,  -54.],
        [-113., -112., -111.]],

       ...

       [[  36.,   37.,   38.],
        [  74.,   75.,   76.],
        [ 147.,  148.,  149.]]])

vector becomes (15,1,1) and the m's (1,3,3) to match, together making (15,3,3).

But if you want the (15,) vector dimension to be last we need to do:

In [13]: (m1[:,:,None]+vector*m2[:,:,None])
Out[13]:
array([[[ -34.,  -29.,  -24.,  -19.,  -14.,   -9.,   -4.,    1.,    6.,
           11.,   16.,   21.,   26.,   31.,   36.],
        [ -33.,  -28.,  -23.,  -18.,  -13.,   -8.,   -3.,    2.,    7.,
           12.,   17.,   22.,   27.,   32.,   37.],
        [ -32.,  -27.,  -22.,  -17.,  -12.,   -7.,   -2.,    3.,    8.,
           13.,   18.,   23.,   28.,   33.,   38.]],
        ...
        [-131., -111.,  -91.,  -71.,  -51.,  -31.,  -11.,    9.,   29.,
           49.,   69.,   89.,  109.,  129.,  149.]]])

Here the broadcasting is (3,3,1) with (15,) => (3,3,15)

We could have also applied a transpose to the first case, changing the (15,3,3) shape to (3,3,15):

(m1+vector[:,None,None]*m2).transpose(1,2,0)

Another way is to join the 15 arrays on a new last axis.

np.stack(answer, axis=2)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM