Ta strona została przetłumaczona przez Cloud Translation API.
Switch to English

Kwantyzacja potreningowa

Kwantyzacja potreningowa to technika konwersji, która może zmniejszyć rozmiar modelu, jednocześnie poprawiając opóźnienie procesora i akceleratora sprzętowego, z niewielkim pogorszeniem dokładności modelu. Możesz kwantyzować już wyuczony model TensorFlow typu float, konwertując go do formatu TensorFlow Lite za pomocą konwertera TensorFlow Lite .

Metody optymalizacji

Do wyboru jest kilka opcji kwantyzacji po treningu. Oto tabela podsumowująca dostępne opcje i korzyści:

Technika Korzyści Sprzęt komputerowy
Kwantyzacja zakresu dynamicznego 4x mniejsze, przyspieszenie 2x-3x procesor
Pełna kwantyzacja liczb całkowitych 4x mniejsze, 3x + przyspieszenie CPU, Edge TPU, mikrokontrolery
Kwantyzacja Float16 2x mniejsze, przyspieszenie GPU CPU, GPU

Poniższe drzewo decyzyjne może pomóc określić, która metoda kwantyzacji po treningu jest najlepsza dla twojego przypadku użycia:

opcje optymalizacji po treningu

Kwantyzacja zakresu dynamicznego

Najprostsza forma kwantyzacji potreningowej kwantyzuje statycznie tylko wagi od zmiennoprzecinkowej do całkowitej, która ma 8-bitową precyzję:

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()

Wnioskując, wagi są konwertowane z 8-bitowej precyzji na zmiennoprzecinkowe i obliczane przy użyciu jądra zmiennoprzecinkowego. Ta konwersja jest wykonywana raz i zapisywana w pamięci podręcznej, aby zmniejszyć opóźnienia.

Aby jeszcze bardziej poprawić opóźnienie, operatorzy „zakresu dynamicznego” dynamicznie kwantyzują aktywacje w oparciu o ich zakres do 8-bitów i wykonują obliczenia z 8-bitowymi wagami i aktywacjami. Ta optymalizacja zapewnia opóźnienia zbliżone do wnioskowania w pełni stałego punktu. Jednak dane wyjściowe są nadal przechowywane przy użyciu zmiennoprzecinkowych, więc przyspieszenie z operacjami dynamicznego zakresu jest mniejsze niż pełne obliczenia stałoprzecinkowe.

Pełna kwantyzacja liczb całkowitych

Możesz uzyskać dalsze ulepszenia opóźnień, zmniejszenie szczytowego wykorzystania pamięci i zgodność z urządzeniami sprzętowymi lub akceleratorami obsługującymi tylko liczby całkowite, upewniając się, że cała matematyka modelu jest kwantyzowana na liczbach całkowitych.

Aby uzyskać pełną kwantyzację liczb całkowitych, musisz zmierzyć dynamiczny zakres aktywacji i wejść, dostarczając próbne dane wejściowe do konwertera. Zapoznaj się z funkcją representative_dataset_gen() używaną w poniższym kodzie.

Liczba całkowita z rezerwą zmiennoprzecinkową (przy użyciu domyślnego wejścia / wyjścia typu float)

Aby w pełni kwantyzować model w liczbach całkowitych, ale użyj operatorów zmiennoprzecinkowych, gdy nie mają implementacji liczb całkowitych (aby zapewnić płynną konwersję), wykonaj następujące czynności:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
def representative_dataset_gen():
  for _ in range(num_calibration_steps):
    # Get sample input data as a numpy array in a method of your choosing.
    yield [input]
converter.representative_dataset = representative_dataset_gen
tflite_quant_model = converter.convert()

Tylko liczby całkowite

Tworzenie modeli zawierających wyłącznie liczby całkowite jest typowym przypadkiem użycia TensorFlow Lite dla mikrokontrolerów i TPU Coral Edge .

Ponadto, aby zapewnić zgodność z urządzeniami obsługującymi wyłącznie liczby całkowite (takimi jak 8-bitowe mikrokontrolery) i akceleratorami (takimi jak Coral Edge TPU), można wymusić pełną kwantyzację liczb całkowitych dla wszystkich operacji, w tym wejścia i wyjścia, wykonując następujące czynności:

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
def representative_dataset_gen():
  for _ in range(num_calibration_steps):
    # Get sample input data as a numpy array in a method of your choosing.
    yield [input]
converter.representative_dataset = representative_dataset_gen
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()

Kwantyzacja Float16

Możesz zmniejszyć rozmiar modelu zmiennoprzecinkowego, kwantyzując wagi do float16, standardu IEEE dla 16-bitowych liczb zmiennoprzecinkowych. Aby włączyć kwantyzację wag typu float16, wykonaj następujące czynności:

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()

