こんにちは、技術開発ユニットの三浦です。今色々なところで「ブラックフライデー」のセールが開催されていますね。これまで見過ごしていたか、気づいていなかっただけなのかもしれませんが、今年は特に「ブラックフライデー」の文字を目にする機会が多い気がします。商品を眺めているだけでも楽しいです。来年の自分への投資をしよう!と専門書などを探しているうちに、気がついたらゲームやコミックを探すことに夢中になっています。
今回は私たちが画像解析の業務で利用することが多い"EfficientNet"という深層学習のモデルについて調べてみたことを紹介します。
EfficientNet
画像解析の分野で高い精度を持つ"畳み込みニューラルネットワーク"には様々な種類があり、より精度の高いものが日々研究されています。EfficientNetは2019年の論文に登場する"畳み込みニューラルネットワーク"の一つです。もう少し詳細に書くと、"EfficientNet-B0"という基本のモデルに対して一定のルールに従ってモデルを拡張していって得られるモデル群を"EfficientNets"と呼んでいます。
深層学習のフレームワークkerasでは"EfficientNet-B0"から"EfficientNet-B7"までが関数で用意され、"ImageNet"データセットで学習済みのものを簡単に呼び出すことが出来ます。
論文
"EfficientNet"は「EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks」( Mingxing Tan, Quoc V. Le,2019)という論文で述べられています。
https://arxiv.org/abs/1905.11946
こちらの論文に目を通してみました。タイトルにあるように、この論文では"EfficientNet"を紹介するだけでなく、"畳み込みニューラルネットワーク"を効率的に、つまり計算コストの増加を抑えながら精度を上げるためのネットワークのスケールアップの方法について取り上げています。ネットワークをスケールアップするための要素として、ネットワークの深さ、幅(チャネル)、解像度(入力の横x高さ)を対象としています。この3つの要素は独立ではなく、互いに影響しあうものであるため、同時にチューニングすることが効率的なネットワークのスケールアップに必要であると述べられています(高い解像度の画像から特徴を抜き出すためにはより深いネットワークが必要になるなど)。 具体的には深さ、幅、解像度をそれぞれ , , のように、あらかじめ小さなサイズのネットワークで求めておいた定数, , をそれぞれ乗することで効率的なネットワークのスケールアップが実現できるとのことです。その場合計算に必要なリソースは倍必要になるそうです。
For example, if we want to use times more computational resources, then we can simply increase the network depth by , width by , and image size by , where , , are constant coefficients determined by a small grid search on the original small model.
引用元:「EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks」( Mingxing Tan, Quoc V. Le,2019)
そして探索によってもとめた基本モデル"EfficientNet-B0"をこの手法でスケールアップして得られたモデル群が"EfficientNets(B0~B7)"です。
kerasで使ってみる
kerasではB0~B7を関数で利用できるため、簡単に試してみることが出来ます。以下のような設定でコードを書いて試してみました。
- "ImageNet"で学習済みの"EfficientNet-B0"を使う
- "CIFAR-10"データセットの分類モデルを作る
- "EfficientNet-B0"の出力層を"CIFAR-10"用に変更
- 学習は変更した層(最上位の全結合層)のみを対象に行う
コードはGoogle Colaboratoryで実行しました。50 epoch 学習させてテストデータに対してAccuracyが60%を超えることを確認しました。
import numpy as np import tensorflow as tf from tensorflow import keras (x_train, y_train), (x_test, y_test) = keras.datasets.cifar10.load_data() NUM_CLASSES = 10 #CIFAR-10のClass数 y_train = keras.utils.to_categorical(y_train) # labelのone-hotエンコーディング y_test = keras.utils.to_categorical(y_test) # labelのone-hotエンコーディング #ネットワークの構築 inputs = keras.layers.Input(shape=(32,32,3)) base_model = keras.applications.efficientnet.EfficientNetB0( include_top=False, weights="imagenet", input_tensor = inputs ) base_model.trainable = False #EfficientNetの重みは学習しない x = keras.layers.GlobalAveragePooling2D()(base_model.output) x = keras.layers.BatchNormalization()(x) outputs = keras.layers.Dense(NUM_CLASSES,activation='softmax')(x) model = keras.Model(inputs, outputs) model.compile( loss='categorical_crossentropy', optimizer='adam', metrics=["accuracy"] ) #モデルの学習 history = model.fit( x_train, y_train, validation_data=(x_test, y_test), batch_size=64, epochs=50, shuffle=True )
出力結果(50epoch)
Epoch 50/50 782/782 [==============================] - 81s 104ms/step - loss: 1.0794 - accuracy: 0.6191 - val_loss: 1.1186 - val_accuracy: 0.6085
まとめ
今回は深層学習モデル"EfficientNet"について調べたことを紹介しました。論文で述べられているネットワークの効率的なスケールアップの方法はとても興味深く、別のモデルをチューニングする際にも参考になりそうだと思いました。また深層学習のフレームワークkerasを使うことで比較的簡単に"EfficientNet"を組み込んだモデルを作ることが出来ました。今回は組み込んだ学習済みモデルは学習対象にしない「転移学習」での利用に留まりましたが、"EfficientNet"の上位層だけを学習対象にするともっと高い精度が出るのでは、と思います。