학습 후 양자화

학습 후 양자화는 모델 크기를 줄이는 동시에 모델 정확성이 거의 저하되지 않으면서 CPU 및 하드웨어 가속기 지연 시간을 개선할 수 있는 변환 기법입니다. TensorFlow Lite 변환기를 사용하여 TensorFlow Lite 형식으로 변환할 때 이미 학습된 부동 소수점 TensorFlow 모델을 양자화할 수 있습니다.

최적화 방법

여러 가지 학습 후 양자화 옵션 중에서 선택할 수 있습니다. 다음은 이러한 옵션과 각 옵션의 이점을 요약한 표입니다.

기법 이점 하드웨어
다이내믹 레인지 양자화 4배 더 작게, 2~3배 속도 향상 CPU
전체 정수 양자화 4배 더 작게, 속도 3배 이상 CPU, Edge TPU, 마이크로컨트롤러
Float16 양자화 2배 더 작은 GPU 가속 CPU, GPU

다음 결정 트리는 사용 사례에 가장 적합한 학습 후 양자화 방법을 결정하는 데 도움이 될 수 있습니다.

학습 후 최적화 옵션

양자화 없음

양자화 없이 TFLite 모델로 변환하는 것부터 시작하는 것이 좋습니다. 그러면 부동 TFLite 모델이 생성됩니다.

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
tflite_quant_model = converter.convert()

원래 TF 모델의 연산자가 TFLite와 호환되고 후속 학습 후 양자화 메서드로 인해 발생하는 양자화 오류를 디버그하는 기준으로 사용할 수도 있는지 확인하기 위한 초기 단계로 이 작업을 실행하는 것이 좋습니다. 예를 들어 양자화된 TFLite 모델이 예기치 않은 결과를 생성하는 경우 부동 TFLite 모델은 정확한 경우, TFLite 연산자의 양자화 버전에 의해 발생하는 오류로 문제를 좁힐 수 있습니다.

다이내믹 레인지 양자화

동적 범위 양자화를 사용하면 보정을 위한 대표 데이터 세트를 제공하지 않고도 메모리 사용량을 줄이고 계산 속도를 높일 수 있습니다. 이 유형의 양자화는 변환 시 부동 소수점에서 정수로의 가중치만 정적 양자화하여 8비트의 정밀도를 제공합니다.

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
tflite_quant_model = converter.convert()

추론 중에 지연 시간을 더욱 줄이기 위해 '동적 범위' 연산자는 8비트까지의 범위를 기준으로 활성화를 동적으로 양자화하고 8비트 가중치 및 활성화로 계산을 실행합니다. 이 최적화는 완전 고정 소수점 추론에 가까운 지연 시간을 제공합니다. 그러나 출력은 여전히 부동 소수점을 사용하여 저장되므로 동적 범위 작업의 빠른 속도는 완전한 고정 소수점 계산보다 적습니다.

전체 정수 양자화

모든 모델 수학이 정수 양자화되도록 하면 지연 시간을 더욱 개선하고 최대 메모리 사용량을 줄이며 정수 전용 하드웨어 기기 또는 액셀러레이터와의 호환성을 얻을 수 있습니다.

전체 정수 양자화의 경우 범위를 보정하거나 추정해야 합니다. 즉, 모델의 모든 부동 소수점 텐서의 (min, max)입니다. 가중치 및 편향과 같은 상수 텐서와 달리, 모델 입력, 활성화 (중간 레이어의 출력), 모델 출력과 같은 가변 텐서는 추론 주기를 몇 차례 실행하지 않는 한 보정할 수 없습니다. 따라서 변환기에는 이를 보정하기 위한 대표 데이터 세트가 필요합니다. 이 데이터 세트는 학습 또는 검증 데이터의 작은 부분집합 (약 100~500개의 샘플)일 수 있습니다. 아래의 representative_dataset() 함수를 참고하세요.

TensorFlow 2.7 버전부터는 다음 예와 같이 서명을 통해 대표 데이터 세트를 지정할 수 있습니다.

def representative_dataset():
  for data in dataset:
    yield {
      "image": data.image,
      "bias": data.bias,
    }

지정된 TensorFlow 모델에 서명이 두 개 이상 있는 경우 서명 키를 지정하여 여러 데이터 세트를 지정할 수 있습니다.

def representative_dataset():
  # Feed data set for the "encode" signature.
  for data in encode_signature_dataset:
    yield (
      "encode", {
        "image": data.image,
        "bias": data.bias,
      }
    )

  # Feed data set for the "decode" signature.
  for data in decode_signature_dataset:
    yield (
      "decode", {
        "image": data.image,
        "hint": data.hint,
      },
    )

입력 텐서 목록을 제공하여 대표 데이터 세트를 생성할 수 있습니다.

def representative_dataset():
  for data in tf.data.Dataset.from_tensor_slices((images)).batch(1).take(100):
    yield [tf.dtypes.cast(data, tf.float32)]

TensorFlow 2.7 버전부터는 입력 텐서 목록 기반 접근 방식보다 서명 기반 접근 방식을 사용하는 것이 좋습니다. 입력 텐서 순서 지정이 쉽게 뒤집힐 수 있기 때문입니다.

테스트를 위해 다음과 같이 더미 데이터세트를 사용할 수 있습니다.

def representative_dataset():
    for _ in range(100):
      data = np.random.rand(1, 244, 244, 3)
      yield [data.astype(np.float32)]
 

부동 소수점 대체가 포함된 정수 (기본 부동 소수점 입력/출력 사용)

