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

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

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プログラムで書いた例を以下に示します.

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

# ①
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([[2.04632076, 1.90246234, 1.04284503, 1.32719069],
       [1.68349874, 1.53580454, 0.75367564, 0.94673303]])

12.5.2. ②,①から入力層のニューロンを回す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([[2.04632076, 1.90246234, 1.04284503, 1.32719069],
       [1.68349874, 1.53580454, 0.75367564, 0.94673303]])

12.5.3. ③,②から隠れ層のニューロンを回す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([[2.04632076, 1.90246234, 1.04284503, 1.32719069],
       [1.68349874, 1.53580454, 0.75367564, 0.94673303]])

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

output = X @ W0 + b0
output
array([[2.04632076, 1.90246234, 1.04284503, 1.32719069],
       [1.68349874, 1.53580454, 0.75367564, 0.94673303]])