Zalety kwantyzacji float16 są następujące:

  • Zmniejsza rozmiar modelu nawet o połowę (ponieważ wszystkie wagi stają się o połowę mniejsze niż ich pierwotne rozmiary).
  • Powoduje minimalną utratę dokładności.
  • Obsługuje niektórych delegatów (np. Delegatów GPU), które mogą działać bezpośrednio na danych typu float16, co skutkuje szybszym wykonaniem niż obliczenia typu float32.

Wady kwantyzacji float16 są następujące:

  • Nie zmniejsza opóźnienia tak bardzo, jak kwantyzacja do matematyki stałoprzecinkowej.
  • Domyślnie skwantowany model typu float16 „dekwantyzuje” wartości wag do float32 po uruchomieniu na procesorze. (Zauważ, że delegat GPU nie wykona tej dekwantyzacji, ponieważ może działać na danych float16).

Tylko liczby całkowite: 16-bitowe aktywacje z 8-bitowymi wagami (eksperymentalne)

To jest eksperymentalny schemat kwantyzacji. Jest podobny do schematu „tylko liczby całkowite”, ale aktywacje są kwantyzowane na podstawie ich zakresu do 16-bitów, wagi są kwantyzowane w 8-bitowych liczbach całkowitych, a odchylenie jest kwantowane do 64-bitowej liczby całkowitej. Jest to dalej określane jako kwantyzacja 16x8.

Główną zaletą tej kwantyzacji jest to, że może ona znacznie poprawić dokładność, ale tylko nieznacznie zwiększyć rozmiar modelu.

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
def representative_dataset_gen():
  for _ in range(num_calibration_steps):
    # Get sample input data as a numpy array in a method of your choosing.
    yield [input]
converter.representative_dataset = representative_dataset_gen
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()

Jeśli kwantyzacja 16x8 nie jest obsługiwana dla niektórych operatorów w modelu, wówczas model nadal może być kwantyzowany, ale operatory nieobsługiwane pozostają w zmiennej zmiennoprzecinkowej. Aby to umożliwić, do parametru target_spec należy dodać następującą opcję.

import tensorflow as tf
converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir)
def representative_dataset_gen():
  for _ in range(num_calibration_steps):
    # Get sample input data as a numpy array in a method of your choosing.
    yield [input]
converter.representative_dataset = representative_dataset_gen
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()

Przykłady przypadków użycia, w których poprawa dokładności zapewniana przez ten schemat kwantyzacji obejmuje: * super rozdzielczość, * przetwarzanie sygnału audio, takie jak redukcja szumów i formowanie wiązki, * redukcja szumów obrazu, * rekonstrukcja HDR z pojedynczego obrazu.

Wadą tej kwantyzacji jest:

  • Obecnie wnioskowanie jest zauważalnie wolniejsze niż 8-bitowa pełna liczba całkowita z powodu braku zoptymalizowanej implementacji jądra.
  • Obecnie jest niekompatybilny z istniejącymi delegatami TFLite z akceleracją sprzętową.

Samouczek dotyczący tego trybu kwantyzacji można znaleźć tutaj .

Dokładność modelu

Ponieważ wagi są kwantyzowane po treningu, może wystąpić utrata dokładności, szczególnie w przypadku mniejszych sieci. W repozytorium modeli TensorFlow Lite udostępniono wstępnie wytrenowane, w pełni skwantyzowane modele dla określonych sieci. Ważne jest, aby sprawdzić dokładność skwantowanego modelu, aby zweryfikować, czy jakiekolwiek pogorszenie dokładności mieści się w dopuszczalnych granicach. Istnieją narzędzia do oceny dokładności modelu TensorFlow Lite .

Alternatywnie, jeśli spadek dokładności jest zbyt duży, rozważ użycie treningu świadomego kwantyzacji . Jednak wykonanie tego wymaga modyfikacji podczas uczenia modelu w celu dodania fałszywych węzłów kwantyzacji, podczas gdy techniki kwantyzacji po treningu na tej stronie wykorzystują istniejący wstępnie wytrenowany model.

Reprezentacja skwantyzowanych tensorów

8-bitowa kwantyzacja aproksymuje wartości zmiennoprzecinkowe przy użyciu następującego wzoru.

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

Przedstawienie składa się z dwóch głównych części:

  • Wagi na oś (aka na kanał) lub wagi na tensor reprezentowane przez wartości uzupełnienia do dwóch int8 w zakresie [-127, 127] z punktem zerowym równym 0.

  • Aktywacje / wejścia per-tensor reprezentowane przez wartości uzupełnienia int8 do dwóch z zakresu [-128, 127], z punktem zerowym w zakresie [-128, 127].

Aby uzyskać szczegółowy widok naszego schematu kwantyzacji, zobacz naszą specyfikację kwantyzacji . Producenci sprzętu, którzy chcą podłączyć się do interfejsu delegata TensorFlow Lite, są zachęcani do implementacji opisanego tam schematu kwantyzacji.