TVMC を使用してモデルをコンパイルおよび最適化する

2 年前

情報

Jiaxin Sun

特色图像

内容の概要:このセクションでは、TVMC を使用したモデルのコンパイルと最適化について説明します。 TVMC は TVM のコマンド ドライバーであり、コマンド ラインを通じて TVM 機能を実行します。このセクションは、TVM がどのように機能するかを理解するための基礎となります。

キーワード:TVMC TVM 機械学習   

このセクションでは、TVM のコマンド ライン ドライバーである TVMC を紹介します。 TVMC は、コマンド ライン インターフェイスを通じて TVM 機能を実行します。(モデルの自動チューニング、コンパイル、分析、実行を含む)。

このセクションを学習した後、TVMC を使用して、次のタスクを実行できます。

  •   TVM ランタイム用に事前トレーニングされた ResNet-50 v2 モデルをコンパイルします。
  •   コンパイルされたモデルを使用して実際の画像を予測し、出力とモデルのパフォーマンスを説明します。
  •   TVM を使用して CPU 上でモデルを調整します。
  •   TVM によって収集されたチューニング データを使用して、最適化されたモデルを再コンパイルします。
  •   最適化されたモデルによって画像を予測し、出力とモデルのパフォーマンスを比較します。

このセクションでは、TVM と TVMC の機能の概要を説明し、TVM がどのように機能するかを理解するための基礎を築きます。

TVMCを使用する

TVMC は Python アプリケーションであり、TVM Python パッケージの一部です。Python パッケージを使用して TVM をインストールすると、次のようなメッセージが表示されます。 TVMC  コマンドラインアプリケーション。このコマンドの場所は、プラットフォームとインストール方法によって異なります。

また、もし $PYTHONPATH  TVM Python モジュールが利用可能な場合は、実行可能な Python モジュールを使用できます ( python -m tvm.driver.tvmc  コマンド) を使用して、コマンド ライン ドライバーの機能にアクセスします。

このチュートリアルで使用される TVMC  または python -m tvm.driver.tvmc  TVMC コマンドラインを開きます。

ヘルプ ページを表示するには、次のコマンドを使用します。

tvmc --help

TVMC  TVM で利用できる主な機能はサブコマンドから提供されます。 コンパイル走る  そして 調子を整える 。使用 tvmc – ヘルプ  特定のサブコマンドの特定のオプションを表示します。

このチュートリアルではこれらのコマンドを紹介します。開始する前に、事前トレーニングされたモデルをダウンロードしてください。

モデルの取得

このチュートリアルでは、ResNet-50 v2 を使用します。 ResNet-50 は、画像の分類に使用される 50 層の深層畳み込みニューラル ネットワークです。次に使用されるモデルは、1000 の異なるカテゴリを持つ 100 万枚以上の画像で事前トレーニングされています。このネットワークへの入力画像のサイズは 224×224 です。

ResNet-50 モデルの構成をさらに詳しく調べるには、Netron (無料の ML モデル ビューアー) をダウンロードすることをお勧めします。

Netron をダウンロード: https://netron.app/

このチュートリアルでは、ONNX 形式のモデルを使用します。

wget https://github.com/onnx/models/raw/b9a54e89508f101a1611cd64f4ef56b9cb62c7cf/vision/classification/resnet/model/resnet50-v2-7.onnx

ヒント 1 サポートされているモデル形式: 

TVMC は、Keras、ONNX、TensorFlow、TFLite、Torch で作成されたモデルをサポートしています。利用可能 –モデル形式  オプションは、使用されているモデル形式を示します。埋め込む tvmc コンパイル –ヘルプ  さらに詳しい情報を得るには。

 ヒント 2 ONNX のサポートを TVM に追加します。 

TVM は、システムで利用可能な ONNX Python ライブラリに依存します。コマンド pip3 install –user onnx onnxoptimizer を使用して ONNX をインストールします。 root アクセス権があり、ONNX をグローバルにインストールする場合は、-user オプションを削除できます。 onnxoptimizer の依存関係はオプションであり、onnx>=1.9 でのみ使用できます。

ONNX モデルを TVM ランタイムにコンパイルする

