トレーニング済みのKerasモデルを読み込んでトレーニングを続行する


98

部分的にトレーニングされたKerasモデルを保存し、モデルを再度ロードした後でトレーニングを続行できるかどうか疑問に思いました。

これは、将来的にトレーニングデータが増え、モデル全体を再トレーニングしたくないためです。

私が使用している機能は次のとおりです。

#Partly train model
model.fit(first_training, first_classes, batch_size=32, nb_epoch=20)

#Save partly trained model
model.save('partly_trained.h5')

#Load partly trained model
from keras.models import load_model
model = load_model('partly_trained.h5')

#Continue training
model.fit(second_training, second_classes, batch_size=32, nb_epoch=20)

編集1:完全に機能する例を追加

10エポック後の最初のデータセットでは、最後のエポックの損失は0.0748で、精度は0.9863です。

モデルを保存、削除、再ロードすると、2番目のデータセットでトレーニングされたモデルの損失と精度はそれぞれ0.1711と0.9504になります。

これは、新しいトレーニングデータまたは完全に再トレーニングされたモデルが原因ですか?

"""
Model by: http://machinelearningmastery.com/
"""
# load (downloaded if needed) the MNIST dataset
import numpy
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense
from keras.utils import np_utils
from keras.models import load_model
numpy.random.seed(7)

def baseline_model():
    model = Sequential()
    model.add(Dense(num_pixels, input_dim=num_pixels, init='normal', activation='relu'))
    model.add(Dense(num_classes, init='normal', activation='softmax'))
    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    return model

if __name__ == '__main__':
    # load data
    (X_train, y_train), (X_test, y_test) = mnist.load_data()

    # flatten 28*28 images to a 784 vector for each image
    num_pixels = X_train.shape[1] * X_train.shape[2]
    X_train = X_train.reshape(X_train.shape[0], num_pixels).astype('float32')
    X_test = X_test.reshape(X_test.shape[0], num_pixels).astype('float32')
    # normalize inputs from 0-255 to 0-1
    X_train = X_train / 255
    X_test = X_test / 255
    # one hot encode outputs
    y_train = np_utils.to_categorical(y_train)
    y_test = np_utils.to_categorical(y_test)
    num_classes = y_test.shape[1]

    # build the model
    model = baseline_model()

    #Partly train model
    dataset1_x = X_train[:3000]
    dataset1_y = y_train[:3000]
    model.fit(dataset1_x, dataset1_y, nb_epoch=10, batch_size=200, verbose=2)

    # Final evaluation of the model
    scores = model.evaluate(X_test, y_test, verbose=0)
    print("Baseline Error: %.2f%%" % (100-scores[1]*100))

    #Save partly trained model
    model.save('partly_trained.h5')
    del model

    #Reload model
    model = load_model('partly_trained.h5')

    #Continue training
    dataset2_x = X_train[3000:]
    dataset2_y = y_train[3000:]
    model.fit(dataset2_x, dataset2_y, nb_epoch=10, batch_size=200, verbose=2)
    scores = model.evaluate(X_test, y_test, verbose=0)
    print("Baseline Error: %.2f%%" % (100-scores[1]*100))

3
あなたはそれをテストしましたか?それが機能しない理由はわかりません。
maz 2017年

私が今見ているのは、モデルをロードした後、精度が約10%低下することです(最初のエポックでのみ)。リロードが機能する場合、これはもちろん新しいトレーニングデータが原因です。しかし、私はこれが確かに事実であることを確認したいだけです。
Wilmar van Ommeren 2017年

