web-dev-qa-db-ja.com

派手な行列ベクトルの乗算

サイズ(n x n)*(n x 1)の2つのテンキー配列を乗算すると、サイズ(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]
138
user3272574

最も簡単なソリューション

numpy.dotまたはa.dot(b)を使用します。ドキュメントを参照してください here

>>> 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のように動作しますが、2つの大きな例外があります。

    >>> np.matmul(a, b)
    array([16, 6, 8])
    
  • numpy.inner は、行列ベクトル乗算のnumpy.dotと同じように機能しますが、異なる動作をします行列行列とテンソル乗算(違いについてはWikipediaを参照してください- 内積と内積 一般的または numpyの実装に関してはこのSO answerを参照 .

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

EdgeケースのRarerオプション

  • テンソル(1以上の次元の配列)がある場合、オプション引数numpy.tensordotaxes=1 を使用できます。

    >>> np.tensordot(a, b, axes=1)
    array([16,  6,  8])
    
  • numpy.vdotを使用しないでください。マトリックスが1D配列に平坦化されるため、複素数のマトリックスがある場合は、検索しようとします。平坦化された行列とベクトルの間の複素共役ドット積(サイズの不一致n*m vs nにより失敗します)。

243
wflynny