LoginSignup
1
2

More than 1 year has passed since last update.

【Python演算処理】行列演算の基本①基本的四則演算と積(Product)

Last updated at Posted at 2021-05-27

本当に基礎からの再出発です。Sympyの威力を改めて実感…Tex構文も吐いてくれるしもうR時代に愛用していたYacsには戻れない?
Linux で科学しよう! - Yacas - メディアラボ

#基本的四則演算
とりあえず一般的加減乗除算の概念がどれだけ通用するか見ていく事にします。

複素数の実行列表現

まず2×2の正方行列(square matrix=行要素の数と列要素の数が一致する行列)を以下の様に規定します。

正方行列 - Wikipedia

A=\begin{bmatrix}A_{11}&A_{12}\\A_{21}&A_{22}\end{bmatrix}

pythonによる実装

import sympy as sp
a11, a12,a21,a22 = sp.symbols('a11, a12,a21,a22')
a=sp.Matrix([[a11,a12],[a21,a22]])
sp.init_printing()
display(a) 
print(sp.latex(a))

出力結果(a)

\left[\begin{matrix}a_{11} & a_{12}\\a_{21} & a_{22}\end{matrix}\right]

ここで驚いたのが以下の考え方との邂逅
ディープラーニングのための線形代数入門:一般的演算の初学者向けガイド

スカラーとの加減算は以下となります。

A±C=\begin{bmatrix}A_{11}±C&A_{12}±C\\A_{21}±C&A_{22}±C\end{bmatrix}

pythonによる実装(numpyとsympyで振る舞いが異なる)

numpyの場合

import numpy as np
an = np.array(
[[1,2], 
 [3,4]])
print(an)
print(an + 1)

an=
[[1 2]
[3 4]]
an+1=
[[2 3]
[4 5]]

sympyの場合こうしないと通らない。

import sympy as sp
a11, a12,a21,a22 = sp.symbols('a11, a12,a21,a22')
C= sp.symbols('C')
a=sp.Matrix([[a11,a12],[a21,a22]])
c=sp.Matrix([[C,C],[C,C]])
sp.init_printing()
display(a) 
print(sp.latex(a))
display(c) 
print(sp.latex(c))
display(a+c) 
print(sp.latex(a+c))
display(a-c) 
print(sp.latex(a-c))

出力結果(a)

\left[\begin{matrix}a_{11} & a_{12}\\a_{21} & a_{22}\end{matrix}\right]

出力結果(C)

\left[\begin{matrix}C & C\\C & C\end{matrix}\right]

出力結果(a+C)

\left[\begin{matrix}C + a_{11} & C + a_{12}\\C + a_{21} & C + a_{22}\end{matrix}\right]

出力結果(a-C)

\left[\begin{matrix}- C + a_{11} & - C + a_{12}\\- C + a_{21} & - C + a_{22}\end{matrix}\right]

こっちが行列の振る舞いとしては普通の筈だ?
行列の演算

対応する成分同士を計算するので、行列の縦横の数が合っていないもの同士は加算・減算できません。なんでも足し引きできた今までの数(スカラー)とは大きく異なる特徴です。

気を取り直して元の引用に復帰。
複素数の実行列表現

行列同士の加減算は以下となります。

A±B=\begin{bmatrix}A_{11}±Β_{11}&A_{12}±B_{12}\\A_{21}±B_{21}&A_{22}±B_{22}\end{bmatrix}

pythonによる実装

import sympy as sp
a11, a12,a21,a22 = sp.symbols('a11, a12,a21,a22')
b11, b12,b21,b22 = sp.symbols('b11, b12,b21,b22')
a=sp.Matrix([[a11,a12],[a21,a22]])
b=sp.Matrix([[b11,b12],[b21,b22]])
sp.init_printing()
display(a+b) 
print(sp.latex(a+b))
display(a-b) 
print(sp.latex(a-b))

出力結果(a+b)

\left[\begin{matrix}a_{11} + b_{11} & a_{12} + b_{12}\\a_{21} + b_{21} & a_{22} + b_{22}\end{matrix}\right]

出力結果(a-b)

\left[\begin{matrix}a_{11} - b_{11} & a_{12} - b_{12}\\a_{21} - b_{21} & a_{22} - b_{22}\end{matrix}\right]

そのスカラー倍は以下となります。

A×C=\begin{bmatrix}A_{11}×C&A_{12}×C\\A_{21}×C&A_{22}×C\end{bmatrix}

pythonによる実装

import sympy as sp
a11, a12,a21,a22 = sp.symbols('a11, a12,a21,a22')
C = sp.symbols('C')
a=sp.Matrix([[a11,a12],[a21,a22]])
sp.init_printing()
display(a*C) 
print(sp.latex(a*C))
display(a/C) 
print(sp.latex(a/C))

出力結果(a*C)

\left[\begin{matrix}C a_{11} & C a_{12}\\C a_{21} & C a_{22}\end{matrix}\right]

出力結果(a/C)

\left[\begin{matrix}\frac{a_{11}}{C} & \frac{a_{12}}{C}\\\frac{a_{21}}{C} & \frac{a_{22}}{C}\end{matrix}\right]

またアダマール積(Hadamard Product=同じサイズの行列A,Bに対し成分ごとの積をとる演算。シューア積(Schur Product)とも)A○Bの求め方は以下となります。

アダマール積

アダマール積は交換則と分配則を満たす。
A∘B=B∘A
A∘(B∘C)=(A∘B)∘C
A∘(B+C)=A∘B+A∘C
例えば機械学習では行列$a^{ij}$と$b^{ij}$それぞれのアダマール積をとって全ての成分の和をとる演算が実践的技法として使われる。

numpyと、アダマール積
ディープラーニングのための線形代数入門:一般的演算の初学者向けガイド

pythonによる実装

