からっぽのしょこ

読んだら書く!書いたら読む!同じ事は二度調べ(たく)ない

6.3.2:行列の和の性質の導出【『スタンフォード線形代数入門』のノート】

はじめに

 『スタンフォード ベクトル・行列からはじめる最適化数学』の学習ノートです。
 「数式の行間埋め」や「Pythonを使っての再現」によって理解を目指します。本と一緒に読んでください。

 この記事は6.3.2節「行列の和」の内容です。
 行列の和の定義を確認して、性質を導出します。また、NumPyライブラリでの扱い方を確認します。

【前の内容】

www.anarchive-beta.com

【他の内容】

www.anarchive-beta.com

【今回の内容】

6.3.2 行列の和の性質の導出

 行列の和の計算を数式とプログラム(NumPyライブラリ)で確認します。
 行列については「【Python】6.1-3:行列の定義と性質【『スタンフォード線形代数入門』のノート】 - からっぽのしょこ」を参照してください。

 利用するライブラリを読み込みます。

# 利用ライブラリ
import numpy as np


行列の和の定義

 まずは、行列の和の定義式を確認します。

  m \times n 行列  \mathbf{A}, \mathbf{B} の和を考えます。

 行列の和は、「各要素の和」で定義されます。

 \displaystyle
\begin{aligned}
\mathbf{C}
   &= \mathbf{A} + \mathbf{B}
\\
   &= \begin{bmatrix}
          a_{1,1} & a_{1,2} & \cdots & a_{1,n} \\
          a_{2,1} & a_{2,2} & \cdots & a_{2,n} \\
          \vdots  & \vdots  & \ddots & \vdots \\
          a_{m,1} & a_{m,2} & \cdots & a_{m,n}
      \end{bmatrix}
      + \begin{bmatrix}
          b_{1,1} & b_{1,2} & \cdots & b_{1,n} \\
          b_{2,1} & b_{2,2} & \cdots & b_{2,n} \\
          \vdots  & \vdots  & \ddots & \vdots \\
          b_{m,1} & b_{m,2} & \cdots & b_{m,n}
        \end{bmatrix}
\\
   &= \begin{bmatrix}
          a_{1,1} + b_{1,1} & a_{1,2} + b_{1,2} & \cdots & a_{1,n} + b_{1,n} \\
          a_{2,1} + b_{2,1} & a_{2,2} + b_{2,2} & \cdots & a_{2,n} + b_{2,n} \\
          \vdots & \vdots & \ddots & \vdots \\
          a_{m,1} + b_{m,1} & a_{m,2} + b_{m,2} & \cdots & a_{m,n} + b_{m,n}
      \end{bmatrix}
\\
   &= \begin{bmatrix}
          c_{1,1} & c_{1,2} & \cdots & c_{1,n} \\
          c_{2,1} & c_{2,2} & \cdots & c_{2,n} \\
          \vdots  & \vdots  & \ddots & \vdots \\
          c_{m,1} & c_{m,2} & \cdots & c_{m,n}
      \end{bmatrix}
\end{aligned}

 各要素は、同じインデックスの要素の和  c_{i,j} = a_{i,j} + b_{i,j} になります。
 そのため、和を求める行列の形状が一致している必要があり、計算結果の行列も同じ形状になります。

 行列を指定して、行列の和を計算します。

# 行列を作成
A = np.array(
    [[0.0, 4.0], 
     [7.0, 0.0], 
     [3.0, 1.0]]
)
B = np.array(
    [[1.0, 2.0], 
     [2.0, 3.0], 
     [0.0, 4.0]]
)
print(A)
print(A.shape)
print(B)
print(B.shape)

# 行列の和を計算
C = A + B
print(C)
print(C.shape)
[[0. 4.]
 [7. 0.]
 [3. 1.]]
(3, 2)
[[1. 2.]
 [2. 3.]
 [0. 4.]]
(3, 2)
[[1. 6.]
 [9. 3.]
 [3. 5.]]
(3, 2)

 和を計算する配列の形状が対応している必要があります。また、計算結果の配列も同じ形状になります。

行列の和の性質

 次は、行列の和の性質を導出します。

交換法則

 和の順番を入れ替えた行列を考えます。

 \displaystyle
