PAI-Blade Python API を使用して TensorFlow モデルを最適化します。 すべての結果は NVIDIA T4 GPU で測定されたものです。
前提条件
-
TensorFlow および PAI-Blade の WHL パッケージがインストールされていること。 詳細については、「Blade のインストール」をご参照ください。
-
トレーニング済みの TensorFlow モデルが利用可能であること。 このトピックでは、公開されている ResNet50 モデルを使用します。
操作手順
このトピックでは、公開されている ResNet50 モデルを使用して TensorFlow モデルを最適化する方法を説明します。 ご自身の TensorFlow モデルに合わせて、これらのステップを適宜変更してください。
-
PAI-Blade と依存関係をインポートします。
import os import numpy as np import tensorflow.compat.v1 as tf import blade -
モデルとテストデータをダウンロードする関数を記述します。
PAI-Blade は、テストデータなしでの最適化 (ゼロ入力最適化) をサポートしていますが、実際の入力データを使用する方が結果の精度は高くなります。 可能な場合はテストデータを提供してください。 次のサンプルコードは、モデルとテストデータをダウンロードします。
def _wget_demo_tgz(): # 公開されている ResNet50 モデルをダウンロードします。 url = 'http://pai-blade.oss-cn-zhangjiakou.aliyuncs.com/demo/mask_rcnn_resnet50_atrous_coco_2018_01_28.tar.gz' local_tgz = os.path.basename(url) local_dir = local_tgz.split('.')[0] if not os.path.exists(local_dir): blade.util.wget_url(url, local_tgz) blade.util.unpack(local_tgz) model_path = os.path.abspath(os.path.join(local_dir, "frozen_inference_graph.pb")) graph_def = tf.GraphDef() with open(model_path, 'rb') as f: graph_def.ParseFromString(f.read()) # 乱数をテストデータとして使用します。 test_data = np.random.rand(1, 800,1000, 3) return graph_def, {'image_tensor:0': test_data} graph_def, test_data = _wget_demo_tgz() -
blade.optimizeを呼び出してモデルを最適化します。 パラメーターの詳細については、「Python API リファレンス」をご参照ください。input_nodes=['image_tensor'] output_nodes = ['detection_boxes', 'detection_scores', 'detection_classes', 'num_detections', 'detection_masks'] optimized_model, opt_spec, report = blade.optimize( graph_def, # 最適化するモデル。 この例では、tf.GraphDef オブジェクトです。 SavedModel のパスも指定できます。 'o1', # 最適化レベル。 有効値: o1 および o2。 device_type='gpu', # ターゲットデバイス。 有効値: gpu、cpu、および edge。 inputs=input_nodes, # 入力ノード。 オプション。 指定しない場合、PAI-Blade は自動的に推測します。 outputs=output_nodes, # 出力ノード。 test_data=[test_data] # テストデータ。 )blade.optimizeは 3 つのオブジェクトを返します:-
optimized_model: 最適化済みモデル。 この例では
tf.GraphDefオブジェクトです。 -
opt_spec: 最適化結果を再現するために必要な設定情報、環境変数、およびリソースファイル。
with文を使用して適用します。 -
report: 最適化レポート。 直接プリントして表示できます。 パラメーターの詳細については、「最適化レポート」をご参照ください。
最適化中の進捗情報:
[Progress] 5%, phase: user_test_data_validation. [Progress] 10%, phase: test_data_deduction. [Progress] 15%, phase: CombinedSwitch_1. [Progress] 24%, phase: TfStripUnusedNodes_22. [Progress] 33%, phase: TfStripDebugOps_23. [Progress] 42%, phase: TfFoldConstants_24. [Progress] 51%, phase: CombinedSequence_7. [Progress] 59%, phase: TfCudnnrnnBilstm_25. [Progress] 68%, phase: TfFoldBatchNorms_26. [Progress] 77%, phase: TfNonMaxSuppressionOpt_27. [Progress] 86%, phase: CombinedSwitch_20. [Progress] 95%, phase: model_collecting. [Progress] 100%, Finished! -
-
最適化レポートをプリントします。
print("Report: {}".format(report))このレポートは、どの最適化項目がパフォーマンス向上に最も貢献しているかを示します。
Report: { // ...... "optimizations": [ // ...... { "name": "TfNonMaxSuppressionOpt", "status": "effective", "speedup": "1.58", // 高速化率。 "pre_run": "522.74 ms", // 最適化前のレイテンシー。 "post_run": "331.45 ms" // 最適化後のレイテンシー。 }, { "name": "TfAutoMixedPrecisionGpu", "status": "effective", "speedup": "2.43", "pre_run": "333.30 ms", "post_run": "136.97 ms" } // ...... ], // エンドツーエンドの最適化結果。 "overall": { "baseline": "505.91 ms", // オリジナルモデルのレイテンシー。 "optimized": "136.83 ms", // 最適化済みモデルのレイテンシー。 "speedup": "3.70" // 高速化率。 }, // ...... } -
最適化前後のパフォーマンスを比較します。
import time def benchmark(model): tf.reset_default_graph() with tf.Session() as sess: sess.graph.as_default() tf.import_graph_def(model, name="") # ウォームアップ! for i in range(0, 1000): sess.run(['image_tensor:0'], test_data) # ベンチマーク! num_runs = 1000 start = time.time() for i in range(0, num_runs): sess.run(['image_tensor:0'], test_data) elapsed = time.time() - start rt_ms = elapsed / num_runs * 1000.0 # 結果を表示します! print("Latency of model: {:.2f} ms.".format(rt_ms)) # オリジナルモデルの速度をテストします。 benchmark(graph_def) # 最適化済みモデルの速度をテストします。 with opt_spec: benchmark(optimized_model)パフォーマンステストの結果。 この結果は、最適化レポートの値と一致します。
モデルのレイテンシ: 530.26 ms。 モデルのレイテンシ: 148.40 ms。
拡張機能
blade.optimize の model パラメーターは、複数の入力フォーマットをサポートしています。 TensorFlow モデルの場合、次のいずれかの方法でモデルを渡します:
-
tf.GraphDef オブジェクトを渡す。
-
ファイルから PB または PBTXT フォーマットのフリーズされたモデルをロードする。
-
指定されたパスから SavedModel をインポートする。
この例では、メモリ内の tf.GraphDef オブジェクトを blade.optimize に渡します。 次のサンプルコードは、他の 2 つの方法を示しています:
-
フリーズされた PB ファイルを渡す
optimized_model, opt_spec, report = blade.optimize( './path/to/frozen_pb.pb', # ファイルは .pbtxt フォーマットも使用できます。 'o1', device_type='gpu', ) -
SavedModel のパスを渡す
optimized_model, opt_spec, report = blade.optimize( './path/to/saved_model_directory/', 'o1', device_type='gpu', )
次のステップ
モデルを最適化したら、Python で直接実行するか、EAS サービスとしてデプロイします。 PAI-Blade は、最適化済みモデルをアプリケーションに統合するための C++ SDK も提供しています。 詳細については、「SDK を使用した TensorFlow 推論モデルのデプロイ」をご参照ください。