このページではNumPyで行う基本的な線形代数計算としてノルム・正規化・正規直交化を学習します。
ノルムと正規化
ノルム
numpy.linalg.normを使用するとベクトルのノルムを求めることができます。ピタゴラス数の小さい2数を使用した2次元ベクトルのサンプルを見てみましょう。
import numpy as np x = np.array([3, 4]) np.linalg.norm(x) # 5.0 y = np.array([33, 56]) np.linalg.norm(y) # 65.0 #
斜辺の長さとなっていることが確認できます。3次元以上でも同様です。
import numpy as np x = np.array([2, 4, 4]) np.linalg.norm(x) # 6.0 #
正規化
numpy.linalg.normでノルムが求まりました。長さで割り算すると正規化することができます。先ほどのサンプルをさらに正規化してみましょう。
import numpy as np x = np.array([2, 4, 4]) norm = np.linalg.norm(x) # 6.0 # ノルムで除算し正規化する e = x / norm # array([ 0.33333333, 0.66666667, 0.66666667]) # 正規化を確認する np.linalg.norm(e) # 1.0 #
最終的にノルムが1の正規化されたベクトルを算出することができました。
正規直交化
次に2つの基底ベクトルが張るベクトル空間に対し、基底を正規直交化してみましょう。線形代数の授業などではグラムシュミットの正規直交化を利用したと思いますが、私も含め難儀された方が多いのではないでしょうか?np.linalg.qrを使用するとQR分解されたものが返されます。すなわち、任意の正則行列Aが直交行列Qと上三角行列Rの積に分解されて値が返されるわけです。
3次元ベクトル空間内に基底(1, 1, 0)、(0, -1, 0)が張る部分空間(つまり3次元空間中のXY平面)があったとします。この基底を正規直交化してみましょう。
import numpy as np # 基底(1, 1, 0)、(0, -1, 0) a = np.array([[1, 1], [1, -1], [0, 0]]) # array([[ 1, 1], # [ 1, -1], # [ 0, 0]]) q, r = np.linalg.qr(a) q # array([[-0.70710678, -0.70710678], # [-0.70710678, 0.70710678], # [-0. , -0. ]]) r # array([[ -1.41421356e+00, 3.33066907e-16], # [ 0.00000000e+00, -1.41421356e+00]])
QR分解された値が取得できました。せっかくなので、実際に正規直交なのかを内積とノルムを計算して確認してみましょう。
# 上サンプル続き # 内積を計算する ip = np.dot(q[0], q[1]) "%.10f" % ip # '-0.0000000000' # ノルムを確認する np.linalg.norm(q[0]) # 0.99999999999999978 np.linalg.norm(q[1]) # 1.0 #
誤差により厳密には0になりませんので、内積の方はフォーマットにより小数点表示で丸めて確認しています。