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\]
つまり、ニューラルネットワークの計算は、行列に置き換えると計算しやすい、ということ。おー、納得した!