このページでは、NumPy を用いて線形代数 (Linear Algebra) の計算を解く方法について解説します。
ベクトルのドット積 (点乗積)
ドット積 (a・b) は、np.dot(a, b)
で計算できます。
ドット積は、1 次元配列ではベクトルの内積、2 次元配列では行列の積と同じ結果になります。
サンプルコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import numpy as np # 整数同士のドット積(通常の掛け算と同じになります) # 3・4 np.dot(3, 4) # 行列同士のドット積 # (2, 3)・(2, 3) np.dot([2, 3], [2, 3]) # 複素数を扱うこともできます # (2j, 3j)・(2j, 3j) np.dot([2j, 3j], [2j, 3j]) # 2 次元行列同士のドット積を計算できます。 a = [[1, 0], [0, 1]] b = [[4, 1], [2, 2]] np.dot(a, b) |
実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
>>> np.dot(3, 4) 12 >>> np.dot([2, 3], [2, 3]) 13 >>> np.dot([2j, 3j], [2j, 3j]) (-13+0j) >>> a = [[1, 0], [0, 1]] >>> b = [[4, 1], [2, 2]] >>> np.dot(a, b) array([[4, 1], [2, 2]]) |
ベクトルの内積
ベクトルの内積 (a・b) は np.inner(a, b)
のようにして計算できます。
サンプルコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# 通常のベクトル同士の内積 # (1, 2, 3)・(0, 1, 0) a = np.array([1, 2, 3]) b = np.array([0, 1, 0]) np.inner(a, b) # 多次元ベクトルの内積を計算 a = np.arange(24).reshape((2,3,4)) a b = np.arange(4) b np.inner(a, b) # b がスカラーの場合は以下のように指定します a = np.eye(2) a np.inner(np.eye(2), 7) |
実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
>>> a = np.array([1, 2, 3]) >>> b = np.array([0, 1, 0]) >>> np.inner(a, b) 2 >>> a = np.arange(24).reshape((2,3,4)) >>> a array([[[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]], [[12, 13, 14, 15], [16, 17, 18, 19], [20, 21, 22, 23]]]) >>> b = np.arange(4) >>> b array([0, 1, 2, 3]) >>> np.inner(a, b) array([[ 14, 38, 62], [ 86, 110, 134]]) >>> a = np.eye(2) >>> a array([[ 1., 0.], [ 0., 1.]]) >>> np.inner(np.eye(2), 7) array([[ 7., 0.], [ 0., 7.]]) |
ベクトルの外積
ベクトルの外積 (a×b) は、np.outer(a, b)
のようにして計算できます。
サンプルコード
1 2 3 4 5 6 7 8 9 10 11 12 13 |
##マンデルブロット (Mandelbrot) rl = np.outer(np.ones((5,)), np.linspace(-2, 2, 5)) rl im = np.outer(1j*np.linspace(2, -2, 5), np.ones((5,))) im grid = rl + im grid # 文字列をベクトルとして計算することもできます x = np.array(['a', 'b', 'c'], dtype=object) np.outer(x, [1, 2, 3]) |
実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
>>> rl = np.outer(np.ones((5,)), np.linspace(-2, 2, 5)) >>> rl array([[-2., -1., 0., 1., 2.], [-2., -1., 0., 1., 2.], [-2., -1., 0., 1., 2.], [-2., -1., 0., 1., 2.], [-2., -1., 0., 1., 2.]]) >>> im = np.outer(1j*np.linspace(2, -2, 5), np.ones((5,))) >>> im array([[ 0.+2.j, 0.+2.j, 0.+2.j, 0.+2.j, 0.+2.j], [ 0.+1.j, 0.+1.j, 0.+1.j, 0.+1.j, 0.+1.j], [ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j], [ 0.-1.j, 0.-1.j, 0.-1.j, 0.-1.j, 0.-1.j], [ 0.-2.j, 0.-2.j, 0.-2.j, 0.-2.j, 0.-2.j]]) >>> grid = rl + im >>> grid array([[-2.+2.j, -1.+2.j, 0.+2.j, 1.+2.j, 2.+2.j], [-2.+1.j, -1.+1.j, 0.+1.j, 1.+1.j, 2.+1.j], [-2.+0.j, -1.+0.j, 0.+0.j, 1.+0.j, 2.+0.j], [-2.-1.j, -1.-1.j, 0.-1.j, 1.-1.j, 2.-1.j], [-2.-2.j, -1.-2.j, 0.-2.j, 1.-2.j, 2.-2.j]]) >>> x = np.array(['a', 'b', 'c'], dtype=object) >>> np.outer(x, [1, 2, 3]) array([['a', 'aa', 'aaa'], ['b', 'bb', 'bbb'], ['c', 'cc', 'ccc']], dtype=object) |
単位行列 (identity array)
対角成分が1でそれ以外が全て0の行列 (単位行列) は、 例えば、N次の単位行列の場合、np.identity(N)
で作成できます。
サンプルコード
1 2 3 4 5 |
# 3 次の単位行列 np.identity(3) # 4 次の単位行列 np.identity(4) |
実行結果
1 2 3 4 5 6 7 8 9 10 |
>>> np.identity(3) array([[ 1., 0., 0.], [ 0., 1., 0.], [ 0., 0., 1.]]) >>> np.identity(4) array([[ 1., 0., 0., 0.], [ 0., 1., 0., 0.], [ 0., 0., 1., 0.], [ 0., 0., 0., 1.]]) |
固有値、固有ベクトル
固有値と固有ベクトルの計算は、numpy.linalg パッケージ (本例では、LAとして読み込み) に含まれる、LA.eig()
を用いて計算できます。
なお、固有ベクトルは正規化 (大きさ= 1) された状態で、出力されます。
サンプルコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# numpy.linalg パッケージを読み込み from numpy import linalg as LA # 2 次行列 [[3, 1], [2, 4]] の固有値、固有ベクトル matrix1 = np.array([[3, 1], [2, 4]]) w, v = LA.eig(matrix1) w # 固有値 v # 固有ベクトル(正規化済) # 3 次行列 [[1, -1, 2], [0, 2, -1], [0, 0, 3]] の固有値、固有ベクトル matrix2 = np.array([[1, -1, 2], [0, 2, -1], [0, 0, 3]]) LA.eig(matrix2) w # 固有値 v # 固有ベクトル(正規化済) |
実行結果
1 2 3 4 5 6 7 8 9 10 11 12 |
>>> matrix1 = np.array([[3, 1], [2, 4]]) >>> matrix1 array([[3, 1], [2, 4]]) >>> w, v = LA.eig(matrix1) >>> w # 固有値 array([ 2., 5.]) >>> v # 固有ベクトル(正規化済) array([[-0.70710678, -0.4472136 ], [ 0.70710678, -0.89442719]]) |
固有値のみを求める場合は、LA.eigvals()
を用いて計算できます。
サンプルコード
1 2 3 4 5 |
# 2 次行列 [[3, 1], [2, 4]] の固有値 LA.eigvals(matrix1) # 3 次行列 [[1, -1, 2], [0, 2, -1], [0, 0, 3]] の固有値 LA.eigvals(matrix2) |
実行結果
1 2 3 4 5 |
>>> LA.eigvals(matrix1) array([ 2., 5.]) >>> LA.eigvals(matrix2) array([ 1., 2., 3.]) |
行列式の値 (determinant)
行列式の値は、np.linalg.det
を用いて計算できます。内部的には、LU 分解で計算しているようです。
サンプルコード
1 2 3 |
# 2次の正方行列 [[1, 2], [3, 4]] の行列式の値 a = np.array([[1, 2], [3, 4]]) np.linalg.det(a) |
実行結果
1 2 3 |
>>> a = np.array([[1, 2], [3, 4]]) >>> np.linalg.det(a) -2.0000000000000004 |
逆行列 (Inverse Matrix)
逆行列は、np.linalg.inv()
で求めることができます。
サンプルコード
1 2 3 4 5 6 7 8 9 |
# 2 次の行列 A = [[1, 2], [3, 4]] の逆行列 A^-1 from numpy.linalg import inv a = np.array([[1, 2], [3, 4]]) inv(a) # 確認 (A・A^-1 = 単位行列 になることを確認) ainv = inv(a) np.dot(a, ainv) |
実行結果
1 2 3 4 5 6 7 8 9 |
>>> a = np.array([[1, 2], [3, 4]]) >>> inv(a) array([[-2. , 1. ], [ 1.5, -0.5]]) >>> ainv = inv(a) >>> np.round(np.dot(a, ainv)) array([[ 1., 0.], [ 0., 1.]]) |
行列式のランク (階数)
Rank (行列の階数) は、np.linalg.matrix_rank
関数にて算出できます。
サンプルコード
1 2 3 4 5 6 7 8 9 10 11 12 |
# numpy.linalg から matrix_rank 関数をロード from numpy.linalg import matrix_rank # 行列 [[1, 2, 3],[3, 2, 1],[2, 4, 6]] のランクを求めます。 matrix1 = np.array([[1, 2, 3], [3, 2, 1], [2, 4, 6]]) matrix1 matrix_rank(matrix1) # 対角行列の場合は常に次数と同じになります matrix2 = np.eye(4) matrix2 matrix_rank(matrix2) |
実行結果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
>>> matrix1 = np.array([[1, 2, 3], [3, 2, 1], [2, 4, 6]]) >>> matrix1 array([[1, 2, 3], [3, 2, 1], [2, 4, 6]]) >>> matrix_rank(matrix1) 2 >>> matrix2 = np.eye(4) >>> matrix2 array([[ 1., 0., 0., 0.], [ 0., 1., 0., 0.], [ 0., 0., 1., 0.], [ 0., 0., 0., 1.]]) >>> matrix_rank(matrix2) 4 |
零行列
零行列 (全ての成分が 0) の行列は np.zeros()
にて作成できます。
サンプルコード
1 2 3 4 5 |
# 長さが 3 の零行列 np.zeros(3) # 長さが 4 x 4 の零行列 np.zeros([4, 4]) |
実行結果
1 2 3 4 5 6 7 8 |
>>> np.zeros(3) array([ 0., 0., 0.]) >>> np.zeros([4, 4]) array([[ 0., 0., 0., 0.], [ 0., 0., 0., 0.], [ 0., 0., 0., 0.], [ 0., 0., 0., 0.]]) |
ノルム
ベクトル a = [1,2,3,4] のノルム ||a||は、LA.norm()
を利用して計算できます。
サンプルコード
1 2 3 4 5 6 7 8 |
from numpy import linalg as LA a = np.array([1, 2, 3, 4]) LA.norm(a) # 2 次の行列 b = [[1, 2], [3, 4]] のノルム ||b|| は以下のように計算できます。 b = np.array([[1, 2], [3, 4]]) LA.norm(b) |
実行結果
1 2 3 4 5 6 7 |
>>> a = np.array([1, 2, 3, 4]) >>> LA.norm(a) 5.4772255750516612 >>> b = np.array([[1, 2], [3, 4]]) >>> LA.norm(b) 5.4772255750516612 |
参考・出典:Linear algebra (numpy.linalg) — NumPy v1.10 Manual