1. ホーム
  2. パイソン

[解決済み】numpyの行列のベクトル乗算【重複あり

2022-04-04 05:34:09

質問

を掛け合わせると numpy の配列は、サイズ (n x n)*(n x 1)の行列を生成します。通常の行列の乗算ルールに従って、(n×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]

解決方法は?

最もシンプルな方法

使用方法 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 (2021年初頭現在)ここで * は、標準的な行列の乗算と同様に扱われます。 numpy.matrix は非推奨で、将来のリリースで削除される可能性があります。 . 参照 ドキュメントにある注意書き (を利用することができます(以下、再掲)。

<ブロッククオート

このクラスを使うことは、たとえ線形代数であっても、もはや推奨されません。代わりに通常の配列を使用してください。このクラスは将来的に削除される可能性があります。

ありがとう@HopeKing。


その他のソリューション

また、他のオプションがあることも知っておいてください。

  • 後述するように、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 を参照してください)。 内積と内点積 一般的に、または 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]])
    
    

エッジケースに対応した希少なオプション

  • テンソル(1以上の次元の配列)がある場合は numpy.tensordot というオプションの引数で axes=1 :

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