からっぽのしょこ

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

6.3.a:行列とスカラーの和の計算【『スタンフォード線形代数入門』のノート】

はじめに

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

 この記事は6.3節を補足する内容です。
 行列とスカラーの和に関して数式での表現を確認します。また、NumPyライブラリでの扱い方を確認します。

【前の内容】

www.anarchive-beta.com

【他の内容】

www.anarchive-beta.com

【今回の内容】

6.3.a 行列とスカラーの和の計算

 行列とスカラーに関する和の計算を数式とプログラム(NumPyライブラリ)で確認します。
 行列同士の和については「行列の和の性質の導出」、行列とスカラーの積については「行列のスカラー倍の性質の導出」を参照してください。

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

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


行列とスカラーの和の計算

 同じ形状の行列の和  \mathbf{A} + \mathbf{B} や、行列とスカラーの積  \gamma \mathbf{A} は計算できました(6.3.2-3項)。しかし、行列とスカラーの和  \mathbf{A} + \gamma は定義されません。
 行列とスカラーに関する和の計算を確認していきます。

行列との和

  m \times n 行列  \mathbf{A} の各要素  a_{i,j}\ (i = 1, 2, \dots, m,\ j = 1, 2, \dots, n) とスカラー  \gamma の和を考えます。

 全ての要素が  1 m \times n 行列(  \mathbf{A} と同じ形状の行列)をイチ行列

 \displaystyle
\mathbf{1}_{m \times n}
    = \underbrace{
          \begin{bmatrix}
              1 & 1 & \cdots & 1 \\
              1 & 1 & \cdots & 1 \\
              \vdots & \vdots & \ddots & \vdots \\
              1 & 1 & \cdots & 1
          \end{bmatrix}
      }_{m \times n}

として、この行列のスカラー倍との和を求めます。

 \displaystyle
\begin{aligned}
\mathbf{B}
   &= \mathbf{A}
      + \gamma
        \mathbf{1}_{m \times n}
\\
   &= \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}
      + \gamma
        \underbrace{
          \begin{bmatrix}
              1 & 1 & \cdots & 1 \\
              1 & 1 & \cdots & 1 \\
              \vdots & \vdots & \ddots & \vdots \\
              1 & 1 & \cdots & 1
          \end{bmatrix}
        }_{m \times n}
\\
   &= \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}
      + \underbrace{
          \begin{bmatrix}
              \gamma & \gamma & \cdots & \gamma \\
              \gamma & \gamma & \cdots & \gamma \\
              \vdots & \vdots & \ddots & \vdots \\
              \gamma & \gamma & \cdots & \gamma
          \end{bmatrix}
        }_{m \times n}
\\
   &= \begin{bmatrix}
          a_{1,1} + \gamma & a_{1,2} + \gamma & \cdots & a_{1,n} + \gamma \\
          a_{2,1} + \gamma & a_{2,2} + \gamma & \cdots & a_{2,n} + \gamma \\
          \vdots & \vdots & \ddots & \vdots \\
          a_{m,1} + \gamma & a_{m,2} + \gamma & \cdots & a_{m,n} + \gamma
      \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}
\end{aligned}

  \gamma, \mathbf{1} の積が、全ての要素が  \gamma の行列になるのを利用して計算します。行列の和の計算なので、 \mathbf{A}, \mathbf{1}_{m \times n} の形状が一致している必要があります。
 計算結果の行列  \mathbf{B} の各要素は、 \mathbf{A} の各要素とスカラーの和  b_{i,j} = a_{i,j} + \gamma になります。

 スカラと行列を指定して、1行列を作成して、行列の各要素とスカラの和を計算します。

# スカラを指定
gamma = 1.5

# 行列(2次元配列)を指定
A = np.array(
    [[0.0, 4.0], 
     [7.0, 0.0], 
     [3.0, 1.0]]
)
print(A)
print(A.shape)

# 1行列を作成
C = np.ones_like(A)
print(C)
print(C.shape)

