TensorFlow : Tutorials : Keras : モデルをセーブしてリストアする (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 08/28/2018
* TensorFlow 1.10 で更に改訂されています。
* TensorFlow 1.9 でドキュメント構成が変更され、数篇が新規に追加されましたので再翻訳しました。
* 本ページは、TensorFlow の本家サイトの Tutorials – Learn and use ML – Save and restore models
を翻訳した上で適宜、補足説明したものです:
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
モデルの進捗は訓練の間に — そして後に — セーブすることが可能です。これは、モデルが (訓練を) 中止したところから再開できて長い訓練時間を回避できることを意味します。セービングはまた貴方がモデルを共有して他の人は貴方のワークを再作成できることもまた意味します。研究モデルとテクニックを公開するとき、多くの機械学習実践者は以下を共有します :
- モデルを作成するためのコード、そして
- モデルのために訓練された重み、またはパラメータ
このデータの共有は他の人たちがモデルがどのように動作するかを理解して新しいデータで彼ら自身がそれを試す手助けとなります。
セットアップ
インストールとインポート
TensorFlow と依存関係をインストールしてインポートします :
!pip install -q h5py pyyaml
You are using pip version 10.0.1, however version 18.0 is available. You should consider upgrading via the 'pip install --upgrade pip' command.
from __future__ import absolute_import, division, print_function import os import tensorflow as tf from tensorflow import keras tf.__version__
'1.9.0'
サンプル・データセットを取得する
重みのセーブを示すために MNIST データセットを使用してモデルを訓練します。これらのデモの実行をスピードアップするために、最初の 1000 サンプルだけを使用します :
(train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.mnist.load_data() train_labels = train_labels[:1000] test_labels = test_labels[:1000] train_images = train_images[:1000].reshape(-1, 28 * 28) / 255.0 test_images = test_images[:1000].reshape(-1, 28 * 28) / 255.0
Downloading data from https://s3.amazonaws.com/img-datasets/mnist.npz 11493376/11490434 [==============================] - 2s 0us/step
モデルを定義する
セーブと重みのロードを示すために使用する単純なモデルを構築しましょう。
# Returns a short sequential model def create_model(): model = tf.keras.models.Sequential([ keras.layers.Dense(512, activation=tf.nn.relu, input_shape=(784,)), keras.layers.Dropout(0.2), keras.layers.Dense(10, activation=tf.nn.softmax) ]) model.compile(optimizer=tf.keras.optimizers.Adam(), loss=tf.keras.losses.sparse_categorical_crossentropy, metrics=['accuracy']) return model # Create a basic model instance model = create_model() model.summary()
_________________________________________________________________ Layer (type) Output Shape Param # ================================================================= dense (Dense) (None, 512) 401920 _________________________________________________________________ dropout (Dropout) (None, 512) 0 _________________________________________________________________ dense_1 (Dense) (None, 10) 5130 ================================================================= Total params: 407,050 Trainable params: 407,050 Non-trainable params: 0 _________________________________________________________________
訓練の間にチェックポイントをセーブする
主要なユースケースは訓練の間と最後にチェックポイントを自動的にセーブすることです。このように訓練されたモデルをそれを再訓練しなければならないことなく、あるいは — 訓練プロセスが中断された場合には — 中止したところから訓練を選択して使用することができます。
tf.keras.callbacks.ModelCheckpoint はこのタスクを遂行する callback です。この callback はチェックポイントを構成するために 2, 3 の引数を取ります。
Checkpoint callback 使用方法
モデルを訓練してそれを ModelCheckpoint チェックポイントに渡します :
checkpoint_path = "training_1/cp.ckpt" checkpoint_dir = os.path.dirname(checkpoint_path) # Create checkpoint callback cp_callback = tf.keras.callbacks.ModelCheckpoint(checkpoint_path, save_weights_only=True, verbose=1) model = create_model() model.fit(train_images, train_labels, epochs = 10, validation_data = (test_images,test_labels), callbacks = [cp_callback]) # pass callback to training
Train on 1000 samples, validate on 1000 samples Epoch 1/10 1000/1000 [==============================] - 0s 342us/step - loss: 1.1603 - acc: 0.6670 - val_loss: 0.6827 - val_acc: 0.7880 Epoch 00001: saving model to training_1/cp.ckpt Epoch 2/10 1000/1000 [==============================] - 0s 129us/step - loss: 0.4071 - acc: 0.8860 - val_loss: 0.5841 - val_acc: 0.8110 Epoch 00002: saving model to training_1/cp.ckpt Epoch 3/10 1000/1000 [==============================] - 0s 118us/step - loss: 0.2796 - acc: 0.9350 - val_loss: 0.4610 - val_acc: 0.8520 Epoch 00003: saving model to training_1/cp.ckpt Epoch 4/10 1000/1000 [==============================] - 0s 121us/step - loss: 0.2025 - acc: 0.9570 - val_loss: 0.4324 - val_acc: 0.8610 Epoch 00004: saving model to training_1/cp.ckpt Epoch 5/10 1000/1000 [==============================] - 0s 117us/step - loss: 0.1489 - acc: 0.9690 - val_loss: 0.4290 - val_acc: 0.8620 Epoch 00005: saving model to training_1/cp.ckpt Epoch 6/10 1000/1000 [==============================] - 0s 127us/step - loss: 0.1194 - acc: 0.9780 - val_loss: 0.4143 - val_acc: 0.8700 Epoch 00006: saving model to training_1/cp.ckpt Epoch 7/10 1000/1000 [==============================] - 0s 118us/step - loss: 0.0845 - acc: 0.9860 - val_loss: 0.4208 - val_acc: 0.8670 Epoch 00007: saving model to training_1/cp.ckpt Epoch 8/10 1000/1000 [==============================] - 0s 118us/step - loss: 0.0648 - acc: 0.9910 - val_loss: 0.4078 - val_acc: 0.8680 Epoch 00008: saving model to training_1/cp.ckpt Epoch 9/10 1000/1000 [==============================] - 0s 121us/step - loss: 0.0531 - acc: 0.9970 - val_loss: 0.4184 - val_acc: 0.8670 Epoch 00009: saving model to training_1/cp.ckpt Epoch 10/10 1000/1000 [==============================] - 0s 121us/step - loss: 0.0391 - acc: 0.9960 - val_loss: 0.4185 - val_acc: 0.8640 Epoch 00010: saving model to training_1/cp.ckpt
これは、各エポックの最後に更新される TensorFlow チェックポイント・ファイルの単一のコレクションを作成します :
!ls {checkpoint_dir}
checkpoint cp.ckpt.data-00000-of-00001 cp.ckpt.index
新しい、未訓練のモデルを作成しましょう。重みだけからモデルをリストアするときは、元のモデルと同じアーキテクチャを持つモデルを持たなければなりません。それは同じモデル・アーキテクチャですから、それがモデルの異なるインスタンスであるにもかかわらず重みを共有することができます。
さて未使用の、未訓練のモデルを再構築して、それをテストセット上で評価しましょう。未訓練モデルは偶然レベル (~10% 精度) で遂行します :
model = create_model() loss, acc = model.evaluate(test_images, test_labels) print("Untrained model, accuracy: {:5.2f}%".format(100*acc))
1000/1000 [==============================] - 0s 105us/step Untrained model, accuracy: 7.20%
それからチェックポイントから重みをロードして、再評価します :
model.load_weights(checkpoint_path) loss,acc = model.evaluate(test_images, test_labels) print("Restored model, accuracy: {:5.2f}%".format(100*acc))
1000/1000 [==============================] - 0s 24us/step Restored model, accuracy: 86.40%
Checkpoint callback オプション
callback は結果としてのチェックポイントに一意の名前を与えて、チェックポイントする頻度を調整するために幾つかのオプションを提供します。
新しいモデルを訓練して、一意に名前付けられたチェックポイントを 5 エポック毎に一度セーブします :
# include the epoch in the file name. (uses `str.format`) checkpoint_path = "training_2/cp-{epoch:04d}.ckpt" checkpoint_dir = os.path.dirname(checkpoint_path) cp_callback = tf.keras.callbacks.ModelCheckpoint( checkpoint_path, verbose=1, save_weights_only=True, # Save weights, every 5-epochs. period=5) model = create_model() model.fit(train_images, train_labels, epochs = 50, callbacks = [cp_callback], validation_data = (test_images,test_labels), verbose=0)
Epoch 00005: saving model to training_2/cp-0005.ckpt Epoch 00010: saving model to training_2/cp-0010.ckpt Epoch 00015: saving model to training_2/cp-0015.ckpt Epoch 00020: saving model to training_2/cp-0020.ckpt Epoch 00025: saving model to training_2/cp-0025.ckpt Epoch 00030: saving model to training_2/cp-0030.ckpt Epoch 00035: saving model to training_2/cp-0035.ckpt Epoch 00040: saving model to training_2/cp-0040.ckpt Epoch 00045: saving model to training_2/cp-0045.ckpt Epoch 00050: saving model to training_2/cp-0050.ckpt
今、結果としてのチェックポイントを見てみましょう (変更日時によりソート) :
import pathlib # Sort the checkpoints by modification time. checkpoints = pathlib.Path(checkpoint_dir).glob("*.index") checkpoints = sorted(checkpoints, key=lambda cp:cp.stat().st_mtime) checkpoints = [cp.with_suffix('') for cp in checkpoints] latest = str(checkpoints[-1]) checkpoints
[PosixPath('training_2/cp-0030.ckpt'), PosixPath('training_2/cp-0035.ckpt'), PosixPath('training_2/cp-0040.ckpt'), PosixPath('training_2/cp-0045.ckpt'), PosixPath('training_2/cp-0050.ckpt')]
Note: デフォルトの tensorflow フォーマットは 5 つの直近のチェックポイントだけをセーブします。
テストするためには、モデルをリセットして最新のチェックポイントをロードします :
model = create_model() model.load_weights(latest) loss, acc = model.evaluate(test_images, test_labels) print("Restored model, accuracy: {:5.2f}%".format(100*acc))
1000/1000 [==============================] - 0s 82us/step Restored model, accuracy: 87.80%
これらのファイルは何でしょう?
上のコードは重みを (訓練された重みだけをバイナリ形式で含む) チェックポイント形式ファイルのコレクションにストアします。チェックポイントは次を含みます : * モデルの重みを含む一つまたはそれ異常のシャード。* どの重みがどのシャードにストアされているかを指し示すインデックスファイル。
単一のマシン上でモデルを訓練しているだけであれば、サフィックス: .data-00000-of-00001 を持つ一つのシャードを持つでしょう。
重みを手動でセーブする
上で重みをどのようにモデルにロードするかを見ました。
手動で重みをセーブするのは同様に単純で、Model.save_weights メソッドを使用します。
# Save the weights model.save_weights('./checkpoints/my_checkpoint') # Restore the weights model = create_model() model.load_weights('./checkpoints/my_checkpoint') loss,acc = model.evaluate(test_images, test_labels) print("Restored model, accuracy: {:5.2f}%".format(100*acc))
1000/1000 [==============================] - 0s 59us/step Restored model, accuracy: 87.80%
モデル全体をセーブする
モデル全体を、重み値、モデルの構成 (= configuration)、そして optimizer の構成さえも含むファイルにセーブできます。これは元のコードへのアクセスなしにモデルをチェックポイントして後で訓練を — 正確に同じ状態から — 再開することを可能にします。
Keras の完全に機能するモデルのセーブは非常に有用です — それらを TensorFlow.js にロードしてから web ブラウザでそれらを訓練して実行することができます。
Keras は標準 HDF5 を使用した基本的なセーブ・フォーマットを提供します。私達の目的のためには、セーブされたモデルは単一のバイナリ・ブロブとして扱うことができます。
model = create_model() model.fit(train_images, train_labels, epochs=5) # Save entire model to a HDF5 file model.save('my_model.h5')
Epoch 1/5 1000/1000 [==============================] - 0s 317us/step - loss: 1.1730 - acc: 0.6640 Epoch 2/5 1000/1000 [==============================] - 0s 109us/step - loss: 0.4257 - acc: 0.8790 Epoch 3/5 1000/1000 [==============================] - 0s 106us/step - loss: 0.2889 - acc: 0.9240 Epoch 4/5 1000/1000 [==============================] - 0s 104us/step - loss: 0.2171 - acc: 0.9390 Epoch 5/5 1000/1000 [==============================] - 0s 106us/step - loss: 0.1615 - acc: 0.9670
さてそのファイルからモデルを再作成します :
# Recreate the exact same model, including weights and optimizer. new_model = keras.models.load_model('my_model.h5') new_model.summary()
_________________________________________________________________ Layer (type) Output Shape Param # ================================================================= dense_12 (Dense) (None, 512) 401920 _________________________________________________________________ dropout_6 (Dropout) (None, 512) 0 _________________________________________________________________ dense_13 (Dense) (None, 10) 5130 ================================================================= Total params: 407,050 Trainable params: 407,050 Non-trainable params: 0 _________________________________________________________________
その精度を確認します :
loss, acc = new_model.evaluate(test_images, test_labels) print("Restored model, accuracy: {:5.2f}%".format(100*acc))
1000/1000 [==============================] - 0s 78us/step Restored model, accuracy: 86.60%
このテクニックは総てをセーブします :
- 重み値。
- モデルの構成 (= configuration) (アーキテクチャ)
- optimizer 構成
Keras はアーキテクチャを調べてモデルをセーブします。現在、TensorFlow optimizer (from tf.train) をセーブすることはできません。それらを使用するときはモデルをロードした後で再コンパイルする必要があり optimizer の状態を解き放つでしょう。
以上