import sympy as sp
a11,a12,a13,a21,a22,a23,a31,a32,a33= sp.symbols('a11,a12,a13,a21,a22,a23,a31,a32,a33')
b11,b12,b13,b21,b22,b23,b31,b32,b33= sp.symbols('b11,b12,b13,b21,b22,b23,b31,b32,b33')
a=sp.Matrix([[a11,a12,a13],[a21,a22,a23],[a31,a32,a33]])
b=sp.Matrix([[b11,b12,b13],[b21,b22,b23],[b31,b32,b33]])
sp.init_printing()
display(a) 
print(sp.latex(a))
display(b) 
print(sp.latex(b))
display(sp.matrix_multiply_elementwise(a,b)) 
print(sp.latex(sp.matrix_multiply_elementwise(a,b)))

出力結果(a)

\left[\begin{matrix}a_{11} & a_{12} & a_{13}\\a_{21} & a_{22} & a_{23}\\a_{31} & a_{32} & a_{33}\end{matrix}\right]

出力結果(b)

\left[\begin{matrix}b_{11} & b_{12} & b_{13}\\b_{21} & b_{22} & b_{23}\\b_{31} & b_{32} & b_{33}\end{matrix}\right]

出力結果(aとbのアダマール積)

\left[\begin{matrix}a_{11} b_{11} & a_{12} b_{12} & a_{13} b_{13}\\a_{21} b_{21} & a_{22} b_{22} & a_{23} b_{23}\\a_{31} b_{31} & a_{32} b_{32} & a_{33} b_{33}\end{matrix}\right]

つまり、片方の行列の逆数を求めると除算も実現可能?

pythonによる実装

import sympy as sp
a11,a12,a13,a21,a22,a23,a31,a32,a33= sp.symbols('a11,a12,a13,a21,a22,a23,a31,a32,a33')
b11,b12,b13,b21,b22,b23,b31,b32,b33= sp.symbols('b11,b12,b13,b21,b22,b23,b31,b32,b33')
a=sp.Matrix([[a11,a12,a13],[a21,a22,a23],[a31,a32,a33]])
b=sp.Matrix([[1/b11,1/b12,1/b13],[1/b21,1/b22,1/b23],[1/b31,1/b32,1/b33]])
sp.init_printing()
display(a) 
print(sp.latex(a))
display(b) 
print(sp.latex(b))
display(sp.matrix_multiply_elementwise(a,b)) 
print(sp.latex(sp.matrix_multiply_elementwise(a,b)))

出力結果(a)

\left[\begin{matrix}a_{11} & a_{12} & a_{13}\\a_{21} & a_{22} & a_{23}\\a_{31} & a_{32} & a_{33}\end{matrix}\right]

出力結果(b)

\left[\begin{matrix}\frac{1}{b_{11}} & \frac{1}{b_{12}} & \frac{1}{b_{13}}\\\frac{1}{b_{21}} & \frac{1}{b_{22}} & \frac{1}{b_{23}}\\\frac{1}{b_{31}} & \frac{1}{b_{32}} & \frac{1}{b_{33}}\end{matrix}\right]

出力結果(aとbのアダマール積)

\left[\begin{matrix}\frac{a_{11}}{b_{11}} & \frac{a_{12}}{b_{12}} & \frac{a_{13}}{b_{13}}\\\frac{a_{21}}{b_{21}} & \frac{a_{22}}{b_{22}} & \frac{a_{23}}{b_{23}}\\\frac{a_{31}}{b_{31}} & \frac{a_{32}}{b_{32}} & \frac{a_{33}}{b_{33}}\end{matrix}\right]

数理処理上何か意味があるかまでは不明…

#行列の積(Product)
ここから先は行列演算独特の世界観に踏み込んで既存の四則演算概念の延長線上では捉えられなくなってきます。

ベクトルと行列の積の基本的な5つの式

行ベクトル(横ベクトル)と行列の積は行ベクトル(横ベクトル)となります。

\begin{bmatrix}a_1&a_2\end{bmatrix}\begin{bmatrix}b_{11}&b_{12}\\b_{21}&b_{22}\end{bmatrix}\\ 
=\begin{bmatrix}a_1b_{11}+a_2b_{21}&a_1b_{12}+a_2b_{22}\end{bmatrix}\\
\left[\begin{matrix}a_{1} & a_{2} & a_{3}\end{matrix}\right]\left[\begin{matrix}b_{11} & b_{12} & b_{13}\\b_{21} & b_{22} & b_{23}\\b_{31} & b_{32} & b_{33}\end{matrix}\right]=\left[\begin{matrix}a_{1} b_{11} + a_{2} b_{21} + a_{3} b_{31} & a_{1} b_{12} + a_{2} b_{22} + a_{3} b_{32} & a_{1} b_{13} + a_{2} b_{23} + a_{3} b_{33}\end{matrix}\right]

pythonによる実装

import sympy as sp
a1, a2 = sp.symbols('a1, a2')
b11,b12,b21,b22 = sp.symbols('b11,b12,b21,b22')
a=sp.Matrix([[a1,a2]])
b=sp.Matrix([[b11,b12],[b21,b22]])
sp.init_printing()
display(a) 
print(sp.latex(a))
display(b) 
print(sp.latex(b))
display(a*b) 
print(sp.latex(a*b))

出力結果(a)

\left[\begin{matrix}a_{1} & a_{2}\end{matrix}\right]

出力結果(b)

\left[\begin{matrix}b_{11} & b_{12}\\b_{21} & b_{22}\end{matrix}\right]

出力結果(a*b)

\left[\begin{matrix}a_{1} b_{11} + a_{2} b_{21} & a_{1} b_{12} + a_{2} b_{22}\end{matrix}\right]
import sympy as sp
a1, a2,a3 = sp.symbols('a1, a2,a3')
b11,b12,b13,b21,b22,b23,b31,b32,b33 = sp.symbols('b11,b12,b13,b21,b22,b23,b31,b32,b33')
a=sp.Matrix([[a1,a2,a3]])
b=sp.Matrix([[b11,b12,b13],[b21,b22,b23],[b31,b32,b33]])
sp.init_printing()
display(a) 
print(sp.latex(a))
display(b) 
print(sp.latex(b))
display(a*b) 
print(sp.latex(a*b))