# 行列の各要素とスカラの和を計算
B = A + gamma * C
print(B)
print(B.shape)
[[0. 4.]
 [7. 0.]
 [3. 1.]]
(3, 2)
[[1. 1.]
 [1. 1.]
 [1. 1.]]
(3, 2)
[[1.5 5.5]
 [8.5 1.5]
 [4.5 2.5]]
(3, 2)

 A と同じ形状の1行列を np.ones_like() で作成します。

 NumPyでは、ブロードキャストにより計算できます。

# 行列の各要素とスカラの和を計算
D = A + gamma
print(D)
print(D.shape)

# 値を比較
print(B == D)
[[1.5 5.5]
 [8.5 1.5]
 [4.5 2.5]]
(3, 2)
[[ True  True]
 [ True  True]
 [ True  True]]

 + 演算子による配列とスカラの計算は、配列の各要素に対して行われます。

列との和

  m \times n 行列  \mathbf{A} j 列目の各要素  a_{i,j}\ (j = 1, 2, \dots, n) とスカラー  \gamma の和を考えます。

 全ての要素が  1 m 次元ベクトル(  \mathbf{A} の行数と同じ次元のベクトル)をイチベクトル

 \displaystyle
\mathbf{1}_{m \times 1}
    = \underbrace{
          \begin{bmatrix}
              1 \\ 1 \\ \vdots \\ 1
          \end{bmatrix}
      }_{m \times 1}

とし、また、 j 番目の要素が  1 で他の要素が  0 n 次元ベクトル(  \mathbf{A} の列数と同じ次元のベクトル)を標準単位ベクトル

 \displaystyle
\mathbf{e}_{n \times 1}^{(j)}
    = \begin{bmatrix}
          e_1^{(j)} \\ e_2^{(j)} \\ \vdots \\ e_j^{(j)} \\ \vdots \\ e_n^{(j)}
      \end{bmatrix}
    = \underbrace{
          \begin{bmatrix}
              0 \\ 0 \\ \vdots \\ 1 \\ \vdots \\ 0
          \end{bmatrix}
      }_{n \times 1}

とします。
 この2つのベクトルの積は、 j 列目の要素が  1 で他の列の要素が  0 m \times n 行列

 \displaystyle
\begin{aligned}
\mathbf{1}_{m \times 1} (\mathbf{e}_{n \times 1}^{(j)})^{\top}
   &= \underbrace{
          \begin{bmatrix}
              1 \\ 1 \\ \vdots \\ 1
          \end{bmatrix}
      }_{m \times 1}
      \underbrace{
          \begin{bmatrix}
              e_1^{(j)} & e_2^{(j)} & \cdots & e_j^{(j)} & \cdots & e_n^{(j)}
          \end{bmatrix}
      }_{1 \times n}
\\
   &= \underbrace{
          \begin{bmatrix}
              e_1^{(j)} & e_2^{(j)} & \cdots & e_j^{(j)} & \cdots & e_n^{(j)} \\
              e_1^{(j)} & e_2^{(j)} & \cdots & e_j^{(j)} & \cdots & e_n^{(j)} \\
              \vdots & \vdots & \ddots & \vdots & \ddots & \vdots \\
              e_1^{(j)} & e_2^{(j)} & \cdots & e_j^{(j)} & \cdots & e_n^{(j)}
          \end{bmatrix}
      }_{m \times n}
\\
   &= \underbrace{
          \begin{bmatrix}
              0 & 0 & \cdots & 1 & \cdots & 0 \\
              0 & 0 & \cdots & 1 & \cdots & 0 \\
              \vdots & \vdots & \ddots & \vdots & \ddots & \vdots \\
              0 & 0 & \cdots & 1 & \cdots & 0
          \end{bmatrix}
      }_{m \times n}
\end{aligned}

