Hailo Model Zoo 를 사용해 모델을 최적화(양자화)할 때, 학습 테스크에 따른 데이터 전/후처리 방법에 대한 내용

Hailo Model Zoo 데이터 처리

Version

Optimization

  • Hailo Model Zoo에서 모델을 최적화하는 과정에서, 모델이 수행하는 테스크(detection, segmentation 등)에 따라 학습에 사용된 데이터셋을 양자화를 위한 캘리브레이션 및 사후학습이 이루어 진다.
  • 이러한 양자화를 위해, 모델의 input/output 데이터를 전처리 및 후처리하는 과정을 테스크별 사전 정의가 되어있으며, 커스텀 모델을 사용하기 위해서는 이러한 전후처리 과정을 직접 정의하거나 수정해야 한다.
  • Hailo Model Zoo에서 제공하는 양자화 캘리브레이션 및 사후학습 관련 스크립트는 .alls 파일을 통해 수정 가능하다.
model_optimization_config(calibration, batch_size=8, calibset_size=93)
post_quantization_optimization(finetune, policy=enabled, dataset_size=93, epochs=8, learning_rate=0.0001)

모델의 전/후처리 정보

  • Hailo Model Zoo에서 사전 작성해놓은 모델 정보에 대한 .yaml 파일에서 모델에 지정된 task 및 네트워크 타입 정보를 확인할 수 있다.
...
# 전처리 관련 정보
preprocessing:
  network_type: classification
  meta_arch: basic_resnet  
 
# 후처리 관련 정보
postprocessing:
  meta_arch: None
  device_pre_post_layers:
    softmax: false
    argmax: false
    bilinear: false
    nms: false
...

최적화 - 데이터 전처리

  • Hailo Model Zoo를 통해 모델을 최적화하는 과정에서, 컴파일러(DFC)는 최적화 단계에서 모델의 명세인 .yaml 파일의 내용 중 preprocessing 항목의 network_typemeta_arch의 값을 읽어서 정의된 데이터 전처리를 수행한다.
  • 대표적으로 classification task에서는 center crop 등, detection task(yolo)에서는 padding 처리 등이 있다.
  • 데이터 전처리 관련 python 코드는 다음 경로에 위치한다: /hailo_model_zoo/core/preprocessing/{model_name}.py

최적화 데이터 전처리 예시

전처리 정보

  • Hailo Model Zoo에서 제공하는 Resnet18 모델에 대한 최적화 데이터 전처리 과정을 살펴 본다.
  • Resnet18 모델의 config 파일은 resnet_v1_18.yaml 파일에 전처리에 대한 정보를 포함하여 작성되어 있다.
preprocessing:
  network_type: classification
  meta_arch: basic_resnet  

전처리 코드

  • 위의 전처리 정보에 해당하는 전처리 코드는 /hailo_model_zoo/core/preprocessing/classification_preprocessing.py 파일에 작성되어 있다.
  • 해당 코드에서 basic_resnet 아키텍처에 해당하는 전처리 내용은 아래와 같다.
...
def _resnet_base_preprocessing(image, output_height=None, output_width=None, resize_side=None, method=None):
    if output_height is not None:
        assert output_width is not None
        assert resize_side is not None
        image = _aspect_preserving_resize(image, resize_side, method=method) #비율보존 리사이즈
        image = _central_crop([image], output_height, output_width)[0]
        image.set_shape([output_height, output_width, 3])
    image = tf.cast(image, tf.float32)
    return image
 
@PREPROCESS_FACTORY.register(name="basic_resnet")
def resnet_v1_18_34(image, image_info=None, output_height=None, output_width=None, **kwargs):
    image = _resnet_base_preprocessing(image, output_height, output_width, RESIZE_SIDE)
    if image_info:
        image_info['img_orig'] = tf.cast(image, tf.uint8)
    return image, image_info
...
  • 일반적으로 resnet18 모델을 학습할 때 사용되는 데이터 전처리 파이프라인(resize, center crop)이 미리 세팅되어 있음을 알 수 있다.
  • 만약, 커스텀 모델이 해당 파이프라인을 따라 학습되지 않은 모델이라면 성능 불일치를 막기 위해 커스텀 모델의 학습 당시 데이터 전처리 파이프라인에 맞게 수정하여야 한다.

최적화 - 데이터 후처리

  • 모델에서 출력되는 데이터에 대한 후처리는 모델 명세 .yaml 파일의 postprocessing 항목에 명시될 수 있다.
  • Hailo Model Zoo에서 제공하는 대표적인 후처리 방법은 detection task의 NMS(Non Maximum Suppression)가 있다.

PPU 레이어

  • Hailo 에는 PPU(pre/post processing unit) 프로세서가 존재하므로 칩셋 내부 연산을 통해 데이터 연산이 가능하다.
  • 일반적으로 비신경망 처리는 호스트 프로세서(CPU)에서 수행되지만, Hailo의 소프트웨어는 일부 전처리 및 후처리 작업을 칩 자체의 전용 전/후처리 장치(PPU) 로 오프로드하는 기능도 지원한다.
  • PPU 레이어에서 처리할 후처리 방법은 모델의 명세 .yaml 파일에 정의할 수 있으며, 네트워크 내부에서 처리 하지 않고 출력 데이터를 외부에서 처리하는 경우 /hailo_model_zoo/core/postprocessing/{models}_postprocessing.py 파일에 후처리 관련 함수가 작성되어 있다.

최적화 데이터 후처리 예시

PPU를 이용한 네트워크 내부 후처리

  • Hailo Model Zoo에서 제공하는 Resnet50 모델에 대한 최적화 데이터 전처리 과정을 살펴 본다.
  • Resnet50 모델의 config 파일은 resnet_v1_50.yaml 파일에 전처리에 대한 정보를 포함하여 작성되어 있다.
postprocessing:
  device_pre_post_layers:
    softmax: true
    argmax: false
    bilinear: false
    nms: false
  • Hailo Model Zoo 에서 제공하는 Resnet50 모델의 경우 네트워크의 출력 레이어 직전에 softmax 레이어가 존재하며, 이 softmax 레이어의 연산을 Hailo 디바이스에서 실행하도록 설정한 내용이라 할 수 있다.

+full

네트워크 외부 후처리

  • Classification에 해당하는 후처리 코드는 /hailo_model_zoo/core/postprocessing/classification_postprocessing.py 파일에 작성되어 있다.
  • 해당 코드에서 기본 후처리에 해당하는 내용은 아래와 같다.
def classification_postprocessing(endnodes, device_pre_post_layers=None, **kwargs):
    if device_pre_post_layers is not None and device_pre_post_layers['softmax']:
        probs = endnodes
    else:
        logits = endnodes
        if not _is_logits_shape_allowed(logits.shape, kwargs['classes']):
            raise PostprocessingException('Unexpected logits shape {}'.format(logits.shape))
        # Verify the shape of the logits tensor has four dimensions
        logits = tf.reshape(logits, [-1, 1, 1, kwargs['classes']])
        probs = tf.nn.softmax(tf.squeeze(logits, axis=(1, 2)), axis=1)
    return {'predictions': probs}
  • 만약 device_pre_post_layers가 주어졌고, 그 안에 'softmax': True이면, 이미 softmax 처리가 된 출력 (probs)라고 간주하고 그대로 사용.
  • 'softmax': True 가 아니면 네트워크 내부에서 softmax 처리를 하지 않으므로 네트워크 내부에서 softmax 함수를 적용하도록 되어 있다.