#はじめに
久しぶりにTensorFlow(Keras)を触ったら忘れていることが多かったので、簡単にメモとして残しておきます。
##学習の流れ
TensorFlow(以下TF)では、
① データセットの準備
② モデルの準備
③ model.compile でoptimizer, loss, metricsの指定
④ callbacksの指定
⑤ model.fitで学習開始
⑥ model.evaluate でテストの評価
⑦ 画像の予想確率だけ得るときは model.predict
のような流れです。
これは比較的簡単な書き方です。もう少し細かいところまで記述したい場合は、以前に記事を書きましたので参考にしてみてください。
##① データセットの準備
ディレクトリに画像を保存しておいてそこから読み込むには、flow_from_directory()を用います。
その前にImageDataGeneratorを使用し、augmentationの中身を記述します。
train_datagen = ImageDataGenerator(
            rescale=1./255,
            zoom_range=0.2,
            horizontal_flip=True,
            rotation_range=20,
            width_shift_range=0.2,
            height_shift_range=0.2,
            )
val_datagen = ImageDataGenerator(rescale=1./255)
train_generator = train_datagen.flow_from_directory(
            TRAIN_DIR,
            target_size=(img_size, img_size),
            batch_size=batch_size,
            classes=classes,
            class_mode='categorical')
val_generator = val_datagen.flow_from_directory(
            VAL_DIR,
            target_size=(img_size,img_size),
            batch_size=batch_size,
            classes=classes,
            class_mode='categorical')
*クラスラベルについては、train_generator.class_indicesのようにすると取得可能。クラスの対応表が出力できます。基本的にはアルファベット順。
以下のように使用できる augmentationは多いので各自タスクに合わせて決めてください。
詳しく知りたい人は、公式ドキュメントで確認してください。
tf.keras.preprocessing.image.ImageDataGenerator(
    featurewise_center=False, samplewise_center=False,
    featurewise_std_normalization=False, samplewise_std_normalization=False,
    zca_whitening=False, zca_epsilon=1e-06, rotation_range=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,
    horizontal_flip=False, vertical_flip=False, rescale=None,
    preprocessing_function=None, data_format=None, validation_split=0.0, dtype=None
)
flow_from_directoryでは、ディレクトリのパスを指定して、オーギュメントされた画像がバッチサイズごとに生成されます。
flow_from_directory(
    directory, target_size=(256, 256), color_mode='rgb', classes=None,
    class_mode='categorical', batch_size=32, shuffle=True, seed=None,
    save_to_dir=None, save_prefix='', save_format='png',
    follow_links=False, subset=None, interpolation='nearest'
)
class_mode : categorical, binary, sparse, input, None が選択可能。デフォは,categorical.
shuffle : Flaseならアルファベット順
save_to_dir : None or str(default:None). ディレクトリを指定することによって augmented data を保存してくれる。可視化に役に立つ。
save_prefix : str. 保存された画像のファイル名に使う。(save_to_dirが設定されている場合有効)
save_format : png or jpeg (Default:'png')
interpolation : nearest(デフォルト), bilinear, bicubic
##② モデルの準備
今回は例として、MobileNetv2を使います。tf.keras.applicationsに他の学習済みモデルもあります。
IMG_SHAPE = (img_size, img_size, channels)
base_model = tf.keras.applications.MobileNetV2(input_shape=IMG_SHAPE,
                                            include_top=False,
                                            weights='imagenet')
global_average_layer = tf.keras.layers.GlobalAveragePooling2D()
prediction_layer = tf.keras.layers.Dense(n_classes, activation='softmax')
model = tf.keras.Sequential([
            base_model,
            global_average_layer,
            prediction_layer
            ])
##③ model.compile で optimizer, loss, metricsの指定
modelに対して学習の詳細を設定します。
model.compile(optimizer=optimizers.SGD(lr=0.0001, momentum=0.99, decay=0, nesterov=True),
            loss='categorical_crossentropy',
            metrics=['accuracy'])
