TensorFlow 2.0 Alpha : Beginner Tutorials : ML 基本 :- モデルをセーブしてリストアする (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 03/31/2019
* 本ページは、TensorFlow の本家サイトの TF 2.0 Alpha – Beginner Tutorials – ML basics の以下のページを翻訳した上で
適宜、補足説明したものです:
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
ML 基本 :- モデルをセーブしてリストアする
モデルの進捗は訓練の間に — そして後に — セーブすることが可能です。これは、モデルが (訓練を) 中止したところから再開できて長い訓練時間を回避できることを意味します。セービングはまた貴方がモデルを共有して他の人は貴方のワークを再作成できることもまた意味します。研究モデルとテクニックを公開するとき、多くの機械学習実践者は以下を共有します :
- モデルを作成するためのコード、そして
- モデルのために訓練された重み、またはパラメータ
このデータの共有は他の人たちがモデルがどのように動作するかを理解して新しいデータで彼ら自身がそれを試す手助けとなります。
Caution: 信頼できない (untrusted) コードに注意してください — TensorFlow モデルはコードです。詳細は Using TensorFlow Securely を見てください。
オプション
TensorFlow モデルをセーブする異なる方法があります — 貴方が使用している API に依拠します。このガイドは tf.keras, TensorFlow でモデルを構築して訓練するための高位 API を使用します。他のアプローチについては、TensorFlow Save and Restore ガイドや Saving in eager を見てください。
セットアップ
インストールとインポート
TensorFlow と依存関係をインストールしてインポートします :
!pip install -q h5py pyyaml
サンプル・データセットを取得する
重みのセーブを実演するために MNIST データセット を使用してモデルを訓練します。これらのデモの実行をスピードアップするために、最初の 1000 サンプルだけを使用します :
from __future__ import absolute_import, division, print_function import os !pip install -q tensorflow==2.0.0-alpha0 import tensorflow as tf from tensorflow import keras tf.__version__
'2.0.0-alpha0'
(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://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz 11493376/11490434 [==============================] - 0s 0us/step
モデルを定義する
重みのセーブとロードを実演するために使用する単純なモデルを構築しましょう。
# Returns a short sequential model def create_model(): model = tf.keras.models.Sequential([ keras.layers.Dense(512, activation='relu', input_shape=(784,)), keras.layers.Dropout(0.2), keras.layers.Dense(10, activation='softmax') ]) model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) return model # Create a basic model instance model = create_model() model.summary()
Model: "sequential" _________________________________________________________________ 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 callback に渡します :
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 # This may generate warnings related to saving the state of the optimizer. # These warnings (and similar warnings throughout this notebook) # are in place to discourage outdated usage, and can be ignored.
Train on 1000 samples, validate on 1000 samples Epoch 1/10 576/1000 [================>.............] - ETA: 0s - loss: 1.5005 - accuracy: 0.5486 Epoch 00001: saving model to training_1/cp.ckpt 1000/1000 [==============================] - 0s 386us/sample - loss: 1.1582 - accuracy: 0.6670 - val_loss: 0.6874 - val_accuracy: 0.7960 Epoch 2/10 544/1000 [===============>..............] - ETA: 0s - loss: 0.4371 - accuracy: 0.8676 Epoch 00002: saving model to training_1/cp.ckpt 1000/1000 [==============================] - 0s 169us/sample - loss: 0.4171 - accuracy: 0.8700 - val_loss: 0.5031 - val_accuracy: 0.8480 Epoch 3/10 544/1000 [===============>..............] - ETA: 0s - loss: 0.3069 - accuracy: 0.9228 Epoch 00003: saving model to training_1/cp.ckpt 1000/1000 [==============================] - 0s 184us/sample - loss: 0.2854 - accuracy: 0.9260 - val_loss: 0.4601 - val_accuracy: 0.8610 Epoch 4/10 960/1000 [===========================>..] - ETA: 0s - loss: 0.2190 - accuracy: 0.9375 Epoch 00004: saving model to training_1/cp.ckpt 1000/1000 [==============================] - 0s 186us/sample - loss: 0.2174 - accuracy: 0.9380 - val_loss: 0.4377 - val_accuracy: 0.8670 Epoch 5/10 960/1000 [===========================>..] - ETA: 0s - loss: 0.1558 - accuracy: 0.9688 Epoch 00005: saving model to training_1/cp.ckpt 1000/1000 [==============================] - 0s 409us/sample - loss: 0.1523 - accuracy: 0.9700 - val_loss: 0.4070 - val_accuracy: 0.8600 Epoch 6/10 960/1000 [===========================>..] - ETA: 0s - loss: 0.1163 - accuracy: 0.9750 Epoch 00006: saving model to training_1/cp.ckpt 1000/1000 [==============================] - 0s 203us/sample - loss: 0.1152 - accuracy: 0.9760 - val_loss: 0.4117 - val_accuracy: 0.8600 Epoch 7/10 960/1000 [===========================>..] - ETA: 0s - loss: 0.0932 - accuracy: 0.9854 Epoch 00007: saving model to training_1/cp.ckpt 1000/1000 [==============================] - 0s 203us/sample - loss: 0.0930 - accuracy: 0.9850 - val_loss: 0.4309 - val_accuracy: 0.8620 Epoch 8/10 960/1000 [===========================>..] - ETA: 0s - loss: 0.0697 - accuracy: 0.9937 Epoch 00008: saving model to training_1/cp.ckpt 1000/1000 [==============================] - 0s 197us/sample - loss: 0.0681 - accuracy: 0.9940 - val_loss: 0.4407 - val_accuracy: 0.8610 Epoch 9/10 928/1000 [==========================>...] - ETA: 0s - loss: 0.0523 - accuracy: 0.9978 Epoch 00009: saving model to training_1/cp.ckpt 1000/1000 [==============================] - 0s 207us/sample - loss: 0.0507 - accuracy: 0.9980 - val_loss: 0.3949 - val_accuracy: 0.8650 Epoch 10/10 928/1000 [==========================>...] - ETA: 0s - loss: 0.0357 - accuracy: 0.9989 Epoch 00010: saving model to training_1/cp.ckpt 1000/1000 [==============================] - 0s 207us/sample - loss: 0.0368 - accuracy: 0.9990 - val_loss: 0.4168 - val_accuracy: 0.8660 <tensorflow.python.keras.callbacks.History at 0x7fb0c5d080f0>
これは、各エポックの最後に更新される 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 100us/sample - loss: 2.3379 - accuracy: 0.1330 Untrained model, accuracy: 13.30%
それからチェックポイントから重みをロードして、再評価します :
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 48us/sample - loss: 0.4168 - accuracy: 0.8660 Restored model, accuracy: 86.60%
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.save_weights(checkpoint_path.format(epoch=0)) 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 <tensorflow.python.keras.callbacks.History at 0x7fb0d04bcc18>
さて、結果としてのチェックポイントを見て最新の一つを選択します :
! ls {checkpoint_dir}
checkpoint cp-0025.ckpt.index cp-0000.ckpt.data-00000-of-00001 cp-0030.ckpt.data-00000-of-00001 cp-0000.ckpt.index cp-0030.ckpt.index cp-0005.ckpt.data-00000-of-00001 cp-0035.ckpt.data-00000-of-00001 cp-0005.ckpt.index cp-0035.ckpt.index cp-0010.ckpt.data-00000-of-00001 cp-0040.ckpt.data-00000-of-00001 cp-0010.ckpt.index cp-0040.ckpt.index cp-0015.ckpt.data-00000-of-00001 cp-0045.ckpt.data-00000-of-00001 cp-0015.ckpt.index cp-0045.ckpt.index cp-0020.ckpt.data-00000-of-00001 cp-0050.ckpt.data-00000-of-00001 cp-0020.ckpt.index cp-0050.ckpt.index cp-0025.ckpt.data-00000-of-00001
latest = tf.train.latest_checkpoint(checkpoint_dir) latest
'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 91us/sample - loss: 0.4783 - accuracy: 0.8780 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 99us/sample - loss: 0.4783 - accuracy: 0.8780 Restored model, accuracy: 87.80%
モデル全体をセーブする
モデルと optimizer はそれらの状態 (重みと変数) とモデル構成 (= configuration) の両者を含むファイルにセーブできます。これはモデルをエクスポートして元の python コードへのアクセスなしに使用できることを可能にします。optimizer-状態がリカバーされますので正確に貴方がやめたところから訓練を再開することさえできます。
完全に機能するモデルのセーブは非常に有用です — それらを TensorFlow.js にロード (HDF5, Saved Model) してから web ブラウザでそれらを訓練して実行することができます、あるいは TensorFlow Lite を使用して (HDF5, Saved Model) モバイルデバイス上で実行するためそれらを変換できます。
HDF5 ファイルとして
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 196us/sample - loss: 1.1492 - accuracy: 0.6900 Epoch 2/5 1000/1000 [==============================] - 0s 110us/sample - loss: 0.4192 - accuracy: 0.8810 Epoch 3/5 1000/1000 [==============================] - 0s 120us/sample - loss: 0.2916 - accuracy: 0.9240 Epoch 4/5 1000/1000 [==============================] - 0s 123us/sample - loss: 0.2059 - accuracy: 0.9540 Epoch 5/5 1000/1000 [==============================] - 0s 127us/sample - loss: 0.1531 - accuracy: 0.9680
さてそのファイルからモデルを再作成します :
# Recreate the exact same model, including weights and optimizer. new_model = keras.models.load_model('my_model.h5') new_model.summary()
Model: "sequential_6" _________________________________________________________________ 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 100us/sample - loss: 0.4323 - accuracy: 0.8540 Restored model, accuracy: 85.40%
このテクニックは総てをセーブします :
- 重み値。
- モデルの構成 (= configuration) (アーキテクチャ)
- optimizer 構成
Keras はアーキテクチャを調べてモデルをセーブします。現在、TensorFlow optimizer (from tf.train) をセーブすることはできません。それらを使用するときはモデルをロードした後で再コンパイルする必要があり、そして optimizer の状態を失うでしょう。
saved_model として
Caution: tf.keras モデルをセーブするこのメソッドは実験的で将来的なバージョンでは変更されるかもしれません。
新しいモデルを構築します :
model = create_model() model.fit(train_images, train_labels, epochs=5)
Epoch 1/5 1000/1000 [==============================] - 0s 185us/sample - loss: 1.1505 - accuracy: 0.6660 Epoch 2/5 1000/1000 [==============================] - 0s 118us/sample - loss: 0.4217 - accuracy: 0.8760 Epoch 3/5 1000/1000 [==============================] - 0s 116us/sample - loss: 0.2763 - accuracy: 0.9270 Epoch 4/5 1000/1000 [==============================] - 0s 120us/sample - loss: 0.2071 - accuracy: 0.9460 Epoch 5/5 1000/1000 [==============================] - 0s 119us/sample - loss: 0.1497 - accuracy: 0.9690 <tensorflow.python.keras.callbacks.History at 0x7fb040483898>
saved_model を作成して、それをタイムスタンプされたディレクトリに置きます :
import time saved_model_path = "./saved_models/{}".format(int(time.time())) tf.keras.experimental.export_saved_model(model, saved_model_path) saved_model_path
WARNING: Logging before flag parsing goes to stderr. W0307 18:47:44.924113 140398839080704 deprecation.py:323] From /usr/local/lib/python3.5/dist-packages/tensorflow/python/saved_model/signature_def_utils_impl.py:253: build_tensor_info (from tensorflow.python.saved_model.utils_impl) is deprecated and will be removed in a future version. Instructions for updating: This function will only be available through the v1 compatibility library as tf.compat.v1.saved_model.utils.build_tensor_info or tf.compat.v1.saved_model.build_tensor_info. W0307 18:47:44.926080 140398839080704 tf_logging.py:161] Export includes no default signature! W0307 18:47:45.413053 140398839080704 tf_logging.py:161] Export includes no default signature! './saved_models/1551984464'
貴方の saved models をリスティングします :
!ls saved_models/
1551984464
saved model から新鮮な (= fresh) keras モデルを再ロードします。
new_model = tf.keras.experimental.load_from_saved_model(saved_model_path) new_model.summary()
Model: "sequential_7" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= dense_14 (Dense) (None, 512) 401920 _________________________________________________________________ dropout_7 (Dropout) (None, 512) 0 _________________________________________________________________ dense_15 (Dense) (None, 10) 5130 ================================================================= Total params: 407,050 Trainable params: 407,050 Non-trainable params: 0 _________________________________________________________________
復元されたモデルを実行します。
model.predict(test_images).shape
(1000, 10)
# The model has to be compiled before evaluating. # This step is not required if the saved model is only being deployed. new_model.compile(optimizer=model.optimizer, # keep the optimizer that was loaded loss='sparse_categorical_crossentropy', metrics=['accuracy']) # Evaluate the restored model. loss, acc = new_model.evaluate(test_images, test_labels) print("Restored model, accuracy: {:5.2f}%".format(100*acc))
1000/1000 [==============================] - 0s 94us/sample - loss: 0.4281 - accuracy: 0.8560 Restored model, accuracy: 85.60%
What’s Next
tf.keras によるセーブとロードへの簡単なガイドでした。
- tf.keras ガイド は tf.keras によるモデルのセーブとロードについて更に示します。
- eager execution の間のセーブについては Saving in eager を見てください。
- Save and Restore ガイドは TensorFlow セービングについての下位詳細を持ちます。
以上