\begin{aligned}
\mathbf{B} + \mathbf{A}
   &= \begin{bmatrix}
          b_{1,1} & b_{1,2} & \cdots & b_{1,n} \\
          b_{2,1} & b_{2,2} & \cdots & b_{2,n} \\
          \vdots  & \vdots  & \ddots & \vdots \\
          b_{m,1} & b_{m,2} & \cdots & b_{m,n}
      \end{bmatrix}
      + \begin{bmatrix}
          a_{1,1} & a_{1,2} & \cdots & a_{1,n} \\
          a_{2,1} & a_{2,2} & \cdots & a_{2,n} \\
          \vdots  & \vdots  & \ddots & \vdots \\
          a_{m,1} & a_{m,2} & \cdots & a_{m,n}
        \end{bmatrix}
\\
   &= \begin{bmatrix}
          b_{1,1} + a_{1,1} & b_{1,2} + a_{1,2} & \cdots & b_{1,n} + a_{1,n} \\
          b_{2,1} + a_{2,1} & b_{2,2} + a_{2,2} & \cdots & b_{2,n} + a_{2,n} \\
          \vdots & \vdots & \ddots & \vdots \\
          b_{m,1} + a_{m,1} & b_{m,2} + a_{m,2} & \cdots & b_{m,n} + a_{m,n}
      \end{bmatrix}
\end{aligned}

 スカラーの和は交換法則  a_{i,j} + b_{i,j} = b_{i,j} + a_{i,j} 成り立つので、各要素の和の順番を入れ替えて、行列の和に分割します。

 \displaystyle
\begin{aligned}
\mathbf{B} + \mathbf{A}
   &= \begin{bmatrix}
          a_{1,1} + b_{1,1} & a_{1,2} + b_{1,2} & \cdots & a_{1,n} + b_{1,n} \\
          a_{2,1} + b_{2,1} & a_{2,2} + b_{2,2} & \cdots & a_{2,n} + b_{2,n} \\
          \vdots & \vdots & \ddots & \vdots \\
          a_{m,1} + b_{m,1} & a_{m,2} + b_{m,2} & \cdots & a_{m,n} + b_{m,n}
      \end{bmatrix}
\\
   &= \begin{bmatrix}
          a_{1,1} & a_{1,2} & \cdots & a_{1,n} \\
          a_{2,1} & a_{2,2} & \cdots & a_{2,n} \\
          \vdots  & \vdots  & \ddots & \vdots \\
          a_{m,1} & a_{m,2} & \cdots & a_{m,n}
      \end{bmatrix}
      + \begin{bmatrix}
          b_{1,1} & b_{1,2} & \cdots & b_{1,n} \\
          b_{2,1} & b_{2,2} & \cdots & b_{2,n} \\
          \vdots  & \vdots  & \ddots & \vdots \\
          b_{m,1} & b_{m,2} & \cdots & b_{m,n}
        \end{bmatrix}
\\
   &= \mathbf{A} + \mathbf{B}
\end{aligned}

 行列の和は、交換法則が成り立ちます。

 行列の和の順番を入れ替えて計算します。

# 行列の和を計算
C = A + B
print(C)
print(C.shape)

# 行列の和を計算
D = B + A
print(D)
print(D.shape)

# 値を比較
print(C == D)
[[1. 6.]
 [9. 3.]
 [3. 5.]]
(3, 2)
[[1. 6.]
 [9. 3.]
 [3. 5.]]
(3, 2)
[[ True  True]
 [ True  True]
 [ True  True]]

 和の順番を入れ替えても計算結果が一致するのを確認できます。

結合法則

  m \times n 行列  \mathbf{A}, \mathbf{B}, \mathbf{C} の和を考えます。

 \displaystyle
\begin{aligned}
(\mathbf{A} + \mathbf{B}) + \mathbf{C}
   &= \left(
          \begin{bmatrix}
              a_{1,1} & a_{1,2} & \cdots & a_{1,n} \\
              a_{2,1} & a_{2,2} & \cdots & a_{2,n} \\
              \vdots  & \vdots  & \ddots & \vdots \\
              a_{m,1} & a_{m,2} & \cdots & a_{m,n}
              \end{bmatrix}
          + \begin{bmatrix}
              b_{1,1} & b_{1,2} & \cdots & b_{1,n} \\
              b_{2,1} & b_{2,2} & \cdots & b_{2,n} \\
              \vdots  & \vdots  & \ddots & \vdots \\
              b_{m,1} & b_{m,2} & \cdots & b_{m,n}
            \end{bmatrix}
      \right)
      + \begin{bmatrix}
          c_{1,1} & c_{1,2} & \cdots & c_{1,n} \\
          c_{2,1} & c_{2,2} & \cdots & c_{2,n} \\
          \vdots  & \vdots  & \ddots & \vdots \\
          c_{m,1} & c_{m,2} & \cdots & c_{m,n}
        \end{bmatrix}