모델을 완전히 정수로 양자화하지만 정수 구현이 없는 경우 부동 소수점 연산자를 사용하려면 (변환이 원활하게 이루어질 수 있도록) 다음 단계를 따르세요.

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.representative_dataset = representative_dataset
tflite_quant_model = converter.convert()

정수만

정수 전용 모델을 만드는 것은 마이크로컨트롤러용 TensorFlow LiteCoral Edge TPU의 일반적인 사용 사례입니다.

또한 정수 전용 기기 (예: 8비트 마이크로 컨트롤러) 및 가속기 (예: Coral Edge TPU)와의 호환성을 보장하려면 다음 단계에 따라 입력 및 출력을 포함한 모든 연산에 완전한 정수 양자화를 적용할 수 있습니다.

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.representative_dataset = representative_dataset
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.int8  # or tf.uint8
converter.inference_output_type = tf.int8  # or tf.uint8
tflite_quant_model = converter.convert()

Float16 양자화

가중치를 16비트 부동 소수점 숫자에 대한 IEEE 표준인 float16으로 양자화하여 부동 소수점 모델의 크기를 줄일 수 있습니다. 가중치의 float16 양자화를 사용 설정하려면 다음 단계를 따르세요.

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_types = [tf.float16]
tflite_quant_model = converter.convert()

float16 양자화의 이점은 다음과 같습니다.

  • 모든 가중치가 원래 크기의 절반이 되므로 모델 크기를 최대 절반까지 줄입니다.
  • 정확도 손실이 최소화됩니다.
  • float16 데이터에서 직접 작동할 수 있는 일부 대리자 (예: GPU 대리자)를 지원하므로 float32 계산보다 실행 속도가 빠릅니다.

float16 양자화의 단점은 다음과 같습니다.

  • 이는 고정 소수점 수학으로의 양자화만큼 지연 시간을 줄이지 않습니다.
  • 기본적으로 float16 양자화 모델은 CPU에서 실행될 때 가중치 값을 float32로 '비양자화'합니다. GPU 대리자는 float16 데이터에서 작동할 수 있으므로 이 역양자화를 실행하지 않습니다.

정수만 해당: 8비트 가중치를 사용하는 16비트 활성화 (실험용)

이는 실험용 양자화 체계입니다. '정수 전용' 체계와 비슷하지만 활성화는 16비트 범위에 따라 양자화되고, 가중치는 8비트 정수로 양자화되고, 편향은 64비트 정수로 양자화됩니다. 이를 16x8 양자화라고 합니다.

이러한 양자화의 주요 이점은 정확도를 크게 개선할 수 있지만 모델 크기만 약간 증가한다는 것입니다.

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.representative_dataset = representative_dataset
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8]
tflite_quant_model = converter.convert()

모델의 일부 연산자에 16x8 양자화가 지원되지 않는 경우 모델은 여전히 양자화될 수 있지만 지원되지 않는 연산자는 부동 소수점으로 유지됩니다. 이를 허용하려면 target_spec에 다음 옵션을 추가해야 합니다.

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.representative_dataset = representative_dataset
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.EXPERIMENTAL_TFLITE_BUILTINS_ACTIVATIONS_INT16_WEIGHTS_INT8,
tf.lite.OpsSet.TFLITE_BUILTINS]
tflite_quant_model = converter.convert()

이 양자화 체계로 정확성이 향상되는 사용 사례의 예는 다음과 같습니다.

  • super-resolution,
  • 주변 소음 제거 및 빔포밍과 같은 오디오 신호 처리
  • 이미지 노이즈 제거,
  • 단일 이미지에서 HDR을 재구성한 영상입니다.

이러한 양자화의 단점은 다음과 같습니다.

  • 현재 추론은 최적화된 커널 구현의 부족으로 인해 8비트 전체 정수보다 현저히 느립니다.
  • 현재는 기존 하드웨어 가속 TFLite 위임과 호환되지 않습니다.

이 양자화 모드에 관한 튜토리얼은 여기에서 확인할 수 있습니다.

모델 정확성

가중치는 학습 후 양자화되므로 특히 소규모 네트워크의 경우 정확성 손실이 발생할 수 있습니다. Kaggle 모델의 특정 네트워크에 대해 선행 학습된 완전 양자화 모델이 제공됩니다. 양자화 모델의 정확성을 검사하여 정확성 저하가 허용 가능한 제한을 초과하지 않는지 확인하는 것이 중요합니다. TensorFlow Lite 모델 정확성을 평가하는 도구가 있습니다.

또는 정확성 저하가 너무 높다면 양자화 인식 학습을 사용해 보세요. 하지만 이렇게 하려면 모델 학습 중에 가짜 양자화 노드를 추가하기 위해 수정해야 하는 반면, 이 페이지의 학습 후 양자화 기법은 선행 학습된 기존 모델을 사용합니다.

양자화 텐서의 표현

8비트 양자화는 다음 수식을 사용하여 부동 소수점 값의 근사치를 계산합니다.

\[real\_value = (int8\_value - zero\_point) \times scale\]

이 표현은 두 가지 주요 부분으로 구성됩니다.

  • [-127, 127] 범위의 int8 2의 보수 값으로 표시되는 축당 (채널별) 또는 텐서당 가중치. 0은 0입니다.

  • [-128, 127] 범위의 int8 2의 보수 값으로 표현되는 텐서별 활성화/입력, [-128, 127] 범위의 0점

양자화 체계에 관한 자세한 보기는 양자화 사양을 참고하세요. TensorFlow Lite의 대리자 인터페이스를 연결하려는 하드웨어 공급업체는 여기에 설명된 양자화 체계를 구현하는 것이 좋습니다.