概要
TensorFlow.keras(以下tf.keras)ではModel.fit()を実行してモデルの訓練を行います。
そのModel.fit()の引数にsteps_per_epochという項目があり、これにどんな値を与えれば良いのかを確認します。データ拡張などでImageDataGeneratorを使用することを前提としています。
ImageDataGenerator
tf.keras内のデータ拡張を簡単に行うことができるクラスです。ImageDataGeneratorは指定したバッチサイズ・画像の加工内容で無限にバッチを生成することができます。このバッチ生成は訓練時に行われるため、大規模データセットや比較的大きなバッチサイズでも使用するメモリを少なくし訓練を可能にします。
# インスタンスの作成 (画像の加工内容の指定)
train_datagen = ImageDataGenerator(
rescale=1./255,
rotation_range=30,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.1,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest'
)
train_generator = train_datagen.flow_from_directory(
TRAIN_DATA_DIR, # データセットがあるディレクトリ
target_size=(IMG_WIDTH, IMG_HEIGHT),
color_mode='rgb',
classes=CLASSES, # クラスの配列 ['dog', 'cat']など
class_mode='categorical',
batch_size=BATCH_SIZE # 1回のバッチ生成で作る画像数
)
ImageDataGeneratorはこのように使われます。classesは与えなくても自動的にディレクトリの構成で判断してくれる機能も備わっています。また、訓練データに対するgeneratorと検証データに対するgeneratorをそれぞれ用意することが一般的です。
ImageDataGeneratorを使用したfit()
ここからが本題です。以下はModel.fit()の実行例です。
# modelは作成したModelクラスのインスタンス (省略)
history = model.fit_generator(
train_generator,
steps_per_epoch=STEPS_PER_EPOCH, # ?
epochs=EPOCHS,
validation_data=validation_generator,
validation_steps=VALIDATION_STEPS # ?
)
第一引数には訓練データのgeneratorを指定します。その他で意味がわかりくいのはsteps_per_epochとvalidation_stepなどだと思います。
steps_per_epoch
各エポックのイテレーション回数を指定します。イテレーションは簡単に言うと各エポックで重みを更新する回数です。通常バッチごとに重みが更新されるので、各エポックでバッチを生成する回数に等しいです。steps_per_epochの値は1以上のint型であればどんな値でもエラーは出ないと思われます。デフォルトの値(None)は、画像数 ÷ バッチサイズで与えられます。
例を示すと以下になります。
1000(訓練用画像数) ÷ 10(バッチサイズ) = 100(steps_per_epoch)
簡単な計算ですが注意があります。
もし、**「データ拡張を使用して画像数を3倍にした」**と解説を添えた場合に、上の計算の総画像数はどうなるでしょうか?これを1000と3000のどちらに定義するのかが曖昧なのです。
色々な解説記事を見てみると、記事によってまちまちだと感じます。
なので、自分が実験で何を比較したいかなどを考えてから設定すべきなのかなーとも思います。それとも、デフォルトの値が生の訓練用画像数を用いて計算していることから「画像数を○倍にした」という解説自体がナンセンスなんでしょうか?自分には答えは出せません...。
どちらにしろ理解していることが重要だと思うので今回記事にさせていただきました。
ぼやき:研究で作成した小さなデータセットでデフォルトの値だと学習曲線がガタガタで何が起きているかわからない...
validation_steps
Model.fit()実行時に各epochの終了時点で検証データに対するlossとaccuracyが計算されます。その際に何回バッチを生成して値を求めるかをvalidation_stepsに与えます。デフォルト(None)ではsteps_per_epochと同様にデータセットの検証データの画像を全て使いきるような値に設定されます。( 検証用画像数 ÷ バッチサイズ )。検証用データには画像加工などを施さないことが一般的なので、こちらはNoneを指定して問題ないと思います。
補足
以前はImageDataGeneratorのデータ拡張を使用した際の訓練はModel.fit_generator()が使用されていましたが、現在はModel.fit()もgeneratorを使用した訓練のサポートがされているため、そちらを使おうという方針になっています。(2020/11/25)
※記事に誤りがあった場合は修正または削除で対応します※