出力結果(a)

\left[\begin{matrix}a_{1} & a_{2} & a_{3}\end{matrix}\right]

出力結果(b)

\left[\begin{matrix}b_{11} & b_{12} & b_{13}\\b_{21} & b_{22} & b_{23}\\b_{31} & b_{32} & b_{33}\end{matrix}\right]

出力結果(a*b)

\left[\begin{matrix}a_{1} b_{11} + a_{2} b_{21} + a_{3} b_{31} & a_{1} b_{12} + a_{2} b_{22} + a_{3} b_{32} & a_{1} b_{13} + a_{2} b_{23} + a_{3} b_{33}\end{matrix}\right]

行列列ベクトル(縦ベクトル)の積は列ベクトル(縦ベクトル)となります。

\begin{bmatrix}a_{11}&a_{12}\\a_{21}&a_{22}\end{bmatrix}\begin{bmatrix}b_1\\b_2\end{bmatrix}=\begin{bmatrix}a_{11}b_1+a_{12}b_2\\a_{21}b_1+a_{22}b_2\end{bmatrix}\\
\left[\begin{matrix}a_{11} & a_{12} & a_{13}\\a_{21} & a_{22} & a_{23}\\a_{31} & a_{32} & a_{33}\end{matrix}\right]\left[\begin{matrix}b_{1}\\b_{2}\\b_{3}\end{matrix}\right]=\left[\begin{matrix}a_{11} b_{1} + a_{12} b_{2} + a_{13} b_{3}\\a_{21} b_{1} + a_{22} b_{2} + a_{23} b_{3}\\a_{31} b_{1} + a_{32} b_{2} + a_{33} b_{3}\end{matrix}\right]

pythonによる実装

import sympy as sp
a11, a12,a21,a22 = sp.symbols('a11, a12,a21,a22')
b1,b2 = sp.symbols('b1,b2')
a=sp.Matrix([[a11,a12],[a21,a22]])
b=sp.Matrix([[b1],[b2]])
sp.init_printing()
display(a) 
print(sp.latex(a))
display(b) 
print(sp.latex(b))
display(a*b) 
print(sp.latex(a*b))

出力結果(a)

\left[\begin{matrix}a_{11} & a_{12}\\a_{21} & a_{22}\end{matrix}\right]

出力結果(b)

\left[\begin{matrix}b_{1}\\b_{2}\end{matrix}\right]

出力結果(a*b)

\left[\begin{matrix}a_{11} b_{1} + a_{12} b_{2}\\a_{21} b_{1} + a_{22} b_{2}\end{matrix}\right]
import sympy as sp
a11, a12,a13,a21,a22,a23,a31,a32,a33 = sp.symbols('a11, a12,a13,a21,a22,a23,a31,a32,a33')
b1,b2,b3 = sp.symbols('b1,b2,b3')
a=sp.Matrix([[a11,a12,a13],[a21,a22,a23],[a31,a32,a33]])
b=sp.Matrix([[b1],[b2],[b3]])
sp.init_printing()
display(a) 
print(sp.latex(a))
display(b) 
print(sp.latex(b))
display(a*b) 
print(sp.latex(a*b))

出力結果(a)

\left[\begin{matrix}a_{11} & a_{12} & a_{13}\\a_{21} & a_{22} & a_{23}\\a_{31} & a_{32} & a_{33}\end{matrix}\right]

出力結果(b)

\left[\begin{matrix}b_{1}\\b_{2}\\b_{3}\end{matrix}\right]

出力結果(a*b)

\left[\begin{matrix}a_{11} b_{1} + a_{12} b_{2} + a_{13} b_{3}\\a_{21} b_{1} + a_{22} b_{2} + a_{23} b_{3}\\a_{31} b_{1} + a_{32} b_{2} + a_{33} b_{3}\end{matrix}\right]

合成すると以下の形となりますね。

\left[\begin{matrix}a_{11} & a_{12}\\a_{21} & a_{22}\end{matrix}\right]\left[\begin{matrix}b_{11} & b_{12}\\b_{21} & b_{22}\end{matrix}\right]=\left[\begin{matrix}a_{11} b_{11} + a_{12} b_{21} & a_{11} b_{12} + a_{12} b_{22}\\a_{21} b_{11} + a_{22} b_{21} & a_{21} b_{12} + a_{22} b_{22}\end{matrix}\right]\\
\left[\begin{matrix}a_{11} & a_{12} & a_{13}\\a_{21} & a_{22} & a_{23}\\a_{31} & a_{32} & a_{33}\end{matrix}\right]\left[\begin{matrix}b_{11} & b_{12} & b_{13}\\b_{21} & b_{22} & b_{23}\\b_{31} & b_{32} & b_{33}\end{matrix}\right]=\left[\begin{matrix}a_{11} b_{11} + a_{12} b_{21} + a_{13} b_{31} & a_{11} b_{12} + a_{12} b_{22} + a_{13} b_{32} & a_{11} b_{13} + a_{12} b_{23} + a_{13} b_{33}\\a_{21} b_{11} + a_{22} b_{21} + a_{23} b_{31} & a_{21} b_{12} + a_{22} b_{22} + a_{23} b_{32} & a_{21} b_{13} + a_{22} b_{23} + a_{23} b_{33}\\a_{31} b_{11} + a_{32} b_{21} + a_{33} b_{31} & a_{31} b_{12} + a_{32} b_{22} + a_{33} b_{32} & a_{31} b_{13} + a_{32} b_{23} + a_{33} b_{33}\end{matrix}\right]

pythonによる実装

import sympy as sp
a11,a12,a21,a22= sp.symbols('a11,a12,a21,a22')
b11,b12,b21,b22= sp.symbols('b11,b12,b21,b22')
a=sp.Matrix([[a11,a12],[a21,a22]])
b=sp.Matrix([[b11,b12],[b21,b22]])
sp.init_printing()
display(a) 
print(sp.latex(a))
display(b) 
print(sp.latex(b))
display(a*b) 
print(sp.latex(a*b))