ResNet-50 モデルをダウンロードした後、使用します TVMCコンパイル  コンパイルします。コンパイルの出力は、モデルの TAR パッケージです (ターゲット プラットフォーム用の動的ライブラリにコンパイルされます)。モデルは、TVM ランタイムを使用してターゲット デバイス上で実行できます。

# 大概需要几分钟,取决于设备 
tvmc compile \
--target "llvm" \
--input-shapes "data:[1,3,224,224]" \
--output resnet50-v2-7-tvm.tar \
resnet50-v2-7.onnx

チェック TVMCコンパイル  モジュール内で作成されるファイル:

mkdir model
tar -xvf resnet50-v2-7-tvm.tar -C model
ls model

解凍後、次の 3 つのファイルが存在します。

mod.so  TVM ランタイムによってロードできるモデルであり、C++ ライブラリとして表されます。

mod.json  TVM リレー計算グラフのテキスト表現です。

mod.params  は、事前トレーニングされたモデルのパラメーターを含むファイルです。

モジュールはアプリケーションによって直接ロードできますが、モデルは TVM ランタイム API を通じて実行できます。

ヒント 3 正しいターゲットを定義します。

正しいターゲットを指定してください (オプション) -ターゲット ) は、ターゲットで利用可能なハードウェア機能を活用できるため、コンパイルされたモジュールのパフォーマンスを大幅に向上させることができます。詳細については、「x86 CPU の畳み込みネットワークの自動チューニング」を参照してください。 CPUの機種や使用するオプション機能を把握し、適切にターゲットを設定することを推奨します。

TVMC を使用してコンパイル済みモジュールからモデルを実行する

モデルがモジュールにコンパイルされた後、TVM ランタイムを使用して予測できます。 TVMC には、コンパイルされた TVM モデルを実行できる TVM ランタイムが組み込まれています。

TVMC でモデルを実行して予測を行うには、次のものが必要です。

  •   新しく生成されたコンパイル済みモジュール。
  •   予測に使用されるモデルへの有効な入力。

モデルはテンソルの形状、形式、データ型が異なります。したがって、ほとんどのモデルでは、入力が有効であり、出力が解釈できることを確認するために前処理と後処理が必要です。 TVMC は NumPy を使用します .npz  複数の配列をファイルにシリアル化するための適切なサポートを提供する形式の入出力。

このチュートリアルで入力する画像は猫の画像を使用していますが、好みに応じて他の画像を選択することもできます。

入力の前処理

ResNet-50 v2 モデルへの入力は ImageNet 形式である必要があります。以下は、ResNet-50 v2 の前処理画像のスクリプトの例です。

初めての使用 pip3 インストール – ユーザー枕  Python イメージ ライブラリをダウンロードして、スクリプトのイメージ ライブラリへの依存関係を満たすようにします。

#!python ./preprocess.py
from tvm.contrib.download import download_testdata
from PIL import Image
import numpy as np

img_url = "https://s3.amazonaws.com/model-server/inputs/kitten.jpg"
img_path = download_testdata(img_url, "imagenet_cat.png", module="data")

# 重设大小为 224x224
resized_image = Image.open(img_path).resize((224, 224))
img_data = np.asarray(resized_image).astype("float32")

# ONNX 需要 NCHW 输入, 因此对数组进行转换
img_data = np.transpose(img_data, (2, 0, 1))

# 根据 ImageNet 进行标准化
imagenet_mean = np.array([0.485, 0.456, 0.406])
imagenet_stddev = np.array([0.229, 0.224, 0.225])
norm_img_data = np.zeros(img_data.shape).astype("float32")
for i in range(img_data.shape[0]):
norm_img_data[i, :, :] = (img_data[i, :, :] / 255 - imagenet_mean[i]) / imagenet_stddev[i]

# 添加 batch 维度
img_data = np.expand_dims(norm_img_data, axis=0)

# 保存为 .npz(输出 imagenet_cat.npz)
np.savez("imagenet_cat", data=img_data)

コンパイルされたモジュールを実行する

モデルと入力データを使用して、予測のために TVMC を実行してみましょう。

tvmc run \
--inputs imagenet_cat.npz \
--output predictions.npz \
resnet50-v2-7-tvm.tar

