画像認識の基礎(tf.keras.applications)

TensorFlow / Kerasを使用した画像認識(分類タスク)のファインチューニングについて。

tf.keras.applcationsに含まれるアルゴリズム

  • ResNet
    • 2015年に登場、100層以上のネットワークを構成し精度を向上させた
    • https://arxiv.org/abs/1512.03385
    • デフォルトの入力サイズは224x224
    • ResNet50(50層)、ResNet101(101層)、ResNet152(152層)
  • DenseNet
    • 2017年に登場、ResNetを踏まえて開発された
    • デフォルトの入力サイズは224x224
    • DenseNet121(121層)、DenseNet169(169層)、DenseNet201(201層)
  • efficientetnet
  • inception_resnet_v2
  • inception_v3
  • mobilenet
  • mobilenet_v2
  • mobilenet_v3
  • nasnet
  • resnet_v2
  • vgg16
  • vgg19
  • xception

比較(Keras Documentationによる)

精度評価はImageNetによる。
Top-1 Accuracyは、最上位の予測結果が正答である精度。
Top-5 Accuraryは、上位5個の予測結果に正答が含まれる精度。

ModelSizeTop-1 AccuracyTop-5 AccuracyParametersDepth
Xception88 MB0.7900.94522,910,480126
VGG16528 MB0.7150.901138,357,54423
VGG19549 MB0.7270.910143,667,24026
ResNet5099 MB0.7590.92925,636,712168
InceptionV392 MB0.7880.94423,851,784159
InceptionResNetV2215 MB0.8040.95355,873,736572
MobileNet17 MB0.6650.8714,253,86488
DenseNet12133 MB0.7450.9188,062,504121
DenseNet16957 MB0.7590.92814,307,880169
DenseNet20180 MB0.7700.93320,242,984201

Kerasにおける引数

各アルゴリズムで共通に用いられる引数(抜粋)

  • weights: None or ‘imagenet’ imagenetを使用した初期の学習を行うか否か。Noneの場合は各ニューロンのウエイトの初期値はランダム。
  • include_top: 出力層側にある全結合層を含むかどうか。
  • classes: 出力層のニューロン数(分類したいクラス数)。include_topがTrueでweightsがNoneの場合しか指定できない。
  • input_shape: 入力する画像の形状。

コード例

import tensorflow as tf

base_model = tf.keras.applications.MobileNetV2(weights='imagenet', include_top=False)
x = base_model.output
x = tf.keras.layers.GlobalAveragePooling2D()(x)
x = tf.keras.layers.Dense(512, activation='relu')(x)
x = tf.keras.layers.Dense(256, activation='relu')(x)
preds = tf.keras.layers.Dense(3, activation='softmax')(x)

model = tf.keras.Model(inputs=base_model.input, outputs=preds)

# ベースモデル部分は再学習しない(Non-trainable params)
for layer in base_model.layers:
    layer.trainable=False

model.compile(optimizer='Adam', loss='categorical_crossentropy', metrics=['accuracy'])
model.summary()

作成されたネットワークはこのようになる。(長いので途中は省略)
include_topがFalseのため、dense (Dense)以下の3層は上記コード内で追加したもの。

__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_1 (InputLayer)            [(None, None, None,  0                                            
__________________________________________________________________________________________________
Conv1 (Conv2D)                  (None, None, None, 3 864         input_1[0][0]                    
__________________________________________________________________________________________________
bn_Conv1 (BatchNormalization)   (None, None, None, 3 128         Conv1[0][0]                      
__________________________________________________________________________________________________
Conv1_relu (ReLU)               (None, None, None, 3 0           bn_Conv1[0][0]                   
__________________________________________________________________________________________________
expanded_conv_depthwise (Depthw (None, None, None, 3 288         Conv1_relu[0][0]                 
__________________________________________________________________________________________________
(中略)
__________________________________________________________________________________________________
dense (Dense)                   (None, 512)          655872      global_average_pooling2d[0][0]   
__________________________________________________________________________________________________
dense_1 (Dense)                 (None, 256)          131328      dense[0][0]                      
__________________________________________________________________________________________________
dense_2 (Dense)                 (None, 3)            771         dense_1[0][0]                    
==================================================================================================
Total params: 3,045,955
Trainable params: 787,971
Non-trainable params: 2,257,984
__________________________________________________________________________________________________

続きのコード。これでモデルのトレーニングが行われる。

train_datagen = tf.keras.preprocessing.image.ImageDataGenerator(
    preprocessing_function = tf.keras.applications.mobilenet_v2.preprocess_input)

train_generator = train_datagen.flow_from_directory('train',
                                                 color_mode='rgb',
                                                 batch_size=10,
                                                 class_mode='categorical',
                                                 shuffle=True)

log_file = model.fit_generator(generator=train_generator,
                   steps_per_epoch=5,
                   epochs=100)

トレーニングの過程を可視化する。

plt.plot(log_file.history['accuracy'], '-bo', label="train_accuracy")
plt.plot(log_file.history['loss'], '-r*', label="train_loss")
plt.title('Training Loss and Accuracy')
plt.ylabel('Loss/Accuracy')
plt.xlabel('Epoch #')
plt.legend(loc='center right')
plt.show()

参考文献