\\
   &= \begin{bmatrix}
          a_{1,1} + b_{1,1} & a_{1,2} + b_{1,2} & \cdots & a_{1,n} + b_{1,n} \\
          a_{2,1} + b_{2,1} & a_{2,2} + b_{2,2} & \cdots & a_{2,n} + b_{2,n} \\
          \vdots & \vdots & \ddots & \vdots \\
          a_{m,1} + b_{m,1} & a_{m,2} + b_{m,2} & \cdots & a_{m,n} + b_{m,n}
      \end{bmatrix}
      + \begin{bmatrix}
          c_{1,1} & c_{1,2} & \cdots & c_{1,n} \\
          c_{2,1} & c_{2,2} & \cdots & c_{2,n} \\
          \vdots  & \vdots  & \ddots & \vdots \\
          c_{m,1} & c_{m,2} & \cdots & c_{m,n}
        \end{bmatrix}
\\
   &= \begin{bmatrix}
          a_{1,1} + b_{1,1} + c_{1,1} & a_{1,2} + b_{1,2} + c_{1,2} & \cdots & a_{1,n} + b_{1,n} + c_{1,n} \\
          a_{2,1} + b_{2,1} + c_{2,1} & a_{2,2} + b_{2,2} + c_{2,2} & \cdots & a_{2,n} + b_{2,n} + c_{2,n} \\
          \vdots & \vdots & \ddots & \vdots \\
          a_{m,1} + b_{m,1} + c_{m,1} & a_{m,2} + b_{m,2} + c_{m,2} & \cdots & a_{m,n} + b_{m,n} + c_{m,n}
      \end{bmatrix}
\end{aligned}

 スカラーの和は結合法則  (a_{i,j} + b_{i,j}) + c_{i,j} = a_{i,j} + (b_{i,j} + c_{i,j}) 成り立つので、各要素の和の順番を入れ替えて、行列の和に分割します。

 \displaystyle
\begin{aligned}
(\mathbf{A} + \mathbf{B}) + \mathbf{C}
   &= \begin{bmatrix}
          a_{1,1} & a_{1,2} & \cdots & a_{1,n} \\
          a_{2,1} & a_{2,2} & \cdots & a_{2,n} \\
          \vdots  & \vdots  & \ddots & \vdots \\
          a_{m,1} & a_{m,2} & \cdots & a_{m,n}
      \end{bmatrix}
      + \begin{bmatrix}
          b_{1,1} + c_{1,1} & b_{1,2} + c_{1,2} & \cdots & b_{1,n} + c_{1,n} \\
          b_{2,1} + c_{2,1} & b_{2,2} + c_{2,2} & \cdots & b_{2,n} + c_{2,n} \\
          \vdots & \vdots & \ddots & \vdots \\
          b_{m,1} + c_{m,1} & b_{m,2} + c_{m,2} & \cdots & b_{m,n} + c_{m,n}
        \end{bmatrix}
\\
   &= \begin{bmatrix}
          a_{1,1} & a_{1,2} & \cdots & a_{1,n} \\
          a_{2,1} & a_{2,2} & \cdots & a_{2,n} \\
          \vdots  & \vdots  & \ddots & \vdots \\
          a_{m,1} & a_{m,2} & \cdots & a_{m,n}
      \end{bmatrix}
      + \left(
          \begin{bmatrix}
              b_{1,1} & b_{1,2} & \cdots & b_{1,n} \\
              b_{2,1} & b_{2,2} & \cdots & b_{2,n} \\
              \vdots  & \vdots  & \ddots & \vdots \\
              b_{m,1} & b_{m,2} & \cdots & b_{m,n}
          \end{bmatrix}
          + \begin{bmatrix}
              c_{1,1} & c_{1,2} & \cdots & c_{1,n} \\
              c_{2,1} & c_{2,2} & \cdots & c_{2,n} \\
              \vdots  & \vdots  & \ddots & \vdots \\
              c_{m,1} & c_{m,2} & \cdots & c_{m,n}
            \end{bmatrix}
        \right)
\\
   &= \mathbf{A} + (\mathbf{B} + \mathbf{C})
\end{aligned}

 行列の和は、結合法則が成り立ちます。

 行列の和の順番を入れ替えて計算します。

# 行列を作成
C = np.array(
    [[1.0, 6.0], 
     [9.0, 3.0], 
     [6.0, 0.0]]
)