。タール  モデル ファイルには、C++ ライブラリ、Relay モデルの説明ファイル、およびモデルのパラメータ ファイルが含まれています。 TVMC には TVM ランタイム (モデルをロードし、入力に対して予測を行うことができます) が含まれています。上記のコマンドを実行すると、TVMC が新しいファイルを出力します。 予測.npzこれには、NumPy 形式のモデル出力テンソルが含まれます。

この例では、モデルのコンパイルに使用されたのと同じマシンが、モデルの実行に使用されたのと同じマシンです。場合によっては、RPC トラッカーを使用してリモートで実行することがあります。チェック tvmc run –ヘルプ  これらのオプションについて詳しく学びましょう。

出力後処理

前に述べたように、各モデルは異なる方法で出力テンソルを提供します。

この例では、このモデル専用に提供されたルックアップ テーブルを使用して後処理を実行し、ResNet-50 v2 の出力形式を読みやすくする必要があります。

次のスクリプトは、コンパイルされたモジュールの出力からラベルを抽出する後処理の例です。

#!python ./postprocess.py
import os.path
import numpy as np

from scipy.special import softmax

from tvm.contrib.download import download_testdata

# 下载标签列表
labels_url = "https://s3.amazonaws.com/onnx-model-zoo/synset.txt"
labels_path = download_testdata(labels_url, "synset.txt", module="data")

with open(labels_path, "r") as f:
labels = [l.rstrip() for l in f]

output_file = "predictions.npz"

# 打开并读入输出张量
if os.path.exists(output_file):
with np.load(output_file) as data:
scores = softmax(data["output_0"])
scores = np.squeeze(scores)
ranks = np.argsort(scores)[::-1]

for rank in ranks[0:5]:
print("class='%s' with probability=%f" % (labels[rank], scores[rank]))

このスクリプトを実行すると、出力は次のようになります。

python postprocess.py
# class='n02123045 tabby, tabby cat' with probability=0.610553
# class='n02123159 tiger cat' with probability=0.367179
# class='n02124075 Egyptian cat' with probability=0.019365
# class='n02129604 tiger, Panthera tigris' with probability=0.001273
# class='n04040759 radiator' with probability=0.000261

上の猫の画像を他の画像に置き換えて、ResNet モデルがどのような予測を行うかを確認してください。

ResNet モデルを自動的に調整する

以前のモデルは TVM ランタイムで実行するようにコンパイルされていたため、プラットフォーム固有の最適化は含まれていませんでした。このセクションでは、TVMC を使用して作業プラットフォームの最適化モデルを構築する方法を紹介します。

コンパイルされたモジュールを使用した推論では、期待されるパフォーマンスが得られない場合があります。この場合、オートチューナーを使用してモデルをより適切に構成できるため、パフォーマンスが向上します。。 TVM でのチューニングとは、特定のターゲット上でモデルを最適化し、実行を高速化することを指します。トレーニングや微調整とは異なり、モデルの精度には影響せず、実行時のパフォーマンスにのみ影響します。

チューニングプロセスの一環として、TVM は、さまざまな演算子のバリエーションを実装して実行し、どれが最もパフォーマンスが高いかを確認します。これらの実行の結果は、チューニング レコード ファイル (tune コマンドの最終出力) に保存されます。

チューニングには少なくとも以下を含める必要があります。

  •   このモデルを実行するターゲット デバイスのプラットフォーム要件
  •   チューニングレコードが保存される出力ファイルへのパス
  •   調整するモデルへのパス。

次の例は、そのワークフローを示しています。

# 默认搜索算法需要 xgboost,有关调优搜索算法的详细信息,参见下文 
pip install xgboost

tvmc tune \
--target "llvm" \
--output resnet50-v2-7-autotuner_records.json \
resnet50-v2-7.onnx

この例では、 -ターゲット  フラグでより具体的なターゲットを指定すると、より良い結果が得られます。たとえば、Intel i7 プロセッサでは、 –target llvm -mcpu=skylake 。このチューニング例では、指定されたアーキテクチャのコンパイラとして LLVM を使用し、CPU 上でローカル チューニングを実行します。

