4.3. 多次元配列の計算

行列のおはなし。

4.3.1. ニューラルネットワークのための行列の積

入力 \(x_1, x_2\)\(X\)、重み \(w_1, w_2, w_3 ... w_6\)\(W\) とすると、その出力結果 \(Y\) はどうなるのか…?というプログラムを書く。

[1]:
import numpy as np

X = np.array([1, 2])                 # 1 x 2の行列
print( f'X.shape = {X.shape}')

W = np.array([[1, 3, 5], [2, 4, 6]]) # 2 x 3の行列
print( f'W = {W}')
print( f'W.shape = {W.shape}')

Y = np.dot(X, W)                    # 1 x 3 の行列
print( f'Y = {Y}')
print( f'Y.shape = {Y.shape}')
X.shape = (2,)
W = [[1 3 5]
 [2 4 6]]
W.shape = (2, 3)
Y = [ 5 11 17]
Y.shape = (3,)

4.3.2. 🤔コピペしたけどよくわからぬ

一旦式にしてみよう。

入力は2つ、数列は\(x_1, x_2\)

出力結果\(Y\)は…今回は2つの入力から、3つの出力を得るので

\[Y = y_1, y_2, y_3\]

重み\(W\)は…2つの入力に対して出力を3つにしたいので…重みは \(2 \times 3 = 6\) 個必要だ。

\[w_1, w_2, w_3, w_4, w_5, w_6\]

出力結果\(Y\)を得るための計算は

\[y_1 = x_1 w_1 + x_2 w_2\]
\[y_2 = x_1 w_3 + x_2 w_4\]
\[y_3 = x_1 w_5 + x_2 w_6\]

つまり、

\[\begin{split}Y = y_1, y_2, y_3 \\ = (x_1 w_1 + x_2 w_2), (x_1 w_3 + x_2 w_4), (x_1 w_5 + x_2 w_6)\end{split}\]

うお、見難いな!…しかしなんとなく行列の積になりそうになってきた。

仮に、\(Y' = \begin{bmatrix} y_1 & y_2 & y_3 \end{bmatrix}\)とすると

\[\begin{split}Y' = \begin{bmatrix} x_1 w_1 + x_2 w_2 & x_1 w_3 + x_2 w_4 & x_1 w_5 + x_2 w_6 \end{bmatrix}\\ = \begin{bmatrix} x_1 & x_2 \end{bmatrix} \begin{bmatrix} w_1 & w_3 & w_4 \\ w_2 & w_5 & w_6 \end{bmatrix}\end{split}\]

それっぽくなってきた。

\(\begin{bmatrix} x_1 & x_2 \end{bmatrix}\)\(X\)\(\begin{bmatrix} w_1 & w_3 & w_4 \\ w_2 & w_5 & w_6 \end{bmatrix}\)\(W\)として、置き換えると

\[Y' = X \times W\]

つまり、ニューラルネットワークの計算は、行列に置き換えると計算しやすい、ということ。おー、納得した!