行列計算で全結合層の計算が実装できる?#

スカラー同士の計算から徐々に行列を使った実装に直していくので,それぞれのコードを見比べて,最終的なコードのお気持ちを理解してください.

import numpy as np 
import matplotlib.pyplot as plt 
from IPython.display import display, Markdown

ハイパーパラメータを定義しておきましょう.

M = 2 # batch_size 
F = 3 # n_features
K = 4 # n_hidden_layer_units
C = 5 #  n_classes

パラメータも初期化しておきます.全て標準正規分布に従う事にします.(初期化の方法は適当です)

X = np.random.random([M,F])
W0 = np.random.random([F,K])
b0 = np.random.random([K,])

ニューラルネットワークの全結合層をPythonプログラムで書いた例を以下に示します.

①,スカラーの四則演算だけで実装する場合#

# ①
output = np.zeros([M,K]) #答えの初期化
for m in range(M):
    for k in range(K):
        xh = np.zeros(F)
        for f in range(F):
            xh[f] = X[m,f] * W0[f,k]
        output[m,k] = xh.sum() + b0[k]
output
array([[0.74817163, 0.83682236, 2.01578713, 0.67566289],
       [1.20714837, 1.3665895 , 2.20171706, 0.93252512]])

②,①から入力層のニューロンを回すfor文を消して,ベクトル同士の内積で置き換えた場合”#

# ②
output = np.zeros([M,K]) #答えの初期化
for m in range(M):
    for k in range(K):
        xh = X[m] @ W0[:,k] # (F)@(F,1)->(,)
        output[m,k] = xh + b0[k]
output
array([[0.74817163, 0.83682236, 2.01578713, 0.67566289],
       [1.20714837, 1.3665895 , 2.20171706, 0.93252512]])

③,②から隠れ層のニューロンを回すfor文を消して,データベクトルと重み行列の内積で置き換えた場合#

# ③
output = np.zeros([M,K]) #答えの初期化
for m in range(M):
    xh = X[m] @ W0 # (F)@(F,K)->(K)
    output[m] = xh + b0 # (K)+(K)->(K)
output
array([[0.74817163, 0.83682236, 2.01578713, 0.67566289],
       [1.20714837, 1.3665895 , 2.20171706, 0.93252512]])

④,③からミニバッチを回すfor文を消して,ミニバッチ行列と重み行列の内積で置き換えた場合#

output = X @ W0 + b0
output
array([[0.74817163, 0.83682236, 2.01578713, 0.67566289],
       [1.20714837, 1.3665895 , 2.20171706, 0.93252512]])