TVMC はモデルのパラメーター空間を検索し、オペレーターのさまざまな構成を試し、プラットフォーム上で最も高速な構成を選択します。これは CPU とモデルの操作に基づくガイド付き検索ですが、検索が完了するまでに数時間かかります。検索の出力は次の場所に保存されます。 resnet50-v2-7-autotuner_records.json  ファイルは、後で最適化モデルをコンパイルするために使用されます。

ヒント 4 チューニング検索アルゴリズムを定義します。

この検索アルゴリズムのデフォルトは、 XGブーストグリッド  アルゴリズムがガイドします。モデルの複雑さと利用可能な時間に応じて、さまざまなアルゴリズムを選択できます。完全なリストを表示できます tvmcチューン – ヘルプ

コンシューマーグレードの Skylake CPU の場合、出力は次のようになります。

チューニングデータを使用して最適化されたモデルをコンパイルする

上記のチューニングプロセスからの出力ファイル `resnet50-v2-7-autotuner_records.json  チューニングレコードが入手可能です。

このファイルは次の目的で使用できます。

  •   さらなるチューニングのための入力として( tvmc チューン -チューニング-レコード )
  •   コンパイラへの入力として

埋め込む tvmc コンパイル –チューニング レコード  このコマンドは、この結果を使用して、指定されたターゲット上のモデルの高性能コードを生成するようにコンパイラーに指示します。チェック tvmc コンパイル –ヘルプ  さらに詳しい情報を得るには。

モデル調整データが収集された後、最適化された演算子を使用してモデルを再コンパイルして、計算を高速化できます。

tvmc compile \
--target "llvm" \
--tuning-records resnet50-v2-7-autotuner_records.json \
--output resnet50-v2-7-tvm_autotuned.tar \
resnet50-v2-7.onnx

最適化されたモデルが実行され、同じ結果が得られることを確認します。

tvmc run \
--inputs imagenet_cat.npz \
--output predictions.npz \
resnet50-v2-7-tvm_autotuned.tar

python postprocess.py

予測値が同じであることを確認します。

# class='n02123045 tabby, tabby cat' with probability=0.610550
# class='n02123159 tiger cat' with probability=0.367181
# class='n02124075 Egyptian cat' with probability=0.019365
# class='n02129604 tiger, Panthera tigris' with probability=0.001273
# class='n04040759 radiator' with probability=0.000261

調整済みモデルと未調整モデルの比較

TVMC はモデル間の基本的な性能評価ツールを提供します。繰り返しの数と、TVMC レポート モデルを実行する期間 (ランタイムの起動とは無関係) を指定できます。チューニングによってモデルのパフォーマンスがどの程度向上するかを大まかに把握できます。

たとえば、Intel i7 システムでテストした場合、調整されたモデルは調整されていないモデルよりも 47% 高速に実行されました。

tvmc run \
--inputs imagenet_cat.npz \
--output predictions.npz \
--print-time \
--repeat 100 \
resnet50-v2-7-tvm_autotuned.tar

# Execution time summary:
# mean (ms) max (ms) min (ms) std (ms)
# 92.19 115.73 89.85 3.15

tvmc run \
--inputs imagenet_cat.npz \
--output predictions.npz \
--print-time \
--repeat 100 \
resnet50-v2-7-tvm.tar

# Execution time summary:
# mean (ms) max (ms) min (ms) std (ms)
# 193.32 219.97 185.04 7.11

最後に書きます

このチュートリアルでは、TVMC (TVM 用のコマンド ライン ドライバー) を紹介します。モデルをコンパイル、実行、調整する方法を示し、入出力の前処理と後処理の必要性について説明します。チューニング後、最適化されていないモデルと最適化されたモデルのパフォーマンスを比較する方法を示します。

このドキュメントでは、ResNet-50 v2 をローカルで使用する簡単な例を示します。ただし、TVMC は、クロスコンパイル、リモート実行、プロファイリング/ベンチマークなど、より多くの機能をサポートしています。

使用 tvmc –ヘルプ  コマンドを使用して、他の利用可能なオプションを確認します。

次のチュートリアル「Python インターフェイスを使用したモデルのコンパイルと最適化」では、Python インターフェイスを使用した同じコンパイルと最適化の手順について説明します。

ぜひお見逃しなく~