Как я могу создать новое измерение при добавлении / умножении векторов и матриц? (Python и NumPy)

#python #arrays #numpy #optimization

#python #массивы #numpy #оптимизация

Вопрос:

Я хотел бы вычислить:

 matrix1   vector * matrix2
  

где:

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

In: vector.shape
Out: (15,)

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

Я сделал это так:

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

Итак, я получаю список len(вектор), в котором каждый ответ имеет форму (3,3). Интересно, как сделать то же самое, но без цикла «for» и с массивами NumPy. Ответом будет массив формы (3, 3, 15). Ответ может быть простым, но у меня нет большого опыта.

Например:

 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]])
  

Мой вывод (список len 15 на данный момент):

 [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.]])]
  

Я бы хотел, чтобы на выходе был массив формы (3, 3, 15).

Комментарии:

1. Я думаю, что вы ищете: matrix1 vector.reshape(1,-1) @ matrix2 . Также, пожалуйста, опубликуйте образцы данных и ожидаемый результат.

2. Спасибо, но я получаю сообщение об ошибке «размер 3 отличается от 15». Я добавил пример и свой вывод!

Ответ №1:

 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) создаст массив (15,3,3). С numpy широковещательной передачей мы можем получить то же самое с:

 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 становится (15,1,1) и m's (1,3,3) для сопоставления, вместе образуя (15,3,3) .

Но если вы хотите, чтобы измерение (15,) vector было последним, нам нужно сделать:

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

Здесь трансляция равна (3,3,1) с (15,) => (3,3,15)

Мы могли бы также применить транспонирование к первому случаю, изменив форму (15,3,3) на (3,3,15):

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

Другой способ — объединить 15 массивов на новой последней оси.

 np.stack(answer, axis=2)
  

Ответ №2:

Вы можете просто вставить дополнительное измерение в матрицы, а NumPy broadcasting сделает все остальное:

 matrix1[..., None]   vector*matrix2[..., None]