出力結果(2行2列の行列a)

\left[\begin{matrix}a_{11} & a_{12}\\a_{21} & a_{22}\end{matrix}\right]

出力結果(2行2列の行列b)

\left[\begin{matrix}b_{11} & b_{12}\\b_{21} & b_{22}\end{matrix}\right]

出力結果(a*b)

\left[\begin{matrix}a_{11} b_{11} + a_{12} b_{21} & a_{11} b_{12} + a_{12} b_{22}\\a_{21} b_{11} + a_{22} b_{21} & a_{21} b_{12} + a_{22} b_{22}\end{matrix}\right]
import sympy as sp
a11,a12,a13,a21,a22,a23,a31,a32,a33= sp.symbols('a11,a12,a13,a21,a22,a23,a31,a32,a33')
b11,b12,b13,b21,b22,b23,b31,b32,b33= sp.symbols('b11,b12,b13,b21,b22,b23,b31,b32,b33')
a=sp.Matrix([[a11,a12,a13],[a21,a22,a23],[a31,a32,a33]])
b=sp.Matrix([[b11,b12,b13],[b21,b22,b23],[b31,b32,b33]])
sp.init_printing()
display(a) 
print(sp.latex(a))
display(b) 
print(sp.latex(b))
display(a*b) 
print(sp.latex(a*b))

出力結果(3行3列の行列a)

\left[\begin{matrix}a_{11} & a_{12} & a_{13}\\a_{21} & a_{22} & a_{23}\\a_{31} & a_{32} & a_{33}\end{matrix}\right]

出力結果(3行3列の行列b)

\left[\begin{matrix}b_{11} & b_{12} & b_{13}\\b_{21} & b_{22} & b_{23}\\b_{31} & b_{32} & b_{33}\end{matrix}\right]

出力結果(a*b)

\left[\begin{matrix}a_{11} b_{11} + a_{12} b_{21} + a_{13} b_{31} & a_{11} b_{12} + a_{12} b_{22} + a_{13} b_{32} & a_{11} b_{13} + a_{12} b_{23} + a_{13} b_{33}\\a_{21} b_{11} + a_{22} b_{21} + a_{23} b_{31} & a_{21} b_{12} + a_{22} b_{22} + a_{23} b_{32} & a_{21} b_{13} + a_{22} b_{23} + a_{23} b_{33}\\a_{31} b_{11} + a_{32} b_{21} + a_{33} b_{31} & a_{31} b_{12} + a_{32} b_{22} + a_{33} b_{32} & a_{31} b_{13} + a_{32} b_{23} + a_{33} b_{33}\end{matrix}\right]

この特殊ケースが漸化式などに応用される「行列の自乗」概念となります。
行列のn乗の求め方と例題

\left[\begin{matrix}a & b\\c & d\end{matrix}\right]^2=\left[\begin{matrix}a^{2} + b c & a b + b d\\a c + c d & b c + d^{2}\end{matrix}\right]=\left[\begin{matrix}a^{2} + b c & a b + b d\\a c + c d & b c + d^{2}\end{matrix}\right]\\
\left[\begin{matrix}a & b & c\\d & e & f\\g & h & i\end{matrix}\right]^2=\left[\begin{matrix}a^{2} + b d + c g & a b + b e + c h & a c + b f + c i\\a d + d e + f g & b d + e^{2} + f h & c d + e f + f i\\a g + d h + g i & b g + e h + h i & c g + f h + i^{2}\end{matrix}\right]\\
\left[\begin{matrix}a & b\\c & d\end{matrix}\right]^3=\left[\begin{matrix}a^{3} + 2 a b c + b c d & a^{2} b + a b d + b^{2} c + b d^{2}\\a^{2} c + a c d + b c^{2} + c d^{2} & a b c + 2 b c d + d^{3}\end{matrix}\right]
\left[\begin{matrix}a & b & c\\d & e & f\\g & h & i\end{matrix}\right]^3=\left[\begin{matrix}a^{3} + 2 a b d + 2 a c g + b d e + b f g + c d h + c g i & a^{2} b + a b e + a c h + b^{2} d + b c g + b e^{2} + b f h + c e h + c h i & a^{2} c + a b f + a c i + b c d + b e f + b f i + c^{2} g + c f h + c i^{2}\\a^{2} d + a d e + a f g + b d^{2} + c d g + d e^{2} + d f h + e f g + f g i & a b d + 2 b d e + b f g + c d h + e^{3} + 2 e f h + f h i & a c d + b d f + c d e + c d i + c f g + e^{2} f + e f i + f^{2} h + f i^{2}\\a^{2} g + a d h + a g i + b d g + c g^{2} + d e h + d h i + f g h + g i^{2} & a b g + b d h + b e g + b g i + c g h + e^{2} h + e h i + f h^{2} + h i^{2} & a c g + b f g + c d h + 2 c g i + e f h + 2 f h i + i^{3}\end{matrix}\right]

pythonによる実装

import sympy as sp
a,b,c,d= sp.symbols('a,b,c,d')
a=sp.Matrix([[a,b],[c,d]])
b=a**2
sp.init_printing()
display(a) 
print(sp.latex(a))
display(b) 
print(sp.latex(b))

出力結果(2行2列の行列)

\left[\begin{matrix}a & b\\c & d\end{matrix}\right]

出力結果(2乗した結果)

\left[\begin{matrix}a^{2} + b c & a b + b d\\a c + c d & b c + d^{2}\end{matrix}\right]
import sympy as sp
a,b,c,d,e,f,g,h,i= sp.symbols('a,b,c,d,e,f,g,h,i')
a=sp.Matrix([[a,b,c],[d,e,f],[g,h,i]])
b=a**2
sp.init_printing()
display(a) 
print(sp.latex(a))
display(b) 
print(sp.latex(b))

出力結果(3行3列の行列)

\left[\begin{matrix}a & b & c\\d & e & f\\g & h & i\end{matrix}\right]

