CV・NLPハマりどころメモ

画像認識と自然言語処理を研究する中でうまくいかなかったことと、その対策をまとめる自分用メモが中心。

自前で用意した花画像を使ってKerasでCNN~学習編~[Keras][CNN][深層学習][Python]

昨今様々な深層学習ライブラリが台頭してきたことにより,最新のソースコードも様々なライブラリを用いて書かれることが大きなって来た.

この為,いつも使っているpytorch以外のライブラリも触れるようにしておかなければならないと感じるようになった.

そこで本記事では,tensorflowをバックエンドとし,コードが書きやすいことで有名なkerasで簡単なCNNを,自前画像で動かしてみることにした.

自前画像の用意

今回は,kaggleから花の画像をダウンロードしてきてから学習を行う.

以下花の画像のリンク

https://www.kaggle.com/alxmamaev/flowers-recognition

花の画像は,6種類・合計4,242枚の画像で構成されており,ファイルサイズも224MBと軽い為,新しいライブラリや実験用のプログラムの検証用として使いやすいデータセットだ.

画像のサイズはバラバラだが,後にkerasのflow_from_directory関数を使用し,整形化するので問題無い.

flowers-recognition.zipをダウンロード後,以下のようにtrainとtestに画像を手動で分けて配置した.割合は8:2

flower
├─test
│  ├─daisy 153 files
│  ├─dandelion 211 files
│  ├─rose 156 files
│  ├─sunflowers 146 files
│  └─tulips 196 files
└─train
    ├─daisy 616 files
    ├─dandelion 844 files
    ├─rose 628 files
    ├─sunflower 588 files
    └─tulip 788 files

学習

qiita.com

上の方のコードを一部修正し,使わせて頂く.

import numpy as np

from keras.preprocessing.image import load_img, img_to_array
from keras.applications.vgg16 import VGG16
from keras.models import Sequential, Model
from keras.layers import Input, Dense, Dropout, Activation, Flatten
from keras.optimizers import SGD
from keras.utils import np_utils
from keras.preprocessing.image import ImageDataGenerator


# 分類クラス
classes = ['daisy', 'dandelion', 'roses', 'sunflowers', 'tulips']
nb_classes = len(classes)
batch_size = 32
nb_epoch = 1

# 画像のサイズ
img_rows, img_cols = 224, 224

# モデルの構築
def build_model() :
    # 画像の読み込み.今回はカラー画像の為,shapeの3番目の引数が3(ch)
    input_tensor = Input(shape=(img_rows, img_cols, 3))
    # VGG16はモデルの名前.引数weightsでpre-trainingしている
    vgg16 = VGG16(include_top=False, weights='imagenet', input_tensor=input_tensor)

    # Sequentialは単純に,前の層の全ノードから矢印を引っ張ってくるモデルを意味している
    # 矢印のつなぎ方を複雑にするには,Functional APIを使う
    # https://qiita.com/Ishotihadus/items/e28dd461a8ba27a2676e
    _model = Sequential()

    _model.add(Flatten(input_shape=vgg16.output_shape[1:]))
    _model.add(Dense(256, activation='relu'))
    _model.add(Dropout(0.5))
    _model.add(Dense(nb_classes, activation='softmax'))

    model = Model(inputs=vgg16.input, outputs=_model(vgg16.output))
    # modelの14層目までのモデル重み
    for layer in model.layers[:15]:
        layer.trainable = False

    # 損失関数と評価関数を指定
    # 評価関数に関して: https://keras.io/ja/metrics/#_3
    model.compile(loss='categorical_crossentropy',
                  optimizer=SGD(lr=1e-4, momentum=0.9), metrics=['accuracy'])
    return model

if __name__ == "__main__":
    # ImageDataGeneratorはリアルタイムにデータ拡張しながら,テンソル画像データのバッチを生成する
    # 要はデータの水増し(Data Augumentation)に関するオプションを指定している
    # https://keras.io/ja/preprocessing/image/#imagedatagenerator_1
    train_datagen = ImageDataGenerator(
        rescale=1.0 / 255, # 画素値のスケーリング
        shear_range=0.2, # 斜め方向(pi/x)に画像を引っ張る
        zoom_range=0.2, # ランダムにズーム
        horizontal_flip=True) # 水平方向にランダムに回転

    # train_generator: 指定したディレクトリから画像を読み込むときに使用する関数
    train_generator = train_datagen.flow_from_directory(
        directory= 'path/to/train',
        target_size=(img_rows, img_cols),
        color_mode='rgb',
        classes=classes,
        class_mode='categorical',
        batch_size=batch_size,
        shuffle=True)

    # 評価用画像の用意
    test_datagen = ImageDataGenerator(rescale=1.0 / 255)

    test_generator = test_datagen.flow_from_directory(
        directory= '/path/to/test',
        target_size=(img_rows, img_cols),
        color_mode='rgb',
        classes=classes,
        class_mode='categorical',
        batch_size=batch_size,
        shuffle=True)
    
    # インスタンスの呼び出し
    model = build_model()
    # model.fit() でモデルを学習
    model.fit_generator(
        train_generator, # 訓練データの配列
        steps_per_epoch=3000, # 終了した1エポックを宣言して次のエポックを始めるまでのステップ数の合計
        epochs=nb_epoch, # エポック(学習の繰り返し回数を指定)
        validation_data=test_generator, # 評価用データの指定
        validation_steps=600 # 停止する前にバリデーションするステップの総数
    )

    # 学習後のモデルを書き出し
    hdf5_file = "flower-model.hdf5"
    model.save_weights(hdf5_file)

上のコードを実行すると学習が開始する.

学習中はlossとaccuが徐々に更新されていく様子が観察できる.

結果

Found 1457 images belonging to 5 classes.
Found 706 images belonging to 5 classes.
Epoch 1/1
3000/3000 [==============================] - 1012s 337ms/step - loss: 0.1224 - acc: 0.9486 - val_loss: 6.0376 - val_acc: 0.4703

Accuracyが0.94.良い結果だ. 評価用のデータセットでのスコア(val_accu)は0.47...

次は,今回学習したモデルを使ってGoogle画像検索でダウンロードした花の画像の識別をさせてみる.