Умножение матричного вектора

Когда я умножаю два массива numpy размеров (n x n) * (n x 1), я получаю матрицу размера (n x n). Следуя правилам нормального матричного умножения, ожидается вектор (n x 1), но я просто не могу найти никакой информации о том, как это делается в модуле Python Numpy.

Дело в том, что я не хочу реализовывать его вручную, чтобы сохранить скорость программы.

Пример кода показан ниже:

a = np.array([[ 5, 1 ,3], [ 1, 1 ,1], [ 1, 2 ,1]])
b = np.array([1, 2, 3])

print a*b
   >>
   [[5 2 9]
   [1 2 3]
   [1 4 3]]

Я хочу:

print a*b
   >>
   [16 6 8]

Ответ 1

Простейшее решение

Используйте numpy.dot или a.dot(b). См. Документацию здесь.

>>> a = np.array([[ 5, 1 ,3], 
                  [ 1, 1 ,1], 
                  [ 1, 2 ,1]])
>>> b = np.array([1, 2, 3])
>>> print a.dot(b)
array([16, 6, 8])

Это происходит потому, что массивы numpy не являются матрицами, а стандартные операции *, +, -, / работают по массиву на массивах. Вместо этого вы можете попробовать использовать numpy.matrix, а * будет рассматриваться как матричное умножение.


Другие решения

Также известно, что есть другие варианты:

  • Как указано ниже, при использовании python3.5 + оператор @ работает так, как вы ожидали:

    >>> print(a @ b)
    array([16, 6, 8])
    
  • Если вы хотите overkill, вы можете использовать numpy.einsum. Документация предоставит вам вкус для того, как это работает, но, честно говоря, я не совсем понял, как использовать его, пока не прочитаю этот ответ и просто играю с ним на мой собственный.

    >>> np.einsum('ji,i->j', a, b)
    array([16, 6, 8])
    
  • По состоянию на середину 2016 года (numpy 1.10.1) вы можете попробовать экспериментальный numpy.matmul, который работает как numpy.dot с двумя основными исключениями: нет скалярного умножения, но он работает со стеками матриц.

    >>> np.matmul(a, b)
    array([16, 6, 8])
    

Более редкие варианты для краевых случаев

  • Если у вас есть тензоры (массивы размерности больше или равны единице), вы можете использовать numpy.tensordot с дополнительным Аргумент axes=1:

    >>> np.tensordot(a, b, axes=1)
    array([16,  6,  8])
    
  • Не используйте numpy.vdot, если у вас есть матрица комплексных чисел, так как матрица будет сплющена к 1D-массиву, тогда она попытается найти комплексное сопряженное точечное произведение между вашей сплющенной матрицей и вектором (что не будет выполнено из-за несоответствия размера n*m vs n).