6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

NumPy における行列積(matmul)についての考察

Posted at

背景

線形代数においては,慣例的にベクトルを列ベクトル(column vector)で定義することが多い.

すなわち,$\boldsymbol{x} = \begin{bmatrix}a&b&c\end{bmatrix}$ ではなく,
$$
\boldsymbol{x} = \begin{bmatrix}a\\ b \\ c\end{bmatrix}
$$
と定義する.

行列の乗法では,例えば $A$ と $B$ の積 $AB$ を考える場合には,$A$ の列数と $B$ の行数を同じ数に揃えなくてはいけない.すなわち,$A$ が $n \times m$ の行列であれば $B$ は $m \times p$ のような形でなければ,積を定義できない.

列ベクトル $\boldsymbol{x}$ に 行列 $A$ を作用させる場合には,$A$ を左から掛けて $A\boldsymbol{x}$ とする.
一方で,行ベクトル $\boldsymbol{x}$ に 行列 $A$ を作用させる場合には,$A$ を右から掛けて $\boldsymbol{x}A$ としなくてはならない.このような表記は一般的ではない1

numpy.matmal での行ベクトルの扱い

Python/NumPy の多次元配列で行列とベクトルの積(numpy.matmal)を計算してみる.

>>> import numpy as np
>>> A = np.array([[1, 2], [3, 4]])
>>> x = np.array([[1], [2]])
>>> A @ x # 行列積(matmul)には @ を用いる
array([[5],
       [11]])

* (dot product) は対象とする行列(あるいはテンソル)の次元によって異なる挙動を示すため,推奨されない.スカラ倍する場合などは * で問題ない.

これは至って問題のない結果といえる.では次の計算はどうか.

>>> A = np.array([[1, 2], [3, 4]])
>>> x = np.array([1, 2])
>>> A @ b
array([5, 11])

これは数学的には矛盾のある結果といえる.背景部分で説明したとおり,$2 \times 2$ の行列と $1 \times 2$ のベクトルはこの順序で積を取ることができない.しかしながら,
上記プログラムはこれを実行して結果を返している.

一つ前の例からも明らかであるが, ここでは(数式的には)以下の処理が行われている.

$$
\left(A\boldsymbol{x}^\top\right)^\top
$$

すなわち,**「指定されたベクトルが行ベクトルだったので,列ベクトルになおして積を取り,結果として得られる列ベクトルを再び行ベクトルに戻して返す」**という処理を行っているのである.便利といえば便利だが,線形代数に詳しい人は少し困惑するのではなかろうか.

もちろん,$\boldsymbol{x}$ が列ベクトルであるので,以下の計算については矛盾がない.

>>> b @ A
array([7, 10])

それでは,再び $\boldsymbol{x}$ を行ベクトルに戻して $\boldsymbol{x} A$ の計算結果がどのようになるか見てみよう.これまでの実験の結果から,「列ベクトルも行ベクトルになおして積をとってくれるのでは」との推察が自然に導かれる.

>>> A = np.array([[1, 2], [3, 4]])
>>> x = np.array([[1], [2]])
>>> x @ A
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 2 is different from 1)

ところが,列ベクトルは行ベクトルへ変換されず,エラーとなってしまう.
これはもちろん数学的には期待通りのエラーであるが,上記の推察からは外れてしまっている.

結論

numpy.matmul における行ベクトルは,そのコンテキストに応じて内部で列ベクトルに変換され,出力時には再度,行ベクトルへと戻される.ただし,列ベクトルについてはかような解釈は実装されていない.

  1. 2020/08/07 現在

6
6
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?