Kwantyzacja po zakończeniu trenowania to technika konwersji, która pozwala zmniejszyć rozmiar modelu oraz skrócenie czasu oczekiwania procesora i akceleratora sprzętowego przy niewielkim pogorszenie dokładności modelu. Możesz skwantyzować już wytrenowaną liczbę zmiennoprzecinkową modelu TensorFlow podczas konwertowania go na format LiteRT za pomocą Konwerter LiteRT
Metody optymalizacji
Masz do wyboru kilka opcji kwantyzacji po zakończeniu trenowania. Oto tabeli podsumowującej dostępne opcje i korzyści, jakie zapewniają:
Metoda | Zalety | Sprzęt |
---|---|---|
Zakres dynamiczny kwantyzacja | 4 razy mniejsze, 2–3 razy szybsze przyspieszenie | CPU |
Pełna liczba całkowita kwantyzacja | 4 razy mniejsze, ponad 3-krotne przyspieszenie | CPU, Edge TPU, Mikrokontrolery |
Kwantyzacja obiektu Float16 | 2 razy mniejszy, GPU acceleration, | CPU, GPU |
Aby określić, którą kwantyzację po trenowaniu pomoże Ci to drzewo decyzyjne, jest najlepsza w Twoim przypadku użycia:
Brak kwantyzacji
Przekonwertowanie na model TFLite bez kwantyzacji to zalecane rozwiązanie, . Spowoduje to wygenerowanie pływającego modelu TFLite.
import tensorflow as tf converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) tflite_quant_model = converter.convert()
Zalecamy wykonanie tej czynności w pierwszej kolejności, aby sprawdzić, czy oryginał Operatory modelu TF są zgodne z TFLite i mogą być również używane jako wartość bazowa do debugowania błędów kwantyzacji wprowadzonych przez kolejne etapy po trenowaniu metod kwantyzacji. Jeśli na przykład skwantyzowany model TFLite generuje nieoczekiwane wyniki, podczas gdy model TFLite jest dokładny, ale można go zawęzić problemu błędów spowodowanych przez kwantową wersję operatorów TFLite.
Kwantyzacja zakresu dynamicznego
Kwantyzacja zakresu dynamicznego zapewnia mniejsze wykorzystanie pamięci i szybsze obliczenia bez konieczności dostarczania reprezentatywnego zbioru danych do kalibracji. Ten typ kwantyzacji, statycznie kwantyfikuje tylko wagi ze zmiennoprzecinkowego na liczbę całkowitą w momencie konwersji, co zapewnia 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()
Aby jeszcze bardziej zmniejszyć opóźnienie podczas wnioskowania, użyj „zakresu dynamicznego” operatory dynamicznie kwantyzuje aktywacje w oparciu o ich zakres do 8-bitów i przeprowadza obliczeń z 8-bitowymi wagami i aktywacjami. Optymalizacja zapewnia czasy oczekiwania są bliskie w pełni stałych punktów. Dane wyjściowe są jednak nadal są przechowywane przy użyciu liczby zmiennoprzecinkowej, więc większa prędkość operacji zakresu dynamicznego jest mniejsza niż w przypadku pełnego, stałego punktu obliczeniowego.
Pełna kwantyzacja liczby całkowitej
Pozwala to jeszcze bardziej ograniczyć opóźnienia, zmniejszyć szczytowe wykorzystanie pamięci oraz urządzenia lub akceleratory tylko dla liczb całkowitych, upewniając się, wszystkie funkcje matematyczne modelu są poddane kwantyzacji liczby całkowitej.
Aby uzyskać pełną kwantyzację, musisz skalibrować lub oszacować zakres.
na przykład (minimalna, maksymalna) wszystkich tensorów zmiennoprzecinkowych w modelu. W przeciwieństwie do stałej
tensory, takie jak wagi i uprzedzenia, tensory zmienne, np. dane wejściowe modelu,
aktywacje (wyjścia warstw pośrednich) i dane wyjściowe modelu nie mogą być
skalibrowany, chyba że przeprowadzimy kilka cykli wnioskowania. W efekcie konwerter
wymaga reprezentatywnego zbioru danych do kalibracji. Ten zbiór danych może być mały,
(około 100–500 próbek) danych treningowych lub walidacyjnych. Więcej informacji:
funkcji representative_dataset()
poniżej.
W TensorFlow 2.7 możesz określić reprezentatywny zbiór danych za pomocą podpis jak w poniższym przykładzie:
def representative_dataset(): for data in dataset: yield { "image": data.image, "bias": data.bias, }
Jeśli w danym modelu TensorFlow jest więcej niż 1 podpis, możesz określ wiele zbiorów danych, określając klucze podpisu:
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, }, )
Możesz wygenerować reprezentatywny zbiór danych, podając listę tensorów wejściowych:
def representative_dataset(): for data in tf.data.Dataset.from_tensor_slices((images)).batch(1).take(100): yield [tf.dtypes.cast(data, tf.float32)]
Ponieważ TensorFlow 2.7 to klucz, zalecamy korzystanie z metody opartej na podpisach na podstawie listy tensorów wejściowych, ponieważ kolejność tensorów wejściowych może można łatwo odwrócić.
Do testowania możesz użyć przykładowego zbioru danych w ten sposób:
def representative_dataset(): for _ in range(100): data = np.random.rand(1, 244, 244, 3) yield [data.astype(np.float32)]
Liczba całkowita z zastępczą wartością zmiennoprzecinkową (z użyciem domyślnego pływającego wejścia/wyjścia)
Aby w pełni poddać modelowi kwantyfikację całkowitą, ale używaj operatorów zmiennoprzecinkowych nie masz implementacji liczb całkowitych (aby zapewnić płynną konwersję), użyj te kroki:
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()
Tylko liczba całkowita
Tworzenie modeli zawierających tylko liczby całkowite jest typowym przypadkiem użycia LiteRT dla Mikrokontrolery i koralowe Edge TPU.
Ponadto, aby zapewnić zgodność z urządzeniami obsługującymi tylko liczby całkowite (np. 8-bitowymi) mikrokontrolerów) i akceleratorów (takich jak Coral Edge TPU), można wymusić pełna kwantyzacja wszystkich operacji, w tym danych wejściowych i wyjściowych, za pomocą funkcji te kroki:
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()
Kwantyzacja obiektu Float16
Możesz zmniejszyć rozmiar modelu zmiennoprzecinkowego, konwertując wagi do wartości float16, standard IEEE dla 16-bitowych liczb zmiennoprzecinkowych. Aby włączyć liczbę zmiennoprzecinkową16 kwantyzacji wag, wykonaj te 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 on rozmiar modelu nawet o połowę (wszystkie ciężary są połową rozmiar oryginalny).
- Powoduje to minimalny spadek dokładności.
- Obsługuje on niektórych przedstawicieli (np.GPU), którzy mogą działać. bezpośrednio na danych float16, co zapewnia szybsze działanie niż float32 i obliczenia.
Kwantyfikacja float16 ma takie wady:
- Nie redukuje opóźnień w takim stopniu jak w przypadku kwantyzacji do obliczeń matematycznych ze stałą wartością.
- Domyślnie kwantyzowany model float16 jest „dekwantyzowany” wartości wag na float32 po uruchomieniu CPU. Pamiętaj, że dostęp do GPU dekwantyzacji, ponieważ może ona działać na danych zmiennoprzecinkowych.
Tylko liczby całkowite: 16-bitowe aktywacje z wagą 8-bitową (eksperymentalna)
To jest eksperymentalny schemat kwantyzacji. Jest podobny do „tylko liczby całkowitej” schemat, ale aktywacje są kwantyzowane na podstawie ich zakresu do 16-bitowego, wagi są kwantyzowane w 8-bitowej liczbie całkowitej, a odchylenie jest kwantyzowane jako 64-bitowa liczba całkowita. Ten co jest dalej nazywane kwantyzacją 16 × 8.
Główną zaletą tej kwantyzacji jest to, że zwiększa dokładność znacznie, ale tylko nieznacznie zwiększyć rozmiar modelu.
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()
Jeśli niektóre operatory w modelu nie obsługują kwantyzacji 16 x 8, nadal można poddać kwantyzacji, ale nieobsługiwane operatory są zachowywane jako liczba zmiennoprzecinkowa. Aby to umożliwić, do atrybutu target_spec należy dodać poniższą opcję.
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()
Przykłady przypadków użycia, w których ulepszenie dokładności zapewnia ta zmiana schemat kwantyzacji obejmuje:
- w superrozdzielczości,
- przetwarzania sygnałów dźwiękowych, np. redukcji szumów i kształtowania wiązki,
- redukcji szumów obrazu,
- Rekonstrukcja HDR z jednego zdjęcia.
Wadą tej kwantyzacji jest:
- Obecnie wnioskowanie jest znacznie wolniejsze niż 8-bitowa pełna liczba całkowita ze względu na z brakiem zoptymalizowanego jądra systemu.
- Obecnie nie jest kompatybilny z istniejącymi układami TFLite z akceleracją sprzętową. delegaci.
Samouczek na temat tego trybu kwantyzacji znajdziesz tutaj.
Dokładność modelu
Wagi są skwantyzowane po trenowaniu, więc może to spowodować utratę dokładności, zwłaszcza w mniejszych sieciach. Wytrenowane w pełni kwantowe modele to: dostępne dla określonych sieci w Kaggle Modele , Ważne jest sprawdzenie dokładności kwantyzowanego modelu, aby upewnić się, wszelkie pogorszenie dokładności mieści się w dopuszczalnych granicach. Istnieją narzędzia, za pomocą których Oceń model LiteRT dokładności.
Jeśli spadek dokładności jest zbyt duży, możesz też użyć kwantyzacji świadomość szkolenia , Wymaga to jednak modyfikacji podczas trenowania modelu, aby można było dodać fałszywe węzłów kwantyzacji, natomiast techniki kwantyzacji po trenowaniu użyj już wytrenowanego modelu.
Reprezentacja tensorów kwantowych
8-bitowa kwantyzacja przybliża wartości zmiennoprzecinkowe za pomocą tego .
\[real\_value = (int8\_value - zero\_point) \times scale\]
Reprezentacja składa się z 2 głównych części:
Wagi na oś (inaczej kanał) lub na poziomie procesora reprezentowane przez wartości int8 dwóch dopełnia wartości z zakresu [-127, 127] punktem 0 równym 0.
Aktywacje/dane wejściowe reprezentowanych przez wartości dopełnienia int8 2 w zakres [-128, 127], gdzie punkt zerowy jest w zakresie [-128, 127].
Szczegółowy opis naszego schematu kwantyzacji znajdziesz w naszym artykule o kwantyzacji specyfikacja. Dostawcy sprzętu, którzy chcą podłączyć do TensorFlow Zachęcamy do wdrożenia schematu kwantyzacji przy użyciu interfejsu przedstawicieli Lite który tam opisano.