出力結果(2乗した結果)

\left[\begin{matrix}a^{2} + b d + c g & a b + b e + c h & a c + b f + c i\\a d + d e + f g & b d + e^{2} + f h & c d + e f + f i\\a g + d h + g i & b g + e h + h i & c g + f h + i^{2}\end{matrix}\right]
import sympy as sp
a,b,c,d= sp.symbols('a,b,c,d')
a=sp.Matrix([[a,b],[c,d]])
b=a**3
sp.init_printing()
display(a) 
print(sp.latex(a))
display(b) 
print(sp.latex(b))

出力結果(2行2列の行列)

\left[\begin{matrix}a & b\\c & d\end{matrix}\right]

出力結果(3乗した結果)

\left[\begin{matrix}a^{3} + 2 a b c + b c d & a^{2} b + a b d + b^{2} c + b d^{2}\\a^{2} c + a c d + b c^{2} + c d^{2} & a b c + 2 b c d + d^{3}\end{matrix}\right]
import sympy as sp
a,b,c,d,e,f,g,h,i= sp.symbols('a,b,c,d,e,f,g,h,i')
a=sp.Matrix([[a,b,c],[d,e,f],[g,h,i]])
b=a**3
sp.init_printing()
display(a) 
print(sp.latex(a))
display(b) 
print(sp.latex(b))

出力結果(3行3列の行列)

\left[\begin{matrix}a & b & c\\d & e & f\\g & h & i\end{matrix}\right]

出力結果(3乗した結果)

\left[\begin{matrix}a^{3} + 2 a b d + 2 a c g + b d e + b f g + c d h + c g i & a^{2} b + a b e + a c h + b^{2} d + b c g + b e^{2} + b f h + c e h + c h i & a^{2} c + a b f + a c i + b c d + b e f + b f i + c^{2} g + c f h + c i^{2}\\a^{2} d + a d e + a f g + b d^{2} + c d g + d e^{2} + d f h + e f g + f g i & a b d + 2 b d e + b f g + c d h + e^{3} + 2 e f h + f h i & a c d + b d f + c d e + c d i + c f g + e^{2} f + e f i + f^{2} h + f i^{2}\\a^{2} g + a d h + a g i + b d g + c g^{2} + d e h + d h i + f g h + g i^{2} & a b g + b d h + b e g + b g i + c g h + e^{2} h + e h i + f h^{2} + h i^{2} & a c g + b f g + c d h + 2 c g i + e f h + 2 f h i + i^{3}\end{matrix}\right]

行ベクトル(横ベクトル)と列ベクトル(縦ベクトル)の積はスカラーになります。いわゆるベクトルの内積(Inner Product)です。

\begin{bmatrix}a_1&a_2\end{bmatrix}\begin{bmatrix}b_1\\b_2\end{bmatrix}=a_1b_1+a_2b_2\\
\begin{bmatrix}a_1&a_2&a_3\end{bmatrix}\begin{bmatrix}b_1\\b_2\\b_3\end{bmatrix}=a_1b_1+a_2b_2+a_3b_3\\

pythonによる実装

import sympy as sp
a1, a2 = sp.symbols('a1, a2')
b1,b2 = sp.symbols('b1,b2')
a=sp.Matrix([[a1,a2]])
b=sp.Matrix([[b1],[b2]])
sp.init_printing()
display(a) 
print(sp.latex(a))
display(b) 
print(sp.latex(b))
display(a*b) 
print(sp.latex(a*b))

出力結果(a)

\left[\begin{matrix}a_{1} & a_{2}\end{matrix}\right]

出力結果(b)

\left[\begin{matrix}b_{1}\\b_{2}\end{matrix}\right]

出力結果(a*b)

\left[\begin{matrix}a_{1} b_{1} + a_{2} b_{2}\end{matrix}\right]
import sympy as sp
a1, a2,a3 = sp.symbols('a1, a2,a3')
b1,b2,b3 = sp.symbols('b1,b2,b3')
a=sp.Matrix([[a1,a2,a3]])
b=sp.Matrix([[b1],[b2],[b3]])
sp.init_printing()
display(a) 
print(sp.latex(a))
display(b) 
print(sp.latex(b))
display(a*b) 
print(sp.latex(a*b))

出力結果(a)

\left[\begin{matrix}a_{1} & a_{2} & a_{3}\end{matrix}\right]

出力結果(b)

\left[\begin{matrix}b_{1}\\b_{2}\\b_{3}\end{matrix}\right]

出力結果(a*b)

\left[\begin{matrix}a_{1} b_{1} + a_{2} b_{2} + a_{3} b_{3}\end{matrix}\right]

列ベクトル(縦ベクトル)と行ベクトル(横ベクトル)の積は行列になります。

\begin{bmatrix}a_1\\a_2\end{bmatrix}\begin{bmatrix}b_1&b_2\end{bmatrix}=\begin{bmatrix}a_1b_1&a_1b_2\\a_2b_1&a_2b_2\end{bmatrix}\\
\left[\begin{matrix}a_{1}\\a_{2}\\a_{3}\end{matrix}\right]\left[\begin{matrix}b_{1} & b_{2} & b_{3}\end{matrix}\right]=\left[\begin{matrix}a_{1} b_{1} & a_{1} b_{2} & a_{1} b_{3}\\a_{2} b_{1} & a_{2} b_{2} & a_{2} b_{3}\\a_{3} b_{1} & a_{3} b_{2} & a_{3} b_{3}\end{matrix}\right]

pythonによる実装

import sympy as sp
a1, a2 = sp.symbols('a1, a2')
b1,b2 = sp.symbols('b1,b2')
a=sp.Matrix([[a1],[a2]])
b=sp.Matrix([[b1,b2]])
sp.init_printing()
display(a) 
print(sp.latex(a))
display(b) 
print(sp.latex(b))
display(a*b) 
print(sp.latex(a*b))

出力結果(a)

\left[\begin{matrix}a_{1}\\a_{2}\end{matrix}\right]

