ReLUファミリー活性化関数を検証してみる(ReLU,leakyReLU,PReLU)

TL;DR

ReLUファミリー最強の活性化関数は今の所PReLU。

ただしRReLUは未検証。

mnistでモデルのみで99.5%を超えたい

How to score 97%, 98%, 99%, and 100% | Kaggle 上記によると

99.5%: If you design a good CNN architecture and then add special features like pooling layers, data augmentation, dropout, batch normalization, decaying learning rate, advanced optimization; You'll have no problem breaking the landmark 99.5% in only 20 epochs!

(意訳) まともなDLモデラーならaccuracy99.5%超えないとやべーよ!!

とのことなので、DL歴2年になった私が改めてやってみようと思った次第。

ただし、このままじゃ面白くないので多少の縛りを。

  • DataAugmentationを使わない

    つまり今日このブログに載せているソースコードをそのまま実行すれば乱数の問題があるにせよそれっぽく再現できる。

    というよりDLモデラーならオーグメンテーション無しでも実現したいところ。

  • epoch数は48までヨシとする(上記の英文では20 epoch以内との記載)

    乱数ガチャが辛いため

  • dropoutを使わない

    なんとなく気分、というか別途検証予定のため

で、とりあえず、↓のモデル(keras)で、29epoch目で99.5%を超えたわけですが…。

from keras import datasets
import numpy as np
((train_x,train_y),(test_x,test_y)) = datasets.mnist.load_data()
train_x = (train_x/255).astype("float32").reshape(-1,28,28,1)
test_x  = (test_x /255).astype("float32").reshape(-1,28,28,1)
train_y = np.eye(10)[train_y]
test_y = np.eye(10)[test_y]

from tensorflow.keras.layers import *
from tensorflow.keras.models import *
from tensorflow.keras.optimizers import Adam

leaky_model = Sequential()
leaky_model.add(Conv2D(filters=32,kernel_size=(3,3),input_shape=(28,28,1),padding="same"))
leaky_model.add(LeakyReLU(alpha=0.1))
leaky_model.add(BatchNormalization())
leaky_model.add(Conv2D(filters=32,kernel_size=(3,3),padding="same"))
leaky_model.add(MaxPool2D(pool_size=(2,2),padding="same")) # 28,28 -> 14,14
leaky_model.add(LeakyReLU(alpha=0.1))
leaky_model.add(BatchNormalization())
leaky_model.add(Conv2D(filters=64,kernel_size=(3,3),padding="same"))
leaky_model.add(LeakyReLU(alpha=0.1))
leaky_model.add(BatchNormalization())
leaky_model.add(Conv2D(filters=64,kernel_size=(3,3),padding="same"))
leaky_model.add(LeakyReLU(alpha=0.1))
leaky_model.add(MaxPool2D(pool_size=(2,2),padding="same")) # 14,14 -> 7,7
leaky_model.add(BatchNormalization())
leaky_model.add(Conv2D(filters=64,kernel_size=(3,3),padding="same"))
leaky_model.add(LeakyReLU(alpha=0.1))
leaky_model.add(BatchNormalization())
leaky_model.add(Conv2D(filters=64,kernel_size=(3,3),padding="same"))
leaky_model.add(LeakyReLU(alpha=0.1))
leaky_model.add(MaxPool2D(pool_size=(2,2),padding="same")) # 7,7 -> 4,4
leaky_model.add(BatchNormalization())
leaky_model.add(Conv2D(filters=64,kernel_size=(3,3),padding="same"))
leaky_model.add(LeakyReLU(alpha=0.1))
leaky_model.add(BatchNormalization())
leaky_model.add(Conv2D(filters=64,kernel_size=(3,3),padding="same"))
leaky_model.add(LeakyReLU(alpha=0.1))
leaky_model.add(MaxPool2D(pool_size=(2,2),padding="same")) # 4,4 -> 2,2
leaky_model.add(BatchNormalization())
leaky_model.add(Conv2D(filters=128,kernel_size=(2,2),padding="same"))
leaky_model.add(LeakyReLU(alpha=0.1))
leaky_model.add(BatchNormalization())
leaky_model.add(Conv2D(filters=128,kernel_size=(2,2),padding="same"))
leaky_model.add(LeakyReLU(alpha=0.1))
leaky_model.add(MaxPool2D(pool_size=(2,2),padding="same")) # 2,2 -> 1,1
leaky_model.add(BatchNormalization())
leaky_model.add(Flatten())
leaky_model.add(Dense(10,activation="softmax"))
leaky_model.summary()

leaky_model.compile(optimizer=Adam(lr=0.0001),metrics=['accuracy'],loss="categorical_crossentropy")
leaky_model_history = leaky_model.fit(train_x,train_y,batch_size=16,epochs=48,validation_data=(test_x,test_y))

活性化関数って本当にこれでいいの?というのが気なったので、

  1. LeakyReLU(0.0) (= ReLU)
  2. LeakyReLU(0.1)
  3. LeakyReLU(0.2)
  4. LeakyReLU(0.3)
  5. PReLU

でどれが一番いいのか、を上記モデルのLeakReLU部分だけを変えて検証してみました。 (他は一切手を加えておりません)

[1505.00853] Empirical Evaluation of Rectified Activations in Convolutional Network

によると、Rondomized ReLU(RReLU)がいいらしいですが、

kerasにまだ実装されていないとのことなので↓

【ReLU, PReLU, シグモイド etc...】ニューラルネットでよく使う活性化関数の効果をKerasで調べてみた - プロクラシスト

今回はこの5通りを試しました。

結果

val_acc

f:id:kazuhitogo:20190904184424p:plain
val_acc

PReLUがepoch 30で瞬間最大風速99.55%を記録しました。

次点でleaky 0.3がepoch 43で99.53%ですね。

ただ、一番悪かったのもreluとleaky0.2で99.45%なのでまぁ誤差といえば誤差な気がします。

もう一回バッチを回すと結果が変わるきがしてならない。

ねんのためval_lossも。

f:id:kazuhitogo:20190904184847p:plain
val_loss

まぁほぼval_accと一緒ですね。

まとめ

PReLUが一番よい。accuracyにして0.1%程度。

有意差はわからない。

とりあえずデータサイエンティストを名乗るための99.5%は超えた。

以上。

現場で使える! TensorFlow開発入門 Kerasによる深層学習モデル構築手法 (AI & TECHNOLOGY)

現場で使える! TensorFlow開発入門 Kerasによる深層学習モデル構築手法 (AI & TECHNOLOGY)