になります。
 この行列のスカラー倍との和を求めます。

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

  \gamma, \mathbf{1} \mathbf{e}_j^{\top} の積が、 j 列目の全て要素が  \gamma の行列になるのを利用して計算します。行列の和の計算なので、 \mathbf{A}, \mathbf{1}_{m \times 1} (\mathbf{e}_{n \times 1}^{(j)})^{\top} の形状が一致している必要があります。
 計算結果の行列  \mathbf{B} j 列目の要素は、 \mathbf{A} の各要素とスカラーの和  b_{i,j} = a_{i,j} + \gamma になります。また、 j 列目以外の要素は、 \mathbf{A} の各要素  b_{i,k} = a_{i,k}\ (k \neq j) になります。

 1ベクトルと標準単位ベクトルを作成して、行列の列とスカラの和を計算します。

# 列インデックスを指定
j = 1

# 行・列数を取得
m, n = A.shape

# 1ベクトルを作成
c = np.ones((m, 1))
print(c)
print(c.shape)

# 標準単位ベクトルを作成
e_j = np.zeros((n, 1))
e_j[j] = 1.0
print(e_j)
print(e_j.shape)

# 行列のj列とスカラの和を計算
B = A + gamma * np.dot(c, e_j.T)
print(B)
print(B.shape)
[[1.]
 [1.]
 [1.]]
(3, 1)
[[0.]
 [1.]]
(2, 1)
[[0.  5.5]
 [7.  1.5]
 [3.  2.5]]
(3, 2)

 np.ones() で1ベクトルを作成します。
 np.zeros() で0ベクトルを作成して、j 番目の要素を 1 にして、標準単位ベクトルを作成します。
 それぞれ転置できるように、縦ベクトル(2次元配列)にしておきます。

 NumPyでは、標準単位ベクトルを用いて、ブロードキャストにより計算できます。

# 標準単位ベクトルを作成
e_j = np.zeros(A.shape[1])
e_j[j] = 1.0
print(e_j)
print(e_j.shape)

# 行列のj列とスカラの和を計算
D = A + gamma * e_j
print(D)
print(D.shape)

# 値を比較
print(B == D)
[0. 1.]
(2,)
[[0.  5.5]
 [7.  1.5]
 [3.  2.5]]
(3, 2)
[[ True  True]
 [ True  True]
 [ True  True]]

 + 演算子による2次元配列と1次元配列の計算は、配列の各行(0軸)に対して行われます。

行との和

  m \times n 行列  \mathbf{A} i 行目の各要素  a_{i,j}\ (i = 1, 2, \dots, m) とスカラー  \gamma の和を考えます。

 全ての要素が  1 n 次元ベクトル(  \mathbf{A} の列数と同じ次元のベクトル)をイチベクトル

 \displaystyle
\mathbf{1}_{n \times 1}
    = \underbrace{
          \begin{bmatrix}
              1 \\ 1 \\ \vdots \\ 1
          \end{bmatrix}
      }_{n \times 1}

とし、また、 i 番目の要素が  1 で他の要素が  0 m 次元ベクトル(  \mathbf{A} の行数と同じ次元のベクトル)を標準単位ベクトル

 \displaystyle
\mathbf{e}_{m \times 1}^{(i)}
    = \begin{bmatrix}
          e_1^{(i)} \\ e_2^{(i)} \\ \vdots \\ e_i^{(i)} \\ \vdots \\ e_m^{(i)}
      \end{bmatrix}
    = \underbrace{
          \begin{bmatrix}
              0 \\ 0 \\ \vdots \\ 1 \\ \vdots \\ 0
          \end{bmatrix}
      }_{m \times 1}

とします。
 この2つのベクトルの積は、 i 行目の要素が  1 で他の列の要素が  0 m \times n 行列

 \displaystyle
\begin{aligned}
\mathbf{e}_{m \times 1}^{(i)} \mathbf{1}_{n \times 1}^{\top}
   &= \underbrace{
          \begin{bmatrix}
              e_1^{(i)} \\ e_2^{(i)} \\ \vdots \\ e_i^{(i)} \\ \vdots \\ e_m^{(i)}
          \end{bmatrix}
      }_{m \times 1}
      \underbrace{
          \begin{bmatrix}
              1 & 1 & \cdots & 1
          \end{bmatrix}
      }_{1 \times n}
