Project ES/: : ONNX

ONNX Tutorial

Jay.P Morgan 2026. 5. 1. 00:11

 

 

 

  1.  ONNX Runtime Inferencing: API Basics 

 

이 튜토리얼에서는 각 언어 API를 사용하여 ONNX 런타임으로 기본적인 추론을 수행하는 방법을 보여줍니다. 더 많은 예제는 microsoft/onnxruntime-inference-examples에서 확인할 수 있습니다.

 

  1.1  Python

 

Scikit-learn Logistic Regression

 

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
  iris = load_iris()
  X, y = iris.data, iris.target
  X_train, X_test, y_train, y_test = train_test_split(X, y)

  from sklearn.linear_model import LogisticRegression
  clr = LogisticRegression()
  clr.fit(X_train, y_train)
  print(clr)
 

>>>

 
          LogisticRegression()
 

 

 

2단계: 모델을 ONNX 형식으로 변환 또는 내보내기

ONNX는 머신러닝 모델을 설명하는 형식입니다. 모델을 구성하는 데 일반적으로 사용되는 연산자 집합을 정의합니다. 다른 모델 형식을 ONNX 형식으로 변환하는 도구가 있습니다. 여기서는 ONNXMLTools를 사용하겠습니다.

<<<

 
  from skl2onnx import convert_sklearn
  from skl2onnx.common.data_types import FloatTensorType

  initial_type = [('float_input', FloatTensorType([None, 4]))]
  onx = convert_sklearn(clr, initial_types=initial_type)
  with open("logreg_iris.onnx", "wb") as f:
  f.write(onx.SerializeToString())
 

 

>>>

 

3단계: ONNX 런타임을 사용하여 모델 로드 및 실행

이 머신러닝 모델의 예측값을 계산하기 위해 ONNX 런타임을 사용합니다.

<<<

 
  import numpy
  import onnxruntime as rt

  sess = rt.InferenceSession(
  "logreg_iris.onnx", providers=rt.get_available_providers())
  input_name = sess.get_inputs()[0].name
  pred_onx = sess.run(None, {input_name: X_test.astype(numpy.float32)})[0]
  print(pred_onx)
 

 

>>>

 
  [0 2 1 0 1 1 1 0 1 0 2 1 2 2 0 1 2 2 0 0 0 2 1 2 1 2 0 1 1 2 2 2 0 0 1 0 1
   0]
 

 

코드에서 특정 출력값을 얻으려면, 출력값의 이름을 목록에 지정하여 코드를 수정할 수 있습니다.

<<<

 
  import numpy
  import onnxruntime as rt

  sess = rt.InferenceSession(
          "logreg_iris.onnx", providers=rt.get_available_providers())
  input_name = sess.get_inputs()[0].name
  label_name = sess.get_outputs()[0].name
  pred_onx = sess.run(
          [label_name], {input_name: X_test.astype(numpy.float32)})[0]
  print(pred_onx)
 

 

>>>

 
  [0 2 1 0 1 1 1 0 1 0 2 1 2 2 0 1 2 2 0 0 0 2 1 2 1 2 0 1 1 2 2 2 0 0 1 0 1
   0]
 

 

 

 

  1.2  Image recognition (Resnet50)

 

 

 

  1.3  C/C++ examples

 

 

 

  1.4  C#

 

 

  1.5  Java

 

 

 

  1.6  JavaScript

 

 

 

  2. Accelation PyTorch

 

  2.1  PyTorch Inference

 

PyTorch 모델 추론

PyTorch에 대해 알아보고 PyTorch 모델을 사용한 추론 방법을 살펴보겠습니다.

 

PyTorch는 사용하기 쉽고 유연한 API, 특히 자연어 처리(NLP) 영역에서 제공되는 풍부한 기성 모델, 그리고 도메인별 라이브러리를 통해 딥러닝 분야를 선도하고 있습니다.

 

PyTorch로 구축된 모델을 사용하려는 개발자와 애플리케이션 생태계가 점점 확대되고 있으며, 이 글에서는 PyTorch 모델 추론에 대한 간략한 개요를 제공합니다. PyTorch 모델을 추론하는 방법은 여러 가지가 있으며, 아래에 나열되어 있습니다.

 

이 글은 PyTorch 모델을 학습시키는 방법이 아닌, PyTorch 모델을 사용한 추론 방법에 대한 정보를 찾는 독자를 대상으로 합니다.

 

목차

 