出力結果(b)

\left[\begin{matrix}b_{1} & b_{2}\end{matrix}\right]

出力結果(a*b)

\left[\begin{matrix}a_{1} b_{1} & a_{1} b_{2}\\a_{2} b_{1} & a_{2} b_{2}\end{matrix}\right]
import sympy as sp
a1, a2,a3 = sp.symbols('a1, a2,a3')
b1,b2,b3 = sp.symbols('b1,b2,b3')
a=sp.Matrix([[a1],[a2],[a3]])
b=sp.Matrix([[b1,b2,b3]])
sp.init_printing()
display(a) 
print(sp.latex(a))
display(b) 
print(sp.latex(b))
display(a*b) 
print(sp.latex(a*b))

出力結果(a)

\left[\begin{matrix}a_{1}\\a_{2}\\a_{3}\end{matrix}\right]

出力結果(b)

\left[\begin{matrix}b_{1} & b_{2} & b_{3}\end{matrix}\right]

出力結果(a*b)

\left[\begin{matrix}a_{1} b_{1} & a_{1} b_{2} & a_{1} b_{3}\\a_{2} b_{1} & a_{2} b_{2} & a_{2} b_{3}\\a_{3} b_{1} & a_{3} b_{2} & a_{3} b_{3}\end{matrix}\right]

このように「行ベクトル(横ベクトル)×列ベクトル(縦ベクトル)」なのか「列ベクトル(縦ベクトル)×行ベクトル(横ベクトル)」なのかによって結果が全く異なるので、注意が必要です。

ちなみに列ベクトル(縦ベクトル)と行ベクトル(横ベクトル)の積の形で表された行列のランクは必ず1(すなわち線形従属状態)となります。

線形代数の基礎 第9回 - 行列のランク
線形代数の基礎 第10回 - 行列のランクの計算

行ベクトル(横ベクトル)×行列×列ベクトル(縦ベクトル)」はスカラーになります。

\begin{bmatrix}x_1&x_2\end{bmatrix}\begin{bmatrix}a_{11}&a_{12}\\a_{21}&a_{22}\end{bmatrix}\begin{bmatrix}y_1\\y_2\end{bmatrix}\\ 
=x_1a_{11}y_1+x_1a_{12}y_2+x_2a_{21}y_1+x_2a_{22}y_2\\
\left[\begin{matrix}x_{1} & x_{2} & x_{3}\end{matrix}\right]\left[\begin{matrix}a_{11} & a_{12} & a_{13}\\a_{21} & a_{22} & a_{23}\\a_{31} & a_{32} & a_{33}\end{matrix}\right]\left[\begin{matrix}y_{1}\\y_{2}\\y_{3}\end{matrix}\right]=\left[\begin{matrix}y_{1} \left(a_{11} x_{1} + a_{21} x_{2} + a_{31} x_{3}\right) + y_{2} \left(a_{12} x_{1} + a_{22} x_{2} + a_{32} x_{3}\right) + y_{3} \left(a_{13} x_{1} + a_{23} x_{2} + a_{33} x_{3}\right)\end{matrix}\right]

pythonによる実装

import sympy as sp
a11, a12,a21,a22 = sp.symbols('a11,a12, a21,a22')
x1,x2 = sp.symbols('x1,x2')
y1,y2 = sp.symbols('y1,y2')
x=sp.Matrix([[x1,x2]])
y=sp.Matrix([[y1],[y2]])
a=sp.Matrix([[a11,a12],[a21,a22]])
sp.init_printing()
display(x) 
print(sp.latex(x))
display(a) 
print(sp.latex(a))
display(y) 
print(sp.latex(y))
display(x*a*y) 
print(sp.latex(x*a*y))

出力結果(x)

\left[\begin{matrix}x_{1} & x_{2}\end{matrix}\right]

出力結果(a)

\left[\begin{matrix}a_{11} & a_{12}\\a_{21} & a_{22}\end{matrix}\right]

出力結果(y)

\left[\begin{matrix}y_{1}\\y_{2}\end{matrix}\right]

出力結果(xay)

\left[\begin{matrix}y_{1} \left(a_{11} x_{1} + a_{21} x_{2}\right) + y_{2} \left(a_{12} x_{1} + a_{22} x_{2}\right)\end{matrix}\right]
import sympy as sp
a11, a12,a13,a21,a22,a23,a31,a32,a33 = sp.symbols('a11,a12,a13,a21,a22,a23,a31,a32,a33')
x1,x2,x3 = sp.symbols('x1,x2,x3')
y1,y2,y3 = sp.symbols('y1,y2,y3')
x=sp.Matrix([[x1,x2,x3]])
y=sp.Matrix([[y1],[y2],[y3]])
a=sp.Matrix([[a11,a12,a13],[a21,a22,a23],[a31,a32,a33]])
sp.init_printing()
display(x) 
print(sp.latex(x))
display(a) 
print(sp.latex(a))
display(y) 
print(sp.latex(y))
display(x*a*y) 
print(sp.latex(x*a*y))

出力結果(x)

\left[\begin{matrix}x_{1} & x_{2} & x_{3}\end{matrix}\right]

出力結果(a)

\left[\begin{matrix}a_{11} & a_{12} & a_{13}\\a_{21} & a_{22} & a_{23}\\a_{31} & a_{32} & a_{33}\end{matrix}\right]

出力結果(y)

\left[\begin{matrix}y_{1}\\y_{2}\\y_{3}\end{matrix}\right]

出力結果(xay)

\left[\begin{matrix}y_{1} \left(a_{11} x_{1} + a_{21} x_{2} + a_{31} x_{3}\right) + y_{2} \left(a_{12} x_{1} + a_{22} x_{2} + a_{32} x_{3}\right) + y_{3} \left(a_{13} x_{1} + a_{23} x_{2} + a_{33} x_{3}\right)\end{matrix}\right]