7
model.saveでモデルを直接保存していますか、それともモデルチェックポイント(keras.io/callbacks/#example-model-checkpoints)を使用していますか?model.saveを使用している場合、最良のモデル(最も低いエラー)ではなく最新のモデル(つまり、最後のエポック)を保存する可能性がありますか?実際のコードを提供できますか?
maz 2017年

最高のモデルではなく、最新のモデルを保存しています(この時点まで、それが可能かどうかはわかりませんでした)。いくつかのコードを準備します
Wilmar van Ommeren 2017年

3
それをリロードして、同じ列車データで訓練を続けることができませんでしたか?これにより、結果が同等である場合はリロードが正常であることを確認できます。
MarcinMożejko2017年

回答:


36

実際に- model.saveあなたのケースでトレーニングを再開するために必要なすべての情報を保存します。モデルのリロードによって台無しになる可能性があるのは、オプティマイザの状態だけです。それを確認するには- saveモデルをリロードしてトレーニングデータでトレーニングしてください。


1
@Marcin:kerasを使用する場合save()、モデルの最良の結果(最小の損失)またはモデルの最後の結果(最終更新)を保存しますか?感謝
Lion Lai

5
最後の更新。モデルチェックポイントコールバックは、最適なものを保存するためのものです。
ホリー2017年

2
@Khajこのkeras.io/callbacks/#modelcheckpointを参照してますか?デフォルトでは、最後の更新が保存されるようです(最適な更新ではありません)。がsave_best_only=True明示的に設定されている場合にのみ、最適なものが保存されます。
flow2k

7

問題は、別のオプティマイザ、またはオプティマイザへの別の引数を使用していることである可能性があります。カスタムの事前トレーニング済みモデルで同じ問題が発生しただけで、

reduce_lr = ReduceLROnPlateau(monitor='loss', factor=lr_reduction_factor,
                              patience=patience, min_lr=min_lr, verbose=1)

事前学習済みモデルの場合、元の学習率は0.0003から始まり、事前学習中はmin_learning率(0.000003)に減少します。

その行を、事前トレーニング済みのモデルを使用するスクリプトにコピーしたところ、精度が非常に悪くなりました。事前トレーニング済みモデルの最後の学習率が最小学習率、つまり0.000003であることに気づくまで。そして、その学習率で開始すると、事前学習済みモデルの出力とまったく同じ精度が得られます-これは理にかなっていますモデルを使用すると、GDが大幅にオーバーシュートし、精度が大幅に低下します。


5

上記の回答のほとんどは重要なポイントをカバーしています。最近のTensorflow(TF2.1以上)を使用している場合は、次の例が役立ちます。コードのモデル部分はTensorflowウェブサイトからのものです。

import tensorflow as tf
from tensorflow import keras
mnist = tf.keras.datasets.mnist

(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

def create_model():
  model = tf.keras.models.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28)),
    tf.keras.layers.Dense(512, activation=tf.nn.relu),  
    tf.keras.layers.Dropout(0.2),
    tf.keras.layers.Dense(10, activation=tf.nn.softmax)
    ])

  model.compile(optimizer='adam', loss='sparse_categorical_crossentropy',metrics=['accuracy'])
  return model

# Create a basic model instance
model=create_model()
model.fit(x_train, y_train, epochs = 10, validation_data = (x_test,y_test),verbose=1)

モデルを* .tf形式で保存してください。私の経験から、custom_lossが定義されている場合、*。h5形式はオプティマイザのステータスを保存しないため、モデルを残したところから再トレーニングする場合は目的に役立ちません。

# saving the model in tensorflow format
model.save('./MyModel_tf',save_format='tf')


# loading the saved model
loaded_model = tf.keras.models.load_model('./MyModel_tf')

# retraining the model
loaded_model.fit(x_train, y_train, epochs = 10, validation_data = (x_test,y_test),verbose=1)

このアプローチでは、モデルを保存する前に、トレーニングを再開します。他の人が述べたように、あなたが最良のモデルの重みを保存したい場合や、モデルの重みに、次のようなオプションでkerasコールバック機能(ModelCheckpoint)を使用する必要があり、すべてのエポックを保存したいsave_weights_only=Truesave_freq='epoch'save_best_only

詳細については、こちらと別の例をこちらで確認しください。


1
いいですね、これは非常に有望に見えます-情報に感謝します。この例では、トレーニングに使用したのと同じデータでモデルを再トレーニングしているように見えます。もしそうなら、正しいアプローチは再トレーニングするトレーニングデータの新しいサブセットをロードすることだと思いましたか?(プロセスに導入される新しい情報を反映するために)?
bibzzzz

1
@bibzzzz同意します。とても良いコメント。パフォーマンスを向上させるために、同じデータで再トレーニングを実演したいと思いました。要点は、モデルを保存する前に停止した場合のパフォーマンスの改善を明確に示しています。さまざまなデータを再トレーニングすることについては完全に同意します。後で試す予定です。ありがとう!
Vishnuvardhan Janapati

すばらしい-これは非常にうまく実証されました。ありがとうございます。
bibzzzz

2

ここに示すように、Kerasはロードされたモデルに問題がある場合があることに注意してください。これは、トレーニングされた同じ精度から開始しない場合を説明する場合があります。


1

上記のすべてが役立つので、モデルと重みが保存されたときに、LRと同じ学習率()から再開する必要あります。オプティマイザで直接設定します。

モデルがローカルな最小値に到達している可能性があるため、そこからの改善は保証されないことに注意してください。制御された方法で学習率を上げて、モデルを遠くない距離にあるより良い最小値にナッジすることを意図していない限り、別の局所最小値を検索するためにモデルを再開する意味はありません。


何故ですか?以前よりも小さいLRを使用できませんか?
lte__

実際には、トレーニングを続けると、より多くのデータを受け取った場合に、より良いモデルが得られる場合があります。したがって、別の極小値を検索するためにモデルを再開するポイントがあります。
Corey Levinson、

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.