ONNX 런타임은 학습 프레임워크에 의존하지 않고 CPU 또는 GPU에서 고성능으로 머신 러닝 모델을 쉽게 실행할 수 있는 방법을 제공합니다. 머신 러닝 프레임워크는 일반적으로 예측보다는 배치 학습에 최적화되어 있지만, 애플리케이션, 웹사이트 및 서비스에서는 예측이 더 일반적인 시나리오입니다. ONNX 런타임을 사용하면 다음과 같은 작업을 수행할 수 있습니다.
(1) 원하는 프레임워크를 사용하여 모델을 학습합니다.
(2) 모델을 ONNX 형식으로 변환하거나 내보냅니다. 자세한 내용은 ONNX 튜토리얼을 참조하세요.
(3) ONNX 런타임을 사용하여 모델을 로드하고 실행합니다.
이 튜토리얼에서는 scikit-learn을 사용하여 파이프라인을 간략하게 구성하고, 이를 ONNX 형식으로 변환한 다음 첫 번째 예측을 실행합니다.
1단계: 선호하는 프레임워크를 사용하여 모델을 학습시키세요.
저희는 유명한 iris 데이터셋을 사용하겠습니다.
<<<
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
PyTorch의 핵심은 nn.Module 클래스입니다. 이 클래스는 전체 딥러닝 모델 또는 단일 레이어를 나타냅니다. 모듈은 조합하거나 확장하여 모델을 구축할 수 있습니다. 자체 모듈을 작성하려면 모델 입력과 학습된 가중치를 기반으로 출력을 계산하는 순방향 함수를 구현해야 합니다. 자체 PyTorch 모델을 작성하는 경우, 모델을 학습시키는 과정도 함께 진행해야 합니다. 또는 PyTorch 자체 또는 HuggingFace와 같은 다른 라이브러리에서 제공하는 사전 학습된 모델을 사용할 수도 있습니다.
PyTorch를 사용하여 이미지 처리 모델을 코딩하는 방법은 다음과 같습니다.
import torch
import torch.nn as nn
import torchvision.transforms as T
from torchvision.models import resnet18, ResNet18_Weights
model =transformers.BertForQuestionAnswering.from_pretrained(model_name)
학습된 모델을 생성하거나 가져온 후, 추론을 수행하기 위해 어떻게 실행할까요? 아래에서는 PyTorch에서 추론을 수행하는 데 사용할 수 있는 몇 가지 접근 방식을 설명합니다.
추론 옵션
PyTorch 네이티브를 사용한 추론
성능이나 크기에 민감하지 않고 Python 실행 파일과 라이브러리가 포함된 환경에서 실행하는 경우, 애플리케이션을 PyTorch 네이티브로 실행할 수 있습니다.
학습된 모델이 준비되면, 데이터 과학 팀에서 추론을 위해 모델을 저장하고 불러오는 데 사용할 수 있는 두 가지 방법이 있습니다. (1) 전체 모델 저장 및 불러오기
# Save the entire model to PATH
torch.save(model, PATH)
# Load the model from PATH and set eval mode for inference
model =torch.load(PATH)
model.eval()
(2) 모델의 매개변수를 저장하고, 모델을 다시 선언한 다음, 매개변수를 불러옵니다.
# Save the model parameters
torch.save(model.state_dict(), PATH)
# Redeclare the model and load the saved parameters
model =TheModel(...)
model.load_state_dict(torch.load(PATH))
model.eval()
어떤 방법을 사용할지는 구성에 따라 다릅니다. 전체 모델을 저장하고 불러오는 방식은 모델을 다시 선언하거나 모델 코드 자체에 접근할 필요가 없다는 장점이 있습니다. 하지만 저장 환경과 불러오는 환경의 클래스, 메서드, 매개변수가 일치해야 한다는 단점이 있습니다(이러한 요소들은 직접 직렬화 및 역직렬화되기 때문입니다).
모델의 학습된 매개변수(상태 사전, state_dict)를 저장하는 방식은 원본 모델 코드에 접근할 수 있는 한 첫 번째 방식보다 유연합니다.
모델 추론에 네이티브 PyTorch를 사용하지 않으려는 주된 이유는 두 가지입니다. 첫째, Python 런타임과 PyTorch 라이브러리 및 관련 종속성이 포함된 환경에서 실행해야 합니다. 이러한 파일들의 용량은 수 기가바이트에 달합니다. 모바일, 웹 브라우저 또는 특수 하드웨어와 같은 환경에서 실행하려는 경우 네이티브 PyTorch를 사용한 PyTorch 추론은 제대로 작동하지 않습니다. 둘째, 성능 문제입니다. PyTorch 모델은 기본 설정 상태에서는 애플리케이션에 필요한 성능을 제공하지 못할 수 있습니다.
TorchScript를 사용한 추론
PyTorch 또는 다른 Python 라이브러리를 설치할 수 없는 제약이 있는 환경에서 실행하는 경우, PyTorch 모델을 TorchScript로 변환하여 추론을 수행하는 옵션이 있습니다. TorchScript는 Python의 하위 집합으로, Python이 아닌 환경에서도 로드하고 실행할 수 있는 직렬화된 모델을 생성할 수 있도록 합니다.
# Export to TorchScript
script =torch.jit.script(model, example)
# Save scripted model
script.save(PATH)
# Load scripted model
model =torch.jit.load(PATH)
model.eval()
#include<torch/script.h>
...
torch::jit::script::Module module;
try{
// Deserialize the ScriptModule
module=torch::jit::load(PATH);
}
catch(constc10::Error& e){
...
}
...
TorchScript 방식을 사용하면 PyTorch 모델에 대한 추론을 수행하기 위해 환경에 Python 런타임이 필요하지는 않지만, libtorch 바이너리를 설치해야 합니다. 그런데 이 바이너리의 용량이 환경에 비해 너무 클 수 있습니다. 또한 애플리케이션에 필요한 성능을 얻지 못할 수도 있습니다.
ONNXRuntime을 사용한 추론
성능과 이식성이 가장 중요한 경우, ONNXRuntime을 사용하여 PyTorch 모델을 추론할 수 있습니다. ONNXRuntime을 사용하면 지연 시간과 메모리 사용량을 줄이고 처리량을 높일 수 있습니다. 또한 ONNXRuntime에서 제공하는 언어 바인딩 및 라이브러리를 사용하여 클라우드, 엣지, 웹 또는 모바일 환경에서 모델을 실행할 수 있습니다.
첫 번째 단계는 PyTorch ONNX 익스포터를 사용하여 PyTorch 모델을 ONNX 형식으로 내보내는 것입니다.
# Specify example data
example = ...
# Export model to ONNX format
torch.onnx.export(model, PATH, example)
ONNX 형식으로 내보낸 후에는 선택적으로 Netron 뷰어에서 모델을 확인하여 모델 그래프, 입력 및 출력 노드의 이름과 모양, 그리고 가변 크기의 입력 및 출력을 가진 노드(동적 축)를 이해할 수 있습니다.
그런 다음 원하는 환경에서 ONNX 모델을 실행할 수 있습니다. ONNXRuntime 엔진은 C++로 구현되었으며 C++, Python, C#, Java, Javascript, Julia 및 Ruby API를 제공합니다. ONNXRuntime은 Linux, Mac, Windows, iOS 및 Android에서 모델을 실행할 수 있습니다. 예를 들어, 다음 코드 스니펫은 C++ 추론 애플리케이션의 기본 구조를 보여줍니다.
// Allocate ONNXRuntime session
auto memory_info =Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeCPU);
ONNXRuntime은 기본적으로 ONNX 그래프에 일련의 최적화를 적용하여 가능한 경우 노드를 결합하고 상수 값을 분리(상수 폴딩)합니다. 또한 ONNXRuntime은 실행 공급자 인터페이스를 통해 CUDA, TensorRT, OpenVINO, CoreML, NNAPI 등 다양한 하드웨어 가속기와 통합되며, 대상 하드웨어 플랫폼에 따라 사용할 수 있는 가속기가 달라집니다.
ONNX 모델의 성능을 더욱 향상시키려면 양자화를 수행할 수 있습니다.
모바일이나 엣지 컴퓨팅과 같이 제약이 있는 환경에서 애플리케이션을 실행하는 경우, 애플리케이션에서 사용하는 모델 또는 모델 세트를 기반으로 크기를 줄인 런타임을 구축할 수 있습니다.
Linux에서는 locale-gen en_US.UTF-8 및 update-locale LANG=en_US.UTF-8 명령을 실행하여 language-pack-en 패키지를 설치하십시오. Windows 빌드에는 Visual C++ 2019 런타임이 필요합니다. 최신 버전을 권장합니다.
CUDA 및 cuDNN
ONNX Runtime GPU 패키지를 사용하려면 CUDA와 cuDNN을 설치해야 합니다. 호환되는 CUDA 및 cuDNN 버전은 CUDA 실행 공급자 요구 사항을 참조하십시오. zlib는 Linux용 cuDNN 9.x에서만 필요합니다(zlib는 cuDNN 9.x Windows 동적 라이브러리에 정적으로 링크됨). Linux 및 Windows용 cuDNN 8.x에서도 zlib가 필요합니다. Linux 또는 Windows에 zlib를 설치하려면 cuDNN 8.9 설치 가이드를 따르십시오. Windows에서는 CUDA bin 및 cuDNN bin 디렉터리의 경로를 PATH 환경 변수에 추가해야 합니다. Linux에서는 CUDA lib64 및 cuDNN lib 디렉터리의 경로를 LD_LIBRARY_PATH 환경 변수에 추가해야 합니다. onnxruntime-gpu 패키지의 경우, CUDA 또는 cuDNN을 수동으로 설치하지 않고도 PyTorch와 함께 사용할 수 있습니다. 자세한 내용은 PyTorch와의 호환성을 참조하십시오.
Python 설치
ONNX Runtime CPU 설치
2.2 Inference on multiple target
ONNX Runtime을 사용하여 다양한 하드웨어 환경에서 PyTorch 모델 추론하기
PyTorch 또는 ONNX 모델을 배포하고 성능과 하드웨어 유연성을 극대화하려는 개발자라면 ONNX 런타임을 활용하여 하드웨어 플랫폼에 최적화된 모델을 실행할 수 있습니다.
(3) 동일한 애플리케이션 코드를 사용하여 모든 하드웨어 플랫폼에서 추론을 로드하고 실행하는 ONNX 런타임을 통해 기본 CPU, NVIDIA CUDA(GPU), Intel OpenVINO에 배포하는 방법
ONNX는 Microsoft, Meta, Amazon 및 기타 기술 기업들이 머신 러닝 모델을 표준화하고 다양한 유형의 하드웨어에 쉽게 배포할 수 있도록 개발한 오픈 소스 ML 모델 형식입니다. ONNX Runtime은 Microsoft에서 기여하고 유지 관리하며, PyTorch, TensorFlow 등의 프레임워크에서 ONNX 모델의 성능을 최적화합니다. ImageNet 데이터셋으로 학습된 ResNet-50 모델은 이미지 분류에 일반적으로 사용됩니다.
환경에 맞는 실행 공급자를 선택하여 ONNX 런타임으로 모델을 추론합니다. CPU를 사용하는 환경이라면 CPUExecutionProvider의 주석을 해제하고, NVIDIA CUDA를 사용하는 환경이라면 CUDAExecutionProvider의 주석을 해제하고, OpenVINOExecutionProvider를 사용하는 환경이라면 OpenVINOExecutionProvider의 주석을 해제합니다. 이때 onnxruntime.InferenceSession의 나머지 코드는 주석 처리해야 합니다.
print("OpenVINO CPU Inference time = {} ms".format(format(sum(latency) * 1000 / len(latency), '.2f')))
print("***** Verifying correctness *****")
for i inrange(2):
print('OpenVINO and ONNX Runtime output {} are close:'.format(i), np.allclose(ort_output,outputs,rtol=1e-05,atol=1e-04))
샘플 출력:
Egyptian cat 0.7820879
tabby 0.113261245
tiger cat 0.020114701
Siamese cat 0.012514038
plastic bag 0.0056432663
OpenVINO CPU Inference time = 31.83 ms
***** Verifying correctness *****
PyTorch and ONNX Runtime output 0 are close: True
PyTorch and ONNX Runtime output 1 are close: True
Conclusion
결론
ONNX Runtime은 CPU, NVIDIA CUDA(GPU), Intel OpenVINO(모바일)에서 PyTorch 또는 ONNX 모델을 실행하는 효과적인 방법임을 입증했습니다. ONNX Runtime을 사용하면 실행 공급자(Execution Providers)에서 제공하는 더 다양한 하드웨어에 배포할 수 있습니다. ONNX Runtime Github repo에 참여하여 여러분의 의견을 들려주시면 감사하겠습니다.
비디오 데모
ResNet-50 배포 및 유연한 추론에 대한 자세한 설명과 단계별 가이드는 여기에서 비디오를 시청하세요.
이 튜토리얼에서는 HuggingFace의 BERT 모델을 ONNX로 변환하고, AzureML을 통해 ONNX 런타임과 함께 ONNX 모델을 배포하는 방법을 설명합니다.
다음 섹션에서는 Stanford Question Answering Dataset(SQuAD) 데이터셋으로 학습된 HuggingFace BERT 모델을 예시로 사용합니다. 자신만의 질의응답 모델을 학습시키거나 미세 조정할 수도 있습니다.
질의응답 시나리오는 질문과 컨텍스트라는 텍스트 조각을 입력으로 받아 컨텍스트에서 추출한 텍스트 문자열인 답변을 생성합니다. 이 시나리오는 질문과 컨텍스트를 토큰화 및 인코딩하고, 입력값을 변환기 모델에 입력하여 컨텍스트에서 가장 가능성이 높은 시작 및 끝 토큰을 생성한 다음, 이를 다시 단어로 매핑하여 답변을 생성합니다.
그런 다음 모델과 스코어링 코드가 온라인 엔드포인트를 사용하여 AzureML에 배포됩니다.
다음 코드는 ONNX Runtime을 사용하여 ONNX 모델을 실행합니다. Azure Machine Learning에 배포하기 전에 로컬에서 테스트할 수 있습니다.
`init()` 함수는 시작 시 호출되어 토크나이저 및 ONNX 런타임 세션 생성과 같은 일회성 작업을 수행합니다.
`run()` 함수는 Azure ML 엔드포인트를 사용하여 모델을 실행할 때 호출됩니다. 필요한 `preprocess()` 및 `postprocess()` 단계를 추가하세요.
로컬 테스트 및 비교를 위해 PyTorch 모델을 실행할 수도 있습니다.
importos
importlogging
importjson
importnumpyasnp
importonnxruntime
importtransformers
importtorch
# 전처리 함수는 질문과 컨텍스트를 입력받아 모델에 필요한 텐서를 생성합니다. # - input_ids: 질문에 포함된 단어들을 정수로 인코딩한 것 # - attention_mask: 이 모델에서는 사용되지 않음 # - token_type_ids: 질문의 단어와 컨텍스트의 단어를 구분하는 0과 1로 이루어진 리스트 # 이 함수는 또한 질문과 컨텍스트에 포함된 단어들을 반환하여, 답변을 구문으로 디코딩할 수 있도록 합니다.
# The pre process function take a question and a context, and generates the tensor inputs to the model:
# - input_ids: the words in the question encoded as integers
# - attention_mask: not used in this model
# - token_type_ids: a list of 0s and 1s that distinguish between the words of the question and the words of the context
# This function also returns the words contained in the question and the context, so that the answer can be decoded into a phrase.
먼저 구성 노트북에서 이전에 생성한 기존 작업 영역에서 작업 영역 개체를 인스턴스화합니다.
참고로, 다음 코드는 노트북과 동일한 디렉터리 또는 .azureml이라는 하위 디렉터리에 구독 정보가 포함된 config.json 파일이 있다고 가정합니다. Workspace.get() 메서드를 사용하여 작업 영역 이름, 구독 이름 및 리소스 그룹을 명시적으로 제공할 수도 있습니다.
# # If you'd like to delete the models from workspace
# model_to_delete = Model(ws, name)
# model_to_delete.delete()
Deploy the model and scoring code as an AzureML endpoint
Note: the endpoint interface of the Python SDK has not been publicly released yet, so for this section, we will use the Azure ML CLI.
There are three YML files in the yml folder:
env.yml: A conda environment specification, from which the execution environment of the endpoint will be generated
endpoint.yml: The endpoint specification, which simply contains the name of the endpoint and the authorization method
deployment.yml: The deployment specification, which contains specifications of the scoring code, model, and environment. You can create multiple deployments per endpoint, and route different amounts of traffic to the deployments. For this example, we will create only one deployment.
The deployment can take up to 15 minutes. Note also that all of the files in the directory with the notebook will be uploaded into the docker container that forms the basis of your endpoint, including any local copies of the ONNX model (which has already been deployed to AzureML in the previous step). To reduce the deployment time remove any local copies of large files, before creating the endpoint.
모델 및 스코어링 코드를 AzureML 엔드포인트로 배포합니다.
참고: Python SDK의 엔드포인트 인터페이스는 아직 공개되지 않았으므로 이 섹션에서는 Azure ML CLI를 사용합니다.
yml 폴더에는 다음 세 개의 YML 파일이 있습니다.
•env.yml: conda 환경 사양으로, 엔드포인트의 실행 환경을 생성하는 데 사용됩니다.
•endpoint.yml: 엔드포인트 사양으로, 엔드포인트 이름과 인증 방법을 포함합니다.
•deployment.yml: 배포 사양으로, 스코어링 코드, 모델 및 환경에 대한 사양을 포함합니다. 엔드포인트당 여러 개의 배포를 생성하고 각 배포로 전송되는 트래픽 양을 다르게 지정할 수 있습니다. 이 예에서는 하나의 배포만 생성합니다.
배포에는 최대 15분이 소요될 수 있습니다. 또한 노트북이 있는 디렉터리의 모든 파일(이전 단계에서 AzureML에 이미 배포된 ONNX 모델의 로컬 복사본 포함)이 엔드포인트의 기반이 되는 Docker 컨테이너에 업로드됩니다. 배포 시간을 단축하려면 엔드포인트를 생성하기 전에 대용량 파일의 로컬 복사본을 모두 제거하십시오.
노트북 파일은 ONNX 모델의 로컬 복사본(이전 단계에서 AzureML에 이미 배포됨)을 포함하여 엔드포인트의 기반이 되는 Docker 컨테이너에 업로드됩니다. 배포 시간을 단축하려면 엔드포인트를 생성하기 전에 대용량 파일의 로컬 복사본을 모두 제거하십시오.