TensorFlow : Guide : 低位 API : セーブとリストア (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
更新日時 : 07/14/2018
作成日時 : 09/19/2017
* 本ページは、TensorFlow 本家サイトの Guide – Low Level APIs – Saving and Restoring を翻訳した上で
適宜、補足説明したものです:
* サンプルコードの動作確認はしておりますが、適宜、追加改変している場合もあります。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
このドキュメントは 変数 とモデルをどのようにセーブしてリストアするするかについて説明します。
変数のセーブとリストア
TensorFlow 変数は貴方のプログラムで操作される共有され永続性のある状態を表わすための最善の方法です (詳細は 変数 を見てください)。このセクションは変数をどのようにセーブしてリストアするかを説明します。Estimator は変数を (model_dir に) 自動的にセーブしてリストアすることに注意してください。
tf.train.Saver クラスはモデルをセーブしてリストアするためのメソッドを提供します。tf.train.Saver コンストラクタはグラフの変数の総て、または指定されたリストのために save と restore ops をグラフに追加します。Saver オブジェクトは、読み書きするチェックポイントファイルのためのパスを指定し、これらの ops を実行するためのメソッドを提供します。
saver は貴方のモデルで既に定義された変数総てをリストアするでしょう。もしそのグラフをどのように構築したのか知らないでモデルをロードする場合は (例えば、モデルをロードする一般的なプログラムを書いている場合)、このドキュメントの後方の モデルのセーブとリストアの概要 セクションを読んでください。
TensorFlow は変数をバイナリ・チェックポイント・ファイルにセーブします、これは大雑把に言えば、変数名をテンソル値にマップします。
変数をセーブする
tf.train.Saver() でモデルの変数総てを管理する Saver を作成します。例えば、次のスニペットは変数をチェックポイント・ファイルにセーブする tf.train.Saver.save メソッドをどのように呼び出すかを示します :
# Create some variables. v1 = tf.get_variable("v1", shape=[3], initializer = tf.zeros_initializer) v2 = tf.get_variable("v2", shape=[5], initializer = tf.zeros_initializer) inc_v1 = v1.assign(v1+1) dec_v2 = v2.assign(v2-1) # Add an op to initialize the variables. init_op = tf.global_variables_initializer() # Add ops to save and restore all the variables. saver = tf.train.Saver() # Later, launch the model, initialize the variables, do some work, and save the # variables to disk. with tf.Session() as sess: sess.run(init_op) # Do some work with the model. inc_v1.op.run() dec_v2.op.run() # Save the variables to disk. save_path = saver.save(sess, "/tmp/model.ckpt") print("Model saved in file: %s" % save_path)
変数をリストアする
tf.train.Saver オブジェクトは変数をチェックポイント・ファイルにセーブするだけでなく、変数をリストアもします。ファイルから変数をリストアするときそれらを予め初期化する必要はないことに注意してください。例えば、次のスニペットはチェックポイント・ファイルから変数をリストアするために tf.train.Saver.restore メソッドをどのように呼び出すかを示します :
tf.reset_default_graph() # Create some variables. v1 = tf.get_variable("v1", shape=[3]) v2 = tf.get_variable("v2", shape=[5]) # Add ops to save and restore all the variables. saver = tf.train.Saver() # Later, launch the model, use the saver to restore variables from disk, and # do some work with the model. with tf.Session() as sess: # Restore variables from disk. saver.restore(sess, "/tmp/model.ckpt") print("Model restored.") # Check the values of the variables print("v1 : %s" % v1.eval()) print("v2 : %s" % v2.eval())
どの変数をセーブしてリストアするかを選択する
tf.train.Saver() にどのような引数も渡さない場合には、saver はグラフの総ての変数を処理します。変数が作成されたときに渡された名前に基づいて各変数はセーブされます。
チェックポイント・ファイルの変数に対して名前を明示的に指定するのは時々有用です。例えば、”weights” という名前の変数を持つ訓練されたモデルを持ち、その値を “params” という名前の変数にリストアすることを望むかもしれません。
モデルで使用される変数のサブセットだけをセーブまたはリストアすることも時々有用です。例えば、貴方は 5 層のニューラルネットを訓練したかもしれません、そして今、5つの訓練された層の既存の重みを再利用した 6 層で新しいモデルを訓練することを望みます。最初の 5 層だけの重みをリストアするために saver を使用できます。
次のいずれかを tf.train.Saver() コンストラクタに渡すことによりセーブまたはロードするために名前と変数を簡単に指定してできます :
- 変数のリスト (それらはそれら自身の名前の下にストアされます)。
- Python 辞書、そこではキーは使用するための名前で値は管理するための変数です。
先に示した save/resotre サンプルからの続きです :
tf.reset_default_graph() # Create some variables. v1 = tf.get_variable("v1", [3], initializer = tf.zeros_initializer) v2 = tf.get_variable("v2", [5], initializer = tf.zeros_initializer) # Add ops to save and restore only `v2` using the name "v2" saver = tf.train.Saver({"v2": v2}) # Use the saver object normally after that. with tf.Session() as sess: # Initialize v1 since the saver will not. v1.initializer.run() saver.restore(sess, "/tmp/model.ckpt") print("v1 : %s" % v1.eval()) print("v2 : %s" % v2.eval())
Notes:
- モデル変数の異なるサブセットをセーブしてリストアする必要がある場合には望むだけの数の Saver オブジェクトを作成することができます。同じ変数は複数の saver オブジェクトでリストされることができます ; その値は Saver.restore() メソッドが実行されるときに変更されるだけです。
- セッション開始時にモデル変数のサブセットだけをリストアする場合、他の変数のために初期化 op を実行しなければなりません。更なる情報のためには tf.variables_initializer を見てください。
- チェックポイントの変数を調べるためには、inspect_checkpoint ライブラリ、特に print_tensors_in_checkpoint_file 関数を使用できます。
- デフォルトでは、Saver は各変数のために tf.Variable.name プロパティの値を使用できます。けれども、Saver オブジェクトを作成するとき、チェックポイント・ファイルの変数のためにオプションで名前を選択しても良いです。
モデルのセーブとリストアの概要
変数、グラフ、そしてグラフのメタデータをセーブそしてロードすることを望むとき — 基本的に、貴方のモデルをセーブまたはリストアすることを望むとき — SavedModel を使用することを推奨します。
SavedModel は言語ニュートラルで、復旧可能で、密封された (= hermetic) シリアライゼーション形式です。SavedModel は高位システムとツールに TensorFlow モデルを生成し、消費し (= consume)、そして変換することを可能にします。TensorFlow は、tf.saved_model API, Estimator API そして CLI を含む、SavedModel と相互作用するための幾つかのメカニズムを提供します。
SavedModel を構築してロードするための API
このセクションは SavedModel を構築してロードするための API にフォーカスを当てます、特に低位 TensorFlow API を使用するときです。
SavedModel を構築する
SavedModel builder の Python 実装を提供します。SavedModelBuilder クラスは複数の MetaGraphDef をセーブするための機能を提供します。MetaGraph はデータフロー・グラフ、加えてそれに関連する変数、アセット、そして signature です。MetaGraphDef は MetaGraph のプロトコル・バッファ表現です。signature はグラフへの入力とグラフからの出力のセットです。
アセットがディスクにセーブされて書き出されるかコピーされる必要がある場合には、最初の MetaGraphDef が追加されたときにそれらは提供されます。複数の MetaGraphDef が同じ名前のアセットに関連付けられる場合には、最初のバージョンだけが保持されます。
SavedModel に追加された各 MetaGraphDef はユーザ指定のタグでアノテートされなければなりません。タグは、変数とアセットの共有されたセットと一緒に、ロードしてリストアするための特定の MetaGraphDef を識別するための方法を提供します。これらのタグは典型的にはその機能性 (例えば、サービングまたは訓練)、そしてオプションでハードウェア仕様的な局面 (例えば、GPU) で MetaGraphDef をアノテートします。
例えば、次のコードは SavedModel を構築するために SavedModelBuilder を使用する典型的な方法を提案します :
export_dir = ... ... builder = tf.saved_model_builder.SavedModelBuilder(export_dir) with tf.Session(graph=tf.Graph()) as sess: ... builder.add_meta_graph_and_variables(sess, [tag_constants.TRAINING], signature_def_map=foo_signatures, assets_collection=foo_assets) ... # Add a second MetaGraphDef for inference. with tf.Session(graph=tf.Graph()) as sess: ... builder.add_meta_graph([tag_constants.SERVING]) ... builder.save()
Python で SavedModel をロードする
SavedModel loader の Python バージョンは SavedModel のためのロードとリストアの性能を提供します。ロード演算は次の情報を必要とします :
- セッション、そこでグラフ定義と変数をリストアします。
- タグ、ロードする MegaGraphDef を識別するために使用されます。
- SavedModel の位置 (ディレクトリ)。
ロード時、特定の MetaGraphDef の一部として供給される変数、アセット、そして signature のサブセットは
供給されるセッション内にリストアされます。
export_dir = ... ... with tf.Session(graph=tf.Graph()) as sess: tf.saved_model.loader.load(sess, [tag_constants.TRAINING], export_dir) ...
C++ で SavedModel をロードする
SavedModel loader の C++ バージョンは SessionOptions と RunOptions を許可し、パスから SavedModel をロードするための API を提供します。ロードされるグラフに関連付けられたタグを指定しなければなりません。SavedModel のロードされたバージョンは SavedModelBundle として参照されて MetaGraphDef とそれが内部にロードされるセッションを含みます。
const string export_dir = ... SavedModelBundle bundle; ... LoadSavedModel(session_options, run_options, export_dir, {kSavedModelTagTrain}, &bundle);
標準的な constants
SavedModel は様々なユースケースのために TensorFlow グラフを構築してロードする柔軟性を提供します。最も一般的なユースケースのために、SavedModel の API は Python と C++ で constants のセットを提供します、これはツールの一貫性に渡り再利用して共有することを容易にします。
標準的な MetaGraphDef タグ
SavedModel にセーブされた MetaGraphDef を一意に識別するためにタグのセットを使用するかもしれません。一般に使用されるタグのサブセットは以下で指定されます :
標準的な SignatureDef constants
SignatureDef はグラフによりサポートされる計算の signature を定義するプロトコル・バッファです。一般的に使用される入力キー、出力キー、そしてメソッド名は以下で定義されます :
Estimator で SavedModel を使用する
Estimator モデルを訓練した後、リクエストを取り結果を返すような、モデルからのサービスを作成することを望むかもしれません、そのようなサービスを貴方のマシン上でローカルに実行したりクラウドでそれをスケーラブルにデプロイすることができます。
サービングのための訓練された Estimator を用意するためには、標準的な SavedModel フォーマットでそれをエクスポートしなければなりません。このセクションはどのように以下を行なうかを説明します :
- 出力ノードとサーブ可能な相当する API を指定する(分類、回帰、または予測する)。
- 貴方のモデルを SavedModel 形式にエクスポートする。
- ローカル・サーバからモデルをサーブして予測を要求する。
サービング入力を準備する
訓練中、input_fn() はデータを摂取してそれをモデルによる使用のために準備します。サービス提供時には、同様に、serving_input_receiver_fn() は推論リクエストを受け取りそれらをモデルのために準備します。この関数は次の目的を持ちます :
- グラフに placeholder を追加する、これにはサービング・システムが推論リクエストを供給します。
- データを入力フォーマットからモデルにより期待される特徴テンソルに変換するために必要な、任意の追加の ops を追加する
関数は tf.estimator.export.ServingInputReceiver オブジェクトを返します、これは placeholder と結果の特徴テンソルを一緒にまとめます。
典型的なパターンは推論リクエストはシリアライズ化された tf.Examples の形式で到着します、そのため serving_input_receiver_fn() はそれらを受け取るために単一の文字列 placeholder を作成します。そして serving_input_receiver_fn() はまたグラフに tf.parse_example op を追加することにより tf.Examples を構文解析する責任も負います。
そのような serving_input_receiver_fn() を書くとき、解析器 (= parser) にどんな特徴名を期待するかそしてどのようにそれらをテンソルにマップするかを教えてるために tf.parse_example に解析仕様 (= parsing specification) を渡さなければなりません。解析仕様は特徴名から tf.FixedLenFeature, tf.VarLenFeature, と tf.SparseFeature への辞書の形式を取ります。この解析仕様はどのようなラベルあるいは重みカラムも含むべきではないことに注意してください、何故ならばそれらはサービング時には利用可能ではないからです — 訓練時に input_fn() で使用される解析使用とは対照的です。
組み合わせて、そして :
feature_spec = {'foo': tf.FixedLenFeature(...), 'bar': tf.VarLenFeature(...)} def serving_input_receiver_fn(): """An input receiver that expects a serialized tf.Example.""" serialized_tf_example = tf.placeholder(dtype=tf.string, shape=[default_batch_size], name='input_example_tensor') receiver_tensors = {'examples': serialized_tf_example} features = tf.parse_example(serialized_tf_example, feature_spec) return tf.estimator.export.ServingInputReceiver(features, receiver_tensors)
tf.estimator.export.build_parsing_serving_input_receiver_fn ユティリティ関数は一般的なケースのためにその入力レシーバーを提供します。
Note: ローカルサーバで Predict API を使用してサーブされるモデルを訓練するとき、解析ステップは必要ありません、何故ならばモデルは生の (= raw) 特徴データを受け取るからです。
解析や他の入力処理を必要としない場合でさえも — つまり、もしサービング・システムが特徴テンソルを直接供給する場合でも — 依然として serving_input_receiver_fn() を提供しなければなりません、これは特徴テンソルのための placeholder を作成してそれらを通り抜けさせます。tf.estimator.export.build_raw_serving_input_receiver_fn ユティリティはこれのために提供します。
もしこれらのユティリティが貴方のニーズに合わない場合には、貴方は貴方自身の serving_input_receiver_fn() を自由に書くことができます。これが必要となるかもしれない一つのケースは貴方の訓練 input_fn() がサービング時に要約 (recapitulated) されなければならない何某かの前処理ロジックを組み入れる場合です。訓練-サービングの歪みのリスクを軽減するためには、そのような処理を、input_fn() and serving_input_receiver_fn() の両者から呼び出される関数内にカプセル化することを推奨します。
serving_input_receiver_fn() はまた signature の入力部分を決定することに注意してください。つまり、serving_input_receiver_fn() を書くとき、どのような signature を期待してそれらを貴方のモデルの期待する入力にどのようにマップするかを解析器 (= parser) に知らせなければなりません。対照的に、signature の出力部分はモデルにより決定されます。
エクスポートを遂行する
訓練された Estimator をエクスポートするためには、tf.estimator.Estimator.export_savedmodel を export ベース・パスと serving_input_receiver_fn と一緒に呼び出します。
estimator.export_savedmodel(export_dir_base, serving_input_receiver_fn)
このメソッドは、特徴テンソルを得るために最初に serving_input_receiver_fn() を呼び出し、そしてそれらの特徴に基づくモデル・グラフを生成するためにこの Estimator の model_fn() を呼び出すことにより、新しいグラフを構築します。それはフレッシュなセッションを開始し、そしてデフォルトでは、最も最近のチェックポイントをそれにリストアします。(必要であれば、異なるチェックポイントが渡されるかもしれません。)
最終的にそれは与えられた export_dir_base の下にタイムスタンプつきの export ディレクトリを作成し (i.e., export_dir_base/
Note: 古い exports をガベージコレクトするのは貴方の責任です。さもなければ、続く export は export_dir_base 下に蓄積されるでしょう。
カスタム・モデルの出力を指定する
カスタム model_fn を書くとき、tf.estimator.EstimatorSpec の export_outputs 要素を戻り値として populate しなければなりません。これは {name: output} の辞書で、エクスポートされてサービングの間に使用される出力 signature を記述します。
単一の予測を行なう通常のケースでは、この辞書は一つの要素を含み、名前は重要ではありません。マルチ・ヘッドのモデルでは、各ヘッドはこの辞書のエントリとして表わされます。名前は貴方の選択の文字列でサービング時に特定のヘッドをリクエストするために使用できます。
各出力値は tf.estimator.export.ClassificationOutput, tf.estimator.export.RegressionOutput, または tf.estimator.export.PredictOutput のような ExportOutput オブジェクトでなければなりません。
これらの出力型は率直に TensorFlow Serving API にマップされてどのリクエスト型が重視されるかを決定します。
Note: マルチ・ヘッドなケースでは、SignatureDef は、model_fn から返される、同じキーで命名された、export_outputs 辞書の各要素のために生成されるでしょう。これらの SignatureDefs は、相当する ExportOutput エントリで定められているように、それらの出力の点のみ異なります。入力は常に serving_input_receiver_fn により提供されるものです。推論リクエストは名前でヘッドを指定するかもしれません。一つのヘッドは、推論リクエストが一つを指定していないときにどの SignatureDef がサーブされるかを示す signature_constants.DEFAULT_SERVING_SIGNATURE_DEF_KEY を使用して命名されなければなりません。
エクスポートされたモデルをローカルでサーブする
ローカル・デプロイメントのためには、TensorFlow Serving を使用して貴方のモデルをサーブできます、これは SavedModel をロードしてそれを gRPC サービスとして公開するオープンソース・プロジェクトです。
最初に、TensorFlow Serving をインストール します。
それから、$export_dir_base を上でエクスポートした SavedModel へのパスで置き換えてローカル model server を構築して実行します :
bazel build //tensorflow_serving/model_servers:tensorflow_model_server bazel-bin/tensorflow_serving/model_servers/tensorflow_model_server --port=9000 --model_base_path=$export_dir_base
今ではポート 9000 上の gRPC 経由で推論リクエストのためにリスンするサーバを持ちます!
ローカルサーバから予測をリクエストする
サーバは PredictionService gRPC API サービス定義に従って gRPC リクエストに応答します。(ネストされたプロトコル・バッファは様々な 近接したファイル で定義されています。)
API サービス定義から、gRPC フレームワークは API へのリモートアクセスを提供するために様々な言語のクライアント・ライブラリを生成します。Bazel ビルドツールを使用したプロジェクトでは、これらのライブラリは自動的にビルドされて (例として Python を使用して) これらのように依存を通して提供されます :
deps = [ "//tensorflow_serving/apis:classification_proto_py_pb2", "//tensorflow_serving/apis:regression_proto_py_pb2", "//tensorflow_serving/apis:predict_proto_py_pb2", "//tensorflow_serving/apis:prediction_service_proto_py_pb2" ]
それから Python クライアント・コードはこのようにしてライブラリをインポートできます :
from tensorflow_serving.apis import classification_pb2 from tensorflow_serving.apis import regression_pb2 from tensorflow_serving.apis import predict_pb2 from tensorflow_serving.apis import prediction_service_pb2
Note: prediction_service_pb2 はサービス全体を定義していますので常に必要です。けれども典型的なクライアントは行なわれるリクエストの型に依存して、classification_pb2, regression_pb2, そして predict_pb2 の一つだけを必要とするでしょう。
そして gRPC リクエストの送信はリクエスト・データを含むプロトコルバッファを集めてそれをサービス・スタブに渡すことによって成されます。リクエスト・プロトコルバッファがどのように空で作成されてそして generated protocol buffer API を通して populate されるかに注意してください。
from grpc.beta import implementations channel = implementations.insecure_channel(host, int(port)) stub = prediction_service_pb2.beta_create_PredictionService_stub(channel) request = classification_pb2.ClassificationRequest() example = request.input.example_list.examples.add() example.features.feature['x'].float_list.value.extend(image[0].astype(float)) result = stub.Classify(request, 10.0) # 10 secs timeout
このサンプルで返される結果は ClassificationResponse プロトコルバッファです。
これはスケルトンのサンプルです ; 更なる詳細のためには TensorFlow Serving 文書と サンプル を見てください。
Note: ClassificationRequest と RegressionRequest は tensorflow.serving.Input プロトコルバッファを含み、これは tensorflow.Example プロトコルバッファのリストを順番に含みます。PredictRequest は対照的に、特徴名から TensorProto を通してエンコードされる値へのマッピングを含みます。相応して: Classify と Regress API を使用するとき、TensorFlow Serving はシリアライズ化された tf.Examples をグラフに供給しますので、serving_input_receiver_fn() は tf.parse_example() Op を含むべきです。一般的な Predict API を使用するときは、けれども、TensorFlow Serving は生の特徴データをグラフに供給しますので、serving_input_receiver_fn() の通り抜けが使用さえるべきです。
SavedModel を探求して実行する CLI
SavedModel を探求して実行するために SavedModel コマンドライン・インターフェイス (CLI, Command Line Interface) を使用することができます。例えば、モデルの SignatureDefs を探求するために CLI を使用できます。CLI は入力 テンソルの dtype と shape がモデルに適合しているかを迅速に確かめることを可能にします。更に、貴方のモデルをテストすることを望むのであれば、様々な形式 (例えば、Python 式) のサンプル入力を渡してそれから出力を取得することでサニティ・チェックを行なうために CLI を使用できます。
SavedModel CLI をインストールする
大まかに言えば、TensorFlow を次の2つの方法のどちらかでインストールできます :
- 事前ビルドされた TensorFlow バイナリをインストールする。
- ソースコードから TensorFlow をビルドする。
もし事前ビルドされた TensorFlow ライブラリを通して TensorFlow をインストールしたのであれば、SavedModel CLI は貴方のシステムにパス名 bin\saved_model_cli で既にインストールされています。
もしソースコードから TensorFlow をビルドした場合には、saved_model_cli をビルドするために次の追加のコマンドを実行しなければなりません :
$ bazel build tensorflow/python/tools:saved_model_cli
コマンドの概要
SavedModel CLI は SavedModel の MetaGraphDef 上の次の2つのコマンドをサポートします :
- show, これは SavedModel の MetaGraphDef 上の計算を表示します。
- run, これは MetaGraphDef 上の計算を実行します。
show コマンド
SavedModel は、タグセットで識別される一つまたはそれ以上の MetaGraphDefs を含みます。モデルをサーブするために、どのような種類の SignatureDefs が各モデルにあり、そしてそれらの入力と出力が何であるか知りたいと思うかもしれません。show コマンドは SavedModel の内容を階層順で調べることを許します。ここに構文があります :
usage: saved_model_cli show [-h] --dir DIR [--all] [--tag_set TAG_SET] [--signature_def SIGNATURE_DEF_KEY]
例えば、次のコマンドは SavedModel の総ての利用可能な MetaGraphDef タグセットを表示します :
$ saved_model_cli show --dir /tmp/saved_model_dir The given SavedModel contains the following tag-sets: serve serve, gpu
次のコマンドは MetaGraphDef の総ての利用可能な SignatureDef キーを表示します :
$ saved_model_cli show --dir /tmp/saved_model_dir --tag_set serve The given SavedModel `MetaGraphDef` contains `SignatureDefs` with the following keys: SignatureDef key: "classify_x2_to_y3" SignatureDef key: "classify_x_to_y" SignatureDef key: "regress_x2_to_y3" SignatureDef key: "regress_x_to_y" SignatureDef key: "regress_x_to_y2" SignatureDef key: "serving_default"
MetaGraphDef がタグセットの複数のタグを持つ場合には、各タグがカンマ区切りの、総てのタグを指定しなければなりません。例えば :
$ saved_model_cli show --dir /tmp/saved_model_dir --tag_set serve,gpu
特定の SignatureDef のための総ての入力と出力 TensorInfo を表示するためには、signature_def オプションに SignatureDef キーを渡します。これは、計算グラフを後で実行するために入力テンソルのテンソル・キー値、dtype と shape を知りたいときに非常に有用です。例えば :
$ saved_model_cli show --dir \ /tmp/saved_model_dir --tag_set serve --signature_def serving_default The given SavedModel SignatureDef contains the following input(s): inputs['x'] tensor_info: dtype: DT_FLOAT shape: (-1, 1) name: x:0 The given SavedModel SignatureDef contains the following output(s): outputs['y'] tensor_info: dtype: DT_FLOAT shape: (-1, 1) name: y:0 Method name is: tensorflow/serving/predict
SavedModel で利用可能な総ての情報を表示するためには、–all オプションを使用します。例えば :
$ saved_model_cli show --dir /tmp/saved_model_dir --all MetaGraphDef with tag-set: 'serve' contains the following SignatureDefs: signature_def['classify_x2_to_y3']: The given SavedModel SignatureDef contains the following input(s): inputs['inputs'] tensor_info: dtype: DT_FLOAT shape: (-1, 1) name: x2:0 The given SavedModel SignatureDef contains the following output(s): outputs['scores'] tensor_info: dtype: DT_FLOAT shape: (-1, 1) name: y3:0 Method name is: tensorflow/serving/classify ... signature_def['serving_default']: The given SavedModel SignatureDef contains the following input(s): inputs['x'] tensor_info: dtype: DT_FLOAT shape: (-1, 1) name: x:0 The given SavedModel SignatureDef contains the following output(s): outputs['y'] tensor_info: dtype: DT_FLOAT shape: (-1, 1) name: y:0 Method name is: tensorflow/serving/predict
run コマンド
グラフ計算を実行するためには run コマンドを起動します、入力を渡してそれから出力を表示します (そしてオプションでセーブ)。ここに構文があります :
usage: saved_model_cli run [-h] --dir DIR --tag_set TAG_SET --signature_def SIGNATURE_DEF_KEY [--inputs INPUTS] [--input_exprs INPUT_EXPRS] [--outdir OUTDIR] [--overwrite] [--tf_debug]
run コマンドは入力をモデルに渡す次の2つの方法を提供します :
- –inputs オプションはファイルの numpy ndarray を渡すことを可能にします。
- –input_exprs オプションは Python 式を渡すことを可能にします。
–inputs
ファイルで入力データを渡すためには、–inputs オプションを指定します、これは次の一般的な形式を取ります :
--inputs <INPUTS>
ここで INPUTS は次の形式のいずれかです :
- <input_key>=<filename>
- <input_key>=<filename>[<variable_name>]
複数の INPUTS を渡しても良いです。複数の inputs を渡す場合には、INPUTS の各々を分割するためにセミコロンを使用してください。
saved_model_cli はファイル名をロードするために numpy.load を使用します。ファイル名は次の形式のどれでも良いです :
- .npy
- .npz
- pickle 形式
.npy ファイルは常に numpy ndarray を含みます。従って、.npy ファイルからロードするときは、内容は指定された入力テンソルに直接的に割り当てられます。もし variable_name をその .npy ファイルで指定した場合には、variable_name は無視されて警告が発行されるでしょう。
.npz (zip) ファイルからロードするときは、入力テンソル・キーに対してロードするために zip ファイル内の変数を識別するための variable_name をオプションで指定しても良いです。variable_name を指定しない場合には、SavedModel CLI は zip ファイルに一つのファイルだけが含まれていることを確認して指定された入力テンソル・キーのためにそれをロードします。
pickle ファイルからロードするときは、角括弧 (= square brackets) で variable_name が指定されない場合、pickle ファイル内が何であれそれが指定された入力テンソル・キーに渡されます。そうでなければ、SavedModel CLI は辞書が pickle ファイルにストアされていると仮定して variable_name に相当する値が使用されるでしょう。
–inputs_exprs
Python 式を通して入力を渡す場合には、–input_exprs オプションを指定します。これは、転がっているデータファイルを持たないが、しかし依然として (モデルの SignatureDefs の dtype と shape に適合する) 何某かの単純な入力でモデルをサニティ・チェックすることを望むときのために有用です。例えば :
`input_key=[[1], [2], [3]]`
Python 式に加えて、numpy 関数を渡しても良いです。例えば :
input_key=np.ones((32, 32, 3))
(numpy モジュールは np として既に利用可能であることに注意してください。)
出力をセーブする
デフォルトでは、SavedModel CLI は出力を stdout に書きます。もしディレクトリが –outdir オプションで渡された場合は、出力は出力テンソル・キーにちなんで命名された npy ファイルとして与えられたディレクトリ下にセーブされます。
既存の出力ファイルに上書きするためには –overwrite を使用します。
TensorFlow デバッガー (tfdbg) 統合
–tf_debug オプションがセットされた場合は、SavedModel CLI は TensorFlow デバッガー (tfdbg) を使用して SavedModel を実行する間、中間テンソルと実行時グラフまたはサブグラフを監視します。
完全なサンプル
以下を仮定した場合 :
- モデルは単に x1 と x2 を加算して出力 y を得ます。
- モデルの総てのテンソルは shape (-1, 1) を持ちます。
- 2つの npy ファイルを持ちます :
- /tmp/my_data1.npy, これは numpy ndarray [[1], [2], [3]] を含みます。
- /tmp/my_data2.npy, これは他の numpy ndarray [[0.5], [0.5], [0.5]] を含みます。
出力 y を得るためのモデルを通してこれら2つの npy ファイルを実行するには、 次のコマンドを発行します ;
$ saved_model_cli run --dir /tmp/saved_model_dir --tag_set serve \ --signature_def x1_x2_to_y --inputs x1=/tmp/my_data1.npy;x2=/tmp/my_data2.npy \ --outdir /tmp/out Result for output key y: [[ 1.5] [ 2.5] [ 3.5]]
先のサンプルを少し変更しましょう。今度は、2つの .npy ファイルの代わりに、今は .npz ファイルと pickle ファイルを持ちます。更に、既存の出力ファイルに上書きしたいとします。ここにコマンドがあります :
$ saved_model_cli run --dir /tmp/saved_model_dir --tag_set serve \ --signature_def x1_x2_to_y \ --inputs x1=/tmp/my_data1.npz[x];x2=/tmp/my_data2.pkl --outdir /tmp/out \ --overwrite Result for output key y: [[ 1.5] [ 2.5] [ 3.5]]
入力ファイルの代わりに python 式を指定しても良いです。例えば、次のコマンドは入力 x2 を Python 式で置き換えます :
$ saved_model_cli run --dir /tmp/saved_model_dir --tag_set serve \ --signature_def x1_x2_to_y --inputs x1=/tmp/my_data1.npz[x] \ --input_exprs 'x2=np.ones((3,1))' Result for output key y: [[ 2] [ 3] [ 4]]
モデルを TensorFlow デバッガー on で実行するためには、次のコマンドを発行します :
$ saved_model_cli run --dir /tmp/saved_model_dir --tag_set serve \ --signature_def serving_default --inputs x=/tmp/data.npz[x] --tf_debug
SavedModel ディレクトリの構造
SavedModel 形式でモデルをセーブするとき、TensorFlow は次のサブディレクトリとファイルから成る SavedModel ディレクトリを作成します :
assets/ assets.extra/ variables/ variables.data-?????-of-????? variables.index saved_model.pb|saved_model.pbtxt
ここで :
- assets は語彙のような補助 (外部) ファイルを含むサブフォルダです。assets は特定の MetaGraphDef をロードするときに SavedModel 位置へコピーされ読まれます。
- assets.extra はサブフォルダでここでは高位ライブラリとユーザがそれら自身のモデルと共存するアセットを追加できますが、グラフによりロードされません。このサブフォルダは SavedModel ライブラリにより管理されません。
- variables は tf.train.Saver からの出力を含むサブフォルダです。
- saved_model.pb または saved_model.pbtxt は SavedModel プロトコルバッファです。それは MetaGraphDef プロトコルバッファとしてグラフ定義を含みます。
単一の SavedModel は複数のグラフを表わすことができます。この場合、SavedModel の総てのグラフはチェックポイント (variables) と assets の単一のセットを共有します。例えば、次のダイアグラムは3つの MetaGraphDefs を含む一つの SavedModel を示します、それらの3つ総てはチェックポイントと assets の同じセットを共有します :
以上