PyTorch 개요

 

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


  class Predictor(nn.Module):

         def __init__(self):
                  super().__init__()
                  weights = ResNet18_Weights.DEFAULT
                  self.resnet18 = resnet18(weights=weights, progress=False).eval()
                  self.transforms = weights.transforms()

         def forward(self, x: torch.Tensor) -> torch.Tensor:
                  with torch.no_grad():
                           x = self.transforms(x)
                           y_pred = self.resnet18(x)
                           return y_pred.argmax(dim=1)
 

HuggingFace 라이브러리를 사용하여 언어 모델을 생성하려면 다음 단계를 따르세요.

 

 
  model_name = "bert-large-uncased-whole-word-masking-finetuned-squad"

  tokenizer = transformers.BertTokenizer.from_pretrained(model_name)
  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 (const c10::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);
  Ort::Env env;
  Ort::Session session{env, ORT_TSTR("model.onnx"), Ort::SessionOptions{nullptr}};

  // Allocate model inputs: fill in shape and size
  std::array<float, ...> input{};
  std::array<int64_t, ...> input_shape{...};
  Ort::Value input_tensor = Ort::Value::CreateTensor<float>(memory_info, input.data(), input.size(), input_shape.data(),   input_shape.size());
  const char* input_names[] = {...};

  // Allocate model outputs: fill in shape and size
  std::array<float, ...> output{};
  std::array<int64_t, ...> output_shape{...};
  Ort::Value output_tensor = Ort::Value::CreateTensor<float>(memory_info, output.data(), output.size(), output_shape.data(), output_shape.size());
  const char* output_names[] = {...};

  // Run the model
  session_.Run(Ort::RunOptions{nullptr}, input_names, &input_tensor, 1, output_names, &output_tensor, 1);
 

 

ONNXRuntime은 기본적으로 ONNX 그래프에 일련의 최적화를 적용하여 가능한 경우 노드를 결합하고 상수 값을 분리(상수 폴딩)합니다. 또한 ONNXRuntime은 실행 공급자 인터페이스를 통해 CUDA, TensorRT, OpenVINO, CoreML, NNAPI 등 다양한 하드웨어 가속기와 통합되며, 대상 하드웨어 플랫폼에 따라 사용할 수 있는 가속기가 달라집니다.

 

ONNX 모델의 성능을 더욱 향상시키려면 양자화를 수행할 수 있습니다.

 

모바일이나 엣지 컴퓨팅과 같이 제약이 있는 환경에서 애플리케이션을 실행하는 경우, 애플리케이션에서 사용하는 모델 또는 모델 세트를 기반으로 크기를 줄인 런타임을 구축할 수 있습니다.

원하는 언어와 환경에서 시작하려면 Get started with ONNX Runtime를 참조하세요.

 

예제

Export model to ONNX 

Accelerated inference with ONNXRuntime 

RESNET-50 

 

 

 

 

 

 

   요구 사항

 

  모든 빌드에는 en_US.UTF-8 로케일이 포함된 영어 언어 패키지가 필요합니다.

  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 런타임을 활용하여 하드웨어 플랫폼에 최적화된 모델을 실행할 수 있습니다.

이 튜토리얼에서는 다음 내용을 학습합니다.

  (1) 이미지 분류를 위한 PyTorch ResNet-50 모델 사용 방법

  (2) ONNX 형식으로 변환하는 방법

  (3) 동일한 애플리케이션 코드를 사용하여 모든 하드웨어 플랫폼에서 추론을 로드하고 실행하는 ONNX 런타임을 통해 기본 CPU, NVIDIA CUDA(GPU), Intel OpenVINO에 배포하는 방법

 

ONNX는 Microsoft, Meta, Amazon 및 기타 기술 기업들이 머신 러닝 모델을 표준화하고 다양한 유형의 하드웨어에 쉽게 배포할 수 있도록 개발한 오픈 소스 ML 모델 형식입니다. ONNX Runtime은 Microsoft에서 기여하고 유지 관리하며, PyTorch, TensorFlow 등의 프레임워크에서 ONNX 모델의 성능을 최적화합니다. ImageNet 데이터셋으로 학습된 ResNet-50 모델은 이미지 분류에 일반적으로 사용됩니다.

 

이 튜토리얼에서는 Microsoft Azure Machine Learning을 사용하여 OpenVINO 및 ONNX 런타임으로 CPU, GPU 및 Intel 하드웨어에서 ONNX 모델을 실행하는 방법을 보여줍니다.

 

