概要
EfficientNetを用いた画像分類を行っていきます。この記事で実際に紹介するものは以下の通りです。
- EfficientNetのインストール
- 学習済みモデルを用いた画像分類
- ファインチューニングによる再学習
EfficientNetのインストール
Requirements
- Keras >= 2.2.0 / TensorFlow >= 1.12.0
- keras_applications >= 1.0.7
- scikit-image
インストール
$ pip install -U git+https://github.com/qubvel/efficientnet
学習済みモデルを用いた画像分類
学習済みモデル一覧
以下利用できる学習済みモデルです。今回はこの中のEfficientNetB0(Imagenet)
を利用していきます。
Architecture | @top1* Imagenet | @top1* Noisy-Student |
---|---|---|
EfficientNetB0 | 0.772 | 0.788 |
EfficientNetB1 | 0.791 | 0.815 |
EfficientNetB2 | 0.802 | 0.824 |
EfficientNetB3 | 0.816 | 0.841 |
EfficientNetB4 | 0.830 | 0.853 |
EfficientNetB5 | 0.837 | 0.861 |
EfficientNetB6 | 0.841 | 0.864 |
EfficientNetB7 | 0.844 | 0.869 |
学習済みモデルで画像分類してみる。
githubでも使われている以下のパンダの画像をテスト画像に使います。
コードは以下の通り。シンプル。
import os
import sys
import numpy as np
from skimage.io import imread
import matplotlib.pyplot as plt
from keras.applications.imagenet_utils import decode_predictions
from efficientnet.keras import EfficientNetB0
from efficientnet.keras import center_crop_and_resize, preprocess_input
# テスト画像
image = imread('./panda.jpg')
# 学習済みモデルのロード
model = EfficientNetB0(weights='imagenet')
# 画像の前処理
image_size = model.input_shape[1]
x = center_crop_and_resize(image, image_size=image_size)
x = preprocess_input(x)
x = np.expand_dims(x, 0)
# 分類
y = model.predict(x)
print(decode_predictions(y))
"""出力
[[('n02510455', 'giant_panda', 0.75878674),
('n02134084', 'ice_bear', 0.008354761),
('n02132136', 'brown_bear', 0.007207236),
('n02509815', 'lesser_panda', 0.004130227),
('n02120079', 'Arctic_fox', 0.004021081)]]
"""
パンダと予測されていますね。
ファインチューニングによる再学習
画像変換関数
今回はmnistを用いて再学習を行います。mnistなら簡単に試せるやろ、という気持ちです。しかし以下の2点で学習させる際に引っかかってしまうことが判明。
- 最低でも32x32の画像な!
- チャンネル数は3やで!
mnistは28x28な上に、チャンネル数は1という。。。なので関数を作り前処理をさせます。冗長なコードですがお許しください。ちなみに上記の2点に当てはまらない場合はこれは無視して大丈夫です!
def mnist_preprocessing(X):
import cv2
X_list = []
for x_i in X:
resize_X = cv2.resize(x_i, (32, 32))
img = cv2.cvtColor(resize_X, cv2.COLOR_GRAY2BGR)
X_list.append(img)
X_list = np.array(X_list)
return X_list
学習
import keras
from efficientnet.keras import EfficientNetB0
from efficientnet.keras import center_crop_and_resize, preprocess_input
from keras.datasets import mnist
import numpy as np
def mnist_preprocessing(X):
import cv2
X_list = []
for x_i in X:
resize_X = cv2.resize(x_i, (32, 32))
img = cv2.cvtColor(resize_X, cv2.COLOR_GRAY2BGR)
X_list.append(img)
X_list = np.array(X_list)
return X_list
# データの準備。今回はmnist。
(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_train_processed = mnist_preprocessing(X_train)
X_test_processed = mnist_preprocessing(X_test)
y_train_categorical = keras.utils.to_categorical(y_train)
y_test_categorical = keras.utils.to_categorical(y_test)
# efficientnetに必要なところ。
X_train = preprocess_input(X_train)
X_test_processed = preprocess_input(X_test_processed)
n_classes = 10
# モデルの構築
INPUT_SHAPE = (32, 32, 3)
base_model = EfficientNetB0(input_shape=INPUT_SHAPE, weights='imagenet', include_top=False)
x = keras.layers.GlobalAveragePooling2D()(base_model.output)
output = keras.layers.Dense(n_classes, activation='softmax')(x)
model = keras.models.Model(inputs=[base_model.input], outputs=[output])
# 学習
model.compile(optimizer='SGD', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(X_train_processed, y_train_categorical) #epoch数とか諸々のものは一般のkerasと同様ここでオプション追加する
model.save('my_model.h5')
モデル評価
model = keras.models.load_model("my_model.h5")
score = model.evaluate(X_test_processed, y_test_categorical, verbose=0)
print("loss:", score[0])
print("accuracy:", score[1])
"""出力
loss: 0.08207062631845474
accuracy: 0.9783999919891357
"""
まとめ
efficientnetの使い方を紹介した。