\\
   &= \underbrace{
          \begin{bmatrix}
              e_1^{(i)} & e_1^{(i)} & \cdots & e_1^{(i)} \\
              e_2^{(i)} & e_2^{(i)} & \cdots & e_2^{(i)} \\
              \vdots & \vdots & \ddots & \vdots \\
              e_i^{(i)} & e_i^{(i)} & \cdots & e_i^{(i)} \\
              \vdots & \vdots & \ddots & \vdots \\
              e_m^{(i)} & e_m^{(i)} & \cdots & e_m^{(i)}
          \end{bmatrix}
      }_{m \times n}
\\
   &= \underbrace{
          \begin{bmatrix}
              0 & 0 & \cdots & 0 \\
              0 & 0 & \cdots & 0 \\
              \vdots & \vdots & \ddots & \vdots \\
              1 & 1 & \cdots & 1 \\
              \vdots & \vdots & \ddots & \vdots \\
              0 & 0 & \cdots & 0
          \end{bmatrix}
      }_{m \times n}
\end{aligned}

になります。
 この行列のスカラー倍との和を求めます。

 \displaystyle
\begin{aligned}
\mathbf{B}
   &= \mathbf{A}
      + \gamma
        \mathbf{e}_{m \times 1}^{(i)} \mathbf{1}_{n \times 1}^{\top}
\\
   &= \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_{i,1} & a_{i,2} & \cdots & a_{i,n} \\
          \vdots  & \vdots  & \ddots & \vdots \\
          a_{m,1} & a_{m,2} & \cdots & a_{m,n}
      \end{bmatrix}
      + \gamma
        \underbrace{
          \begin{bmatrix}
              0 & 0 & \cdots & 0 \\
              0 & 0 & \cdots & 0 \\
              \vdots & \vdots & \ddots & \vdots \\
              1 & 1 & \cdots & 1 \\
              \vdots & \vdots & \ddots & \vdots \\
              0 & 0 & \cdots & 0
          \end{bmatrix}
      }_{m \times n}
\\
   &= \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_{i,1} & a_{i,2} & \cdots & a_{i,n} \\
          \vdots  & \vdots  & \ddots & \vdots \\
          a_{m,1} & a_{m,2} & \cdots & a_{m,n}
      \end{bmatrix}
      + \underbrace{
          \begin{bmatrix}
              0 & 0 & \cdots & 0 \\
              0 & 0 & \cdots & 0 \\
              \vdots & \vdots & \ddots & \vdots \\
              \gamma & \gamma & \cdots & \gamma \\
              \vdots & \vdots & \ddots & \vdots \\
              0 & 0 & \cdots & 0
          \end{bmatrix}
      }_{m \times n}
\\
   &= \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_{i,1} + \gamma & a_{i,2} + \gamma & \cdots & a_{i,n} + \gamma \\
          \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_{i,1} & b_{i,2} & \cdots & b_{i,n} \\
          \vdots  & \vdots  & \ddots & \vdots \\
          b_{m,1} & b_{m,2} & \cdots & b_{m,n}
      \end{bmatrix}
\end{aligned}

  \gamma, \mathbf{e}_i \mathbf{1}^{\top} の積が、 i 行目の全て要素が  \gamma の行列になるのを利用して計算します。行列の和の計算なので、 \mathbf{A}, \mathbf{e}_{m \times 1}^{(i)} \mathbf{1}_{n \times 1}^{\top} の形状が一致している必要があります。
 計算結果の行列  \mathbf{B} i 行目の要素は、 \mathbf{A} の各要素とスカラーの和  b_{i,j} = a_{i,j} + \gamma になります。また、 i 行目以外の要素は、 \mathbf{A} の各要素  b_{k,j} = a_{k,j}\ (k \neq i) になります。

 1ベクトルと標準単位ベクトルを作成して、行列の行とスカラの和を計算します。

# 行インデックスを指定
i = 1

# 行・列数を取得
m, n = A.shape

# 1ベクトルを作成
c = np.ones((n, 1))
print(c)
print(c.shape)

