PyTorch深層学習⑩ニューラルネットワーク
前回は、ロジスティック回帰の実装を行いました。その以前には線形回帰モデルを取り扱いました。
これらのモデルはニューラルネットワークの枠組みから理解することができます。
今回の記事では、線形回帰やロジスティック回帰を再訪し、ニューラルネットワークを包括的な枠組みとして解説します。
では、さっそく始めましょう。
線形回帰
まずは、ー変数だけの単純な線形回帰を考えます。
$$
\hat{y} = w\,x + b
$$
入力値$${x}$$に対して、予測値$${\hat{y}}$$を出力しています。$${w}$$は重み、$${b}$$はバイアスです。
これを以下のような図にすることができます。

青色の丸をノードと呼びます。計算を行うノードはニューロンと呼ばれます。
ノードが一つしかないのに、入力層、出力層と大袈裟に聞こえますが、処理の流れとして並列に行われる部分を層として縦割りに考えます。
といっても単純すぎて逆にイメージが湧かないかもしれません。
入力が3で、出力が4だったらどうでしょうか。

これも線形回帰です。層のイメージが湧きましたでしょうか。
ロジスティック回帰
今度は、二変数のロジスティック回帰を考えます。
$$
\hat{p} = \sigma(W\, \boldsymbol{x} + b) = \sigma(w_1 x_1 + w_2 x_2 + b)
$$
入力値$${\boldsymbol{x} = (x_1, x_2)}$$に対して、確率の予測値$${\hat{p}}$$を返します。$${\sigma}$$はシグモイド関数です。$${W}$$は重み、$${b}$$はバイアスです。
$$
\boldsymbol{x} = \begin{bmatrix}
x_1 \\
x_2
\end{bmatrix}
$$
$$
W = \begin{bmatrix}
x_1 \\
x_2
\end{bmatrix}
$$
これを図にすると以下になります。

線形回帰とロジスティック回帰では、活性化関数があるかないかの違いがありますが、同じような図にすることができました。
ニューラルネットワーク
これまでは入力層と出力層だけのモデルを考察しました。次に、さらに層を加えることでより複雑な計算を行うことを考えます。

入力層と出力層はモデルの外部との接触がありますが、それ以外の中間層はモデル内部にとどまるので、これを隠れ層と呼びます。
隠れ層によってより複雑な計算が可能となります。また、隠れ層は、受け取ったデータから特徴量を抽出して次の層へ渡すので、階層的な構造を見つけるのに役立ちます。
例えば、画像分類などの初期の層では線や点などの特徴を取り出し、段々とより高度で抽象的な特徴(例えば、目、鼻、口など)を抽出していきます。
このアプローチを使うと、隠れ層の数や隠れ層内部のノードの数などを調節することでたくさんのバリエーションが考えられます。また、隠れ層では単純な線形層だけでなく、畳み込み層やリカレント層など目的によって異なる仕組みを導入することもできます。
こういった一般的な枠組みによって構成されたモデルを人工ニューラルネットワークあるいは単にニューラルネットワークと呼びます。また、ニューラルネットワークを日本語にすると神経回路網になります。
「人工」と付ける場合は、生物学的なニューラルネットワークと対比するためです。
具体例として、隠れ層が1つのニューラルネットワークを考えます。

いきなり複雑さが増したように見えますが、そんなことはありません。単に層を一つ加えただけです。順を追って解説します。
まず、入力層は入力データそのものです。
$$
\boldsymbol{x} = \begin{bmatrix}
x_1 \\
x_2
\end{bmatrix}
$$
この隠れ層には、二つのノードあります。これは出力層のノードと同様に計算を行うものです。これらの計算ノードをニューロンと呼びます。
各ノードに対して重みとバイアスが存在します。入力値が2つなので、重みは各ノードごとに2つ必要です。式にまとめると次のようになります。
$$
\begin{aligned}
h^{(1)}_1 &= a^{(1)}(w^{(1)}_{11}\, x_1 + w^{(1)}_{12}\, x_2 + b^{(1)}_1) \\
h^{(1)}_2 &= a^{(1)}(w^{(1)}_{21}\, x_1 + w^{(1)}_{22}\, x_2 + b^{(1)}_2)
\end{aligned}
$$
$${(1)}$$と付いているのは、入力層後の第一番目の層だからです。$${h^{(1)}_1}$$はこの層の中の一番めのノードからの計算値を意味します。また、$${h^{(1)}_2}$$は2番目のノードからの計算値です。
$${a^{(1)}}$$は活性化関数です。活性化関数は層ごとに共通なものを通常は使います。
一つの隠れ層ノードに注目して、層番号やノード番号を取り除くと、次のようになります。
$$
h = a(w_{1}\, x_1 + w_{2}\, x_2 + b)
$$
もし、活性化関数$${a}$$がシグモイド関数であれば、ロジスティック回帰と同様の計算をしていることになります。
よって、上述のニューラルネットワークの一部は我々がすでに学んだモデルと同じ計算をしていることになります。逆にいうと、線形回帰もロジスティック回帰もニューラルネットワークの一種として考えることができます。
しかし、そう捉えることで何が嬉しいのでしょうか。
ニューラルネットワークという枠組みで考えられるモデルは、誤差逆伝播や勾配降下法という手法を使って訓練することができます。以前にも解説しましたが、損失関数を計算し、誤差逆伝播で勾配を得てパラメータの更新を行います。こういった手法はニューラルネットワークであれば共通に適用できます。

つまり、これまで実践してきた線形回帰やロジスティック回帰の学習手法をもっと複雑なニューラルネットワークに活用できることが、モデルをニューラルネットワークとして扱う利点となります。
モデル自体はさまざまな工夫や複雑性を織り込むことができますが、訓練のやり方には似たようなアプローチが使えるというわけです。
活性化関数の必要性
単純な線形回帰やロジスティック回帰のモデルでは隠れ層がありません。なぜならこれらのモデルが扱う問題は基本的に線形の関数で解決できるからです。
以前に扱った二変数のロジスティック回帰の問題を思い出してください。$${x_1}$$と$${x_2}$$の値からクラスを二つに分ける問題でした。

ロジスティック回帰は線形層を使って次のような線形の境界を探しています。線形層のパラメータを調節することで最適な境界を見つけます。

この境界線上の点はどちらのクラスに対しても50%の確率が予測されます。例えば、境界線より上へ離れるほど青のクラスの確率が高く予測されます。
しかし、境界線がもっと複雑なものだとしたらどうでしょうか。線形では境界線に対する良い近似を見つけることができません。

このような問題では隠れ層における活性化関数(非線形性)が役に立ちます。実は、隠れ層には必ず活性化関数が必要です。その理由はこちらの記事で解説しました。
次回予告
次回は、PyTorchを使ってニューラルネットワークを構築します。MNISTの手書きの数字データセットを使って画像分類を行います。
お楽しみに!
