TensorFlow Hubから取得した機械学習モデルをONNX形式に変換する
4行まとめ
- TensorFlow HubからはSavedModel形式で機械学習モデルをダウンロードできる。
-
tf2onnx
を使うことでSavedModel形式からONNX形式に変換できる。 -
tf2onnx
では--rename-inputs
、--rename-outputs
オプションを使うことでノード名を指定できる。 -
onnx
、tensorflow
、tf2onnx
パッケージの依存関係はややこしい。
はじめに
TensorFlow Hubでは様々な機械学習モデルが配布されています。
これらの機械学習モデルをONNX形式に変換して利用する機会がありましたので、その手順を備忘録としてまとめました。
手順
TensorFlow Hubからの機械学習モデルの取得、SavedModel形式からONNX形式への変換の手順は、大きく以下の通りです。
- TensorFlow Hubで目的の機械学習モデルを見つける。
- SavedModel形式のモデルをダウンロードする。
-
tar.gz
を展開する。 -
tf2onnx
を使ってONNXモデルに変換する。
環境
SavedModel形式からONNX形式への変換にはonnx
、tensorflow
、tf2onnx
パッケージが必要です。
今回は以下のDockerfile
を使い、Docker内で作業を実施しました。
FROM ubuntu:22.04
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install --yes --no-install-recommends \
ca-certificates \
python3-dev \
python3-pip \
python3-setuptools \
wget \
&& rm --recursive --force /var/lib/apt/lists/*
RUN python3 -m pip install --upgrade \
pip==22.3.1 \
setuptools==65.6.3
RUN python3 -m pip install \
onnx==1.13.0 \
tensorflow==2.9.0 \
tf2onnx==1.13.0
onnx
、tensorflow
、tf2onnx
パッケージの依存関係は幾分ややこしいので、「最新のバージョンを使おう」と考えず、実績のある組み合わせで実施することをお勧めします。
対象の機械学習モデル
今回は以下の機械学習モデルを対象としました。ImageNet-21KでトレーニングされたEfficientNet V2のSサイズ、特徴量抽出用のバージョン2です。
実際の変換手順
まずはDockerイメージをビルドし、作業ディレクトリをマウントした状態でシェルを起動します。今回はtfhub_onnx
というイメージ名にしました。
docker build --tag tfhub_onnx .
docker run --interactive --tty --rm \
--volume $(pwd):/workspace \
--workdir /workspace \
tfhub_onnx
続いて、起動したDockerコンテナ内で変換を実施します。実施例は以下の通りです。
今回使用した機械学習モデルの入力ノード名、出力ノード名は分かりづらいので、 --rename-inputs
オプション、--rename-outputs
オプションを使って上書きしました。
なお、GPUに関する警告メッセージが出力されていますが、変換するだけならGPUは不要です。
# SavedModel形式の機械学習モデルをダウンロードする
docker$ wget \
--output-document efficientnet_v2_imagenet21k_s_v2.tar.gz \
"https://tfhub.dev/google/imagenet/efficientnet_v2_imagenet21k_s/feature_vector/2?tf-hub-format=compressed"
docker$ ls -l efficientnet_v2_imagenet21k_s_v2.tar.gz
-rw-r--r-- 1 root root 76099140 Jul 21 2021 efficientnet_v2_imagenet21k_s_v2.tar.gz
docker$ sha1sum efficientnet_v2_imagenet21k_s_v2.tar.gz
553c076fbc59f9e5a63947297b2d27cbc138efd9 efficientnet_v2_imagenet21k_s_v2.tar.gz
# ダウンロードしたアーカイブを展開する
docker$ mkdir efficientnet_v2_imagenet21k_s_v2
docker$ tar zxfv efficientnet_v2_imagenet21k_s_v2.tar.gz -C efficientnet_v2_imagenet21k_s_v2
./
./variables/
./variables/variables.index
./variables/variables.data-00000-of-00001
./saved_model.pb
# SavedModel形式をONNX形式に変換する
docker$ python3 -m tf2onnx.convert \
--saved-model efficientnet_v2_imagenet21k_s_v2 \
--output efficientnet_v2_imagenet21k_s_v2.onnx \
--rename-inputs input_image \
--rename-outputs output_feature
2023-01-07 07:13:04.439761: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libcudart.so.11.0'; dlerror: libcudart.so.11.0: cannot open shared object file: No such file or directory
2023-01-07 07:13:04.439781: I tensorflow/stream_executor/cuda/cudart_stub.cc:29] Ignore above cudart dlerror if you do not have a GPU set up on your machine.
/usr/lib/python3.10/runpy.py:126: RuntimeWarning: 'tf2onnx.convert' found in sys.modules after import of package 'tf2onnx', but prior to execution of 'tf2onnx.convert'; this may result in unpredictable behaviour
warn(RuntimeWarning(msg))
2023-01-07 07:13:05.349991: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libcuda.so.1'; dlerror: libcuda.so.1: cannot open shared object file: No such file or directory
2023-01-07 07:13:05.350005: W tensorflow/stream_executor/cuda/cuda_driver.cc:269] failed call to cuInit: UNKNOWN ERROR (303)
2023-01-07 07:13:05.350029: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:163] no NVIDIA GPU device is present: /dev/nvidia0 does not exist
2023-01-07 07:13:05.350193: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: AVX2 FMA
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
2023-01-07 07:13:05,351 - WARNING - '--tag' not specified for saved_model. Using --tag serve
2023-01-07 07:13:10,476 - INFO - Signatures found in model: [serving_default].
2023-01-07 07:13:10,476 - WARNING - '--signature_def' not specified, using first signature: serving_default
2023-01-07 07:13:10,478 - INFO - Output names: ['output_1']
2023-01-07 07:13:10.506651: I tensorflow/core/grappler/devices.cc:66] Number of eligible GPUs (core count >= 8, compute capability >= 0.0): 0
2023-01-07 07:13:10.506767: I tensorflow/core/grappler/clusters/single_machine.cc:358] Starting new session
2023-01-07 07:13:12.667590: I tensorflow/core/grappler/devices.cc:66] Number of eligible GPUs (core count >= 8, compute capability >= 0.0): 0
2023-01-07 07:13:12.667720: I tensorflow/core/grappler/clusters/single_machine.cc:358] Starting new session
2023-01-07 07:13:13,245 - INFO - Using tensorflow=2.9.0, onnx=1.13.0, tf2onnx=1.13.0/2c1db5
2023-01-07 07:13:13,245 - INFO - Using opset <onnx, 13>
2023-01-07 07:13:17,363 - INFO - Computed 0 values for constant folding
2023-01-07 07:13:20,247 - INFO - Optimizing ONNX model
2023-01-07 07:13:24,449 - INFO - After optimization: BatchNormalization -105 (110->5), Const -375 (731->356), GlobalAveragePool +31 (0->31), Identity -2 (2->0), ReduceMean -31 (31->0), Reshape -30 (30->0), Squeeze +1 (0->1), Transpose -589 (590->1)
2023-01-07 07:13:24,513 - INFO -
2023-01-07 07:13:24,513 - INFO - Successfully converted TensorFlow model efficientnet_v2_imagenet21k_s_v2 to ONNX
2023-01-07 07:13:24,513 - INFO - Model inputs: ['input_image']
2023-01-07 07:13:24,513 - INFO - Model outputs: ['output_feature']
2023-01-07 07:13:24,513 - INFO - ONNX model is saved at efficientnet_v2_imagenet21k_s_v2.onnx
docker$ ls -l efficientnet_v2_imagenet21k_s_v2.onnx
-rw-r--r-- 1 root root 80650295 Jan 7 07:13 efficientnet_v2_imagenet21k_s_v2.onnx
おわりに
パッケージの依存関係でハマり時間を浪費してしまいましたが、無事にSavedModel形式をONNX形式に変換することができました。
何らかの参考になれば幸いです。
Discussion