# 標準単位ベクトルを作成
e_i = np.zeros((m, 1))
e_i[i] = 1.0
print(e_i)
print(e_i.shape)

# 行列のi行とスカラの和を計算
B = A + gamma * np.dot(e_i, c.T)
print(B)
print(B.shape)
[[1.]
 [1.]]
(2, 1)
[[0.]
 [1.]
 [0.]]
(3, 1)
[[0.  4. ]
 [8.5 1.5]
 [3.  1. ]]
(3, 2)

 「列との和」のときと同様にして計算します。

 NumPyでは、標準単位ベクトルを用いて、ブロードキャストにより計算できます。

# 行列のi行とスカラの和を計算
D = A + gamma * e_i
print(D)
print(D.shape)

# 値を比較
print(B == D)
[[0.  4. ]
 [8.5 1.5]
 [3.  1. ]]
(3, 2)
[[ True  True]
 [ True  True]
 [ True  True]]

 + 演算子による2次元配列と1列の2次元配列の計算は、配列の各列(1軸)に対して行われます。

要素との和

  m \times n 行列  \mathbf{A} i j 列目の要素  a_{i,j} とスカラー  \gamma の和を考えます。

  i 行目と  j 列目に対応する標準単位ベクトルをそれぞれ

 \displaystyle
\mathbf{e}_{m \times 1}^{(i)}
    = \begin{bmatrix}
          e_1^{(i)} \\ e_2^{(i)} \\ \vdots \\ e_i^{(i)} \\ \vdots \\ e_m^{(i)}
      \end{bmatrix}
    = \underbrace{
          \begin{bmatrix}
              0 \\ 0 \\ \vdots \\ 1 \\ \vdots \\ 0
          \end{bmatrix}
      }_{m \times 1}
,\ 
\mathbf{e}_{n \times 1}^{(j)}
    = \begin{bmatrix}
          e_1^{(j)} \\ e_2^{(j)} \\ \vdots \\ e_j^{(j)} \\ \vdots \\ e_n^{(j)}
      \end{bmatrix}
    = \underbrace{
          \begin{bmatrix}
              0 \\ 0 \\ \vdots \\ 1 \\ \vdots \\ 0
          \end{bmatrix}
      }_{n \times 1}

とします。 e_j^{(i)} = 0, e_j^{(i)} = 0 です。
 この2つのベクトルの積は、 i j 列目の要素が  1 で他の要素が  0 m \times n 行列

 \displaystyle
\begin{aligned}
\mathbf{e}_{m \times 1}^{(i)} (\mathbf{e}_{n \times 1}^{(j)})^{\top}
   &= \begin{bmatrix}
          e_1^{(i)} \\ e_2^{(i)} \\ \vdots \\ e_i^{(i)} \\ \vdots \\ e_m^{(i)}
      \end{bmatrix}
      \begin{bmatrix}
          e_1^{(j)} & e_2^{(j)} & \cdots & e_j^{(j)} & \cdots & e_n^{(j)}
      \end{bmatrix}
\\
   &= \begin{bmatrix}
          e_1^{(i)} e_1^{(j)} & e_1^{(i)} e_2^{(j)} & \cdots & e_1^{(i)} e_j^{(j)} & \cdots & e_1^{(i)} e_n^{(j)} \\
          e_2^{(i)} e_1^{(j)} & e_2^{(i)} e_2^{(j)} & \cdots & e_2^{(i)} e_j^{(j)} & \cdots & e_2^{(i)} e_n^{(j)} \\
          \vdots & \vdots & \ddots & \vdots & \ddots & \vdots \\
          e_i^{(i)} e_1^{(j)} & e_i^{(i)} e_2^{(j)} & \cdots & e_i^{(i)} e_j^{(j)} & \cdots & e_i^{(i)} e_n^{(j)} \\
          \vdots & \vdots & \ddots & \vdots & \ddots & \vdots \\
          e_m^{(i)} e_1^{(j)} & e_m^{(i)} e_2^{(j)} & \cdots & e_m^{(i)} e_j^{(j)} & \cdots & e_m^{(i)} e_n^{(j)}
      \end{bmatrix}
