AIQuestの画像分類で四苦八苦した内容をまとめた

公開:2020/11/08
更新:2020/11/10
9 min読了の目安(約8400字TECH技術記事

ここ1ヶ月近く、AIQuestの画像分類の課題に取り組んでいました。

テーブルデータや自然言語処理は少し触ったことはありましたが、画像は初めてだったのでかなりハマってしまいました。

3週間ほど、精度もくそもなく全て0と分類されてしまうような状態で格闘し続けたので、その時の学びをメモしたいと思います。

なお、AIQuestの規定上、課題の詳細な内容やコード等は開示できませんことをご了承ください。

開発環境

ローカル環境(Windows10)
Python 3.7
Anaconda
Tensorflow2 + Keras
JypterLab
VGG16で転移学習

素早く回して試すことを優先させる

基本的なことですが、コードエラーをつぶしていないうちは画像は1枚だけ読み込むとか、エポック数は一桁にしておく等の工夫が大事でした。

画像処理は数時間、下手すると日単位で処理に時間がかかるので、対策しないと無限に時間が溶けていくので気を付けましょう。。。

画像処理に数時間かかったのちに、しょうもないところでコードエラーが発生するとかなしみです。

ファインチューニング 出力層

最初、VGG16の出力層を、Maxpooling層+分類したいカテゴリ数の層というシンプルなものを使っていたのですが、もう少し工夫しなければよい結果は得られなかったようです。

出力層の変更の参考サイト
(Keras公式ドキュ ModelクラスAPI)[https://keras.io/ja/models/model/]

# モデルと出力層 サンプルコード
from keras.models import Model
from keras.layers import Input, Dense

a = Input(shape=(32,)) # 入力層
b = Dense(32)(a) # 出力層

model = Model(
    inputs=a, # 入力層
    outputs=b # 出力層
    )

一部層の凍結の参考サイト
Deep learningで画像認識⑧〜Kerasで畳み込みニューラルネットワーク vol.4〜

ファインチューニング 層の凍結

最初うっかり全ての層を学習させていたことに気づきませんでしたが、出力層の一部のみを学習させると効果的でした。

(参考サイト)TensorFlow, Kerasでレイヤー、モデルのtrainable属性を設定(Freeze / Unfreeze)

なお、ご存知かもしれませんが、凍結しているかどうかは、.summary()に表示されているのですが、私はスルーしていました、反省。

model.summary()

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         (None, 224, 224, 3)       0         
_________________________________________________________________
()
=================================================================
Total params: xx,xxx,xxx
Trainable params: xx,xxx,xxx # ココが学習可能なパラメーターの数
Non-trainable params: xx,xxx,xxx # ココが凍結したパラメーターの数

ファインチューニングの学習率

ファインチューニングの場合、学習させすぎるとせっかくの学習済みモデルの重みが崩れてしまうので、学習率を下げるようです。

やりすぎない程度にこの学習率もいじると精度に影響しました。

# 学習率 サンプルコード
model.compile(optimizer=tf.keras.optimizers.RMSprop(learning_rate=0.00001), # learning_rate 学習率
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

(再掲)TensorFlow, Kerasでレイヤー、モデルのtrainable属性を設定(Freeze / Unfreeze)

データ拡張

kerasには画像を回転させたりナナメに引っ張ったりして画像の水増しをする便利な関数があります。

ナナメに引っ張ると正常と異常の区別がつきにくくなるかも、とか、円形だと回転させてもあまり意味がないかも、とか、画像の特性を考えながら拡張する項目を選ぶとよいようです。

Keras 公式ドキュ ImageDataGenerator

keras.preprocessing.image.ImageDataGenerator(
    featurewise_center=False,               # データセット全体で,入力の平均を0にする
    samplewise_center=False,                # 各サンプルの平均を0にする
    featurewise_std_normalization=False,    # 入力をデータセットの標準偏差で正規化する
    samplewise_std_normalization=False,     # 各入力をその標準偏差で正規化する
    zca_whitening=False,                    # ZCA白色化のイプシロン.デフォルトは1e-6
    zca_epsilon=1e-06,                      # ZCA白色化を適用
    rotation_range=0.0,                     # 画像をランダムに回転する回転範囲
    width_shift_range=0.0,                  # ランダムに水平シフトする範囲
    height_shift_range=0.0,                 # ランダムに垂直シフトする範囲
    brightness_range=None,                  # 明るさをランダムに変更する
    shear_range=0.0,                        # シアー強度(反時計回りのシアー角度)
    zoom_range=0.0,                         # ランダムにズームする範囲
    channel_shift_range=0.0,                # ランダムに色調を変える範囲
    fill_mode='nearest',                    # 指定されたモードに応じて,入力画像の境界周りを埋める
    cval=0.0,                               # fill_mode = "constant"のときに境界周辺で利用される値
    horizontal_flip=False,                  # 水平方向に入力をランダムに反転
    vertical_flip=False,                    # 垂直方向に入力をランダムに反転
    rescale=1./255,                         # 画素値のリスケーリング係数
    preprocessing_function=None,            # 各入力に適用される関数
    data_format=None,                       # {"channels_first", "channels_last"}のいずれか
    validation_split=0.0                    # 検証のために予約しておく画像の割合
)

(参考サイト)白色化とは?

(参考サイト)データの前処理〜白色化 その2〜

(参考サイト)channel_shift_range

やれなかったこと

なんとなく ImageDataGeneratorメソッドを使うだけでしたが、どうもfor文で繰り返す回数を指定することで、水増しする枚数を指定できるようです。

ImageDataGeneratorを使っているのにカウントされる画像の枚数が特に増えていなかったのが気になっていたので、このテクニックを試したいと思います。

自分の狙った箇所で特徴をとらえているのか可視化するツールのようです。

余裕がなくて精度の数値だけでチェックしていましたが、もしかすると意図しない特徴量をとらえてたまたま精度が出ている可能性も捨てきれませんので、試していきたいと思いました。

  • ハイパーパラメータ hyperas
    勾配ブースティングでOptunaとかは使ったことがありますが、ディープラ-二ングでもハイパーパラメーターチューニングのツールがあるんですね。

  • ローカルGPUを使う
    自前のノートPCのGPUのメモリが2GBしかなく、確実にCuda Out of Memory になるので結局使いませんでした。
    CPUだと処理がめちゃくちゃ遅いので、お高いけどお金貯めて外付けGPUが欲しいなと思いました。
    なお、Goole Colaboはタダなのにめっちゃ使えますし、有料のAWSやGCPは素晴らしいと思うのですが、自宅のネット回線が弱いのでローカルがイイなと思いました。

参考図書

課題取り組み時に役だった/役立ちそうな本を紹介していきます。

現場のプロが伝える前処理技術 ~基礎から実践まで学ぶ テーブルデータ/自然言語/画像データの前処理

画像処理の前処理についても記載されています。

scikit-learn、Keras、TensorFlowによる実践機械学習 第2版

第2版の翻訳版が発売されたばっかりですが、画像系以外も機械学習の基礎知識から幅広くのっているし全てコードがGitHubでクローン可とのことで役立ちそうです。

ディジタル画像処理 第2版

画像系の理論が光学系からディープラーニングまで幅広くのっております。
コーディングには正直役立ちませんが、用語や理論背景の理解に役立ちそうです。

人工知能システムのプロジェクトがわかる本 企画・開発から運用・保守まで

AI導入に向けて気を付けるべきポイントがまとめられており、ビジネス課題に取り組むときの参考になりそうです。

以上になります、最後までお読みいただきありがとうございました。