설정

  운영체제 필수 조건

    환경에 curl이 설치되어 있어야 합니다.

 

  장치 필수 조건(Device Prerequisites)

onnxruntime-gpu 라이브러리는 장치 또는 컴퓨팅 클러스터의 NVIDIA CUDA 가속기에 대한 액세스가 필요하지만, CPU 및 OpenVINO-CPU 데모는 CPU에서만 실행해도 작동합니다.

 

  추론 필수 조건(Inference Prerequisites)

추론할 이미지가 있는지 확인하십시오. 이 튜토리얼에서는 Notebook 파일과 같은 디렉터리에 "cat.jpg" 이미지가 있습니다.

 

  환경 필수 조건(Environment Prerequisites)

Azure Notebook 터미널 또는 AnaConda 프롬프트 창에서 다음 명령을 실행하여 CPU, GPU 및/또는 OpenVINO용 환경 3개를 생성합니다(차이점은 굵게 표시됨).

 

CPU

 
  conda create -n cpu_env_demo python=3.8
  conda activate cpu_env_demo
  conda install -c anaconda ipykernel
  conda install -c conda-forge ipywidgets
  python -m ipykernel install --user --name=cpu_env_demo
  jupyter notebook
 

 

 

GPU

 
  conda create -n gpu_env_demo python=3.8
  conda activate gpu_env_demo
  conda install -c anaconda ipykernel
  conda install -c conda-forge ipywidgets
  python -m ipykernel install --user --name=gpu_env_demo
  jupyter notebook
 
 

OpenVINO

 
  conda create -n openvino_env_demo python=3.8
  conda activate openvino_env_demo
  conda install -c anaconda ipykernel
  conda install -c conda-forge ipywidgets
  python -m ipykernel install --user --name=openvino_env_demo
  python -m pip install --upgrade pip
  pip install openvino
 
 

라이브러리 요구 사항

첫 번째 코드 셀에서 다음 코드 조각을 사용하여 필요한 라이브러리를 설치하세요(차이점은 굵게 표시).

 

CPU + GPU

 
  import sys

  if sys.platform in ['linux', 'win32']: # Linux or Windows
         !{sys.executable} -m pip install torch==1.9.0+cu111 torchvision==0.10.0+cu111 torchaudio===0.9.0 -f https://download.pytorch.org/whl/torch_stable.html
  else: # Mac
         print("PyTorch 1.9 MacOS Binaries do not support CUDA, install from source instead")

  !{sys.executable} -m pip install onnxruntime-gpu onnx onnxconverter_common==1.8.1 pillow
 

 

 

OpenVINO

 
  import sys

  if sys.platform in ['linux', 'win32']: # Linux or Windows
         !{sys.executable} -m pip install torch==1.9.0+cu111 torchvision==0.10.0+cu111 torchaudio===0.9.0 -f https://download.pytorch.org/whl/torch_stable.html
  else: # Mac
         print("PyTorch 1.9 MacOS Binaries do not support CUDA, install from source instead")

  !{sys.executable} -m pip install onnxruntime-openvino onnx onnxconverter_common==1.8.1 pillow

  import openvino.utils as utils
  utils.add_openvino_libs_to_path()
 
 
 

ResNet-50 데모

환경 설정

모델을 가져오고 추론을 실행하는 데 필요한 라이브러리를 가져옵니다.

 
  from torchvision import models, datasets, transforms as T
  import torch
  from PIL import Image
  import numpy as np
 

 

 
 

사전 학습된 ResNet-50 모델을 ONNX로 로드 및 내보내기


PyTorch에서 사전 학습된 ResNet-50 모델을 다운로드하고 ONNX 형식으로 내보냅니다.

 
  resnet50 = models.resnet50(pretrained=True)

  # Download ImageNet labels
  !curl -o imagenet_classes.txt https://raw.githubusercontent.com/pytorch/hub/master/imagenet_classes.txt

  # Read the categories
  with open("imagenet_classes.txt", "r") as f:
         categories = [s.strip() for s in f.readlines()]

  # Export the model to ONNX
  image_height = 224
  image_width = 224
  x = torch.randn(1, 3, image_height, image_width, requires_grad=True)
  torch_out = resnet50(x)
  torch.onnx.export(resnet50,                                   # model being run
                                  x,                                                 # model input (or a tuple for multiple inputs)
                                  "resnet50.onnx",                       # where to save the model (can be a file or file-like object)
                                  export_params=True,               # store the trained parameter weights inside the model file
                                  opset_version=12,                     # the ONNX version to export the model to
                                  do_constant_folding=True,      # whether to execute constant folding for optimization
                                  input_names = ['input'],           # the model's input names
                                  output_names = ['output'])     # the model's output names
 

 

