複数データの同時入力

複数データの同時入力

 

複数データの同時入力

重みパラメータ $W$ を最適化するためには、たくさんのデータ $\boldsymbol{x}$ を入力し、ネットワークから出力値を得て、実測値との差分から損失関数を計算する必要があります。前回記事 で定義した layer()関数は1度に1個のデータしか渡せなかったので、複数データをまとめて入力 できるように layer() を改良してみましょう。
 
ミニサイズのニューラルネットワーク(Artificial Neural Network) 改訂版
前回記事で扱ったように、上図の $b$ 層への入力総和は
 \[\boldsymbol{u}=W \boldsymbol{x}=\begin{bmatrix}w_{00} & w_{01} & w_{02}\\
w_{10} & w_{11} & w_{12}\end{bmatrix}\begin{bmatrix}x_0\\x_1\\x_2\end{bmatrix}\]
で表されます。$x_2$ は常に $1$ の値をとるダミー入力です。行列の演算規則から、$w_{02}$ と $w_{12}$ はバイアスにかかる重みとなります。ネットワークに $3$ 個のデータ
 \[\boldsymbol{x_0}=\begin{bmatrix}x_{00}\\x_{10}\\x_{20}\end{bmatrix},\quad
\boldsymbol{x_1}=\begin{bmatrix}x_{01}\\x_{11}\\x_{21}\end{bmatrix},\quad
\boldsymbol{x_2}=\begin{bmatrix}x_{02}\\x_{12}\\x_{22}\end{bmatrix}\]
をまとめて入力することを考えます。$\boldsymbol{x_0},\ \boldsymbol{x_1},\ \boldsymbol{x_2}$ を横に並べた行列
 \[X=[\boldsymbol{x_0}\ \boldsymbol{x_1}\ \boldsymbol{x_2}]=\begin{bmatrix}
x_{00} & x_{01} & x_{02}\\ x_{10} & x_{11} & x_{12}\\x_{20} & x_{21} & x_{22}\end{bmatrix}\]
を定義すると、行列演算の性質から、それぞれのデータに対応する入力総和は $U=WX$ で計算することができます(行列はベクトルを並べたもの考えることができます)。
 \[U=\begin{bmatrix}u_{00} & u_{01} & u_{02}\\u_{10} & u_{11} & u_{12}\end{bmatrix}
=\begin{bmatrix}w_{00} & w_{01} & w_{02}\\ w_{10} & w_{11} & w_{12}\end{bmatrix}
\begin{bmatrix}x_{00} & x_{01} & x_{02}\\ x_{10} & x_{11} & x_{12}\\x_{20} & x_{21} & x_{22}\end{bmatrix}\]
行列 $U$ の縦に並んだ成分(入力総和ベクトル)は、行列 $X$ の縦に並んだ成分(入力ベクトル)に対応しています(下図参照)。
 
Python 入力行列(input matrix)と入力総和行列(input sum matrix)対応図
ちなみに当サイトではベクトルや行列の成分を 0 番から数えていますが、これは NumPy の配列インデックスに対応させるためです。

それでは、layer()関数を再定義してみましょう。下図にあるように、2次元配列の中に入力ベクトル (1次元配列) を縦積みして、入力総和ベクトルと出力ベクトルも同じ形式で揃えるようにします。
 
Python データの表示形式を揃える
$U=WX$ を転置すると、
 \[U^T=(WX)^T=X^TW^T\]
となるので、実装するときは
 \[U^T=\begin{bmatrix}x_{00} & x_{10} & x_{20}\\ x_{01} & x_{11} & x_{21}\\x_{02} & x_{12} & x_{22}\end{bmatrix}
\begin{bmatrix}w_{00} & w_{10}\\ w_{01} & w_{11}\\w_{02} & w_{12}\end{bmatrix}\]
の形でデータを処理します。

# Multi_Input

# In[1]

import numpy as np

# 恒等関数
def identity(x):
    return x

# シグモイド関数
def sigmoid(x):
    f = 1 / (1 + np.exp(-x))
    return f

# ニューラルネットワークの層
def layer(xm, wm, func = identity):
    if xm.ndim == 1:
        xm = np.append(xm, 1)
    else:
        dummy = np.ones((xm.shape[0], 1))  # ダミー信号
        xm = np.append(xm, dummy, axis=1)  # 入力信号にダミー信号を追加
    u = np.dot(xm, wm.T)  # 入力総和を計算

    if u.ndim == 0:
        return np.array([[func(u)]])
    elif u.ndim == 1:
        return np.array([func(u)])
    else:
        return func(u)

シグモイド関数 を組込んだ層の出力を確認しておきます。

# In[2]

# [.1 .2],[.3 .4],[.5 .6]を同時入力
X = np.array([[.1, .2],
              [.3, .4],
              [.5, .6]])

# 重み行列を設定
W = np.array([[0.5, -1.0,  1.5],
              [2.0,  3.0, -1.5]])

# Xを入力して出力を得る
Y = layer(X, W, sigmoid)
Y = np.round(Y, 3)

print(Y)
# [[0.794 0.332]
#  [0.777 0.574]
#  [0.76  0.786]]