Lesson 4
深層学習(ディープラーニング)概論
Lesson 4
Chapter 1
深層学習の基礎
深層学習とは
深層学習は、これまでの Lesson でも何度か登場してきた概念で、多層のニューラルネットワークを用いた機械学習のことですが、この Lesson 4 で詳しく説明していきます。 現在の最先端のAIに用いられているのは基本的にこの深層学習になります。 まずはニューラルネットワークとは何なのかについて学びましょう。
パーセプトロン
ニューラルネットワークがどういうものかを理解するには、それの元となったパーセプトロンというものについて知る必要があります。 パーセプトロンは、AIを作るにあたって、人間の脳をモデル化しようという発想の下に考えられたものです。 まず単純パーセプトロンは、2値分類のために用いることのできるモデルです。 具体的には、複数の入力に対して、それらを重みづけして和をとったものがある閾値を超えたら1(真)、超えなければ0(偽)を出力します。 これは、以下のような図と数式によって表現できます。この例では入力数が3の場合を示しています。$x_i$は各入力、$y$は出力、$\theta$は閾値を指します。
パーセプトロンの例
上のようなグラフはパーセプトロンを直観的によく表しており、今後も似たような図が出てきます。 各入力値を表すノード(頂点)が、重みをつけられながら1つのノードに有向エッジを経由して「集められ」、その「集まったもの」が出力になるというイメージです。
パーセプトロンでは、重みを学習によって求めることで2値分類のタスクを解くことができるとされます。 しかし、この単純なパーセプトロンは線形分離可能(2次元平面のデータ点の例でいうと、直線で2つのクラスに分けられるということ)なデータに対してしか利用で畿内という欠点があります。
ニューラルネットワークの構造と仕組み
ニューラルネットワークとは、基本的には多層のパーセプトロンのことです。 線形分離不可能なものにも対応できるように、層を複数にしたパーセプトロンが考案され、それを原型として現在に至るまでニューラルネットワークが主な機械学習のモデルとして研究されています。
ニューラルネットワークの入力部分のノードのことを入力層、出力部分のノードのことを出力層と呼び、それらの間にある層をすべて隠れ層と呼びます。 入力された値は、隠れ層に順番に渡されていき、最終的に出力層に渡されて出力されます。 隠れ層の数は取り組む問題によってさまざまですが、ここでは隠れ層の部分が2層(つまり全体として4層)のニューラルネットワークを例にします。
ニューラルネットワークの例
上の図を使って説明していきます。 計算の流れは通常左から右なので、エッジの向きについては省略します。
まず、入力層が入力を受け取ったら、それらの値が第2層のそれぞれのノードに集められます。 ノードにおける計算の方法は単純パーセプトロンと同様で、各ノードは集められたそれぞれの値に重みづけして和をとります。 なおこのとき重みづけ線形和にさらにバイアスという定数の値を加えることも多いです。このバイアスも含め、各ノードで用いられる計算のためのパラメータを重みと呼びます。 そしてその和を出力するのですが、一般的にはそのまま出力するのではなく、活性化関数(後述)を適用した後の値を出力します。
今、第2層の出力が求まったので、次は第3層に移ります。 先ほどと同様に、第2層から出力されたそれぞれの値は、第3層のそれぞれのノードに集められ、重みづけした和が計算され、活性化関数が施され、出力されます。
そして第4層である出力層においても同様の計算が行われ、ニューラルネットワーク全体としての出力が決定されることになります。
構造については以上ですが、今説明したのは全結合型ニューラルネットワークと呼ばれる、それぞれのノードが密に結合したものです。 全結合型が基本にはなりますが、他にもニューラルネットワークのモデル(アーキテクチャ)がいくつかあるので、それらはChapter2で紹介します。
さて、このニューラルネットワークをどのように学習させるのかという話に入る前に、行列を使えば数式によって簡単に全結合型のニューラルネットワークが記述できることを説明しておきます。 行列を知らないという方は、Lesson 9 で行列について学んだあとに再び読むと良いでしょう。
再び先ほどの図を例にして説明します。 まず入力は3つの値ですが、これを$\mathbf{x} = [x_1, x_2, x_3]$というベクトルで表します。 これらが第2層に渡されるとき、どのような計算が起きているかというと、ある3x4の行列$\mathbf{W_1}$と長さ3のベクトル$\mathbf{b_1}$、そして活性化関数$f_1$を用いて \[ \mathbf{z_1} = f_1(\mathbf{x}\mathbf{W_1} + \mathbf{b_1}) \] としたとき、$\mathbf{z_1}$が第2層の出力(をベクトルの要素として並べたもの)になります。 詳しく説明すると、行列$\mathbf{W_1}$の各行が第2層の各ノードの重みを表し、ベクトル$\mathbf{b_1}$の各要素が各ノードのバイアスを表しています。 なおここでは活性化関数はベクトルの要素ごとに適用するものとします。 そして第3層の出力$\mathbf{z_2}$についても、4x4の行列$\mathbf{W_1}$、長さ4のベクトル$\mathbf{b_1}$、活性化関数$f_2$を用いて \[ \mathbf{z_2} = f_2(\mathbf{z_1}\mathbf{W_2} + \mathbf{b_2}) \] と表せ、最後の出力$\mathbf{y} = [y_1, y_2]$についても同様に \[ \mathbf{y} = f_3(\mathbf{z_2}\mathbf{W_3} + \mathbf{b_3}) \] となります($\mathbf{W_3}$の形状は4x2、$\mathbf{b_3}$の長さは2)。以下にまとめておきます。 \begin{align*} \mathbf{z_1} &= f_1(\mathbf{x}\mathbf{W_1} + \mathbf{b_1}) \\ \mathbf{z_2} &= f_2(\mathbf{z_1}\mathbf{W_2} + \mathbf{b_2}) \\ \mathbf{y} &= f_3(\mathbf{z_2}\mathbf{W_3} + \mathbf{b_3}) \\ \end{align*}
行列によってニューラルネットワークを記述することは、計算の内容が簡明になり見通しがよくなるだけでなく、 次に述べる誤差逆伝播においても非常に役に立つことなので、ぜひ身につけましょう。
深層のニューラルネットワーク
ニューラルネットワークは、層の数を増やすほど、パラメータが増え、その表現力が上がります(もちろん中間層のノードの数を増やしてもパラメータは増えます)。
表現力というのは、学習データにどれほど適合できるかを指しています。
したがって、一般に深層学習AIはほかの機械学習モデルに比べ非常に強力なモデルになりえます。
しかし層の数をただ増やせばいいというわけではありません。
層の数を増やしすぎると、学習データに過剰に適合してしまったり(過学習)、また学習にかかるコストも多くなるからです。
取り組む問題によってどのくらいの層の数にすべきかが変わってくるので、問題ごとに検討する必要があります。
ちなみに、何層以上であれば深層であるというのかについては明確な定義はありませんが、目安としては中間層が3層以上であるときに深層学習ということが多いです。
深層学習と言ったら、単に何層かの中間層があるニューラルネットワークのことを指していると思えば特に問題ありません。
誤差逆伝播
続いて、ニューラルネットワークを学習させるための重要な手法である誤差逆伝播について説明していきます。 誤差逆伝播とは、ニューラルネットワークなどの機械学習モデルにおいて、そのモデルの予測値の実際の正しい値からのずれ、すなわち誤差に対して、 各パラメータがどのように影響を与えるのかを求めるための手法です。 この次に述べる勾配降下法においてその「影響の与え方」が用いられます。
まず逆伝播という言葉について説明しますが、これは何が逆なのかというと、計算の向きです。 先ほど、ニューラルネットワークにおいてどのように入力値が各層に伝わっていって出力されるのか、ということを説明しましたが、この計算の過程を順伝播と呼びます。 それに対して逆伝播とは、出力側から入力側の向きに進むある計算のことをいいます。 それは何の計算のことかというと、「パラメータによる出力値の微分」です。 微分については Lesson 8 で学びますが、これは端的に言えば「パラメータをわずかに変化させたときの出力値の変化率」です。
順伝播と逆伝播
では誤差逆伝播とは何でしょうか。 これは、逆伝播によってモデルのパラメータによる「出力値と正解の値の誤差」の微分を求めることです。 ニューラルネットワークの最後の層に、誤差の計算のための層(この層は重みなどのパラメータを持ちません)、すなわち損失関数を計算する層を加えたものを考えれば、これはまさしく「パラメータによる出力値の微分」のことになります。
逆伝播を行うためには、各層における計算について、その層からの出力の、入力およびパラメータによる微分を求めなくてはなりません。 逆に、それらが求めれば合成関数の微分を用いることで「パラメータによる出力値の微分」がわかります。 先ほどのニューラルネットワークの例で考えてみましょう。 このモデルの順伝播の計算を行ったときの誤差を$L$とします。 今求めたいのは「パラメータによる出力値の微分」なので、例えば$\mathbf{W_2}$による$L$の(偏)微分$\dfrac{\partial L}{\partial \mathbf{W_2} }$を考えてみます。 すると、合成関数の微分により、 \[ \dfrac{\partial L}{\partial \mathbf{W_2} } = \dfrac{\partial L}{\partial \mathbf{y} } \cdot \dfrac{\partial \mathbf{y} }{\partial \mathbf{z_2} } \cdot \dfrac{\partial \mathbf{z_2} }{\partial \mathbf{W_2} } \] となります。$\dfrac{\partial L}{\partial \mathbf{y} }$は損失関数が何かわかれば求まります。 $\dfrac{\partial \mathbf{y} }{\partial \mathbf{z_2} }$は活性化関数$f_3$の微分と行列の積$\mathbf{z_2}\mathbf{W_3}$の$\mathbf{z_2}$による微分が分かれば求まり(合成関数の微分を再び使います)、右辺第3項についても同様です (行列についてまだ説明していないので行列積の微分がわからないかもしれませんが、参考までに、例えば行列積$\mathbf{x}\mathbf{W}$の$\mathbf{x}$による微分は$\mathbf{W}^T$で与えられます)。 したがって、ニューラルネットワーク内の各計算における微分を個別に求めておけば、$\dfrac{\partial L}{\partial \mathbf{W_2} }$が上の式によって求められることがわかりました。 他のパラメータについても同様にして求められます。
ニューラルネットワークの誤差逆伝播
先ほどニューラルネットワークの計算を行列によって表現しましたが、その結果誤差逆伝播によって誤差のパラメータによる微分が簡単に求められるようになっています。 機械学習という観点からは、この誤差逆伝播による手法は機械的に行えるものになっているということが重要であり、ニューラルネットワークが考案されて以降現在に至るまで非常によく用いられています。
勾配降下法
先ほどまで我々が「パラメータによる出力値の微分」と呼んでいたものは、機械学習においては特にパラメータの勾配(ベクトル)と呼ばれます。 ではなぜ誤差逆伝播によってパラメータの勾配を求めるのでしょうか。 これは、モデルの誤差が小さくなるようにニューラルネットワークの重みを更新するためです。 一般に、勾配を用いて目的関数(現在の例では損失関数)を最小化しようとする手法を勾配降下法(あるいは勾配法)といいます。 以下に手順を示します。
- 入力データを入力層に与え、順伝播によって出力を計算する
- 損失関数を用いて誤差を計算する
- 求めた誤差を用いて誤差逆伝播によって各パラメータの勾配を求める
- 求めた勾配を用いて各パラメータを更新する
- 誤差が収束するまで(あるいは閾値を下回るまで)ステップ1~4を繰り返す
ステップ4について詳しく説明します。まず勾配ベクトルは、実はパラメータをある方向にわずかにずらしたときに誤差が最も増えるような方向を表しています。 そこで、勾配とは逆方向にパラメータをわずかにずらすことで、誤差が減ることを期待します。具体的には誤差Lに対しパラメータ$\mathbf{W}$を次のように更新します。 \[ \mathbf{W} \leftarrow \mathbf{W} - \alpha \dfrac{\partial L}{\partial \mathbf{W} } \] $\alpha$は学習率で、パラメータの1度にどのくらい更新するかということをつかさどるハイパーパラメータです。
勾配降下法の基本は以上ですが、勾配降下法にはいくつかのバリエーションがあります。 例えば学習ループごとに学習データの一部をランダムに選んでパラメータの勾配を計算する確率的勾配降下法(Stochastic Gradient Descent、SGD)や、 パラメータの動きに慣性を考慮したモメンタム、学習が進むにつれて見かけの学習率が小さくなっていくAdaGradのほか、RMSPropやAdamなどがあります。 興味のある人は調べてみましょう。
局所解
簡単のため、パラメータを上手く2次元に次元削減し、3次元空間内にパラメータと目的関数の関係をグラフで図示できたとしましょう。
また現在のパラメータに対応する点を考え、パラメータを動かすことをその点を動かすこととして考えてみましょう。
このとき、勾配降下法の目的はこの点を最も深い「谷」の底に移動させることです。
勾配降下法では、勾配とは逆向きにパラメータを動かすことで目的関数を最小化しようとします。
こうすることによって、確かに最初の位置よりはだんだん低いところ、つまり3次元空間内における谷の底の方に点が落ちていくことが期待されます。
しかし、複雑なニューラルネットワークになるとこのグラフは複雑になり、谷がいくつも現れてきます。
すると、単純な勾配降下法ではそれほど深くない谷の底に移動し、そこにとどまってしまう可能性があります。
これでは目的関数の最小化に成功したとはいえません。
こういった「浅い谷」の底に対応するようなパラメータのことを、目的関数の最小化における局所解と呼びます。
逆に、より広い範囲(あるいはパラメータ空間全体)において目的関数が最小になるパラメータを大域解と呼びます。
局所解にとどまらず、大域解を上手く見つけてくれるような勾配降下法の手法をとるべきですが、さまざまな勾配降下法の種類のうちどれが最も適切かという問題は複雑な問題です。
実際にいくつかの手法を試さなければどれが適しているかは分からないことも多く、また勾配降下法の選択には収束の早さなどの別のことも考慮する必要があるためです。
活性化関数の種類と役割
ニューラルネットワークの計算のやり方を説明する過程で、活性化関数というものが登場しましたが、ここでそれについて説明します。 活性化関数は結局のところ単なる数学的な関数に過ぎないのですが、色んな種類があり、それぞれに異なる役割があります。 なおそれらに共通することもあって、それはモデルの表現力を上げるという目的があることです。 もし活性化関数がなければ、全結合型のニューラルネットワークがすることは線形変換(行列を掛けるだけでなくバイアスを加えるので、通常の意味では線形変換とは言いませんが、 機械学習の文脈ではバイアスを加えることまで含めて線形変換と呼ぶことが多いです)のみになってしまいます。 そこで非線形な関数を活性化関数として用いることで、モデルの表現力を向上させる狙いがあります。
それでは活性化関数の具体例について見ていきましょう。
線形関数
線形関数は恒等関数とも呼ばれ、以下の式で表されます。 \[ f(x) = x \] 言ってしまえば「何もしない関数」です。 こんな活性化関数は必要ないのではと思うかもしれませんが、基本的には各層で活性化関数を施すことになっているので、 活性化が不要な層においてこの線形関数が用いられることがあります。
誤差逆伝播において活性化関数の微分が必要になるので、導関数も示しておきます。 \[ f'(x) = 1 \]
線形関数は主に回帰問題における出力層で用いられます。
ステップ関数
ステップ関数とは、グラフが階段(step)状になることからその名がついており、以下のように表されます。 \[ f(x) = \begin{cases} 1 & (x \geq 0)\\ 0 & (x \lt 0) \end{cases} \]
ステップ関数はパーセプトロンの学習で用いられていましたが、ニューラルネットワークで用いられることはあまりありません。 その理由として、導関数が常に0($x=0$は定義されない)になるため、逆伝播の際に出力側からの勾配が入力側に伝わらなくなることがあります。
シグモイド関数
シグモイド関数は、どんな値を入力しても0と1の間の値をとるという特徴がある活性化関数で、以下のように表されます。 \[ f(x) = \dfrac{1}{1 + e^{-x} } \] シグモイド関数にはもうひとつ特徴があり、それは導関数が以下のようにシンプルに表せることです(確かめてみましょう)。 \[ f'(x) = f(x)(1-f(x)) \] このことにどういった意味があるのかというと、$f'(x)$が$f(x)$のみで表せるので、シグモイド関数を用いる層において順伝播の際に出力値を覚えておけば、 あとで逆伝播を行う時の計算が非常に楽になるという利点があります。
出力値が0から1の間に収まるので、シグモイド関数を用いることで出力値を確率と見なすことができます。 例えば2値分類の出力層の活性化関数として用いられることが多いです。
tanh関数
tanh関数は、ハイパボリックタンジェントと呼ばれ、次のように表されます。 \[ f(x) = \dfrac{e^x - e^{-x} }{e^x + e^{-x} } \] 特徴としては、出力が-1.0と1.0の間の値をとることや、シグモイド関数と同様に導関数が$f(x)$のみでシンプルに書けることがあります。 \[ f'(x) = 1 - (f(x))^2 \]
シグモイド関数は、微分値が最大でも0.25で、1よりも小さいことから、逆伝播の際に途中で勾配が消えてしまう(勾配消失問題)ことがありました。 イメージとしては、シグモイド関数を何層にもわたって用いると、その小さめな微分値が何回も掛け算され、0に近づいてしまうからです。 一方tanh関数は微分値の最大値は1.0なので、勾配がやや消えにくくなっています。
tanh関数は系列データを扱うモデル(LSTMなど、後述)でよく用いられます。
ReLU関数
ReLU(Rectified Linear Unit)関数は、次のように定義される、現在非常によく使われている活性化関数です。
\[ f(x) = \begin{cases} x & (x > 0)\\ 0 & (x \leq 0) \end{cases} \] 入力値が正のときはそのまま、そうでないときは0を出力します。 また導関数は次のようになります($x=0$においては導関数は定義できませんが、便宜的に0としていることが多いです)。 \[ f'(x) = \begin{cases} 1 & (x > 0)\\ 0 & (x \leq 0) \end{cases} \]
ReLU関数を用いるメリットをいくつか紹介します。 まず、計算が他の(線形関数以外の)活性化関数に比べて非常にシンプルなことです。 ニューラルネットワークを学習させるときには似たような計算が何度も行われるので、シンプルな活性化関数を用いることは処理速度の改善に役立ちます。 また、入力値が0以下のときは常に0を出力するので、各ノードの活性化がまばら(スパース)になり、モデルの解釈性が上がります。 さらに、入力値が正のときの微分値が常に1で、勾配消失問題も起きにくいです。
以下にステップ関数、シグモイド関数、tanh関数、そしてReLU関数を比較するための図を示します。 それぞれがどんな関数なのかのイメージをしっかり持っておきましょう。
活性化関数の図示(Matplotlib により作成)
ソフトマックス関数
ソフトマックス関数は、これまでに紹介してきた活性化関数とは少し系統が異なります。 まず、入力として受け取るのは1つの値ではなくベクトルです。 ソフトマックス関数は、受け取ったベクトルを、すべての要素が0と1の間の値をとり、かつそれらの合計が1になるように変換します。 ソフトマックス関数の入力値を$\mathbf{x} = [x_1, x_2, ... x_n]$、出力値を$\mathbf{y} = [y_1, y_2, ... y_n]$とすると、各$y_i$は以下のように表されます。 \[ y_i = \dfrac{e^{x_i} }{\sum_{j=1}^n e^{x_j} } \] これは先ほどのソフトマックス関数による変換の性質を満たしていることがわかるでしょう。 また$y_i$を$x_j$で(偏)微分したものは、次のように比較的シンプルに書けます。 \[ \dfrac{\partial y_i}{\partial x_j} = \begin{cases} y_i(1-y_i) & (i = j) \\ -y_i y_j & (i \neq j) \end{cases} \]
ソフトマックス関数は、その出力が確率分布と見なせることから、多値分類のモデルの出力層において用いられることが多いです。

Lesson 4
Chapter 2
モデルの構築
ここでは、全結合型以外のニューラルネットワークのアーキテクチャについて学びます。 それぞれに異なる特徴があるので、目的に応じてどのようなニューラルネットワークを用いるのかを適切に選ぶことが重要です。
畳み込みニューラルネットワーク(CNN)
畳み込みニューラルネットワーク(Convolutional Neural Network、CNN)とは、主に入力が高次元な場合に用いられるニューラルネットワークです。 特に画像処理において頻繁に用いられます。 通常、畳み込み層やプーリング層、全結合層を含むもののことをCNNといいます。 全結合層は全結合型で用いられるものと同じ(つまり、行列を掛け、バイアスを加え、活性化関数を適用する)ものなので、畳み込み層およびプーリング層について説明します。 なお説明の都合上、入力は画像であるとします。 これは、画像を数が2次元に並んだものと捉えてCNNに入力するということです。
畳み込み層は、フィルタと呼ばれるものを用いて画像の特徴量を抽出し、マッピングします。 フィルタを用いて行う処理は畳み込みと呼ばれるもので、以下のような計算です。
- フィルタを画像の左上に重ねる
- フィルタ中の値と対応する画像中の値をそれぞれかけ合わせ、その和をとる
- 得られた値を出力の一番左上の値とする
- 処理する位置を右にずらし、再びステップ2、3を繰り返す。右端に到達したら左端に戻って下にずらし、再び右にずらしながら処理していく
- 右端までたどりついたら、出力全体に共通のバイアスを加えて終了
こうしてできた出力は、画像のローカルな特徴量を取り出した、2次元の数の並び(つまり新しい画像)で、特徴マップと呼ばれます。 なおフィルタは通常複数用意し、フィルタごとに異なる特徴量を取り出すことが期待されます。 畳み込み層の出力はフィルタの数と同数の画像ということになります。
畳み込み層への入力は1枚の画像である必要はなく、例えばRGB画像のように3枚の画像を入力してもよいです (このとき、フィルタごとに、畳み込みを3枚の画像に施したあとで和をとるので、出力はフィルタ数分の画像のままです)。 したがって畳み込み層を重ねて用いることも可能です。 なお、畳み込み層への入力の画像の数をチャネル数といいます。
畳み込みの例(バイアスは省略)
続いてプーリング層についてですが、これは畳み込み層の後で使い、特徴マップのサイズを小さくするものです。 画像処理分野でいうところのダウンサンプリング、つまり解像度を下げる効果があります。
プーリング層にもいくつか種類があるのですが、代表的なものとしてMaxプーリングを紹介しておきます。 Maxプーリングでは、特徴マップ上で、あるサイズのウインドウを用いて「ウインドウ内で最大の値を求め、それを対応する位置の出力の値とする」ということを、 ウインドウをずらしながら特徴マップ全体に行います。 ウインドウのサイズを大きくすればするほど、画像の解像度は下げられることになります。
Maxプーリングの例
CNNでは、畳み込み層とプーリング層を何度か繰り返し使った後で、最後の出力層では全結合層を用いる、という構造が基本です。 CNNにおける学習では、畳み込み層のフィルタの値と全結合層の重みが学習対象のパラメータとなり、畳み込み層のフィルタの数やストライド (フィルタをずらしていくときにどのくらいの幅でずらすか)、パディング(フィルタを適用すると画像が小さくなるが、そのときのサイズ調整をどうするか)、そしてプーリング層のウインドウサイズはハイパーパラメータということになります。
リカレントニューラルネットワーク(RNN)
リカレントニューラルネットワーク(Recurrent Neural Network、RNN)は、時系列データの処理に特化したニューラルネットワークです。 特徴として、「過去」の情報を隠れ状態として保存しているために、「現在」の入力に対する予測の精度を向上させようとしています。
RNNの説明に入る前に、時系列データとはどういったものなのかを見てみましょう。 時系列データは、時間の経過に伴って変化するデータのことを指します。 例を挙げると、日々の気温や株価、地震の発生数、人口の増加数などが該当します。 また、「時間」という考え方をより抽象化して、単に順番に並んだデータを時系列データとして処理することもあります。 例えば我々が話したり書いたりする言語(自然言語)や音の波などです。 自然言語なら、単語あるいはトークンとよばれる単位に分けて、文章中に並んでいる順番にRNNに入力します。
さて、RNNの構造は、よく以下のような図で表現されます。
RNN
RNNは時系列データを扱うので、その計算は「時刻$t$」を用いて表します。 毎時刻$t$に、RNNは入力$\mathbf{x_t}$と前の時刻$t-1$の隠れ状態$\mathbf{h_{t-1} }$を受け取ります。 これらを用いて、RNNは隠れ状態$\mathbf{h_t}$および出力$\mathbf{y_t}$を出力します。これらはいずれもベクトルを想定しています。 このときの計算式は次のようになります。 \begin{align*} \mathbf{h_t} &= f^{(hidden)}(\mathbf{W_{hh} h_{t-1} } + \mathbf{W_{xh} x_t}) \\ \mathbf{y_t} &= f^{(output)}(\mathbf{W_{hy} h_{t} } ) \end{align*} $f^{(hidden)}およびf^{(output)}$はそれぞれ活性化関数で、tanh関数やReLU関数が用いられることが多いです。 $\mathbf{W_{hh} }$、$\mathbf{W_{xh} }$、$\mathbf{W_{hy} }$はいずれも重み行列です。 上記の式には入っていませんが、バイアスを加えることもあります。
なお上記の図は、リカレント、つまり「再帰」をコンパクトな形でよく表しているといえますが、わかりやすさのために下のような展開された図を用いることもあります。 どちらを用いても特に問題はありません。
RNN(展開後)
RNNは時系列データの処理に向いていますが、長い時系列データに対しては、層が深くなって逆伝播の際に勾配が消失してしまうという問題があります。 したがって、長期的なデータを保存、「記憶」することは難しくなっています。
リカレントニューラルネットワークの改良(LSTM、GRU)
RNNの欠点を改良するために、多くの改良案が考えられてきました。
まずはLSTM(Long Short Term Memory)です。 隠れ状態$h_t$を出力するための隠れ層があるのは通常のRNNと同様ですが、その隠れ層の内部構造が異なります。 LSTMの重要な要素はセル状態と呼ばれるものです。 これは、古い、あるいは既に必要ない情報を捨てたり、逆に新しく必要な情報を取り入れたりといった、時系列データを扱う際に我々が当たり前のようにやっていることを行うためのものです。
LSTMの隠れ層は以下のように表されます。
LSTMの隠れ層
まず前時刻の隠れ状態$h_{t-1}$と現在の入力$x_t$を連結(Concatenate)します。連結したものを Concat と呼ぶことにしましょう。
最初に、Concatを忘却ゲート(forget gate)という活性化関数としてシグモイド関数を用いた層に通し、前時刻のセル状態$c_{t-1}$のうちどの部分を忘れるのかを決めます。
また、Concat を入力ゲート(input gate)に通すことで、セル状態のどの部分を更新するかを決めるとともに、new cell と書かれた部分で新しいセル状態の候補値を決めます。 前者ではシグモイド関数が、後者ではtanh関数が用いられます。 これらを合わせて、(忘却ゲートを通った後の)セル状態に変更を加え、新しいセル状態$c_t$を完成させます。
後は現時刻の隠れ状態$h_t$ですが、これは Concat を出力ゲート(output gate)に通し、セル状態のどの部分を隠れ状態として出力するかを判断します。 出力ゲートの活性化関数はシグモイド関数です。 そして出力ゲートを通った後の Concat とセル状態$c_t$を組み合わせることで、先ほど出力すると判断した部分を隠れ状態とします。
構造の説明は以上です。LSTMは、通常のRNNに比べ時系列データを処理する性能が高く、現在では単にRNNといったらLSTMのことを指すこともあるほどよく使われるようになりました。
そんなLSTMは、計算がやや複雑というデメリットを持っています。 そこで、処理を高速化するために、LSTMと似たような仕組みを持ちながら軽量化がされているGRU(Gated Recurrent Unit)が考案されました。 GRUのLSTMとの違いとしては、セル状態がないことや、ゲートが2つになっていることがあります。
GRUの隠れ層
上はGRUの隠れ層の図です(ただしかなり簡略化しています)。 ゲートとしては更新ゲート(update gate)およびリセットゲート(reset gate)があります。 更新ゲート(活性化関数はシグモイド関数)は、新たな状態$h_t$を作る際に、どれくらいの割合で新しい「記憶」を取り入れるか決め、リセットゲート(こちらもシグモイド関数)はどれくらい「記憶」を忘れるかということを決める役割があります。 新しい隠れ状態としての候補は、図中の new state(活性化関数はtanh関数) で作っています。 そしてこれらをもとに Update という部分で最終的な隠れ状態$h_t$を完成させています。
GRUは、LSTMよりもシンプルで計算量が少なく、学習が高速であるため、自然言語処理、音声認識、画像キャプションなど、さまざまな分野で広く使用されています。 先ほども述べましたが、上記の図はシンプルに描かれたものなので、計算の詳細を詳しく知りたい方は自分で調べてみましょう。

Lesson 4
Chapter 3
深層学習の応用分野
ここでは、深層学習がどのような場面で使われているかをいくつかの分野ごとに紹介します。 深層学習は、その表現力の高さからさまざまな分野で利用されており、また高い性能を発揮しています。
自然言語処理(NLP)
自然言語とは、我々が普段日常生活で扱うような、人間社会で自然に生まれてきた言語のことを指します。 その自然言語を対象とするさまざまな研究分野を、まとめて自然言語処理(Natural Language Processing、NLP)といいます。 NLPにおいて、深層学習は例えば以下のような分野で使われています。
- テキスト分類:テキストを事前に定義されたカテゴリに分類する技術。レビューをポジティブ・ネガティブに分ける、など
- 機械翻訳:言語間の自動翻訳を行う技術。英語の文章を自動で日本語に翻訳する、など
- 質問自動応答:質問テキストに自動的に答える技術。チャットボットなど
- 文書生成:複数の文章から新しい文章を生成する技術。自動要約システムなど
これらの技術には、我々が既に学んだLSTMや、Attention と呼ばれる構造を用いた Transformer などが用いられています。
画像認識
画像認識とは、与えられた画像をコンピュータが自動で処理することを指し、以下のような深層学習の応用があります。
- 物体検出:画像中の物体を自動的に検出する技術。医療画像の異常部位の検出など
- セマンティックセグメンテーション:画像を複数の意味的な領域に分割する技術。写真中の人と背景を分割する、など
- 超解像度:低解像度の画像を高解像度の画像に変換する技術
- モノクロ画像の色付け:白黒の画像に自動で色を付ける技術
一般的に、画像認識で用いられるニューラルネットワークはCNNです。 CNNを使えば画像の特徴量を取り出すなどといったことができ、そのことが上記のような応用につながっています。
音声認識
音声認識とは、人間の声などの音声データをコンピュータによって自動で処理することを指します。 深層学習による音声認識技術の例をいくつか紹介します。
- テキスト変換:音声データを文字データに変換する技術。音声認識アシスタントなど
- 話者認識:音声データから話者の特徴を抽出する技術。音声認証によるセキュリティシステムなど
- 話者変換:話者の声を別の話者の声に変換する技術
- 音声合成:テキストデータから音声を生成する技術。音声アシスタントの応答など
音声認識には、自然言語処理と同様にRNNなどが用いられます。 スマートフォンを所持している方にとっては、音声認識アシスタントなどは非常になじみ深い技術といえるでしょう。
深層強化学習
深層強化学習とは、従来の強化学習(方策勾配法やQ学習など)と深層学習を組み合わせたものです。 深層学習モデルは、高次元の状態や行動空間を扱うことができ、表現力が高いため、複雑な問題に対応することができます。 基本的には、環境の状態を入力として受け取り、その状態の価値や次の行動を出力するようなニューラルネットワークが用いられます。
深層強化学習が利用されている例をいくつか見てみましょう。
- ゲームAI:囲碁や将棋、ビデオゲームなどをプレイするAI。将棋のプロ棋士など、そのゲームのトップレベルの人間と勝負して勝つことのできるものもある
- 自動運転:自動車の運転をAIが自動で制御する。車両が周囲の状況を観測し、最適な操作を学習することで、交通事故を減らすことができる
- ロボット制御:何らかのタスクを行うロボットを自動で制御する。目的地まで移動するために最適な行動をとるロボットなどがある
- 金融取引:金融取引の予測に深層強化学習によるAIが利用されることがある。株価の予測やポートフォリオの最適化など、投資家にとって重要な問題を解決することが期待される
従来の強化学習では、低次元の状態や離散的な行動しか扱えなかったものの、深層学習を組み合わせることで上記のような複雑な問題にも対処できます。

Lesson 4
Chapter 4
深層学習のチューニングと最適化
深層学習のチューニングなどについては、基本的に Lesson 3 で紹介したものと同様の部分が多いのですが、 深層学習で特に用いられることの多い手法について紹介します。
モデルの評価とチューニング
評価
深層学習モデルを評価する際には、基本的にはデータを学習データとテストデータに分け、 学習データのみを用いて学習させたあとで、テストデータを用いて損失関数などによる評価が行われます。 これは未知のデータにどれだけ対応できるかを見るためです。
このとき、交差検証と呼ばれる手法が用いられることがあります。 これは、学習データを複数のグループに分割し、それぞれのグループを交互に学習データとして用いる方法です。 それらを用いて複数回の学習を行い、複数回のテストデータに対する予測精度を平均することで、モデルの予測精度をより正確に評価することができます。
また分類問題において、真陽性率や偽陽性率、再現率、そして適合率などといった指標による評価の方法もあります。 これには、Lesson 3 で紹介した混合行列のほか、ROC曲線やPrecision-Recall曲線といったものが使われます。 ROC曲線は、偽陽性率と真陽性率の関係を表した曲線であり、AUC(グラフの下部分の面積)を用いてモデルの予測精度を評価することができます。 Precision-Recall曲線は、適合率と再現率の関係を表した曲線であり、AP(これもグラフの下の面積)を用いてモデルの予測精度を評価することができます。
また、自然言語処理などの分野においては、人間による評価も重要になってきます。 例えば機械翻訳において、生成された翻訳文がその言語の文章としてどれほど自然なのか、といったことを人間が評価する必要があります。
チューニング
続いて深層学習におけるチューニングについて説明します。 チューニングといえばハイパーパラメータの調整が代表的ですが、これについては後ほど説明します。 それ以外では、例えば損失関数を変更することが考えられます。 損失関数は、学習時に最適化する目的関数として事前に決めておくものであり、どんなモデルを作るのかという点において非常に重要な点です。 どんなタスクに取り組んでいるかによってどの損失関数を使うかは自然に決まってくる部分もありますが、 例えば外れ値が含まれやすいような回帰問題においては、平均二乗誤差の代わりに外れ値に頑健なHuber損失と呼ばれるものを用いることがあります。
チューニングにおいては、データ拡張と呼ばれるものも使われます。 これは、学習データを人工的に増やすことで、モデルの汎化性能を向上させる手法です。 例えば画像を学習データとして用いる際、元の画像に対し左右反転・拡大縮小・色の変更などの操作を施したものも学習データに含めることで、 学習データを人工的に多様化させることができます。 ただし、元の学習データがそもそも少なすぎたり、データへの手の加え方が不適切であったりすると、あまり汎化性能の向上が見られないので注意しましょう、
転移学習も紹介しておきます。 これは、ある問題で学習したモデルの一部を再利用し、別の問題に対して学習する手法です。 例えば、学習済みのニューラルネットワークの一部分の重みなどをそのままコピーし、新たなタスクのための新しい層の重みのみを学習させることで、 以前に行った学習を活かしつつ、学習コストを抑えながら新たなタスクに対応できるモデルを作ることができます。
ファインチューニング・蒸留
転移学習に関連するものとして、ファインチューニングと蒸留があります。 ファインチューニングは転移学習と似たような概念ですが、これはモデル全体の重みをコピーした後で、それらを新たなタスク用に学習・微調整するという点が異なります。 蒸留は、学習済みモデルのパラメータをコピーする代わりに、そのモデルを教師モデルとして用いて小さいモデルを学習させることで、似たような性能を持ちながらも軽量化されたモデルを作成するという手法です。
モデルの最適化と正則化
深層学習において、モデルの正則化を行う手法について説明します。 正則化とは、学習データへの適合の度合いとモデルの複雑さとのバランスをとり、過学習を防ごうとすることです。 モデルの最適化において正則化を行うことは未知のデータに対する汎化性能を向上させるために重要になってきます。
まずL1正則化およびL2正則化について説明します。これらはいずれも回帰問題において用いられます。
L1正則化
L1正則化においては、通常の目的関数に重みの大きさ(L1ノルム)の総和を定数倍したものを正則化項として加えます。 こうすることで、目的関数の最小化の際に自動で重みが0に近づくように調整され、モデルの複雑化を回避して過学習を防ぐことができます。 L1正則化の特徴として、学習の結果スパースな重み(つまり値の多くが0)が得られやすいことがあります。 したがって、疎な特徴量を持つデータセットにおいて、重要な特徴量を上手く選択するような効果を持っています。
L2正則化
一方L2正則化では、目的関数に正則化項を加える点では同じですが、それが重みの大きさの2乗(L2ノルム)の総和を定数倍したものであるという点が異なります。 この場合、目的関数の最小化の際に重みが大きくなりすぎないような制限がかかります。これにより不要な特徴量の影響を減らすことができます。 L1正則化とは異なり、一般的にスパースな解は得られませんが、L1正則化よりも滑らかな解が得られるという利点があります。
ドロップアウト
続いて、ドロップアウトという正則化手法について説明します。これは学習中にニューラルネットワークの一部のノードを無効化することで過学習を防ぐ手法です。 具体的には、学習中に、一定の確率でランダムに選ばれたノードを無効化する(重みを0にする)ことで、そのノードが学習に寄与する確率を下げます。 これにより、モデルがデータに過剰に適合するのを防ぎ、より汎化された特徴を学習できるようになります。 また、ドロップアウトによって、ネットワーク全体での情報の流れがより多様化され、過剰適合の原因となるノード間の共依存関係を緩和する効果もあります。 なお、無効化するノードの割合はハイパーパラメータです。また、無効化するノードは学習データごと(例えばミニバッチごと)に変化させます。
さまざまな正則化手法を適切に用いることでモデルの汎化性能を上げましょう。
ハイパーパラメータの最適化
深層学習におけるハイパーパラメータは多岐にわたり、ニューラルネットワークの層の数、学習率、エポック数、CNNにおけるフィルタの数やパディングなどがあります。 それらの調整方法について学びましょう。
グリッドサーチ
まず1つ目はグリッドサーチと呼ばれる手法です。 これは調整したいハイパーパラメータについて、ある範囲内ですべての組み合わせを試す手法です。 ハイパーパラメータの数が少なかったり、試す範囲がある程度決まっている場合にグリッドサーチは有効であるとされます。 しかしすべての組み合わせに対して学習を行う都合上、いずれ最適なハイパーパラメータを見つけられるとしても、学習回数が増え、計算コストが高くなってしまうのは間違いありません。
ランダムサーチ
2つ目はランダムサーチです。 これはすべての組み合わせを試すグリッドサーチとは対照的に、ある範囲内でランダムにハイパーパラメータの値の組み合わせを探していきます。 探索数がある上限値に達したらそこで終了するので、グリッドサーチよりも早く終了するという利点があります。 しかし探索はランダムなので、運が悪いと適切なハイパーパラメータにたどりつくことができません。
ベイズ最適化
最後にベイズ最適化について説明します。 これはハイパーパラメータの探索過程において、「これまでの結果を元に探索する場所を決める」という方針をとるものです。 最初はランダムに探索していくのですが、もしある程度適切なハイパーパラメータが見つかったら、その付近を(不適切なハイパーパラメータがありそうなところよりも)優先的に探索するようになります。 ただしこれではハイパーパラメータの「局所解」に陥ってしまう可能性があるので、まだあまり探索していないようなところもある程度試すようにします。 このようなバランスのいい探索をしようとするのがベイズ最適化です。 具体的な手法についてはやや複雑なので省略しますが、興味のある人はベイズ最適化について調べてみましょう。