# 行列の和を計算
D = (A + B) + C
print(D)
print(D.shape)

# 行列の和を計算
E = A + (B + C)
print(E)
print(E.shape)

# 値を比較
print(D == E)
[[ 2. 12.]
 [18.  6.]
 [ 9.  5.]]
(3, 2)
[[ 2. 12.]
 [18.  6.]
 [ 9.  5.]]
(3, 2)
[[ True  True]
 [ True  True]
 [ True  True]]

 和の順番を入れ替えても計算結果が一致するのを確認できます。

ゼロ行列との和

 ゼロ行列については「6.1-3:行列の定義と例【『スタンフォード線形代数入門』のノート】 - からっぽのしょこ」を参照してください。

 ゼロ行列(全ての要素が0の行列)との和を考えます。

 \displaystyle
\mathbf{O}
    = \begin{bmatrix}
          O_{1,1} & O_{1,2} & \cdots & O_{1,n} \\
          O_{2,1} & O_{2,2} & \cdots & O_{2,n} \\
          \vdots  & \vdots  & \ddots & \vdots \\
          O_{m,1} & O_{m,2} & \cdots & O_{m,n}
      \end{bmatrix}
    = \begin{bmatrix}
          0 & 0 & \cdots & 0 \\
          0 & 0 & \cdots & 0 \\
          \vdots & \vdots & \ddots & \vdots \\
          0 & 0 & \cdots & 0
      \end{bmatrix}

 各要素に0を足すので値が変わりません。

 \displaystyle
\begin{aligned}
\mathbf{A} + \mathbf{O}
   &= \begin{bmatrix}
          a_{1,1} & a_{1,2} & \cdots & a_{1,n} \\
          a_{2,1} & a_{2,2} & \cdots & a_{2,n} \\
          \vdots  & \vdots  & \ddots & \vdots \\
          a_{m,1} & a_{m,2} & \cdots & a_{m,n}
      \end{bmatrix}
      + \begin{bmatrix}
          O_{1,1} & O_{1,2} & \cdots & O_{1,n} \\
          O_{2,1} & O_{2,2} & \cdots & O_{2,n} \\
          \vdots  & \vdots  & \ddots & \vdots \\
          O_{m,1} & O_{m,2} & \cdots & O_{m,n}
      \end{bmatrix}
\\
   &= \begin{bmatrix}
          a_{1,1} + 0 & a_{1,2} + 0 & \cdots & a_{1,n} + 0 \\
          a_{2,1} + 0 & a_{2,2} + 0 & \cdots & a_{2,n} + 0 \\
          \vdots & \vdots & \ddots & \vdots \\
          a_{m,1} + 0 & a_{m,2} + 0 & \cdots & a_{m,n} + 0
      \end{bmatrix}
\\
   &= \begin{bmatrix}
          a_{1,1} & a_{1,2} & \cdots & a_{1,n} \\
          a_{2,1} & a_{2,2} & \cdots & a_{2,n} \\
          \vdots  & \vdots  & \ddots & \vdots \\
          a_{m,1} & a_{m,2} & \cdots & a_{m,n}
      \end{bmatrix}
\\
   &= \mathbf{A}
\end{aligned}

 ゼロ行列との和は、元の行列のままです。

 ゼロ行列との和を計算します。

# ゼロ行列を作成
O = np.zeros_like(A)
print(O)
print(O.shape)

# 行列の和を計算
C = A + O
print(C)
print(C.shape)

# 値を比較
print(A == C)
[[0. 0.]
 [0. 0.]
 [0. 0.]]
(3, 2)
[[0. 4.]
 [7. 0.]
 [3. 1.]]
(3, 2)
[[ True  True]
 [ True  True]
 [ True  True]]

 配列を np.zeros_like() に渡すと、同じ形状で全ての値が 0 の配列を返します。
 ゼロ行列を足しても値が変わらないのを確認できます。

転置行列の和

 行列の和の転置行列を考えます。

 \displaystyle
\begin{aligned}
(\mathbf{A} + \mathbf{B})^{\top}
   &= \left(
          \begin{bmatrix}
              a_{1,1} & a_{1,2} & \cdots & a_{1,n} \\
              a_{2,1} & a_{2,2} & \cdots & a_{2,n} \\
              \vdots  & \vdots  & \ddots & \vdots \\
              a_{m,1} & a_{m,2} & \cdots & a_{m,n}
          \end{bmatrix}
          + \begin{bmatrix}
              b_{1,1} & b_{1,2} & \cdots & b_{1,n} \\
              b_{2,1} & b_{2,2} & \cdots & b_{2,n} \\
              \vdots  & \vdots  & \ddots & \vdots \\
              b_{m,1} & b_{m,2} & \cdots & b_{m,n}
            \end{bmatrix}
        \right)^{\top}
