技術をかじる猫

適当に気になった技術や言語、思ったこと考えた事など。

ニューラルネットの形状に関して

エポックとバッチ

1エポック = 全データを 1 回学習すること。
教師データのセット単位を 1 バッチ。

1 エポック = 複数バッチ

バッチ学習

バッチサイズ = エポックサイズ の学習のこと。
学習が安定してて高速ではあるが、局所解にハマりやすい。

オンライン学習

バッチサイズが 1 となる。
個々のデータに振り回されるので、バーストには弱いが、局所解にとらわれにくい。

ミニバッチ学習

訓練データを複数のバッチに分割して、バッチ単位で重みとバイアスの学習を行う。
局所解に囚われにくいし、個々のデータで振れ幅もさほどではない。

1000 の教師データがあるとき、

  • バッチ学習「1000で1回重みとバイアス計算を行う」
  • オンライン学習「1エポック当たり 1000 回学習するよ」
  • ミニバッチ学習「1バッチ 50で設定したら、20 回学習するよ」

行列での演算

バッチサイズを 8 入力数(入力層のニューロン数) 3 とすると、入力を表す行列サイズは 8x3。
バッチサイズが 1 の時、1x3 になるので、ベクトルの様な形状になる。

試しに 4x3 (バッチサイズ 2)の思考実験をすると

import numpy as np


X = np.array([
    [1, 2, 3, 4],
    [4, 5, 6, 7]
])

W = np.array([
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
    [10, 11, 12]
])

X.dot(W)
array([[ 70,  80,  90],
       [136, 158, 180]])

もう少し汎用的に考えると バッチサイズ  h 、入力層  m ニューロン n の行列はこんな感じか


XW = \left(
        \begin{array}{xxxx}
            x_{11} & x_{12} & ... & x_{1m} \\
            x_{21} & x_{22} & ... & x_{2m} \\
            ...    & ...    & ... & ... \\
            x_{h1} & x_{h2} & ... & x_{hm}
        \end{array}
    \right)
    \left(
        \begin{array}{xxxx}
            w_{11} & w_{12} & ... & w_{1n} \\
            w_{21} & w_{22} & ... & w_{2n} \\
            ...    & ...    & ... & ... \\
            w_{m1} & w_{m2} & ... & w_{mn}
        \end{array}
    \right)

うげ…でも数式書いてみると理解できる。
この時、座標 1,1 の結果は


x_{11}w_{11} + x_{12}w_{21} + ... + x_{1m}w_{m1}  \\
= \sum^m_{k=1} x_{1k}w_{k1}

となるので、同様に考えて


XY = \left(
        \begin{array}{xxxx}
            \sum^m_{k=1} x_{1k}w_{k1} & \sum^m_{k=1} x_{1k}w_{k2} & ... & \sum^m_{k=1} x_{1k}w_{kn} \\
            \sum^m_{k=1} x_{2k}w_{k1} & \sum^m_{k=1} x_{2k}w_{k2} & ... & \sum^m_{k=1} x_{2k}w_{kn} \\
            ...    & ...    & ... & ... \\
            \sum^m_{k=1} x_{hk}w_{k1} & \sum^m_{k=1} x_{hk}w_{k2} & ... & \sum^m_{k=1} x_{hk}w_{kn}
        \end{array}
    \right)

で、バイアスはニューロン毎に定義されるので数は ニューロン数と同数の  n


XY+B = \left(
        \begin{array}{xxxx}
            \sum^m_{k=1} x_{1k}w_{k1} + b_1 & \sum^m_{k=1} x_{1k}w_{k2} + b_2 & ... & \sum^m_{k=1} x_{1k}w_{kn} + b_n \\
            \sum^m_{k=1} x_{2k}w_{k1} + b_1 & \sum^m_{k=1} x_{2k}w_{k2} + b_2 & ... & \sum^m_{k=1} x_{2k}w_{kn} + b_n \\
            ...    & ...    & ... & ... \\
            \sum^m_{k=1} x_{hk}w_{k1} + b_1 & \sum^m_{k=1} x_{hk}w_{k2} + b_2 & ... & \sum^m_{k=1} x_{hk}w_{kn} + b_n
        \end{array}
    \right) = U

ここに活性関数  f(x) を適用すると結果 Y は  Y = f(U)

コード的に関係性を書くと

## 値は適当だけど、実装的にはこな感じ

X = np.array([
    [1, 2, 3, 4],
    [4, 5, 6, 7]
])

W = np.array([
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
    [10, 11, 12]
])

B = np.array([ 1, 2, 3 ])

U = X.dot(W) + B

print(U)

def sigmoid(u):
    return 1 / (1 + np.exp(-u))

sigmoid(U)

さて、ネタは揃った、いや、揃っちゃった(汗
後はこの値に最終層(恒等関数 or ソフトマックス関数)+誤差関数 を含んだ状態で微分して、勾配降下法で W, B の値を更新すればニューラルネットワークの学習ができるはず。

次回は微分地獄かー(汗