\\
   &= \underbrace{
          \begin{bmatrix}
              0 & 0 & \cdots & 0 & \cdots & 0 \\
              0 & 0 & \cdots & 0 & \cdots & 0 \\
              \vdots & \vdots & \ddots & \vdots & \ddots & \vdots \\
              0 & 0 & \cdots & 1 & \cdots & 0 \\
              \vdots & \vdots & \ddots & \vdots & \ddots & \vdots \\
              0 & 0 & \cdots & 0 & \cdots & 0
          \end{bmatrix}
      }_{m \times n}
\end{aligned}

になります。
 この行列のスカラー倍との和を求めます。

 \displaystyle
\begin{aligned}
\mathbf{B}
   &= \mathbf{A}
      + \gamma
        \mathbf{e}_{m \times 1}^{(i)} (\mathbf{e}_{n \times 1}^{(j)})^{\top}
\\
   &= \begin{bmatrix}
          a_{1,1} & a_{1,2} & \cdots & a_{1,j} & \cdots & a_{1,n} \\
          a_{2,1} & a_{2,2} & \cdots & a_{2,j} & \cdots & a_{2,n} \\
          \vdots  & \vdots  & \ddots & \vdots  & \ddots & \vdots \\
          a_{i,1} & a_{i,2} & \cdots & a_{i,j} & \cdots & a_{i,n} \\
          \vdots  & \vdots  & \ddots & \vdots  & \ddots & \vdots \\
          a_{m,1} & a_{m,2} & \cdots & a_{m,j} & \cdots & a_{m,n}
      \end{bmatrix}
      + \gamma
        \underbrace{
          \begin{bmatrix}
              0 & 0 & \cdots & 0 & \cdots & 0 \\
              0 & 0 & \cdots & 0 & \cdots & 0 \\
              \vdots & \vdots & \ddots & \vdots & \ddots & \vdots \\
              0 & 0 & \cdots & 1 & \cdots & 0 \\
              \vdots & \vdots & \ddots & \vdots & \ddots & \vdots \\
              0 & 0 & \cdots & 0 & \cdots & 0
          \end{bmatrix}
        }_{m \times n}
\\
   &= \begin{bmatrix}
          a_{1,1} & a_{1,2} & \cdots & a_{1,j} & \cdots & a_{1,n} \\
          a_{2,1} & a_{2,2} & \cdots & a_{2,j} & \cdots & a_{2,n} \\
          \vdots  & \vdots  & \ddots & \vdots  & \ddots & \vdots \\
          a_{i,1} & a_{i,2} & \cdots & a_{i,j} & \cdots & a_{i,n} \\
          \vdots  & \vdots  & \ddots & \vdots  & \ddots & \vdots \\
          a_{m,1} & a_{m,2} & \cdots & a_{m,j} & \cdots & a_{m,n}
      \end{bmatrix}
      + \underbrace{
          \begin{bmatrix}
              0 & 0 & \cdots & 0 & \cdots & 0 \\
              0 & 0 & \cdots & 0 & \cdots & 0 \\
              \vdots & \vdots & \ddots & \vdots & \ddots & \vdots \\
              0 & 0 & \cdots & \gamma & \cdots & 0 \\
              \vdots & \vdots & \ddots & \vdots & \ddots & \vdots \\
              0 & 0 & \cdots & 0 & \cdots & 0
          \end{bmatrix}
        }_{m \times n}
\\
   &= \begin{bmatrix}
          a_{1,1} & a_{1,2} & \cdots & a_{1,j} & \cdots & a_{1,n} \\
          a_{2,1} & a_{2,2} & \cdots & a_{2,j} & \cdots & a_{2,n} \\
          \vdots  & \vdots  & \ddots & \vdots  & \ddots & \vdots \\
          a_{i,1} & a_{i,2} & \cdots & a_{i,j} + \gamma & \cdots & a_{i,n} \\
          \vdots  & \vdots  & \ddots & \vdots  & \ddots & \vdots \\
          a_{m,1} & a_{m,2} & \cdots & a_{m,j} & \cdots & a_{m,n}
      \end{bmatrix}