\\
   &= \begin{bmatrix}
          a_{1,1} + b_{1,1} & a_{1,2} + b_{1,2} & \cdots & a_{1,n} + b_{1,n} \\
          a_{2,1} + b_{2,1} & a_{2,2} + b_{2,2} & \cdots & a_{2,n} + b_{2,n} \\
          \vdots & \vdots & \ddots & \vdots \\
          a_{m,1} + b_{m,1} & a_{m,2} + b_{m,2} & \cdots & a_{m,n} + b_{m,n}
      \end{bmatrix}^{\top}
\\
   &= \begin{bmatrix}
          a_{1,1} + b_{1,1} & a_{2,1} + b_{2,1} & \cdots & a_{m,1} + b_{m,1} \\
          a_{1,2} + b_{1,2} & a_{2,2} + b_{2,2} & \cdots & a_{m,2} + b_{m,2} \\
          \vdots & \vdots & \ddots & \vdots \\
          a_{1,n} + b_{1,n} & a_{2,n} + b_{2,n} & \cdots & a_{m,n} + b_{m,n}
      \end{bmatrix}
\end{aligned}

 行列の和に分割します。

 \displaystyle
\begin{aligned}
(\mathbf{A} + \mathbf{B})^{\top}
   &= \begin{bmatrix}
          a_{1,1} & a_{2,1} & \cdots & a_{m,1} \\
          a_{1,2} & a_{2,2} & \cdots & a_{m,2} \\
          \vdots  & \vdots  & \ddots & \vdots \\
          a_{1,n} & a_{2,n} & \cdots & a_{m,n}
      \end{bmatrix}
      + \begin{bmatrix}
          b_{1,1} & b_{2,1} & \cdots & b_{m,1} \\
          b_{1,2} & b_{2,2} & \cdots & b_{m,2} \\
          \vdots  & \vdots  & \ddots & \vdots \\
          b_{1,n} & b_{2,n} & \cdots & b_{m,n}
        \end{bmatrix}
\\
   &= \begin{bmatrix}
          a_{1,1} & a_{1,2} & \cdots & a_{1,n} \\
          a_{2,1} & a_{2,2} & \cdots & a_{2,n} \\
          \vdots  & \vdots  & \ddots & \vdots \\
          a_{m,1} & a_{m,2} & \cdots & a_{m,n}
      \end{bmatrix}^{\top}
      + \begin{bmatrix}
          b_{1,1} & b_{1,2} & \cdots & b_{1,n} \\
          b_{2,1} & b_{2,2} & \cdots & b_{2,n} \\
          \vdots  & \vdots  & \ddots & \vdots \\
          b_{m,1} & b_{m,2} & \cdots & b_{m,n}
        \end{bmatrix}^{\top}
\\
   &= \mathbf{A}^{\top} + \mathbf{B}^{\top}
\end{aligned}

 行列の和の転置行列は、それぞれの転置行列の和と一致します。

 転置行列の和を計算します。

# 行列の和を計算
C = A + B
print(C)
print(C.shape)

# 行列の和を計算
Ct = A.T + B.T
print(Ct)
print(Ct.shape)

# 値を比較
print(C.T == Ct)
[[1. 6.]
 [9. 3.]
 [3. 5.]]
(3, 2)
[[1. 9. 3.]
 [6. 3. 5.]]
(2, 3)
[[ True  True  True]
 [ True  True  True]]

 「行列の和の転置行列」と「転置行列の和の行列」が一致するのを確認できます。

 この記事では、行列同士の和を確認しました。次の記事では、行列とスカラーの積を確認します。

参考書籍

  • Stephen Boyd・Lieven Vandenberghe(著),玉木 徹(訳)『スタンフォード ベクトル・行列からはじめる最適化数学』講談社サイエンティク,2021年.

おわりに

 正直このレベルの内容を書くのはもういいかなと思いました。ただ今後、行列の公式を導出していくのなら、ここから始めるのもいいかなと思ったり思わなかったりもします。次の記事もそんな感じです。

 この曲を聴きたい気分です。

 今日はエビ中の春ツアーの千秋楽でした。私は観れていませんが。ライブに行きたーい。

【次の内容】

www.anarchive-beta.com