샘플 출력:

 
  % Total % Received % Xferd Average Speed Time Time Time Current
  Dload Upload Total Spent Left Speed
  100 10472 100 10472 0 0 50581 0 --:--:-- --:--:-- --:--:-- 50834
 

 

 

추론을 위한 전처리 설정(Set up Pre-Processing for Inference )

모델을 사용하여 추론할 이미지(예: cat.jpg)에 대한 전처리를 생성합니다.

 
  # Pre-processing for ResNet-50 Inferencing, from https://pytorch.org/hub/pytorch_vision_resnet/
  resnet50.eval()
  filename = 'cat.jpg'   # change to your filename

  input_image = Image.open(filename)
  preprocess = T.Compose([
         T.Resize(256),
         T.CenterCrop(224),
         T.ToTensor(),
         T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
  ])
  input_tensor = preprocess(input_image)
  input_batch = input_tensor.unsqueeze(0)   # create a mini-batch as expected by the model

  # move the input and model to GPU for speed if available
  print("GPU Availability: ", torch.cuda.is_available())
  if torch.cuda.is_available():
         input_batch = input_batch.to('cuda')
         resnet50.to('cuda')
 

 

 

샘플 출력:

 
  GPU Availability: False
 

 

 

ONNX 런타임을 사용하여 ResNet-50 ONNX 모델 추론하기

환경에 맞는 실행 공급자를 선택하여 ONNX 런타임으로 모델을 추론합니다. CPU를 사용하는 환경이라면 CPUExecutionProvider의 주석을 해제하고, NVIDIA CUDA를 사용하는 환경이라면 CUDAExecutionProvider의 주석을 해제하고, OpenVINOExecutionProvider를 사용하는 환경이라면 OpenVINOExecutionProvider의 주석을 해제합니다. 이때 onnxruntime.InferenceSession의 나머지 코드는 주석 처리해야 합니다.

 
  # Inference with ONNX Runtime
  import onnxruntime
  from onnx import numpy_helper
  import time

  session_fp32 = onnxruntime.InferenceSession("resnet50.onnx", providers=['CPUExecutionProvider'])
  # session_fp32 = onnxruntime.InferenceSession("resnet50.onnx", providers=['CUDAExecutionProvider'])
  # session_fp32 = onnxruntime.InferenceSession("resnet50.onnx", providers=['OpenVINOExecutionProvider'])

  def softmax(x):
         """Compute softmax values for each sets of scores in x."""
         e_x = np.exp(x - np.max(x))
         return e_x / e_x.sum()

  latency = []
  def run_sample(session, image_file, categories, inputs):
         start = time.time()
         input_arr = inputs.cpu().detach().numpy()
         ort_outputs = session.run([], {'input':input_arr})[0]
         latency.append(time.time() - start)
         output = ort_outputs.flatten()
         output = softmax(output)   # this is optional
         top5_catid = np.argsort(-output)[:5]
         for catid in top5_catid:
                  print(categories[catid], output[catid])
         return ort_outputs

  ort_output = run_sample(session_fp32, 'cat.jpg', categories, input_batch)
  print("ONNX Runtime CPU/GPU/OpenVINO Inference time = {} ms".format(format(sum(latency) * 1000 / len(latency), '.2f')))

 

샘플 출력:

 
  Egyptian cat 0.78605634
  tabby 0.117310025
  tiger cat 0.020089425
  Siamese cat 0.011728076
  plastic bag 0.0052174763
  ONNX Runtime CPU Inference time = 32.34 ms
 

 

PyTorch와의 비교

PyTorch를 사용하여 ONNX 런타임의 CPU 및 GPU 정확도와 지연 시간을 벤치마킹해 보세요.

 
  # Inference with PyTorch
  latency = []
  start = time.time()
  with torch.no_grad():
         torch_output = resnet50(input_batch)
  latency.append(time.time() - start)

  # Convert to numpy
  torch_output_np = torch_output.cpu().detach().numpy()

  # Print classification results
  output = torch_output_np.flatten()
  output = softmax(output)
  top5_catid = np.argsort(-output)[:5]
  for catid in top5_catid:
         print(categories[catid], output[catid])

  print("PyTorch CPU Inference time = {} ms".format(format(sum(latency) * 1000 / len(latency), '.2f')))

  print("***** Verifying correctness *****")
  for i in range(2):
         print('PyTorch and ONNX Runtime output {} are close:'.format(i), np.allclose(ort_output, torch_output_np, rtol=1e-05, atol=1e-04))
 

 