compile(
    optimizer='rmsprop', loss=None, metrics=None, loss_weights=None,
    weighted_metrics=None, run_eagerly=None, steps_per_execution=None, **kwargs
)
optimizer : string or optimizer instance (default: rmsprop)
画像系のタスクだと個人的には、SGDかな?
ex) SGD, RMSprop, Adam, Adadelta,...
sgd = tf.keras.optimizers.SGD(
    learning_rate=0.01, momentum=0.0, nesterov=False, name='SGD', **kwargs
)
*このsgdを model.compileのoptimizerに設定する
loss : string, object function or tf.keras.losses.Loss instance
metrics : trainingとtestで使用するmetricsのリスト
loss_weights : ロスに重み付けする
##④ callbacksの指定
CSVLogger, History, ProgbarLogger, TensorBoard, EarlyStopping, ReduceLROnPlateau など設定できます。
model.fitで学習する際に渡すことができます。詳しくは公式ドキュメントをご確認ください。
例をいくつか挙げておきます。
tf.keras.callbacks.EarlyStopping(
    monitor='val_loss', min_delta=0, patience=0, verbose=0,
    mode='auto', baseline=None, restore_best_weights=False
)
tf.keras.callbacks.ModelCheckpoint(
    filepath, monitor='val_loss', verbose=0, save_best_only=False,
    save_weights_only=False, mode='auto', save_freq='epoch',
    options=None, **kwargs
)
filepath : string or PathLike, モデルを保存するパス。指定できる変数は、epoch, loss, acc, val_loss, val_accです。
ex) filepath = '{val_loss:.2f}-{val_acc:.2f}.hdf5'
monitor : 何を基準にモデルを保存するか。accuracy, val_accuracy, loss, val_loss
*もし metrics name が分からなかったら、 history = model.fit() で history.historyを確認。
mode : {auto, min, max}
save_best_only : もし、filepathが{epoch}のようなフォーマットを含んでいなかったら、filepathはオーバーライドされる
save_weights_only : modelの重みのみ保存
save_freq : epoch, or integer.
tf.keras.callbacks.LearningRateScheduler(
    schedule, verbose=0
)
tf.keras.callbacks.ReduceLROnPlateau(
    monitor='val_loss', factor=0.1, patience=10, verbose=0,
    mode='auto', min_delta=0.0001, cooldown=0, min_lr=0, **kwargs
)
tf.keras.callbacks.RemoteMonitor(
    root='http://localhost:9000', path='/publish/epoch/end/',
    field='data', headers=None, send_as_json=False
)
tf.keras.callbacks.CSVLogger(
    filename, separator=',', append=False
)
##⑤ model.fitで学習開始
例
history = model.fit(
        train_generator,
        steps_per_epoch=steps_per_epoch,
        validation_data=val_generator,
        validation_steps=validation_steps,
        epochs=CONFIG.epochs,
        shuffle=True,
        callbacks=[cp_callback])
fit(
    x=None, y=None, batch_size=None, epochs=1, verbose=1, callbacks=None,
    validation_split=0.0, validation_data=None, shuffle=True, class_weight=None,
    sample_weight=None, initial_epoch=0, steps_per_epoch=None,
    validation_steps=None, validation_batch_size=None, validation_freq=1,
    max_queue_size=10, workers=1, use_multiprocessing=False
)
validation_split : [0~1]. training dataの一部をa validation data とする。x, yの後ろのデータが用いられる(シャッフルする前)。
validation_data : validation data. validation_splitがある場合はオーバーライドされる
class_weight : データが少ないクラスのlossに重きを置く方法。辞書型で渡す。例) {0:0.66, 1:1.33}
steps_per_epoch : Integer or None. training data // batch_size で求められる。
validation_steps : Integer or None. validation data // batch_size で求められる。
##⑥ model.evaluate でテストの評価
test_loss, test_acc = model.evaluate(test_generator, steps=test_steps)
evaluate(
    x=None, y=None, batch_size=None, verbose=1, sample_weight=None, steps=None,
    callbacks=None, max_queue_size=10, workers=1, use_multiprocessing=False,
    return_dict=False
)
x : 入力データ。 Numpy array, tensor, tf.data.dataset, (inputs, targets) or (inputs, targets, sample_weights)
y : ターゲットデータ。
batch_size : Integer or None.
verbose :  0 or 1. Verbosity mode. 0 = silent, 1 = progress bar.
sample_weight :
steps : Integer or None
callbacks : list of keras.callbacks.Callback instances
max_queue_size : Integer.
workers : Integer.
use_multiprocessing : boolean
return_dict : もしTrueなら、metric results をdictで返す
##⑦ 画像の予想確率だけ得るときは model.predict
predict(
    x, batch_size=None, verbose=0, steps=None, callbacks=None, max_queue_size=10,
    workers=1, use_multiprocessing=False
)
##+α
####<<モデルを保存した際に作成されるファイルについて>>
checkpoint : 1ファイルのみ作成。どのファイルが最新か確認可能。学習の際に必要なのでテストの際はなくても大丈夫。保存したデータから再度学習を始める場合に必要。
XXXXX.data-0000-of-00001 : 変数名をテンソル値としてマッピングした独自のフォーマット。
XXXXX.index : このファイルはバイナリファイル。複数のステップでデータを保存した際に同名の「.data-0000-of-00001」ファイルが、どのステップのどのデータであるか一意に定まる。
#終わりに
細かい設定まで今回目を通すことができて良い機会になりました。
#参考文献
