matmul関数【numpy】
配列で与えられた行列同士の積を求めるにはmatmul関数【NumPy】が提供されている。このはたらきは@演算子と同じものである。まず、
A : 2D array
x : 1D array
b : 0D array
とする。
code:p01.py
import numpy as np
A = np.array(1, 2, 3], 4, 5, 6, [7, 8, 9)
x = np.array(1, 2 , 3)
b = np.array(2)
print(A.ndim, A.shape)
print(x.ndim, x.shape)
print(b.ndim, b.shape)
# 2 (3, 3)
# 1 (3,)
# 0 ()
2D同士
結果は2D、通常の行列積が計算される。@演算子、 dot関数【numpy】と同じ。
code:(続き)p01.py
y = np.matmul(A, A)
print(y.ndim, y.shape)
print(y)
# 2 (3, 3)
# [ 30 36 42
# 66 81 96
# 102 126 150]
2Dと1D
結果は1Dとなる。@演算子、 dot関数【numpy】と同じ。
code:(続き)p1.py
y1 = np.matmul(A, x)
print(y1.ndim, y1.shape)
print(y1)
y2 = np.matmul(x, A)
print(y2.ndim, y2.shape)
print(y2)
# 1 (3,)
# 14 32 50
# 1 (3,)
# 30 36 42
行列$ Aとベクトル$ xの積について
ベクトル$ xを適当な長さの縦ベクトルとすると、計算可能なのは$ Ax, x^\top Aの場合である。
しかしながら、1D配列は軸を1本しか持たないので縦横の区別は無く、転置といった操作を行うことはできない。
そのため、ここでの処理は前後どちらからベクトルを掛けた場合でも、計算可能な形状に解釈され、行列積が計算されている。
ただし、結果の次元は1Dであることに注意。
× 2Dと0D
計算できない。dot関数【numpy】とは異なる動作である。
code:(続き)p01.py
y = np.matmul(A, b)
print(y.ndim, y.shape)
print(y)
# ValueError: matmul: Input operand 1 does not have enough dimensions (has 0, gufunc core with signature (n?,k),(k,m?)->(n?,m?) requires 1)
1D同士
結果は0D、内積が求まっている。@演算子、dot関数【numpy】と同じ。
code:(続き)p01.py
y = np.matmul(x, x)
print(y.ndim, y.shape)
print(y)
# 0 ()
# 14
× 1Dと0D
計算できない。dot関数【numpy】とは異なる動作である。
code:(続き)p01.py
y = np.matmul(x, b)
# ValueError: matmul: Input operand 1 does not have enough dimensions (has 0, gufunc core with signature (n?,k),(k,m?)->(n?,m?) requires 1)
× 0D同士
計算できない。dot関数【numpy】とは異なる動作である。
code:(続き)p01.py
y = np.matmul(b, b)
# ValueError: matmul: Input operand 0 does not have enough dimensions (has 0, gufunc core with signature (n?,k),(k,m?)->(n?,m?) requires 1)
まとめると、matmul関数【numpy】で計算を行うには、2つのオペランドのうち少なくともどちらかが、いずれかの軸方向に1以上の長さをもつ必要があるようだ。(@演算子と同じ)
3次元以上の配列は未確認。
まとめ
np.matmul(2D, 2D) → 2D
np.matmul(2D, 1D) → 1D
0D → 計算できない