ホーム » Keras » TensorFlow 2.0 : ガイド : Keras :- Keras でモデルをセーブしてシリアライズする

TensorFlow 2.0 : ガイド : Keras :- Keras でモデルをセーブしてシリアライズする

TensorFlow 2.0 : ガイド : Keras :- Keras でモデルをセーブしてシリアライズする (翻訳/解説)

翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 12/04/2019

* 本ページは、TensorFlow org サイトの Guide – Keras の以下のページを翻訳した上で
適宜、補足説明したものです:

* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。

 

無料セミナー開催中 クラスキャット主催 人工知能 & ビジネス Web セミナー

人工知能とビジネスをテーマにウェビナー (WEB セミナー) を定期的に開催しています。スケジュールは弊社 公式 Web サイト でご確認頂けます。
  • お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
  • Windows PC のブラウザからご参加が可能です。スマートデバイスもご利用可能です。

お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。

株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション
E-Mail:sales-info@classcat.com ; WebSite: https://www.classcat.com/
Facebook: https://www.facebook.com/ClassCatJP/

 

ガイド : Keras :- Keras でモデルをセーブしてシリアライズする

このガイドの最初のパートは Sequential モデルと Functional API を使用して構築されたモデルのためのセーブとシリアライゼーションをカバーします。セーブとシリアライゼーション API はモデルのこれらのタイプの両者について正確に同じです。

モデルのカスタム・サブクラスのためのセーブはセクション「サブクラス化されたモデルをセーブする」でカバーされます。この場合の API は Sequential や Functional モデルのためのものとは僅かに異なります。

 

セットアップ

from __future__ import absolute_import, division, print_function, unicode_literals

import tensorflow as tf

tf.keras.backend.clear_session()  # For easy reset of notebook state.

 

Part I: Sequential モデルまたは Functional モデルをセーブする

次のモデルを考えましょう :

from tensorflow import keras
from tensorflow.keras import layers

inputs = keras.Input(shape=(784,), name='digits')
x = layers.Dense(64, activation='relu', name='dense_1')(inputs)
x = layers.Dense(64, activation='relu', name='dense_2')(x)
outputs = layers.Dense(10, activation='softmax', name='predictions')(x)

model = keras.Model(inputs=inputs, outputs=outputs, name='3_layer_mlp')
model.summary()
Model: "3_layer_mlp"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
digits (InputLayer)          [(None, 784)]             0         
_________________________________________________________________
dense_1 (Dense)              (None, 64)                50240     
_________________________________________________________________
dense_2 (Dense)              (None, 64)                4160      
_________________________________________________________________
predictions (Dense)          (None, 10)                650       
=================================================================
Total params: 55,050
Trainable params: 55,050
Non-trainable params: 0
_________________________________________________________________

オプションとして、このモデルを訓練してみましょう、そしてそれはセーブするための重み値と optimizer 状態を持ちます。
もちろん、まだ訓練していないモデルもセーブできますが、明らかにそれは面白くないでしょう。

