EfficientNet B0의 Keeras 모델을 ONX 모델로 변환하여 추론
개시하다
"불합리한 이미지 분류기를 만들어 보다"시리즈에서 Keeras와 EfficientNetB0을 사용하여 이미지 분류기를 실현했다.
나는 그 이미지 분류 모델을 ONX 모델로 바꾸어 추론하고 싶다.
ONX가 뭐예요?
온NX(Open Neural Network Exchange)는 페이스북, 마이크로소프트가 주도해 머신러닝 프레임워크를 상호 운용하는 프로그램이다.자세한 내용은 먼저 구글에서 확인하세요.
왜 ONX 모형으로 바꿨어요?
개인적으로 가장 큰 이유는'ONXRuntime의 추론이 빠르다'는 것이지만, 추론할 때Kers, PyTorch 등 서로 다른 기계 학습 프레임워크를 사용해 학습하는 모델을 통일적으로 처리할 수 있다는 기쁨도 있다.
모형을 바꾸는 두 가지 방법
대략적인 조사만 하면 Kers 모델을 ONX 모델로 변환하는 방법은 다음과 같은 두 가지가 있다.
tf2onnx
로 변환 ← 추천!keras2onnx
로 변환 ← 실패또 이 글은 학습을 하지 않고 전환, 추론만 하고 학습 후 전환하는 순서도 같다.
컨디션
어떤 변환, 추론이든 다음과 같은 환경에서 집행된다.Docker 내에서 실행되며 GPU는 사용되지 않습니다.
tf2 onx로 변환→성공
tf2onnx는 TensorFolow 모델을 ONX 모델로 변환하는 도구입니다.
Kers에서 모델을 만든 후 TensorFolow Saved Model 형식으로 모델을 저장하면 이 도구로 변환할 수 있습니다.
Kers H5 형식은 사용할 수 없습니다.
Docker 이미지 만들기
사용한 경우
Dockerfile
와 requirements.txt
는 다음과 같다.Dockerfile
FROM nvidia/cuda:11.0.3-cudnn8-devel-ubuntu20.04
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install --yes --no-install-recommends \
build-essential \
ca-certificates \
python3-dev \
python3-pip \
python3-setuptools \
tzdata \
&& rm --recursive --force /var/lib/apt/lists/*
RUN python3 -m pip install --upgrade pip setuptools
WORKDIR /opt/app
COPY requirements.txt ./
RUN python3 -m pip install --requirement requirements.txt
ENV LANG C.UTF-8
ENV TZ Asia/Tokyo
requirements.txtonnxruntime==1.7.0
tensorflow-hub==0.11.0
tensorflow==2.4.1
tf2onnx==1.8.4
모델 생성
TensorFlow Hub에서 학습한 EfficientNet B0를 그대로 저장하여 모델 파일을 생성합니다.
원래 공부를 했는데 이번에는 전환 전후를 통해 학습 전의 추론 결과를 비교하여 전환의 성공 여부를 판단한다.
save_model.py
#!/usr/bin/env python3
import tensorflow as tf
import tensorflow_hub as hub
model = tf.keras.Sequential(
[
hub.KerasLayer(
"https://tfhub.dev/tensorflow/efficientnet/b0/feature-vector/1",
trainable=False,
),
tf.keras.layers.Dense(1, activation="sigmoid"),
]
)
model.build([None, 224, 224, 3])
model.summary()
model.save("efficientnet-b0")
실행 예는 다음과 같다.성공하면 efficientnet-b0
디렉터리를 생성합니다.$ ./save_model.py
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
keras_layer (KerasLayer) (None, 1280) 4049564
_________________________________________________________________
dense (Dense) (None, 1) 1281
=================================================================
Total params: 4,050,845
Trainable params: 1,281
Non-trainable params: 4,049,564
_________________________________________________________________
2021-04-23 00:07:12.365759: W tensorflow/python/util/util.cc:348] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
$ ls efficientnet-b0
assets saved_model.pb variables
Keeras로 추론하다
원스 모델로 전환하기 전에 케어스의 추론 결과를 확인해 보자.
여기에 흑백 두 장의 그림에 대해 추론을 진행한다.
predict_keras.py
#!/usr/bin/env python3
import numpy as np
import tensorflow as tf
model = tf.keras.models.load_model("efficientnet-b0")
images = np.array(
[
np.zeros((224, 224, 3), dtype=np.float32),
np.ones((224, 224, 3), dtype=np.float32),
]
)
results = model.predict(images)
print(results)
실행 예는 다음과 같다.모든 조합 층은 무작위 수로 초기화되어 있기 때문에 모델을 저장할 때마다 값이 달라질 수 있음을 주의하십시오.$ ./predict_keras.py
WARNING:tensorflow:No training configuration found in save file, so the model was *not* compiled. Compile it manually.
[[0.5295639]
[0.5148043]]
변환 모델
tf2onnx
를 사용하여 모델을 변환합니다.convert.sh
#!/bin/bash
python3 -m tf2onnx.convert --saved-model efficientnet-b0 --output efficientnet-b0.onnx
실행 예는 다음과 같다.몇 개의 경고를 내보냈지만 이번에는 무시했다.$ ./convert.sh
/usr/lib/python3.8/runpy.py:127: 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))
2021-04-23 00:14:01,125 - WARNING - '--tag' not specified for saved_model. Using --tag serve
2021-04-23 00:14:06,873 - INFO - Signatures found in model: [serving_default].
2021-04-23 00:14:06,873 - WARNING - '--signature_def' not specified, using first signature: serving_default
2021-04-23 00:14:06,873 - INFO - Output names: ['dense']
WARNING:tensorflow:From /usr/local/lib/python3.8/dist-packages/tf2onnx/tf_loader.py:557: extract_sub_graph (from tensorflow.python.framework.graph_util_impl) is deprecated and will be removed in a future version.
Instructions for updating:
Use `tf.compat.v1.graph_util.extract_sub_graph`
2021-04-23 00:14:09,553 - WARNING - From /usr/local/lib/python3.8/dist-packages/tf2onnx/tf_loader.py:557: extract_sub_graph (from tensorflow.python.framework.graph_util_impl) is deprecated and will be removed in a future version.
Instructions for updating:
Use `tf.compat.v1.graph_util.extract_sub_graph`
2021-04-23 00:14:10,275 - INFO - Using tensorflow=2.4.1, onnx=1.9.0, tf2onnx=1.8.4/cd55bf
2021-04-23 00:14:10,275 - INFO - Using opset <onnx, 9>
2021-04-23 00:14:11,053 - INFO - Computed 0 values for constant folding
2021-04-23 00:14:13,763 - INFO - Optimizing ONNX model
2021-04-23 00:14:17,027 - INFO - After optimization: BatchNormalization -42 (49->7), Const -240 (442->202), Identity -926 (926->0), Squeeze -16 (16->0), Transpose -275 (276->1), Unsqueeze -64 (64->0)
2021-04-23 00:14:17,056 - INFO -
2021-04-23 00:14:17,057 - INFO - Successfully converted TensorFlow model efficientnet-b0 to ONNX
2021-04-23 00:14:17,057 - INFO - Model inputs: ['keras_layer_input:0']
2021-04-23 00:14:17,057 - INFO - Model outputs: ['dense']
2021-04-23 00:14:17,057 - INFO - ONNX model is saved at efficientnet-b0.onnx
원스로 추론하다
변환된 ONX 모델을 사용하여 추론합니다.
predict_onnx.py
#!/usr/bin/env python3
import numpy as np
import onnxruntime
session = onnxruntime.InferenceSession("efficientnet-b0.onnx")
images = np.array(
[
np.zeros((224, 224, 3), dtype=np.float32),
np.ones((224, 224, 3), dtype=np.float32),
]
)
results = session.run(["dense"], {"keras_layer_input:0": images})
print(results)
실행 예는 다음과 같다.$ ./predict_onnx.py
[array([[0.52956396],
[0.5148051 ]], dtype=float32)]
케어스 모델의 추론 결과와 엄격하게 일치하지 않지만 소수점 5위까지 일치하기 때문에 문제가 없는 것 같습니다.keras2 onx로 변환 → 실패
다음은 keras2onnx로 변환해 보세요.
tf2onnx
의 전환은 단번에 성공했지만 keras2onnx
의 전환은 상당히 어렵다.참고는 다음과 같습니다.
keras2onnx
는 TensorFlowv2입니다.4 대응 없음, TensorFlowv2.대응(2021년 4월 23일 기준, v1.7.0)Docker 이미지 만들기
사용한 경우
Dockerfile
와 requirements.txt
는 다음과 같다.CUDA, TensorFolow의 버전 등과
tf2onnx
의 상황은 다르다.Dockerfile
FROM nvidia/cuda:10.1-cudnn7-devel-ubuntu18.04
RUN apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install --yes --no-install-recommends \
build-essential \
ca-certificates \
python3-dev \
python3-pip \
python3-setuptools \
tzdata \
&& rm --recursive --force /var/lib/apt/lists/*
RUN python3 -m pip install --upgrade pip setuptools
WORKDIR /opt/app
COPY requirements.txt ./
RUN python3 -m pip install --requirement requirements.txt
ENV LANG C.UTF-8
ENV TZ Asia/Tokyo
requirements.txtkeras2onnx==1.7.0
onnxruntime==1.7.0
tensorflow-hub==0.11.0
tensorflow==2.2.1
모델 생성
기본 단계는
tf2onnx
와 같지만 왜fit
나 predict
를 호출하지 않으면 모델을 저장할 때 오류가 발생합니다.save_model.py
#!/usr/bin/env python3
import numpy as np
import tensorflow as tf
import tensorflow_hub as hub
model = tf.keras.Sequential(
[
hub.KerasLayer(
"https://tfhub.dev/tensorflow/efficientnet/b0/feature-vector/1",
trainable=False,
),
tf.keras.layers.Dense(1, activation="sigmoid"),
]
)
model.build([None, 224, 224, 3])
model.summary()
model.predict(np.zeros((1, 224, 224, 3), dtype=np.float32))
model.save("efficientnet-b0")
실행 예는 다음과 같습니다.$ ./save_model.py
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
keras_layer (KerasLayer) multiple 4049564
_________________________________________________________________
dense (Dense) multiple 1281
=================================================================
Total params: 4,050,845
Trainable params: 1,281
Non-trainable params: 4,049,564
_________________________________________________________________
2021-04-23 00:35:08.379870: W tensorflow/python/util/util.cc:329] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/resource_variable_ops.py:1817: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.
Instructions for updating:
If using Keras pass *_constraint arguments to layers.
WARNING:tensorflow:From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/resource_variable_ops.py:1817: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.
Instructions for updating:
If using Keras pass *_constraint arguments to layers.
Keeras로 추론하다
소스 코드가
tf2onnx
와 같기 때문에 생략합니다.실행 예는 다음과 같다.
$ ./predict_keras.py
WARNING:tensorflow:No training configuration found in save file, so the model was *not* compiled. Compile it manually.
[[0.41439614]
[0.43379608]]
변환 모델
keras2onnx
를 사용하여 모델을 변환합니다.convert.py
#!/usr/bin/env python3
import keras2onnx
import onnx
import tensorflow as tf
model = tf.keras.models.load_model("efficientnet-b0")
onnx_model = keras2onnx.convert_keras(model, "efficientnet-b0")
onnx.save_model(onnx_model, "efficientnet-b0.onnx")
실행 예는 다음과 같다.$ ./convert.py
WARNING:tensorflow:No training configuration found in save file, so the model was *not* compiled. Compile it manually.
tf executing eager_mode: True
tf.keras model eager_mode: False
2021-04-23 00:41:39.446674: W tensorflow/python/util/util.cc:329] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
WARN: No corresponding ONNX op matches the tf.op node sequential/keras_layer/StatefulPartitionedCall/StatefulPartitionedCall/StatefulPartitionedCall/StatefulPartitionedCall/StatefulPartitionedCall/tf_op_layer_BroadcastTo_1/PartitionedCall/BroadcastTo_1 of type BroadcastTo
The generated ONNX model needs run with the custom op supports.
The ONNX operator number change on the optimization: 4007 -> 492
원스로 추론하다
소스 코드가
tf2onnx
와 같기 때문에 생략합니다.실행 예는 다음과 같다.
$ ./predict_onnx.py
Traceback (most recent call last):
File "./predict_onnx.py", line 6, in <module>
session = onnxruntime.InferenceSession("efficientnet-b0.onnx")
File "/usr/local/lib/python3.6/dist-packages/onnxruntime/capi/onnxruntime_inference_collection.py", line 280, in __init__
self._create_inference_session(providers, provider_options)
File "/usr/local/lib/python3.6/dist-packages/onnxruntime/capi/onnxruntime_inference_collection.py", line 307, in _create_inference_session
sess = C.InferenceSession(session_options, self._model_path, True, self._read_config_from_model)
onnxruntime.capi.onnxruntime_pybind11_state.Fail: [ONNXRuntimeError] : 1 : FAIL : Load model from efficientnet-b0.onnx failed:Fatal error: BroadcastTo is not a registered function/op
/오류가 발생했습니다.변환 시 정보와 같이 ONX에서 지원하지 않는 운영자
BroadcastTo
때문일 수 있습니다.맞춤형 조작원을 추가하면 대응이 가능할 수 있지만
tf2onnx
전환이 성공해 조사가 중단됐다.결론
tf2onnx
사용하세요.
Reference
이 문제에 관하여(EfficientNet B0의 Keeras 모델을 ONX 모델로 변환하여 추론), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/kleamp1e/articles/202104-keras-onnx텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)