特に、行列が対称行列(Symmetric Matrix=自身の転置行列と一致するような正方行列を)で、行ベクトル(横ベクトル)と列ベクトル(縦ベクトル)の成分が同じであるようなものを二次形式と言います。

対称行列 - Wikipedia
二次形式の意味,微分,標準形など

\begin{bmatrix}x_1&x_2\end{bmatrix}\begin{bmatrix}a_1&b\\b&a_2\end{bmatrix}\begin{bmatrix}x_1\\x_2\end{bmatrix}\\ 
=a_1x_1^2+a_2x_2^2+2bx_1x_2\\
\left[\begin{matrix}x_{1} & x_{2} & x_{3}\end{matrix}\right]\left[\begin{matrix}a_{1} & b & c\\b & a_{2} & d\\c & d & a_{3}\end{matrix}\right]\left[\begin{matrix}x_{1}\\x_{2}\\x_{3}\end{matrix}\right]\\
=a_1x_1^2+a_2x_2^2+a_3x_3^2+2bx_1x_2+2cx_1x_3+2dx_2x_3

pythonによる実装
[SymPy] 数式の簡略化

import sympy as sp
a,b,c = sp.symbols('a,b,c')
x1,x2= sp.symbols('x1,x2')
#Rows
x=sp.Matrix([[x1,x2]])
#Columns
y=sp.Matrix([[x1],[x2]])
a=sp.Matrix([[a,b],[b,c]])
sp.init_printing()
display(x) 
print(sp.latex(x))
display(a) 
print(sp.latex(a))
display(y) 
print(sp.latex(y))
display(sp.simplify(x*a*y)) 
print(sp.latex(sp.simplify(x*a*y)))

出力結果(xRows)

\left[\begin{matrix}x_{1} & x_{2}\end{matrix}\right]

出力結果(a)

\left[\begin{matrix}a_{1} & b\\b & a_{2}\end{matrix}\right]

出力結果(xColumns)

\left[\begin{matrix}x_{1}\\x_{2}\end{matrix}\right]

出力結果(xRowsaxColumns)

\left[\begin{matrix}x_{1} \left(a_{1} x_{1} + b x_{2}\right) + x_{2} \left(a_{2} x_{2} + b x_{1}\right)\end{matrix}\right]
import sympy as sp
a1,a2,a3,b,c,d= sp.symbols('a1,a2,a3,b,c,d')
x1,x2,x3= sp.symbols('x1,x2,x3')
#Rows
x=sp.Matrix([[x1,x2,x3]])
#Columns
y=sp.Matrix([[x1],[x2],[x3]])
a=sp.Matrix([[a1,b,c],[b,a2,d],[c,d,a3]])
sp.init_printing()
display(x) 
print(sp.latex(x))
display(a) 
print(sp.latex(a))
display(y) 
print(sp.latex(y))
display(sp.simplify(x*a*y)) 
print(sp.latex(sp.simplify(x*a*y)))

出力結果(xRows)

\left[\begin{matrix}x_{1} & x_{2} & x_{3}\end{matrix}\right]

出力結果(a)

\left[\begin{matrix}a_{1} & b & c\\b & a_{2} & d\\c & d & a_{3}\end{matrix}\right]

出力結果(xColumns)

\left[\begin{matrix}x_{1}\\x_{2}\\x_{3}\end{matrix}\right]

出力結果(xRowsaxColumns)

\left[\begin{matrix}x_{1} \left(a_{1} x_{1} + b x_{2} + c x_{3}\right) + x_{2} \left(a_{2} x_{2} + b x_{1} + d x_{3}\right) + x_{3} \left(a_{3} x_{3} + c x_{1} + d x_{2}\right)\end{matrix}\right]

ちなみに正方行列には行列式(Determinant)が定義で可能で、こちらは外積(Outer Product)と関係してきます。

2×2行列(2次正方行列)の行列式の定義と意味(行列と外積の関係)

行列Aの行列式は以下の様に表される。

A=\begin{bmatrix}a&b\\c&d\end{bmatrix}\\
det(A)/detA/|A|=\begin{vmatrix}a&b\\c&d\end{vmatrix}=ad-bc

ここで$\vec{x}=(a,b),\vec{y}=(c,d)$とすると

|A|=ad-bc=\vec{x}×\vec{y}

つまり行列の行列式は行列を行ごとに分解してできるベクトルの外積であり、二つのベクトルがなす平行四辺形の面積を意味する。

【Rで球面幾何学】そもそも「内積(Inner Product)」とは「外積(Outer Product)」とは何か?
pythonによる実装その1

import sympy as sp
a, b,c,d = sp.symbols('a,b, c,d')
a=sp.Matrix([[a,b],[c,d]])
sp.init_printing()
display(a) 
print(sp.latex(a))
display(a.det()) 
print(sp.latex(a.det()))

出力結果(a)

\left[\begin{matrix}a & b\\c & d\end{matrix}\right]

出力結果(aの行列式)

a d - b c

pythonによる実装その2

import sympy as sp
a11, a12,a21,a22 = sp.symbols('a11,a12, a21,a22')
a=sp.Matrix([[a11,a12],[a21,a22]])
sp.init_printing()
display(a) 
print(sp.latex(a))
display(a.det()) 
print(sp.latex(a.det()))

出力結果(a)

\left[\begin{matrix}a_{11} & a_{12}\\a_{21} & a_{22}\end{matrix}\right]

出力結果(aの行列式)

a_{11} a_{22} - a_{12} a_{21}

3行×3列の行列の場合

import sympy as sp
a, b,c,d,e,f,g,h,i= sp.symbols('a,b,c,d,e,f,g,h,i')
a=sp.Matrix([[a,b,c],[d,e,f],[g,h,i]])
sp.init_printing()
display(a) 
print(sp.latex(a))
display(a.det()) 
print(sp.latex(a.det()))

出力結果(a)

\left[\begin{matrix}a & b & c\\d & e & f\\g & h & i\end{matrix}\right]

出力結果(aの行列式)

