深層学習のメカニズム
ここでは、とくに画像処理のための工夫を加えた深層学習のメカニズムについて簡単に説明します。
まず、多層パーセプトロンによる画像処理
Pythonの深層学習ライブラリ Keras
ニューラルネットワーク(深層学習)のライブラリはたくさんある
Kerasというライブラリを使うとTensorFlow等を簡単に動かせる ドキュメントはここにあるので、使ってみたい場合は適宜参照しよう
MNIST手書き数字データベース
MNIST(Modified National Institute of Standards and Technology)データベース
画像処理の研究用の手書き数字データベース
60,000枚の学習用画像、10,000枚のテスト用画像
28×28ピクセルの画像
https://gyazo.com/4df1c3a8d396914562d87995dba0b0e1
(参考)データのひとつをスプレッドシートで可視化してみました
ニューラルネットワーク(多層パーセプトロン)で分類してみる
28×28=784のピクセルの値を入力とする(784次元入力)
各ピクセルは0(白)~255(黒)の値が入っている
255で割って0(白)~1(黒)に正規化しておく
中間層は適当な数のニューロンを置く
出力層は0~9の数字(クラス)に対応する10個のニューロンを置く(ソフトマックスで確率値にする)
https://gyazo.com/392dcd97a61fc25dab6effc3bafba695
(参考)確率的勾配法
演習用コードでは、重みの学習(最適化)にAdamというアルゴリズムを用いている
これは確率的勾配法のひとつ
更新の1ステップごとにすべてのデータに対する誤差関数の微分(勾配)を求めるのではなく、データの一部を用いる
この1回のステップで用いるデータの大きさをバッチサイズという
一部のデータを用いるので真の勾配方法とは異なるが、逆にそのおかげで局所解を抜け出す可能性がある
確率的に「ふらふらしながら」低い方向へ向かっていく、というアイデア
https://gyazo.com/f4dd13e3cdbbbb432d1095b606bec138
学習データが60,000個でバッチサイズが1,000の場合、すべての学習データを使うのに60回のパラメータ更新が行われるが、これを1エポックとよぶ
活性化関数の工夫
前回のニューラルネットワークでは、中間層のニューロンにはシグモイド関数を用いた
これを活性化関数(activation function)とよぶが、シグモイド関数のほかにもたくさん提案されている
近年のニューラルネットワーク・深層学習では、ReLU(Rectified Linear Unit)が用いられることが多い
https://gyazo.com/ead044820807378346978b4f9feed041
シグモイド関数は入力が大きくなると常に1に近い値を出力するので、偏微分が0に近くなり、学習が進まなくなるが、これを解消できる
層が深くなると勾配がほぼ消えてしまう勾配消失問題があった
計算が簡単になるので学習が高速になる
(厳密には$ x=0で微分不可能だが、便宜的に微分係数0に含めるなどする)
Kerasではactivetion = 'relu'とすればよい
中間層への重みパラメータを可視化してみる
28×28の入力から各中間層ニューロンへの重みを可視化してみる
https://gyazo.com/515df4904c0c334d63d852ed6cea9bdd
黒い部分が正、白い部分が負の値
黒い部分に文字があるとそのニューロンは活性化され、白い部分に文字があると抑制される、というイメージ
「2」っぽい形があるなど、数字の特徴的な形に対応したニューロンがありそう
画像処理のための工夫
画像としての空間的な情報を使う
単純なニューラルネットワークのモデルでもある程度分類は可能
「2次元画像」であるということを活用し、空間情報を用いればより精度が上がると期待できる
いまのネットワークでは、入力層ニューロンの「順番」は全く考慮していないので、ここを改良できそう
https://gyazo.com/ed5b58c55f5633e00d9fe409ff517cd9
空間フィルター
空間的な情報、つまり、2次元上で、直線、曲線、円、四角など、形を表わす情報を用いたい
ここで空間フィルターという画像処理法がある
下図のように、2次元行列で表わすフィルターを、スライドさせながら画像の全領域で求める
この計算を畳み込み演算(Convolution)という
縦のエッジ、横のエッジ、斜めのエッジ、画像の平滑化、細かい部分の強調など、フィルターの数値次第でいろいろな空間情報を抽出できる
https://gyazo.com/fc9168370cfbba02744a3b5fad06f6d1
https://gyazo.com/d1367f50b498e20c8018047fad49ae48
パディング
フィルターを適用すると出力画像が一回り小さくなってしまう
連続的にさまざまなフィルターをかけると、画像がどんどん小さくなる
この対策として、0などの固定要素で周囲を水増ししておくパディングという操作がある
https://gyazo.com/508a2e20deaa8adb41605a09f5cf1f5d
ストライド
フィルターをかける際、フィルターをずらす間隔をストライドという
ストライドを大きくすると出力画像は小さくなる
https://gyazo.com/8f80a8b23d2fb69eeaa72f0e4a634c1f
これらを用いた畳み込みニューラルネットワーク(CNN: Convolutional Neural Network)
畳み込みニューラルネットワーク(CNN: Convolutional Neural Network)
上のようなフィルターを使ったニューラルネットワークを畳み込みニューラルネットワーク(CNN: Convolutional Neural Network)という
フィルター自体を学習するニューラルネットワークといえる
本来、フィルター的なもので「特徴量抽出」をするというのが、画像認識の際の前処理として重要だったが、これ自体を学習するという意味で画期的であり、非常に高性能な画像認識ができるようになった
例として、3×3のフィルターを8枚使ったCNNを組んでみる
https://gyazo.com/28f956a0b2880da1dc0ec3eb3fb49fee
中間層にて、「3×3のフィルター、パディング1、ストライド1」が8種類できることになる
各フィルターの出力は、入力画像と同じ大きさの28×28=784次元の出力になるので、8つのフィルターをあわせると、中間層は784×8=6272次元の出力になる
これを出力層の10個のニューロンにソフトマックスで結合する
(参考)学習で得られた8枚のフィルター
https://gyazo.com/453b54423700b3434e667502e305e12e
こうしたフィルターが学習により(つまりデータから自動的に)得られる!
プーリング
画像の位置のずれに対して頑健(ロバスト)にするための手法にプーリングがある
https://gyazo.com/596703e00b253906aafcf1a9bb3865c3
ドロップアウト
これはCNNに特有の操作ではないが、学習を改善する(過学習を防ぐ)方法としてドロップアウトがある
学習時に、入力層・中間層のニューロンを確率$ pでランダムに選び、それ以外を無効化する
無効化したニューロンは存在しないものとして学習を更新する
ミニバッチごとにニューロンを選出し直して、この手続を繰り返す
学習したあとの予測時には、すべてのニューロンを使うが、学習時には$ pの割合のニューロンしかない状態で学習していたので、そのままだと出力が大きくなってしまう。そのため、ドロップアウトを施した層の出力重みを$ p倍することで、重みを調整する
実質的に、構造の異なる複数のネットワークを並列で学習し、それをアンサンブルする効果がある
https://gyazo.com/44a8adb8dcd405bfa7c74ae4dada6c6b
多層のCNNを作ってみる
ここまでのあらゆるテクニックを使って、7層(入力層を除いて7層)のCNNを作ってみる
https://gyazo.com/cbe109739c29dcf6518e718ce0269361
これが最適というわけではもちろんない