\\
   &= \begin{bmatrix}
          b_{1,1} & b_{1,2} & \cdots & b_{1,j} & \cdots & b_{1,n} \\
          b_{2,1} & b_{2,2} & \cdots & b_{2,j} & \cdots & b_{2,n} \\
          \vdots  & \vdots  & \ddots & \vdots  & \ddots & \vdots \\
          b_{i,1} & b_{i,2} & \cdots & b_{i,j} & \cdots & b_{i,n} \\
          \vdots  & \vdots  & \ddots & \vdots  & \ddots & \vdots \\
          b_{m,1} & b_{m,2} & \cdots & b_{m,j} & \cdots & b_{m,n}
      \end{bmatrix}
\end{aligned}

  \gamma, \mathbf{e}_i \mathbf{e}_j^{\top} の積が、 i j 列目の要素が  \gamma の行列になるのを利用して計算します。行列の和の計算なので、 \mathbf{A}, \mathbf{e}_{m \times 1}^{(i)} (\mathbf{e}_{n \times 1}^{(j)})^{\top} の形状が一致している必要があります。
 計算結果の行列  \mathbf{B} i j 列目の要素は、 \mathbf{A} の要素とスカラーの和  b_{i,j} = a_{i,j} + \gamma になります。また、 i j 列目以外の要素は、 \mathbf{A} の各要素  b_{k,l} = a_{k,l}\ (k \neq i, l \neq j) になります。

 標準単位ベクトルを作成して、行列の要素とスカラの和を計算します。

# 行・列インデックスを指定
i = 1
j = 1

# 行・列数を取得
m, n = A.shape

# 標準単位ベクトルを作成
e_i = np.zeros((m, 1))
e_i[i] = 1.0
e_j = np.zeros((n, 1))
e_j[j] = 1.0
print(e_i)
print(e_i.shape)
print(e_j)
print(e_j.shape)

# 行列のi,j要素とスカラの和を計算
B = A + gamma * np.dot(e_i, e_j.T)
print(B)
print(B.shape)
[[0.]
 [1.]
 [0.]]
(3, 1)
[[0.]
 [1.]]
(2, 1)
[[0.  4. ]
 [7.  1.5]
 [3.  1. ]]
(3, 2)

 「列との和」と「行との和」のときと同様にして計算します。

 NumPyでは、添字により計算できます。

# 行列のi,j要素とスカラの和を計算
D = A.copy()
D[i, j] += gamma
print(D)
print(D.shape)

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

 NumPy配列の copy() メソッドで配列を複製して、インデックスを指定した要素のみを計算します。

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

参考書籍

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

おわりに

 ベクトルや行列とスカラの和は定義されず、数式上ではブロードキャストされない、なので  \mathbf{x} + \gamma のように書いてはいけない。なのに近頃は、NumPyライブラリなどでの計算(書き方)につられて、ブロードキャストを意図した式の書き方が増えている。
 ということが少し前に話題になってました。へー初めて知ったと思うと同時に、やっべこのブログでたぶん書いてるぞと焦りました。さっさと修正しないといけないのですが、その前に定義に沿った書き方を確認しておかないと直し方が分からない。ということでとりあえずやってみました。修正の方はおいおい...

 ところで、ブロードキャストするように行列とスカラの和を定義したらどうなるんでしょうか。行列とスカラの積が定義されていれば今回のように表現できるから不要なのか、なんらかの不都合が生じるんでしょうか。

 2023年7月20日は、OCHA NORMAの中山夏月姫さんの18歳のお誕生日です。

 ずっとぽわぽわしてる印象だったけど、ドッキリ企画で「辛い時は分けっこしたかった」って言っててほんまえぇ子やとなって、座右の銘も格好良くて、最近印象が変わりました。
 今年の5月に加賀温泉郷の観光大使に就任し色々とイベントも実施され始めていて、今後の活躍が楽しみです。

【次の内容】

www.anarchive-beta.com