Kerasで学習を中断した後、途中から再開する方法をご紹介します。
- モデルを学習途中(エポック単位)で出力する。
- 出力したモデルを読み込み学習を再開する。
目次
条件
- Windows 10 64bit
- Python 3.7.0
- Keras 2.1.2
- tensorflow 1.14.1
- matplotlib 3.1.0
モデルの出力
モデルを訓練する際に、model.fit()の「callbacks=」に「ModelCheckpoint」を指定することで、適宜モデルを出力することが出来ます。
サンプルソース
以下はサンプルソースです。
ModelCheckpoint()でモデルの出力先パス等を指定し、model.fitの「callbacks=」で渡します。
from __future__ import division, print_function
from keras.callbacks import ModelCheckpoint
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.utils import np_utils
import os
import matplotlib.pyplot as plt
BATCH_SIZE = 128
NUM_EPOCHS = 20
MODEL_DIR = "/tmp"
(Xtrain, ytrain), (Xtest, ytest) = mnist.load_data()
Xtrain = Xtrain.reshape(60000, 784).astype("float32") / 255
Xtest = Xtest.reshape(10000, 784).astype("float32") / 255
Ytrain = np_utils.to_categorical(ytrain, 10)
Ytest = np_utils.to_categorical(ytest, 10)
print(Xtrain.shape, Xtest.shape, Ytrain.shape, Ytest.shape)
# モデル定義
model = Sequential()
model.add(Dense(512, input_shape=(784,), activation="relu"))
model.add(Dropout(0.2))
model.add(Dense(512, activation="relu"))
model.add(Dropout(0.2))
model.add(Dense(10, activation="softmax"))
model.summary()
model.compile(optimizer="rmsprop", loss="categorical_crossentropy",
metrics=["accuracy"])
if not os.path.exists(MODEL_DIR): # ディレクトリが存在しない場合、作成する。
os.makedirs(MODEL_DIR)
checkpoint = ModelCheckpoint(
filepath=os.path.join(MODEL_DIR, "model-{epoch:02d}.h5"), save_best_only=True) # 精度が向上した場合のみ保存する。
# 学習実行
history = model.fit(Xtrain, Ytrain, batch_size=BATCH_SIZE, nb_epoch=NUM_EPOCHS,
validation_split=0.1, callbacks=[checkpoint])
# グラフ描画
# Accuracy
plt.plot(range(1, NUM_EPOCHS+1), history.history['acc'], "o-")
plt.plot(range(1, NUM_EPOCHS+1), history.history['val_acc'], "o-")
plt.title('model accuracy')
plt.ylabel('accuracy') # Y軸ラベル
plt.xlabel('epoch') # X軸ラベル
plt.legend(['train', 'test'], loc='upper left')
plt.show()
# loss
plt.plot(range(1, NUM_EPOCHS+1), history.history['loss'], "o-")
plt.plot(range(1, NUM_EPOCHS+1), history.history['val_loss'], "o-")
plt.title('model loss')
plt.ylabel('loss') # Y軸ラベル
plt.xlabel('epoch') # X軸ラベル
plt.legend(['train', 'test'], loc='upper right')
plt.show()
実行結果
ModelCheckpoint()で「save_best_only=True」としているため、精度が向上した場合のみモデルが保存されます。
今回は、エポック1,3,6でモデルが保存されました。
損失関数のグラフで確認すると以下のことが分かります。
- testに対する損失の最小値が更新されているのは、epoch:1,3,6。
- epoch:7以降は、testに対する損失は増加傾向にある。(過学習)
毎回出力
ModelCheckpoint()で「save_best_only=False」とすれば、epochごとにモデルを出力することが出来ます。
途中から学習実行
サンプルソース
以下のようにモデルをロードします。
- model.load_weights(os.path.join(MODEL_DIR, “model-07.h5”))
今回は、epoch:7のモデルを読み込んで、その後さらに20回学習を行います。
from __future__ import division, print_function
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.utils import np_utils
import os
import matplotlib.pyplot as plt
BATCH_SIZE = 128
NUM_EPOCHS = 20
MODEL_DIR = "/tmp"
(Xtrain, ytrain), (Xtest, ytest) = mnist.load_data()
Xtrain = Xtrain.reshape(60000, 784).astype("float32") / 255
Xtest = Xtest.reshape(10000, 784).astype("float32") / 255
Ytrain = np_utils.to_categorical(ytrain, 10)
Ytest = np_utils.to_categorical(ytest, 10)
print(Xtrain.shape, Xtest.shape, Ytrain.shape, Ytest.shape)
# モデル定義
model = Sequential()
model.add(Dense(512, input_shape=(784,), activation="relu"))
model.add(Dropout(0.2))
model.add(Dense(512, activation="relu"))
model.add(Dropout(0.2))
model.add(Dense(10, activation="softmax"))
model.summary()
model.compile(optimizer="rmsprop", loss="categorical_crossentropy",
metrics=["accuracy"])
# モデルの読み込み
model.load_weights(os.path.join(MODEL_DIR, "model-07.h5")) # epoch:7のモデルを指定
# 学習実行
history = model.fit(Xtrain, Ytrain, batch_size=BATCH_SIZE, nb_epoch=NUM_EPOCHS,
validation_split=0.1)
# グラフ描画
# Accuracy
plt.plot(range(1, NUM_EPOCHS+1), history.history['acc'], "o-")
plt.plot(range(1, NUM_EPOCHS+1), history.history['val_acc'], "o-")
plt.title('model accuracy')
plt.ylabel('accuracy') # Y軸ラベル
plt.xlabel('epoch') # X軸ラベル
plt.legend(['train', 'test'], loc='upper left')
plt.show()
# loss
plt.plot(range(1, NUM_EPOCHS+1), history.history['loss'], "o-")
plt.plot(range(1, NUM_EPOCHS+1), history.history['val_loss'], "o-")
plt.title('model loss')
plt.ylabel('loss') # Y軸ラベル
plt.xlabel('epoch') # X軸ラベル
plt.legend(['train', 'test'], loc='upper right')
plt.show()
実行結果
以下のグラフから、初めから学習した場合と比較して、損失が少ない値から開始されていることが分かります。
epoch:7のモデルを読み込んで20回学習
初めから学習した場合
以上のように、モデルを出力したりロードしたりすることで途中から学習を再開することが出来ます。
参考
Keras Documentation:コールバックの使い方
https://keras.io/ja/callbacks/
Keras Documentation:モデルについて
https://keras.io/ja/models/about-keras-models/

