2017.10.03 Tue |
Kaggleで1677チーム中144位(2017年10月2日時点)になりました!
前回、前々回とDeepLearningのHyper-parameter Tuningを行ってきました。
その結果とさらなるいくつかの検証ののち、精度が良いモデルを作成して、
Kaggle Competitionという機械学習のコンテストにおいて、どれくらいの順位になるか試してみました。
ちなみにKaggle Competitionとは、2017年3月にGoogleが買収したKaggle社が開催する機械学習のコンテストになります。
https://www.kaggle.com/competitions
2017年10月3日現在16個のコンテストが開催されています。
https://www.kaggle.com/competitions
今回はその一つである、Digit Recognizerというコンテストに参加してみました。
https://www.kaggle.com/c/digit-recognizer
これは機械学習用の画像データとしては最も基本的かつよく使われるMNISTデータセットを用いた画像の分類コンテストです。
手書きで数字の0~9が書かれた28×28ピクセルの画像を教師有機械学習で学習させ、その学習器に、テスト用の画像データを読み込ませ、それぞれの画像がどの数字を表しているかを予測させるものです。
このようなタスクは2000年代前半まではLinear kernelを用いたsupport vector machineが最も高い精度を出していましたが、2012年以降は、DeepLearningの方が高い精度を出すようになりました。
ですので、今回使用したモデルも、DeepLearningになります。
DeepLearningの中でも、畳み込みニューラルネットワーク(Convolutional Neural Network:CNN)を使用します。
この分野はここ数年の進歩がものすごく早く、有名なものだとAlexNet, GoogLeNet,ResNet,またそれぞれの改良版があります。
今回は練習の意味合いも込めて、有名なモデルは使わず、パーセプトロンに少しずつ、畳み込み層を導入していき一番良いモデルを探すという方法をとりました。
結果として、畳み込み層は4層で落ち着きました。
参考までにネットワークアーキテクチャだけ載せておきます。
model %>%
layer_conv_2d(filter = 32, kernel_size = c(5,5), padding = “same”,
input_shape = c(28, 28, 1)) %>%
layer_activation(“relu”) %>%
layer_conv_2d(filter = 32, kernel_size = c(5,5),padding = “same”) %>%
layer_activation(“relu”) %>%
layer_max_pooling_2d(pool_size = c(2,2)) %>%
layer_dropout(0.25) %>%
layer_conv_2d(filter = 64, kernel_size = c(3,3), padding = “same”) %>%
layer_activation(“relu”) %>%
layer_conv_2d(filter = 64, kernel_size = c(3,3), padding = “same”) %>%
layer_activation(“relu”) %>%
layer_max_pooling_2d(pool_size = c(2,2)) %>%
layer_dropout(0.25) %>%
layer_flatten() %>%
layer_dense(256) %>%
layer_activation(“relu”) %>%
layer_dropout(0.5) %>%
layer_dense(10) %>%
layer_activation(“softmax”)
これで、実行しKaggleに提出したところ、
1677チーム中144位(2017年10月2日時点)
となりました。基本的にそれなりに機械学習ができないと提出すらできないので、データサイエンティスト1677人中144番と言ってよいと思います。トップレベルのデータサイエンティストはそれほど参加していない気もしますが、上位の方たちで精度0.999が出ている人はどう考えても素人ではないでしょう。
スタートからかけた時間は大体6日くらいでした。
なぜかGoogleCloudPlatformからGPU割り当ての許可がおりず、CPUを8つもったPCを3台同時並行で使ってやっていました。一回当たりの計算時間は1.5時間くらいで、ものによっては一回16時間かかるものもありました。
一回の実行当たり10時間以上かかるとその間そのPCが使えないので、GPUの使用が不可欠と感じました。(GPUを使えば50倍速くらいで計算を終わらせることができたはずです)
今回は、MNISTデータセットかつあまり複雑でないモデルを使用したので、どれだけ一般的なことが言えるのかわかりませんが、得られた知見をまとめてみました。
今後皆さんがDeepLearningを実行するときのご参考になればと思います。
・BatchNormalizationは世間で言われているほど必要ない。
・いろいろ試したもののBatchNormalizationはどれでも精度を下げた。
・epochは単純に増やせばよいというものではない。
・畳み込み層も単純に増やせばよいというものではない。
・DataAugmentationのやり方は、学習する画像の種類によって変わる。
・DataAugmentationをやらないと精度0.993程度で頭打ち。
・活性化関数として、PReLuやLeakyReluがあるが、自分が試した範囲では、層を深くすると、ReLuほど精度は上がらなかった。
・自分が調べた範囲では、DeepLearningのHyper-parameter tuningの実際の結果に関する情報はかなり少ない。
・層が薄いときと厚いときでよいハイパーパラメータは違う気がする。
・DeepLearningでのハイパーパラメータチューニングを本格的にやろうとしたらGPU必須。
・Kaggle Competitionで出ないと、精度0.990くらいで満足してしまいがちだけど、Kaggle Competitionに出ると精度0.990から精度0.999に近付ける作業を体験することになり、DeepLearnig(CNN)の本当の難しさを知ることになる。
・Reinforcement LearningやGenerative Adversarial Neural Networkにおいても畳み込み層をいれるので、Kaggle CompetitionでCNNのハイパーパラメタ調整をしておく経験は無駄にはならないのではないか。
・今回Kaggle Competitionに挑戦するにあたり、20名ほど仲間を誘ってSlack中でみんなのコメントをもらいながら進めていったことがすごくよかった。いろんなアドバイスがもらえるのとわからないことを聞ける。
もともとPFNにいた友人からは、
BatchNormalization・PReLu・LeakyReluが精度を上げなかったのは、MNISTデータがシンプルすぎるか、モデルの層が浅いのではないかという指摘を受けました。
個人的には今後いろんなデータで、いろんなネットワークアーキテクチャで、BatchNormalization・PReLu・LeakyReluの効果を検証していく予定です。
それでは今回はここまで。
鈴木瑞人
東京大学大学院新領域創成科学研究科 メディカル情報生命専攻 博士課程
NPO法人Bizjapan テクノロジー部門BizXチームリーダー