샘플 출력:

 
  Egyptian cat 0.78605634
  tabby 0.117310025
  tiger cat 0.020089425
  Siamese cat 0.011728076
  plastic bag 0.0052174763
  PyTorch CPU Inference time = 34.56 ms
  ***** Verifying correctness *****
  PyTorch and ONNX Runtime output 0 are close: True
  PyTorch and ONNX Runtime output 1 are close: True
 
 

 

OpenVINO와의 비교

OpenVINO를 사용하여 ONNX 런타임과 OpenVINO의 정확도 및 지연 시간을 비교 평가합니다.

 
  # Inference with OpenVINO
  from openvino.runtime import Core

  ie = Core()
  onnx_model_path = "./resnet50.onnx"
  model_onnx = ie.read_model(model=onnx_model_path)
  compiled_model_onnx = ie.compile_model(model=model_onnx, device_name="CPU")

  # inference
  output_layer = next(iter(compiled_model_onnx.outputs))

  latency = []
  input_arr = input_batch.detach().numpy()
  inputs = {'input':input_arr}
  start = time.time()
  request = compiled_model_onnx.create_infer_request()
  output = request.infer(inputs=inputs)

  outputs = request.get_output_tensor(output_layer.index).data
  latency.append(time.time() - start)

  print("OpenVINO CPU Inference time = {} ms".format(format(sum(latency) * 1000 / len(latency), '.2f')))

  print("***** Verifying correctness *****")
  for i in range(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 배포 및 유연한 추론에 대한 자세한 설명과 단계별 가이드는 여기에서 비디오를 시청하세요.

 

 

 

  1.3  Accelerate PyTorch Training

 

ORTModule Examples

 

 

 

  2.  Accelating TensorFlow

Accelerate TensorFlow model inferencing 

ONNX 런타임은 TensorFlow, TFLite 및 Keras 모델의 추론 시간을 단축할 수 있습니다.

 

 

Get Started 

Export model to ONNX 

TensorFlow/Keras 

These examples use the TensorFlow-ONNX converter, which supports TensorFlow 1, 2, Keras, and TFLite model formats.

TFLite 

 

 

 

  3.  Accelerate Hugging Face models

 

 

ONNX Runtime can accelerate training and inferencing popular Hugging Face NLP models.

 

 

  1.1  Yocto Project 소개

 

Accelerate Hugging Face model inferencing 

Additional resources 

 

 

  4. AzureML에서 ONNX 런타임을 사용하여 고성능 질의응답 모델 배포하기

 

이 튜토리얼에서는 HuggingFace의 BERT 모델을 ONNX로 변환하고, AzureML을 통해 ONNX 런타임과 함께 ONNX 모델을 배포하는 방법을 설명합니다.

 

다음 섹션에서는 Stanford Question Answering Dataset(SQuAD) 데이터셋으로 학습된 HuggingFace BERT 모델을 예시로 사용합니다. 자신만의 질의응답 모델을 학습시키거나 미세 조정할 수도 있습니다.

 

질의응답 시나리오는 질문과 컨텍스트라는 텍스트 조각을 입력으로 받아 컨텍스트에서 추출한 텍스트 문자열인 답변을 생성합니다. 이 시나리오는 질문과 컨텍스트를 토큰화 및 인코딩하고, 입력값을 변환기 모델에 입력하여 컨텍스트에서 가장 가능성이 높은 시작 및 끝 토큰을 생성한 다음, 이를 다시 단어로 매핑하여 답변을 생성합니다.

 

 

그런 다음 모델과 스코어링 코드가 온라인 엔드포인트를 사용하여 AzureML에 배포됩니다.

 

 

목차

 

필수 조건

튜토리얼의 소스 코드는 GitHub에 게시되어 있습니다.
AzureML에서 실행하려면 다음이 필요합니다.

 

      Azure 구독

      Azure Machine Learning 작업 영역(작업 영역이 없는 경우 the AzureML configuration notebook을 참조하여 작업 영역을 생성하세요.)

      Azure Machine Learning SDK

      Azure CLI 및 Azure Machine Learning CLI 확장 프로그램(버전 2.2.2 이상)

 

다음 리소스도 유용할 수 있습니다.

      Azure Machine Learning 아키텍처 및 용어(architecture and terms) 이해

      Azure Portal에서 배포 상태를 추적할 수 있습니다.

 

AzureML 구독에 액세스할 수 없는 경우 이 자습서를 로컬에서 실행할 수 있습니다.

 

 

환경

의존성을 직접 설치하려면 다음 명령을 실행하세요.

 
 
  pip install torch
  pip install transformers
  pip install azureml azureml.core
  pip install onnxruntime
  pip install matplotlib
 


conda 환경에서 Jupyter 커널을 생성하려면 다음 명령을 실행하세요. <kernel name>을 생성한 커널 이름으로 바꾸세요.

 
  conda install -c anaconda ipykernel
  python -m ipykernel install --user --name=<kernel name>


아래 배포 단계에서 사용되는 AzureML CLI 확장 프로그램을 설치하세요.

 
  az login
  az extension add --name ml
  # azure-cli-ml 확장 프로그램이 설치되어 있으면 제거하세요. az ml 확장 프로그램과 호환되지 않습니다.
  az extension remove azure-cli-ml
 

 

 

PyTorch 모델을 가져와 ONNX 형식으로 변환

아래 코드에서는 HuggingFace의 SQUAD 데이터셋을 사용하여 질문 답변에 최적화된 BERT 모델을 가져옵니다.


BERT 모델을 처음부터 사전 학습하려면 Pre-train BERT model의 지침을 따르세요. 자체 데이터셋으로 모델을 미세 조정하려면 AzureML BERT Eval Squa 또는 AzureML BERT Eval GLUE를 참조하세요.

 

모델 내보내기

PyTorch ONNX 익스포터를 사용하여 ONNX 런타임에서 실행할 수 있는 ONNX 형식의 모델을 생성합니다.

 

 
  import torch
  from transformers import BertForQuestionAnswering

  model_name = "bert-large-uncased-whole-word-masking-finetuned-squad"
  model_path = "./" + model_name + ".onnx"
  model = BertForQuestionAnswering.from_pretrained(model_name)

  # 모델을 추론 모드로 설정 (set the model to inference mode)
  # 모델을 내보내기 전에 torch_model.eval() 또는 torch_model.train(False)를 호출하는 것이 중요합니다.
  #  (It is important to call torch_model.eval() or torch_model.train(False) before exporting the model)
  # 드롭아웃이나 배치 정규화와 같은 연산자는
  # 추론 모드와 학습 모드에서 다르게 동작하기 때문에 모델을 추론 모드로 전환해야 합니다.
  #  (to turn the model to inference mode. This is required since operators like dropout or batchnorm)
  #  (behave differently in inference and training mode.)
  model.eval()

  # 모델에 더미 입력을 생성합니다. 필요에 따라 조정하세요. (Generate dummy inputs to the model. Adjust if necessary)
  inputs = {
                'input_ids': torch.randint(32, [1, 3], dtype=torch.long),    # 토큰화된 텍스트의 숫자 ID 목록
                'attention_mask': torch.ones([1, 32], dtype=torch.long),  # dummy list of ones
                'token_type_ids': torch.ones([1, 32], dtype=torch.long)   # dummy list of ones
        }

  symbolic_names = {0: 'batch_size', 1: 'max_seq_len'}
  torch.onnx.export(model,                                                                           # model being run
                                  (inputs['input_ids'],
                                   inputs['attention_mask'],
                                   inputs['token_type_ids']),                                         # model input (or a tuple for multiple inputs)
                                  model_path,                                              # where to save the model (can be a file or file-like object)
                                  opset_version=11,                                    # the ONNX version to export the model to
                                  do_constant_folding=True,                     # whether to execute constant folding for optimization
                                  input_names=['input_ids',
                                                            'input_mask',
                                                            'segment_ids'],               # the model's input names
                                  output_names=['start_logits', "end_logits"],          # the model's output names
                                  dynamic_axes={'input_ids': symbolic_names,
                                                              'input_mask' : symbolic_names,
                                                              'segment_ids' : symbolic_names,
                                                              'start_logits' : symbolic_names,
                                                              'end_logits': symbolic_names})     # variable length axes

 

 

 

ONNX Runtime을 사용하여 ONNX 모델 실행

다음 코드는 ONNX Runtime을 사용하여 ONNX 모델을 실행합니다. Azure Machine Learning에 배포하기 전에 로컬에서 테스트할 수 있습니다.

`init()` 함수는 시작 시 호출되어 토크나이저 및 ONNX 런타임 세션 생성과 같은 일회성 작업을 수행합니다.

`run()` 함수는 Azure ML 엔드포인트를 사용하여 모델을 실행할 때 호출됩니다. 필요한 `preprocess()` 및 `postprocess()` 단계를 추가하세요.

로컬 테스트 및 비교를 위해 PyTorch 모델을 실행할 수도 있습니다.

 

 
  import os
  import logging
  import json
  import numpy as np
  import onnxruntime
  import transformers
  import torch

  # 전처리 함수는 질문과 컨텍스트를 입력받아 모델에 필요한 텐서를 생성합니다.
  # - 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.
  def preprocess(question, context):
         encoded_input = tokenizer(question, context)
         tokens = tokenizer.convert_ids_to_tokens(encoded_input.input_ids)
         return (encoded_input.input_ids, encoded_input.attention_mask, encoded_input.token_type_ids, tokens)

  # 후처리 함수는 질문과 컨텍스트의 텍스트 토큰을 사용하여 시작 및 종료 로그 확률 목록을 텍스트 답변으로 매핑합니다.
  # The post process function maps the list of start and end log probabilities onto a text answer, using the text tokens from the question
  # and context.
  def postprocess(tokens, start, end):
         results = {}
         answer_start = np.argmax(start)
         answer_end = np.argmax(end)
         if answer_end >= answer_start:
                  answer = tokens[answer_start]
                  for i in range(answer_start+1, answer_end+1):
                           if tokens[i][0:2] == "##":
                                    answer += tokens[i][2:]
                           else:
                                    answer += " " + tokens[i]
                  results['answer'] = answer.capitalize()
         else:
                 results['error'] = "이 질문에 대한 답을 찾을 수 없습니다. 다른 질문을 해주시겠습니까? I am unable to find the answer to this question. Can you please ask another question?"
         return results

  # 예측을 위한 일회성 초기화를 수행합니다. 초기화 코드는 엔드포인트가 설정될 때 한 번 실행됩니다.
  # Perform the one-off initialization for the prediction. The init code is run once when the endpoint is setup.
  def init():
         global tokenizer, session, model

         model_name = "bert-large-uncased-whole-word-masking-finetuned-squad"
         model = transformers.BertForQuestionAnswering.from_pretrained(model_name)

         # AZUREML_MODEL_DIR을 사용하여 배포된 모델을 가져옵니다. 여러 모델이 배포된 경우,
         # use AZUREML_MODEL_DIR to get your deployed model(s). If multiple models are deployed,
       # model_path = os.path.join(os.getenv('AZUREML_MODEL_DIR'), '$MODEL_NAME/$VERSION/$MODEL_FILE_NAME')
         model_dir = os.getenv('AZUREML_MODEL_DIR')
         if model_dir == None:
                  model_dir = "./"
         model_path = os.path.join(model_dir, model_name + ".onnx")

         # Create the tokenizer
         tokenizer = transformers.BertTokenizer.from_pretrained(model_name)

         # Create an ONNX Runtime session to run the ONNX model
         session = onnxruntime.InferenceSession(model_path, providers=["CPUExecutionProvider"])


  # Run the PyTorch model, for functional and performance comparison
  def run_pytorch(raw_data):
         inputs = json.loads(raw_data)

         model.eval()

         logging.info("Question:", inputs["question"])
         logging.info("Context: ", inputs["context"])

         input_ids, input_mask, segment_ids, tokens = preprocess(inputs["question"], inputs["context"])
         model_outputs = model(torch.tensor([input_ids]), token_type_ids=torch.tensor([segment_ids]))
         return postprocess(tokens, model_outputs.start_logits.detach().numpy(), model_outputs.end_logits.detach().numpy())

  # Run the ONNX model with ONNX Runtime
  def run(raw_data):
         logging.info("Request received")
         inputs = json.loads(raw_data)
         logging.info(inputs)

         # Preprocess the question and context into tokenized ids
         input_ids, input_mask, segment_ids, tokens = preprocess(inputs["question"], inputs["context"])
logging.info("Running inference")
 
         # Format the inputs for ONNX Runtime
         model_inputs = {
                  'input_ids': [input_ids],
                  'input_mask': [input_mask],
                  'segment_ids': [segment_ids]
                  }
 
         outputs = session.run(['start_logits', 'end_logits'], model_inputs)
         logging.info("Post-processing")

         # Post process the output of the model into an answer (or an error if the question could not be answered)
         results = postprocess(tokens, outputs[0], outputs[1])
         logging.info(results)
         return results


  if __name__ == '__main__':
         init()

         input = "{\"question\": \"What is Dolly Parton's middle name?\", \"context\": \"Dolly Rebecca Parton is an American singer-songwriter\"}"

         run_pytorch(input)
         print(run(input))
 

 

 

AzureML을 통해 ONNX 런타임을 사용하여 모델 배포하기

이제 ONNX 모델과 ONNX 런타임을 사용하여 모델을 실행하는 코드가 준비되었으므로 Azure ML을 사용하여 모델을 배포할 수 있습니다.

 

환경을 확인하세요 (Check your environment)

 
  import azureml.core
  import onnxruntime
  import torch
  import transformers

  print("Transformers version: ", transformers.__version__)
  torch_version = torch.__version__
  print("Torch (ONNX exporter) version: ", torch_version)
  print("Azure SDK version:", azureml.core.VERSION)
  print("ONNX Runtime version: ", onnxruntime.__version__)
 

 

 

 

Azure ML 작업 영역 로드

먼저 구성 노트북에서 이전에 생성한 기존 작업 영역에서 작업 영역 개체를 인스턴스화합니다.

참고로, 다음 코드는 노트북과 동일한 디렉터리 또는 .azureml이라는 하위 디렉터리에 구독 정보가 포함된 config.json 파일이 있다고 가정합니다. Workspace.get() 메서드를 사용하여 작업 영역 이름, 구독 이름 및 리소스 그룹을 명시적으로 제공할 수도 있습니다.

 
  import os
  from azureml.core import Workspace

  ws = Workspace.from_config()
  print(ws.name, ws.location, ws.resource_group, ws.subscription_id, sep = '\n')
  Register your model with Azure ML
  Now we upload the model and register it in the workspace.

  from azureml.core.model import Model

  model = Model.register(model_path = model_path,   # Name of the registered model in your workspace.
                                            model_name = model_name,   # Local ONNX model to upload and register as a model
                                            model_framework=Model.Framework.ONNX ,   # Framework used to create the model.
                                            model_framework_version=torch_version,   # Version of ONNX used to create the model.
                                            tags = {"onnx": "demo"},
                                            description = "HuggingFace BERT model fine-tuned with SQuAd and exported from PyTorch",
                                            workspace = ws)
 

 

 

 

등록된 모델 목록 보기

이 워크스페이스에 등록된 모든 모델 목록을 볼 수 있습니다.

 
  models = ws.models
  for name, m in models.items():
         print("Name:", name,"\tVersion:", m.version, "\tDescription:", m.description, m.tags)
 
  #         # 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 컨테이너에 업로드됩니다. 배포 시간을 단축하려면 엔드포인트를 생성하기 전에 대용량 파일의 로컬 복사본을 모두 제거하십시오.

 
  az ml online-endpoint create --name question-answer-ort --file yml/endpoint.yml --subscription {ws.subscription_id} --resource-group {ws.resource_group} --workspace-name {ws.name}
  az ml online-deployment create --endpoint-name question-answer-ort --name blue --file yml/deployment.yml --all-traffic --subscription {ws.subscription_id} --resource-group {ws.resource_group} --workspace-name {ws.name}

 

 

배포된 엔드포인트 테스트

다음 명령은 배포된 질문-답변 모델을 실행합니다. test-data.json 파일에 테스트 질문이 있습니다. 이 파일을 직접 질문과 컨텍스트로 편집할 수 있습니다.

 
  az ml online-endpoint invoke --name question-answer-ort --request-file test-data.json --subscription {ws.subscription_id} --resource-group {ws.resource_group} --workspace-name {ws.name}

 

여기까지 진행했다면 ONNX 모델을 사용하여 질문에 답변하는 엔드포인트를 배포한 것입니다.

질문과 컨텍스트를 직접 제공하여 질문에 답변할 수 있습니다!

 

 

Azure 리소스 정리

다음 명령은 배포한 AzureML 엔드포인트를 삭제합니다. AzureML 작업 영역, 컴퓨팅 리소스 및 등록된 모델도 정리할 수 있습니다.

 
  az ml online-endpoint delete --name question-answer-ort --yes --subscription {ws.subscription_id} --resource-group {ws.resource_group} --workspace-name {ws.name}

 

 

 

 

 

 

 

 

'Project ES > : : ONNX' 카테고리의 다른 글

ONNX Runtime 설치  (0) 2026.04.30
ONNX Runtime 소개  (0) 2026.04.28