Sansan Tech Blog

Sansanのものづくりを支えるメンバーの技術やデザイン、プロダクトマネジメントの情報を発信

歴史をたどってディープラーニングを学ぶ 第三回 Cifar10と勾配消失問題についての考察

こんにちは、ニューラルネット老人こと糟谷勇児です。
最近は恐竜に凝っていて化石を買ったりしています。ニューラルネット界の化石と化してしまう前に、今回もディープラーニングを勉強していきたいと思います。

さて、前回はReLUについて自作のプログラムで検証しました。
これまでMNISTを題材にしてやってきましたが、MNISTの認識はディープラーニングより単純な手法のほうがうまくいくと思われるので、いまいち真実味に欠けるところがありました。

そこで、今回はタスクをちょっとだけ難しくするべくCifar10というデータセットに挑戦していきます。
https://www.cs.toronto.edu/~kriz/cifar.html

Cifar-10

ちなみにCifarはCanadian Institute For Advanced Researchの略のようです。暗号を表すCipherと似てるのでいつもわからなくなります。

Cifar-10には、10種類のクラスがあり、airplane, automobile, bird, cat, deer, dog, frog, horse, ship, truck がそれぞれ数字でタグ付けされています。
マルチクラス分類は学習データが必然的に増えるのでクイックに検証をまわすために、今回は2クラスに絞ってみます。
やはり一番かわいい猫を選びたくなりますね。

画像を見てみると・・・

f:id:kasuya_ug:20191222181727j:plainf:id:kasuya_ug:20191222181730j:plainf:id:kasuya_ug:20191222182140j:plainf:id:kasuya_ug:20191222182142j:plainf:id:kasuya_ug:20191222182145j:plain
小さいけど猫だ。

f:id:kasuya_ug:20191222181144j:plainf:id:kasuya_ug:20191222181321j:plainf:id:kasuya_ug:20191222181555j:plainf:id:kasuya_ug:20191222181724j:plain
ねこ・・・?

f:id:kasuya_ug:20191222181422j:plain
ねこ・・・だけど・・・。

今回のような認識タスクでは、人がミスったものを目で見て「これはしょうがないでしょ」とか「これはなんで認識できないんだろう」など分析するんですが、結構判断に困る画像が出てきそうなので、比較的わかりやすそうな飛行機と船を題材にすることにします。

飛行機
f:id:kasuya_ug:20191222182351j:plainf:id:kasuya_ug:20191222182354j:plainf:id:kasuya_ug:20191222182357j:plainf:id:kasuya_ug:20191222182400j:plainf:id:kasuya_ug:20191222182402j:plain


f:id:kasuya_ug:20191222182254j:plainf:id:kasuya_ug:20191222182256j:plainf:id:kasuya_ug:20191222182259j:plainf:id:kasuya_ug:20191222182301j:plainf:id:kasuya_ug:20191222182304j:plain

なお、Pythonの場合はPickelした画像が用意されているのですが、C#にはないのでファイルに落としてから、OpenCvSharpというC#用のOpenCVのラッパーを用いて読み込むようにしています。

Sigmoid VS ReLU 多層化で認識精度は上がるの?

さて、飛行機か船の画像が入ってきたらどちらなのかを判定するニューラルネットを作ってみようと思います。
今回は多層パーセプトロンで、中間層を色々変えて、活性化関数をSigmoidとReLUでそれぞれ試してみました。
なお、学習には飛行機と船2000枚ずつ、評価には200枚ずつを使用しています。入力層は画像を0-1にノーマライズして32*32の解像度でそのまま入れています。出力層は一つのニューロンを設けて、飛行機は1を出すように、船は0を出すように学習しています。

実験結果はこちら

f:id:kasuya_ug:20191222202359p:plain


結果は正解率70%前後と、伸びしろのある精度です。(よかった)
分かっていたことではありますが、単純に多層化してもそんなに精度は変わらないですね。
若干3層よりSigmoiは5層、ReLUは6層のニューラルネットのほうが精度は上でした。多層化も一定の効果はありそうではあります。
また、今回のような全結合の場合はSigmoidのほうが性能は上のようです。

勾配消失問題

前回からの疑問として勾配消失問題の謎が残っています。
勾配消失問題は「Sigmoid関数は層を重ねるたびに勾配に 0~1 の値が掛け算されていくので、下の層に届く前に勾配の値が小さくなりすぎ、学習が遅くなってしまう」という書かれ方をします。
勾配の絶対値が小さいだけで方向性が正しいなら、学習率を大きくしてあげるだけで問題ないはずです。
そこで今回は謎を探るべく、第一層の重みを変えたときに二乗誤差がどう変わるかを図示してみました。
使用したニューラルネットは上で使用した、隠れ層が150,100,50,30,15のニューラルネットです。
f:id:kasuya_ug:20191222210231p:plain
図の左がReLU、右がSigmoidです。
グラフの縦軸が二乗誤差の値、横軸がある結合の重みの値です。
今回10パターンぐらい実験したのですが、今回は紙面の関係で無作為に3つ出してみました。
ReLUは凹んでるところがありますね。

ReLUの場合は二乗誤差が極小になる値が、重みの変更範囲にあることがわかります。
例えば、あるニューロンからつながっている次の層のニューロンが2の出力を出すとき二乗誤差が最小になるとします。
Sigmoidは最大が1のため2の出力を出すことはできません。そのため、できる範囲でなるべく出力を大きくしようとすると、出力が1に近づくように重みを変えていくわけですが、その方向で動くと勾配はどんどん小さくなっていきます。

一方でReLUの場合は出力が0以上ならいくつでも取れるので、探索範囲に最適になるような場所があるため、
そこに近づけるように重みが更新されます。そのため勾配が小さくなった時には極小の値になっているわけです。

また、ReLUはその層の出力を大きくすると場合によっては最終層まで届くこともありますが、Sigmoidは次の層で1以下に正規化されてしまうので、下層の影響力が小さいということもあります。

勾配消失問題は単純に絶対値が減っていくだけではなく、様々な問題が複合的に起こっているととらえるのがよさそうです。
もっと層が増えたときや複雑なネットワークの時は別の問題が起こっているのかもしれません。継続してウォッチしていきたいですね。

次回は

さて、今回から自然画像を扱うようにしましたが、まだまだ精度は72%ぐらいです。
次回はコンボリューショナルニューラルネットワークを作って本格的に画像を扱ってみたいと思います。
歴史をたどってLeNetあたりから攻めてみようと思います。


この連載の過去記事

buildersbox.corp-sansan.com

buildersbox.corp-sansan.com

© Sansan, Inc.