a e i - a f h - b d i + b f g + c d h - c e g
import sympy as sp
a11,a12,a13,a21,a22,a23,a31,a32,a33= sp.symbols('a11,a12,a13,a21,a22,a23,a31,a32,a33')
a=sp.Matrix([[a11,a12,a13],[a21,a22,a23],[a31,a32,a33]])
sp.init_printing()
display(a) 
print(sp.latex(a))
display(a.det()) 
print(sp.latex(a.det()))

出力結果(a)

\left[\begin{matrix}a_{11} & a_{12} & a_{13}\\a_{21} & a_{22} & a_{23}\\a_{31} & a_{32} & a_{33}\end{matrix}\right]

出力結果(aの行列式)

a_{11} a_{22} a_{33} - a_{11} a_{23} a_{32} - a_{12} a_{21} a_{33} + a_{12} a_{23} a_{31} + a_{13} a_{21} a_{32} - a_{13} a_{22} a_{31}

#行列演算は連立方程式の発展形?

それにつけても、どうして行列では掛け合わせる順番が異なると結果が異なるのでしょう? それはこの演算が単なる四則演算ではなく連立方程式における係数と変数の分離なる概念の延長線上に現れたからなのです。

行列の演算

行列の積では掛け合わせる順番で結果が異なります。

pythonによる実装

import sympy as sp
a=sp.Matrix([[2,1],[1,3]])
b=sp.Matrix([[2,3],[1,2]])
sp.init_printing()
display(a) 
print(sp.latex(a))
display(b) 
print(sp.latex(b))
display(a*b) 
print(sp.latex(a*b))
display(b*a) 
print(sp.latex(b*a))

出力結果(a)

\left[\begin{matrix}2 & 1\\1 & 3\end{matrix}\right]

出力結果(b)

\left[\begin{matrix}2 & 3\\1 & 2\end{matrix}\right]

出力結果(a*b)

\left[\begin{matrix}5 & 8\\5 & 9\end{matrix}\right]

出力結果(b*a)

\left[\begin{matrix}7 & 11\\4 & 7\end{matrix}\right]

四則演算の延長線上で考えるからこの振る舞いが奇異に映るのです。あくまで連立方程式の延長線上で考えましょう。例えば以下。

\left\{
\begin{array}{l}
2x+4y=7\\
x+3y=6
\end{array}
\right.

この連立方程式を行列に置き換えたのが以下。

\begin{bmatrix}2&4\\1&3\end{bmatrix}\begin{bmatrix}x\\y\end{bmatrix}=\begin{bmatrix}7\\6\end{bmatrix}

実際に計算して見ましょう。

pythonによる実装

import sympy as sp
x,y = sp.symbols('x,y')
a=sp.Matrix([[2,4],[1,3]])
b=sp.Matrix([[x],[y]])
sp.init_printing()
display(a) 
print(sp.latex(a))
display(b) 
print(sp.latex(b))
display(a*b) 
print(sp.latex(a*b))

出力結果(a)

\left[\begin{matrix}2 & 4\\1 & 3\end{matrix}\right]

出力結果(b)

\left[\begin{matrix}x\\y\end{matrix}\right]

出力結果(a*b)

\left[\begin{matrix}2 x + 4 y\\x + 3 y\end{matrix}\right]

ちなみに以下はサイズ違いからエラーとなってしまいます。

\begin{bmatrix}x\\y\end{bmatrix}\begin{bmatrix}2&4\\1&3\end{bmatrix}

この形なら計算こそ通りますが、答えが変わってしまいます。

\begin{bmatrix}x&y\end{bmatrix}\begin{bmatrix}2&4\\1&3\end{bmatrix}

pythonによる実装

import sympy as sp
x,y = sp.symbols('x,y')
a=sp.Matrix([[2,4],[1,3]])
b=sp.Matrix([[x,y]])
sp.init_printing()
display(a) 
print(sp.latex(a))
display(b) 
print(sp.latex(b))
display(b*a) 
print(sp.latex(b*a))

出力結果(a)

\left[\begin{matrix}2 & 4\\1 & 3\end{matrix}\right]

出力結果(b)

\left[\begin{matrix}x & y\end{matrix}\right]

出力結果(b*a)

\left[\begin{matrix}2 x + y & 4 x + 3 y\end{matrix}\right]

要するに上掲の正方行列間の計算では、この「縦横変換」が勝手に起こってしまった様です。つまりはそういう事である?

線形代数とは何か

線形代数の「線形」の部分は「Linear」の訳である.これは「線状の」つまり,線の形をしたという意味である.ところで,一次関数のグラフは直線である.二次関数になると曲線になってしまう.2x+3y=0というような形のグラフも直線である.つまり「この分野では一次式のみを扱います」というニュアンスがここに込められているわけだ.

代数というのは,変数を記号で表して,そこに数値を代入して方程式を解いたりする学問である.

要するに線形代数とは「連立一次方程式」についての学問なのである.正体が分かってしまうだけで随分と気が楽になるだろう(注意:現代では「線形」の意味も「代数」の意味ももっと抽象化されてしまっているので,こんな不正確な説明を野放しにしておくわけにはいかないとばかりに多くの批判が来そうではある.まあ,勉強を続けていればいずれ気付くときが来るだろう.)

線形代数とは「連立一次方程式をいかに効率よく解くか」というテクニックを追求した結果をまとめたもの・・・,最初の目的を越えて少々やりすぎてしまったという感じのものだ.突き詰めてみると意外と奥が深かったために,学問に昇格したというやつである.

この応用範囲がかなり広いので軽視するわけにはいかない.物理学に限ってみても,変数のやたら多い複雑な力学の問題を解くための解法を用意してくれたりする.それだけでなく,意外なところで微分方程式との関係も出てくるし,ついには量子力学にまで関係してくることになる。

ちなみに実際に連立方程式を解くには、さらに逆関数(Inverse Matrix)概念の援用が必要となります。
【Python演算処理】行列演算の基本②単位行列と逆行列そして連立一次方程式の解法

とりあえず、こんな感じで以下続報…

1
2
8

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
1
2