android studio에서 pytorch로 학습시킨 model을 바로 사용하는 것은 불가능하다. 애초에 여기서 선택지가 있는데, pytorch mobile version 사용하기 와 onnx를 거쳐 tensorflow로 변환하기 이렇게 두 가지가 있다.
그 중에서도 이번에는 onnx를 거쳐 tensorflow로 변환하는 과정에 대해 시도해 볼 것이다.
그래서 우리는 몇가지 step을 거쳐야한다.
pytorch model --> onnx --> tensorflow 로 바꿀 것이다.
우선 pytorch version에서 onnx로 바꾸는 것 부터 해보자.
본 내용은 pytorch_tutorial 을 참고하였다.
ONNX 형식으로 바꾸기 전에 잠깐 ONNX 가 무엇인지 살펴보도록하자.
ONNX 런타임은 ONNX모델을 위한 엔진으로서 성능에 초점을 맞추고 있고 여러 다양한 플랫폼과 하드웨어(윈도우, 리눅스, 맥을 비롯한 플랫폼 뿐만 아니라 CPU, GPU 등의 하드웨어)에서 효율적인 추론을 가능하게 한다.
ONNX 에 대해 더 자세한 설명이 필요하다면, 이 사이트를 참고하도록 하자. 이제 본격적으로 본 튜터리얼을 위해 필요한 library들을 설치해보자.
pip install onnx
pip install onnxruntime
import torch.onnx
로 진행하면 된다.
(물론 torch는 prerequisted library 이다.)
사용할 모델 정의 후, 미리 학습된 가중치를 가져온다. batch_size는 임의의 수를 넣어주고 학습된 가중치로 모델을 초기화 해준다.
이후! 모델을 추론모드로 전환 해야한다. 즉 torch_model.eval() 또는 torch_model.train(False)를 호출해야하는 것이다. ( 이는 dropout이나 batchnorm과 같은 연산들이 추론과 학습모드에서 작동 방식에 차이가 있기 때문에 필요에 따라 꼭 바꾸어 주여야한다. )
tracing, scripting 두 가지 방법이 존재하는데 우선 tracing 부터 살펴보도록하자. torch.onnx.export() 이 함수 하나만 이용하면 변환이 쉽게 가능하다.
이 함수는
torch.onnx.export(model, args, f, export_params=True, verbose=False, training=<TrainingMode.EVAL: 0>, input_names=None, output_names=None, aten=False, operator_export_type=None, opset_version=None, _retain_param_name=True, do_constant_folding=True, example_outputs=None, strip_doc_string=True, dynamic_axes=None, keep_initializers_as_inputs=None, custom_opsets=None, enable_onnx_checker=True, use_external_data_format=False)
이런 파라미터들을 다양하게 가지는데, 조금 더 자세한 설명은 torch.onnx.export 를 참고해도 좋다.
그럼 실제로 어떻게 사용하면 되는지 하나씩 살펴보겠다.
우선 모델에 대한 입력값을 정해준다. 자료형과 shape만 맞으면 돼고, 안에 들어가는 값은 랜덤하게 들어가도 괜찮다. 우리는 x를 input으로 정의해주자.
x = torch.randn(batch_size, 1, 224,224, requires_grad=True)
이제 진짜 모델을 변환하도록하겠다!!
torch.onnx.export(torch_model, # 실행될 모델
x, # 모델 입력값 (튜플 또는 여러 입력값들도 가능)
"onnx_version_model.onnx", # 모델 저장 경로 (파일 또는 파일과 유사한 객체 모두 가능)
export_params=True, # 모델 파일 안에 학습된 모델 가중치를 저장할지의 여부
opset_version=10, # 모델을 변환할 때 사용할 ONNX 버전
do_constant_folding=True, # 최적하시 상수폴딩을 사용할지의 여부
input_names = ['input'], # 모델의 입력값을 가리키는 이름
output_names = ['output'], # 모델의 출력값을 가리키는 이름
dynamic_axes={'input' : {0 : 'batch_size'}, # 가변적인 길이를 가진 차원
'output' : {0 : 'batch_size'}})
중요한 것 중하나는 daynamic_axes 부분인데, 이 부분에서 우리는 batch_size가 가변적으로 변해도 괜찮다는 것을 알려줘야한다. 그리고 모델 저장 경로는 자신이 원하는 대로 바꿔주면 된다~
이제 저장한 ONNX 파일을 Tensorflow 형태로 바꾸면, android studio에서 불러 낼 수 있게 된다. 본 단계는 onnx-tensorflow를 참고하였다.
우선 oonx-tf를 사용할 것이기 때문에!
이 단계에서도 엄청 여러가지 단계가 있는데 난 코드 짜기가 귀찮아서,,ㅎ commandline으로 해결하겠다!
pip install onnx-tf
install 잘 되었는지 확인 할 겸 command 창에서
onnx-tf convert -h
를 쳐보자.
잘 설치가 되었다면
usage: onnx-tf [-h] --infile INFILE --outdir OUTDIR [--extdatadir EXTDATADIR]
[--device DEVICE] [--strict STRICT]
[--logging_level LOGGING_LEVEL] [--auto_cast AUTO_CAST]
This is the converter for converting protocol buffer between tf and onnx.
optional arguments:
-h, --help show this help message and exit
--infile INFILE, -i INFILE
Input file path.
--outdir OUTDIR, -o OUTDIR
Output directory.
--extdatadir EXTDATADIR, -e EXTDATADIR
External input data file directory.
backend arguments (onnx -> tf):
--device DEVICE The device to execute this model on. It can be either
CPU (default) or CUDA. (from onnx_tf.backend.prepare)
--strict STRICT Whether to enforce semantic equivalence between the
original model and the converted tensorflow model,
defaults to True (yes, enforce semantic equivalence).
Changing to False is strongly discouraged. Currently,
the strict flag only affects the behavior of MaxPool
and AveragePool ops. (from onnx_tf.backend.prepare)
--logging_level LOGGING_LEVEL
The logging level, default is INFO. Change it to DEBUG
to see more conversion details or to WARNING to see
less (from onnx_tf.backend.prepare)
--auto_cast AUTO_CAST
Whether to auto cast data types that might lose
precision for the tensors with types not natively
supported by Tensorflow, default is False (from
onnx_tf.backend.prepare)
라는 내용이 안내 될 것이다.
onnx-tf convert -i /path/to/input.onnx -o /path/to/output
/path/to/input.onnx 자리에 input으로 넣어줄 onnx 파일을
/path/to/output 이부분에는 output을 저장할 위치를 적어주면 된다.