빠른 시작#
이 문서에서는 qubee를 사용하여 calibration 데이터셋을 준비하고, 모델을 컴파일하며, 추론을 수행하는 방법에 대해 설명합니다. 더 많은 예제와 자세한 내용은 튜토리얼을 참조하세요.
Calibration Data 준비#
모델을 컴파일하기 위해서는 calibration 데이터셋(모델이 실제로 사용하는 입력의 전처리된 형태)을 준비해야 합니다. qubee는 calibration 데이터셋을 준비하기 위한 두 가지 방법을 제공합니다:
사전 정의된 전처리 구성 YAML 파일을 활용하는 방법
사용자가 직접 정의한 전처리 함수를 사용하는 방법
Remark Calibration 데이터셋을 생성하는 과정은 CPU Offloading 사용 여부에 따라 달라질 수 있습니다. 현재 qubee는 기본적으로 CPU Offloading 없이 모델을 컴파일합니다. 이 경우, 사전 처리된 입력 형태는 (H, W, C) 형식이어야 합니다. 반면, CPU Offloading이 사용되는 경우, 사전 처리된 입력 형태는 원래 모델이 사용하는 입력 형태와 일치해야 합니다.
이하에서는 ImageNet으로부터 선별된 1000개의 이미지를 사용하여 분류 모델을 위한 calibration 데이터셋을 준비하는 방법에 대해 설명합니다.
전처리 구성 YAML 파일을 활용한 방법#
이미지 크기 조정, 자르기, 정규화와 같은 이미지 전처리 기술은 머신 비전 작업에서 자주 사용됩니다. 사용자는 YAML 파일을 사용하여 전처리 구성을 작성하고, qubee에서 제공하는 API인 make_calib를 통해 calibration 데이터셋을 준비할 수 있습니다. 이 방법은 원시 데이터가 이미지인 경우에만 사용할 수 있습니다. 아래는 예제 코드입니다. 이 코드는 calibration을 위한 이미지가 /workspace/calibration/cali_1000 디렉토리에 준비되어 있다고 가정합니다.
먼저, 실행 가능한 Python 스크립트(예: prepare_calib.py)를 생성하고 다음 내용을 작성합니다:
from qubee.calibration import make_calib
make_calib(
args_pre="/workspace/resnet50.yaml", # path to pre-processing configuration yaml file
data_dir="/workspace/calibration/cali_1000", # path to folder of original calibration data files such as images
save_dir="/workspace/calibration/", # path to folder to save pre-processed calibration data files
save_name="resnet50", # tag for the generated calibration dataset
max_size=100 # Maximum number of data to use for calibration
)
그 후, 위 코드에서 지정한 디렉토리에 사전 처리 구성 YAML 파일(예: resnet50.yaml)을 작성합니다. YAML 파일에는 사전 처리 함수와 해당 매개변수가 포함되어야 합니다. 아래는 ResNet50 사전 처리를 위한 YAML 파일의 예입니다.
# resnet50.yaml
Datatype: Image
GetImage:
to_float32: false
channel_order: RGB
Pre-Order: [ResizeTorch, CenterCrop, Normalize, SetOrder]
Pre-processing:
ResizeTorch:
size: 256
interpolation: bilinear
CenterCrop:
size: [224, 224]
Normalize:
mean: [0.485, 0.456, 0.406]
std: [0.229, 0.224, 0.225]
to_float_div255: true
SetOrder:
shape: HWC
위의 코드를 실행하면, 지정된 디렉토리에 사전 처리된 calibration 데이터셋(NumPy 배열)이 포함된 디렉토리가 생성됩니다. 이 디렉토리는 /workspace/calibration/resnet50에 위치합니다. 또한, 사전 처리된 NumPy 파일의 경로를 포함하는 메타 txt 파일이 생성되며, 이름은 /workspace/calibration/resnet50.txt입니다.
Remark 사전 정의된 전처리 구성 YAML 파일을 사용하는 경우, calibration 데이터셋은 이미지 형식이 동일해야 합니다. 만약 일부가 컬러 이미지이고 다른 일부가 그레이스케일 이미지인 경우, calibration 데이터셋이 제대로 생성되지 않습니다.
사용자 정의 전처리 함수를 사용하는 방법#
사용자 정의 전처리 함수를 사용하여 calibration 데이터셋을 준비할 수도 있습니다. 이 경우 qubee에서 제공하는 API인 make_calib_man를 사용하여 calibration 데이터셋을 생성할 수 있습니다. 사용자 정의 전처리 함수는 이미지 경로를 입력으로 받아 NumPy 배열을 반환해야 합니다. 아래는 예제 코드입니다. 이 코드는 calibration을 위한 이미지가 /workspace/calibration/cali_1000 디렉토리에 준비되어 있다고 가정합니다.
이전의 YAML 파일을 사용하는 방법과 유사하게, 사용자 정의 전처리 함수를 사용하여 calibration 데이터셋을 준비하려면 먼저 실행 가능한 Python 스크립트(예: prepare_calib.py)를 생성하고 다음 내용을 작성합니다:
import torch
import numpy as np
from PIL import Image
import torchvision.transforms.functional as F
from torchvision.transforms import InterpolationMode
from qubee.calibration import make_calib_man
def preprocess_resnet50(img_path: str):
img = Image.open(img_path)
resize_size=256
crop_size=(224, 224)
mean=[0.485, 0.456, 0.406]
std=[0.229, 0.224, 0.225]
out = F.pil_to_tensor(img)
out = F.resize(out, size=resize_size, interpolation = InterpolationMode.BILINEAR)
out = F.center_crop(out, output_size=crop_size)
out = out.to(torch.float, copy=False) / 255.
out = F.normalize(out, mean, std)
out = np.transpose(out.numpy(), axes=[1, 2, 0])
return out
make_calib_man(
pre_ftn=preprocess_resnet50, # callable function to pre-process the calibration data
data_dir="/workspace/calibration/cali_1000", # path to folder of original calibration data files such as images
save_dir="/workspace/calibration/", # path to folder to save pre-processed calibration data files
save_name="resnet50", # tag for the generated calibration dataset
max_size=100 # Maximum number of data to use for calibration
)
위의 코드를 실행하면, 지정된 디렉토리에 사전 처리된 calibration 데이터셋(NumPy 텐서)이 포함된 디렉토리가 생성됩니다. 이 디렉토리는 /workspace/calibration/resnet50에 위치합니다. 또한, 사전 처리된 NumPy 파일의 경로를 포함하는 메타 txt 파일이 생성되며, 이름은 /workspace/calibration/resnet50.txt입니다.
Remark 사용자 정의 전처리 함수를 사용하는 경우, 함수 내부적으로 적절한 예외처리가 포함되지 않는 한, calibration 데이터셋은 동일한 형식의 이미지로 구성되어야 합니다. 이전 방법과 마찬가지로, 일부가 컬러 이미지이고 다른 일부가 그레이스케일 이미지인 경우, calibration 데이터셋이 제대로 생성되지 않습니다.
딥러닝 모델 컴파일#
calibration 데이터셋이 준비되면, qubee 컴파일러를 사용하여 모델을 컴파일할 수 있습니다. qubee 컴파일러는 ONNX, PyTorch, Keras, TensorFlow 및 TensorFlow Lite와 같은 다양한 딥러닝 프레임워크를 지원합니다. 컴파일 과정은 모델을 읽고 양자화하여 Mobilint IR(MXQ) 파일을 생성하는 과정을 포함합니다.
ONNX 모델 컴파일#
ONNX는 훈련된 모델을 Mobilint IR로 컴파일하는 데 가장 권장되는 프레임워크입니다. 간단한 코드로 ONNX 모델을 직접 파싱하여 Mobilint IR을 얻을 수 있습니다. 아래는 예제 코드입니다. 이 코드는 calibration 데이터셋과 모델이 각각 /workspace/calibration/resnet50와 /workspace/resnet50.onnx 디렉토리에 준비되어 있다고 가정합니다.
먼저, 실행 가능한 Python 스크립트(예: compile_onnx.py)를 생성하고 다음 내용을 작성합니다:
""" Compile ONNX model"""
from qubee import mxq_compile
onnx_model_path = "/workspace/resnet50.onnx"
calib_data_path = "/workspace/calibration/resnet50"
# calib_data_path can be replaced with the path to the calibration meta file such as "/workspace/calibration/resnet50.txt"
mxq_compile(
model=onnx_model_path,
calib_data_path=calib_data_path,
save_path="resnet50.mxq",
backend="onnx"
)
PyTorch 모델 컴파일#
qubee compiler는 PyTorch 모델의 다이렉트 컴파일을 지원합니다. 컴파일을 시작하기 전에 feed_dict를 준비해야 하며, 이는 모델 입력 이름을 key로 하고 해당 입력에 대응하는 토치텐서를 value로 갖는 딕셔너리입니다. 컴파일 대상 모델의 forward 함수 파라미터 이름과 feed_dict의 key는 정확히 일치해야 합니다. 예를 들어 torchvision의 resnet50 기본 입력 이름은 “x”입니다. 또한 feed_dict에 넣는 텐서는 컴파일하려는 모델의 입력 과 동일해야 하며, 그 크기로 forward를 호출했을 때 오류가 없어야 합니다. resnet50의 입력으로 (1, 3, 224, 224) 같은 텐서는 유효하지만, (1, 8, 224, 224)처럼 채널 수가 잘못된 텐서는 컴파일되지 않습니다.
""" Compile PyTorch model"""
from qubee import mxq_compile
### get resnet50 from torchvision
import torchvision
import torch
import numpy as np
calib_data_path = "/workspace/calibration/resnet50"
# A calibration meta file such as "/workspace/calibration/resnet50.txt" can be used instead.
torch_model = torchvision.models.resnet50(pretrained=True)
torch_model.eval().cpu()
feed_dict = {"x": torch.randn(1, 3, 224, 224).cpu()}
mxq_compile(
model=torch_model,
calib_data_path=calib_data_path,
backend="torch",
save_path="resnet50.mxq",
feed_dict=feed_dict,
)
Torchscript 모델 컴파일#
qubee compiler는 TorchScript 형식으로 변환된 모델의 컴파일을 지원합니다. 아래 예시 코드는 torchvision ResNet-50 모델을 TorchScript 저장후 로드하여 컴파일 하는 예시 코드입니다.
""" Compile PyTorch model"""
from qubee import mxq_compile
### get resnet50 from torchvision
import torchvision
import torch
import numpy as np
calib_data_path = "/workspace/calibration/resnet50"
# A calibration meta file such as "/workspace/calibration/resnet50.txt" can be used instead.
### get resnet50 from torchvision and convert it to torchscript
torch_model = torchvision.models.resnet50(pretrained=True)
torchscript_model_path = "/workspace/resnet50.pt"
dummy_input = np.random.randn(1,3,224,224).astype(np.float32)
feed_dict = {"input": dummy_input}
#When compiling with TorchScript, feed_dict information is required, which contains the temporary input name and a sample input.
scripted_model = torch.jit.script(torch_model, torch.tensor(dummy_input))
torch.jit.save(scripted_model, torchscript_model_path)
mxq_compile(
model=torchscript_model_path,
calib_data_path=calib_data_path,
backend="torchscript",
save_path="resnet50.mxq",
feed_dict=feed_dict,
)
TensorFlow/Keras 모델 컴파일#
Keras는 현재 TensorFlow의 고수준 API로 통합되어 있으며, Keras 모델은 TensorFlow 모델로 간주됩니다. 따라서 Keras 모델을 Mobilint IR로 컴파일하기 위해서는 TensorFlow 백엔드를 사용하게 되며, 두 프레임워크의 모델 컴파일 과정은 동일합니다. 현재 Keras 모델은 TensorFlow의 SavedModel 또는 frozen graph 형식으로 저장되어야 합니다. qubee 컴파일러는 SavedModel 또는 고수준 저장 형식(.keras 또는 h5)으로 저장된 TensorFlow 모델을 컴파일할 수 있습니다. 아래 코드는 calibration 데이터셋과 모델이 각각 /workspace/calibration/resnet50와 /workspace/tf_models/resnet50.h5 디렉토리에 준비되어 있다고 가정합니다.
먼저, 실행 가능한 Python 스크립트(예: compile_tf.py)를 생성하고 다음 내용을 작성합니다:
""" Compile Keras/TensorFlow model in SavedModel format """
from qubee import mxq_compile
import tensorflow as tf
keras_model = tf.keras.applications.resnet50.ResNet50() # Load a Keras model
calib_data_path = "/workspace/calibration/resnet50"
# A calibration metadata file such as "/workspace/calibration/resnet50.txt" can be used instead.
keras_model_save_path = "/workspace/tf_models/resnet50.h5" # path to save .h5 keras model
keras_model.save(keras_model_save_path)
mxq_compile(
model=keras_model_save_path,
calib_data_path=calib_data_path,
backend="tf",
save_path="resnet50.mxq",
)
TensorFlow Lite 모델 컴파일#
qubee 컴파일러는 TensorFlow Lite 모델의 컴파일을 지원합니다. 아래 예시 코드는 Keras resnet50 모델을 tflite모델로 변경 후 컴파일을 진행합니다.
""" Compile Tensorflow Lite model """
from qubee import mxq_compile
import tensorflow as tf
keras_model = tf.keras.applications.resnet50.ResNet50() # Load a pre-trained Keras model
calib_data_path = "/workspace/calibration/resnet50"
# A calibration metadata file such as "/workspace/calibration/resnet50.txt" can be used instead.
keras_model_save_path = "/workspace/tf_models/resnet50.h5"# path to save .h5 keras model
tflite_model_path = "/workspace/tflite_models/resnet50.tflite"
keras_model.save(keras_model_save_path)
loaded_keras_model = tf.keras.models.load_model(keras_model_save_path)
tflite_model = tf.lite.TFLiteConverter.from_keras_model(loaded_keras_model).convert() # Convert the model to TFLite format
with open(tflite_model_path, 'wb') as f:
f.write(tflite_model)
mxq_compile(
model=tflite_model_path,
calib_data_path=calib_data_path,
backend="tflite",
save_path="resnet50.mxq",
)
(선택 사항) 양자화 방법 및 매개변수 설정#
학습된 모델을 준비한 후, qubee 컴파일러는 모델을 양자화하여 크기를 줄이고 추론 속도를 향상시킵니다. qubee 컴파일러는 대부분의 모델에 적합한 신중하게 조정된 기본 양자화 방법을 갖추고 있습니다. 그러나 사용자는 특정 모델에 대해 더 나은 성능을 달성하기 위해 양자화 방법과 매개변수를 사용자 정의할 수도 있습니다.
아래 예시는 사용자가 지정한 양자화 방법과 매개변수를 사용하여 모델을 컴파일하는 방법을 보여줍니다. 양자화 방법과 매개변수에 대한 자세한 내용은 mxq_compile 함수에서 확인할 수 있습니다.
""" Quantization Methods and Parameters """
from qubee import mxq_compile
onnx_model_path = "/workspace/resnet50.onnx"
calib_data_path = "/workspace/calibration/resnet50"
mxq_compile(
model=onnx_model_path,
calib_data_path=calib_data_path,
quantization_method=1, # per channel quantization
quantization_mode=2, # max percentile quantization
percentile=0.999,
quantization_output=0, # per layer quantization for the output layer
save_path="resnet50.mxq",
backend="onnx"
)