(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
x_train = x_train.reshape(60000, 784).astype('float32') / 255
x_test = x_test.reshape(10000, 784).astype('float32') / 255

model.compile(loss='sparse_categorical_crossentropy',
              optimizer=keras.optimizers.RMSprop())
history = model.fit(x_train, y_train,
                    batch_size=64,
                    epochs=1)
Train on 60000 samples
60000/60000 [==============================] - 3s 48us/sample - loss: 0.3080
# Save predictions for future checks
predictions = model.predict(x_test)

 

モデル全体のセーブ

Functional API で構築されたモデルを単一のファイルにセーブできます。このファイルから同じモデルを後で再作成できます、モデルを作成したコードへのアクセスをもはや持たない場合でさえも。

このファイルは以下を含みます :

  • モデルのアーキテクチャ
  • モデルの重み値 (それは訓練の間に学習されました)
  • モデルの訓練 config (それは compile に渡したものです)、もしあれば
  • optimizer とその状態、もしあれば (これは貴方がやめたところで訓練を再開することを可能にします)
# Save the model
model.save('path_to_my_model.h5')

# Recreate the exact same model purely from the file
new_model = keras.models.load_model('path_to_my_model.h5')
import numpy as np

# Check that the state is preserved
new_predictions = new_model.predict(x_test)
np.testing.assert_allclose(predictions, new_predictions, rtol=1e-6, atol=1e-6)

# Note that the optimizer state is preserved as well:
# you can resume training where you left off.

 

SavedModel にエクスポートする

TensorFlow SavedModel 形式にモデル全体をエクスポートすることも可能です。SavedModel は TensorFlow オブジェクトのためのスタンドアロン・シリアライゼーション形式で、TensorFlow serving と Python 以外の TensorFlow 実装によりサポートされます。

# Export the model to a SavedModel
model.save('path_to_saved_model', save_format='tf')

# Recreate the exact same model
new_model = keras.models.load_model('path_to_saved_model')

# Check that the state is preserved
new_predictions = new_model.predict(x_test)
np.testing.assert_allclose(predictions, new_predictions, rtol=1e-6, atol=1e-6)

# Note that the optimizer state is preserved as well:
# you can resume training where you left off.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow_core/python/ops/resource_variable_ops.py:1781: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.
Instructions for updating:
If using Keras pass *_constraint arguments to layers.
INFO:tensorflow:Assets written to: path_to_saved_model/assets

作成された SavedModel は以下を含みます :

  • モデル重みを含む TensorFlow チェックポイント。
  • 基礎となる TensorFlow グラフを含む SavedModel proto。

 

アーキテクチャ-only セービング

時に、貴方はモデルのアーキテクチャだけに興味があり、そして重み値や optimizer をセーブする必要がありません。この場合、get_config() メソッドを通してモデルの “config” を取得できます。config は Python 辞書で同じモデルを再作成することを可能にします — スクラッチから初期化され、訓練の間に以前に学習されたどのような情報も持ちません。

config = model.get_config()
reinitialized_model = keras.Model.from_config(config)

# Note that the model state is not preserved! We only saved the architecture.
new_predictions = reinitialized_model.predict(x_test)
assert abs(np.sum(predictions - new_predictions)) > 0.

代わりに from_json() から to_json() を使用することができます、これは config をストアするために Python 辞書の代わりに JSON 文字列を使用します。これは config をディスクにセーブするために有用です。

json_config = model.to_json()
reinitialized_model = keras.models.model_from_json(json_config)

 

重み-only セービング

時に、貴方はアーキテクチャではなくモデルの状態 — その重み値 — にだけ興味があります。この場合、get_weights() を通して重み値を Numpy 配列のリストとして取得できて、set_weights を通してモデルの状態を設定できます :

weights = model.get_weights()  # Retrieves the state of the model.
model.set_weights(weights)  # Sets the state of the model.

貴方のモデルを同じ状態で再作成するために get_config()/from_config() と get_weights()/set_weights() を組み合わせることができます。けれども、model.save() とは違い、これは訓練 config と optimizer を含みません。モデルを訓練のために使用する前に compile() を再度呼び出さなければならないでしょう。

config = model.get_config()
weights = model.get_weights()

new_model = keras.Model.from_config(config)
new_model.set_weights(weights)

# Check that the state is preserved
new_predictions = new_model.predict(x_test)
np.testing.assert_allclose(predictions, new_predictions, rtol=1e-6, atol=1e-6)

# Note that the optimizer was not preserved,
# so the model should be compiled anew before training
# (and the optimizer will start from a blank state).

get_weights() と set_weights(weights) に対する save-to-disk の代替は save_weights(fpath) と load_weights(fpath) です。

ここにディスクにセーブするサンプルがあります :

# Save JSON config to disk
json_config = model.to_json()
with open('model_config.json', 'w') as json_file:
    json_file.write(json_config)
# Save weights to disk
model.save_weights('path_to_my_weights.h5')

# Reload the model from the 2 files we saved
with open('model_config.json') as json_file:
    json_config = json_file.read()
new_model = keras.models.model_from_json(json_config)
new_model.load_weights('path_to_my_weights.h5')

# Check that the state is preserved
new_predictions = new_model.predict(x_test)
np.testing.assert_allclose(predictions, new_predictions, rtol=1e-6, atol=1e-6)

# Note that the optimizer was not preserved.

しかし覚えておいてください、最も単純な、推奨される方法は単にこれです :

model.save('path_to_my_model.h5')
del model
model = keras.models.load_model('path_to_my_model.h5')

 

TensorFlow チェックポイントを使用して重み-only セーブ

save_weights は Keras HDF5 形式か、TensorFlow SavedModel 形式でファイルを作成できることに注意してください。
このフォーマットは貴方が提供するファイル拡張子から推論されます : それが”.h5″ か “.keras” であれば、フレームワークは Keras HDF5 形式を使用します。他の任意のものはチェックポイントをデフォルトとします。

model.save_weights('path_to_my_tf_checkpoint')

総合的な明瞭さのために、フォーマットは save_format 引数を通して明示的に渡すことができます、これは値 “tf” か “h5” を取ることができます :

model.save_weights('path_to_my_tf_checkpoint', save_format='tf')

 

サブクラス化されたモデルをセーブする

Sequential モデルと Functional モデルは層の DAG を表わすデータ構造です。そのようなものとして、それらは安全にシリアライズとデシリアライズされます。

サブクラス化されたモデルはそれがデータ構造ではないという点で異なります、それはコードのピースです。モデルのアーキテクチャは call メソッド本体を通して定義されます。これはモデルのアーキテクチャは安全にシリアライズ化できないことを意味します。モデルをロードするためには、それを作成したコード (モデル・サブクラスのコード) へのアクセスを持つ必要があるでしょう。代わりに、このコードをバイトコードとしてシリアライズすることもできるでしょうが (e.g. pickling を通して)、それは安全ではなく一般に可搬ではありません。

これらの違いについてのより多くの情報は、記事 “What are Symbolic and Imperative APIs in TensorFlow 2.0?” を見てください。

次のサブクラス化されたモデルを考えましょう、これは最初のセクションからのモデルと同じ構造に従います :

class ThreeLayerMLP(keras.Model):

  def __init__(self, name=None):
    super(ThreeLayerMLP, self).__init__(name=name)
    self.dense_1 = layers.Dense(64, activation='relu', name='dense_1')
    self.dense_2 = layers.Dense(64, activation='relu', name='dense_2')
    self.pred_layer = layers.Dense(10, activation='softmax', name='predictions')

  def call(self, inputs):
    x = self.dense_1(inputs)
    x = self.dense_2(x)
    return self.pred_layer(x)

def get_model():
  return ThreeLayerMLP(name='3_layer_mlp')

model = get_model()

最初に、決して使用されていないサブクラス化されたモデルはセーブできません。

それはサブクラス化されたモデルはその重みを作成するために何某かのデータの上で呼び出される必要があるからです。

モデルが作成されるまで、それはそれが期待しているはずの入力データの shape と dtype を知りません、そしてそれ故にその重み変数を作成できません。最初のセクションからの Functional モデルでは、入力の shape と dtype が (keras.Input(…)を通して) 前もって指定されたことを覚えているかもしれません — それが Functional モデルがインスタンス化されてすぐに状態を持つ理由です。

モデルを、それに状態を与えるために、訓練しましょう :

(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
x_train = x_train.reshape(60000, 784).astype('float32') / 255
x_test = x_test.reshape(10000, 784).astype('float32') / 255

model.compile(loss='sparse_categorical_crossentropy',
              optimizer=keras.optimizers.RMSprop())
history = model.fit(x_train, y_train,
                    batch_size=64,
                    epochs=1)
Train on 60000 samples
60000/60000 [==============================] - 3s 42us/sample - loss: 0.3062

サブクラス化されたモデルをセーブする推奨される方法は TensorFlow SavedModel チェックポイントを作成するために save_weights を使用することです、これはモデルに関連する総ての変数の値を含みます :- 層の重み – optimizer の状態 – ステートフル・モデル・メトリクスに関連する任意の変数 (もしあれば)

model.save_weights('path_to_my_weights', save_format='tf')
# Save predictions for future checks
predictions = model.predict(x_test)
# Also save the loss on the first batch
# to later assert that the optimizer state was preserved
first_batch_loss = model.train_on_batch(x_train[:64], y_train[:64])

貴方のモデルをリストアするためには、モデル・オブジェクトを作成したコードへのアクセスが必要です。

optimizer 状態と任意のステートフル・メトリックの状態をリストアするためには、モデルを (前と正確に同じ引数で) compile して load_weights を呼び出す前にそれをあるデータ上で呼び出すべきです :

# Recreate the model
new_model = get_model()
new_model.compile(loss='sparse_categorical_crossentropy',
                  optimizer=keras.optimizers.RMSprop())

# This initializes the variables used by the optimizers,
# as well as any stateful metric variables
new_model.train_on_batch(x_train[:1], y_train[:1])

# Load the state of the old model
new_model.load_weights('path_to_my_weights')

# Check that the model state has been preserved
new_predictions = new_model.predict(x_test)
np.testing.assert_allclose(predictions, new_predictions, rtol=1e-6, atol=1e-6)

# The optimizer state is preserved as well,
# so you can resume training where you left off
new_first_batch_loss = new_model.train_on_batch(x_train[:64], y_train[:64])
assert first_batch_loss == new_first_batch_loss
 

以上



AI導入支援 #2 ウェビナー

スモールスタートを可能としたAI導入支援   Vol.2
[無料 WEB セミナー] [詳細]
「画像認識 AI PoC スターターパック」の紹介
既に AI 技術を実ビジネスで活用し、成果を上げている日本企業も多く存在しており、競争優位なビジネスを展開しております。
しかしながら AI を導入したくとも PoC (概念実証) だけでも高額な費用がかかり取組めていない企業も少なくないようです。A I導入時には欠かせない PoC を手軽にしかも短期間で認知度を確認可能とするサービの紹介と共に、AI 技術の特性と具体的な導入プロセスに加え運用時のポイントについても解説いたします。
日時:2021年10月13日(水)
会場:WEBセミナー
共催:クラスキャット、日本FLOW(株)
後援:働き方改革推進コンソーシアム
参加費: 無料 (事前登録制)
人工知能開発支援
◆ クラスキャットは 人工知能研究開発支援 サービスを提供しています :
  • テクニカルコンサルティングサービス
  • 実証実験 (プロトタイプ構築)
  • アプリケーションへの実装
  • 人工知能研修サービス
◆ お問合せ先 ◆
(株)クラスキャット
セールス・インフォメーション
E-Mail:sales-info@classcat.com