Умножение матрицы на вектор

Когда я умножаю два числовых массива (n x n)*(n x 1), я получаю матрицу размера (n x n). Следуя нормальным правилам умножения матриц, ожидается вектор (nx 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])
    
  • Если вы хотите излишнего, вы можете использовать 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.inner функционирует так же, как numpy.dot для умножения матрицы на вектор, но ведет себя по-разному для умножения матрицы на матрицу и тензора (см. Википедию относительно различий между внутренним произведением и точечным произведением в целом или посмотрите этот SO-ответ относительно реализаций numpy).

    >>> np.inner(a, b)
    array([16, 6, 8])
    
    # Beware using for matrix-matrix multiplication though!
    >>> b = a.T
    >>> np.dot(a, b)
    array([[35,  9, 10],
           [ 9,  3,  4],
           [10,  4,  6]])
    >>> np.inner(a, b) 
    array([[29, 12, 19],
           [ 7,  4,  5],
           [ 8,  5,  6]])
    

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

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

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

Другие вопросы по тегам