2018の19日目の記事です。最近お仕事で使う機会が多く、いろいろと調べたのでSavedModelについてまとめようと思います。SavedModelとは?SavedModelはTensorFlowでモデルを保存する際の汎用的なシリアライゼーション形式です。TensorFlowには基本的なモデルの保存型式としてCheckpointがあります。Pythonでコードを書いてモデルを訓練して、一定間隔毎にモデルを保存する際はCheckpoint形式の保存が適しています。出来上がったモデルをいざ本番環境で推論させたいというような場合を考えると、その推論用のプログラムを別で書く必要があったり、そもそもモデルを搭載するシステムがPythonで書かれていなかったりと、Checkpoint形式だと都合が悪い時があります。Engineなどの高レベルなサービスやツールでTensorFlowのモデルを利用することができるようになります。保存方法まずはモデルとして超シンプルな計算グラフを用意します。tf.InteractiveSession()sess.run(init)本来は訓練などを行なう必要が有りますが、簡単のために諸々省略しています。モデルの定義ができたので、まずはもっとも簡単な方法であるtf.saved_model.simple_saveメソッドを用いてSavedModel形式でモデルをエクスポートしてみます。out})これを実行するとmodelsディレクトリ直下に以下のようなファイルが現れます。Sessionやモデルのディレクトリを引数とするところはtf.train.Saver()によるCheckpoint形式のモデル保存と同じですが異なるのが入力と出力のTensorを指定しているところです。Servingなどのライブラリからしたらそんなこと知ったこっちゃありません。クラス分類をするモデルを考えた時、出力といってもソフトマック関数を作用させた各クラスである確率がアプリケーション側に必要なケースもあれば、単に入力がどのクラスに属するかだけが欲しい場合もあり、後者の場合はソフトマックス関数を作用させる前のTensorだけあれば十分です。そのため、SavedModelをエクスポートする際は入出力の情報を指定してあげる必要があり、そうした入出力の情報をTensorFlowでは"Signature"と呼びます。Servingやsaved_model_cliで利用することができます。Python以外の言語からも読み込むことも可能です。先ほどのtf.saved_model.simple_saveは便利で使いやすいですがミニマムの機能しか提供していません。ここでは細々としたカスタマイズが可能なtf.saved_model.builder.SavedModelBuilder()を用いた保存方法を紹介します。signature})builder.save()simple_saveに比べて少しだけ複雑になっています。ディレクト名を引数にとり、tf.saved_model.builder.SavedModelBuilder()を宣言します。することでmodelsというディレクトリが出来上がりますがまだ中身は空です。次にSignatureを定義しています。ここは先程のsimple_saveと似ています。Signitureの定義に必要なものは入力と出力のTensorの他にメソッドと呼ばれるものが実は必要で、ここではPredictと呼ばれるメソッド用のSignatureを定義しています。各種メソッドの違いなどを知りたい場合はここを参考にするといいと思います。Predict以外のメソッド用のSignatureを定義する関数や、より汎用的なSignatureを作成するためのtf.saved_model.build_signature_def()というメソッドも存在するので必要に応じて使い分けてください。Signatureを定義できたら、add_meta_graph_and_variablesメソッドを用いてモデルを追加します。SessionやSignatureを渡すのは当たり前なのですが、ここでもう一つ新しい概念であるtagというものが出てきます。このtagは一言で言うと複数の計算グラフを区別するためのものです。実はSavedModelには複数の計算グラフを含めることができます。ユースケースとして、訓練用の計算グラフと推論用の計算グラフを分けるということはよく行われます。同じモデルであったとしてもデプロイするエッジデバイスによってGPUが乗っている場合、乗っていない場合など様々です。した際にはCPU版とGPU版でモデルを分けておくことは自然です。この例では1つしか計算グラフを追加していませんが、複数追加する場合、初回は必ずadd_meta_graph_and_variablesメソッドでモデルの骨組みとVariableの両方を加える必要がありますが、2回目以降はadd_meta_graphというメソッドで重みを共有する異なる計算グラフを追加することができます。tagは文字列のリストであるなら何でも良いのですが、よく使う項目としてTensorFlowではSERVINGTRAININGGPUTPUといった固定の文字列が定義されています。GPU]のようにtagを設定しておくとロードする際にわかりやすいでしょう。最後にsaveメソッドでSavedModelをエクスポートします。構造この例ではフルに機能を活用していないので出てきていない項目も有りますが、SavedModelの構造は以下のようになります。variables.indexsaved_model.pb|saved_model.pbtxtsaved_model.pbはメタグラフといって、計算グラフの構造を表すものです。どのオペレーションとどのVariableが足し算されてといった構造を保持しており、Variableの値そのものは保持していません。variables直下の二つのファイルがVariableの値を保持しています。このあたりはtf.train.Saver()を用いた保存とほとんど同じなのでわかりやすいでしょう。assetsは単語辞書ファイルなどの外部ファイルが保存されるフォルダになります。add_meta_graph_and_variables()メソッドの引数assets_collectionで指定できるようです。この辺りがCheckpoint形式と異なるところです。tf.kerasからのエクスポート上記の例ではTensorFlowのLowLevelAPIで記述しておりSessionなどの概念がでてきていました。いうご意見も有るとおもいますし、TF2.0以降ではKerasとよりタイトに統合していきKerasAPI(tf.keras)を推奨していくという流れらしいのでtf.kerasからSavedModelを生成するための方法を参考までに記載したいと思います。model.outputs})tf.keras.backend.get_session()メソッドでSessionが取得できるのであとはそのままという感じですね。直截SavedModelを吐き出す機能は見た所まだ内容なので、一手間かかりますね。TF2.0以降追加されるのを期待しましょう。おわりにあまりSavedModelに関する日本語の記事がなかったので書いてみました。このあとTensorFlowSerivingで使ったりという記事も車内でまとめてあったりするので逐次公開していこうと思います。upLoginユーザーは見つかりませんでした。