Квантизация моделей: int8 и float16

Квантизация моделей — это процесс снижения разрядности чисел, используемых для представления весов и активаций нейронной сети, с целью уменьшения объёма модели и ускорения инференса без существенной потери точности. В TensorFlow.js поддерживаются различные типы квантизации, наиболее распространённые из которых — float16 и int8.


Основы квантизации

Квантизация переводит параметры модели из высокоточной формы (обычно float32) в более компактный формат. Применение квантизации позволяет:

  • Сократить размер модели: уменьшение разрядности чисел снижает объём хранилища, необходимого для весов.
  • Ускорить вычисления: операции над int8 выполняются быстрее, чем float32, особенно на устройствах с ограниченными ресурсами.
  • Снизить энергопотребление: уменьшение объёма данных и числа операций положительно сказывается на мобильных устройствах и браузерах.

Важное отличие между float16 и int8:

Тип квантизации Диапазон значений Потери точности Основное применение
float16 ±6.5×10⁴ минимальные GPU и WebGL ускорение, точные модели
int8 -128…127 выше, требует калибровки Устройства с низкой памятью и ограниченным CPU

Квантизация в TensorFlow.js

TensorFlow.js поддерживает квантизацию моделей на этапе их экспорта из TensorFlow или при конвертации формата SavedModel / Keras → TensorFlow.js Layers или Graph Model.

Конвертация с float16

Для получения модели с весами float16 используется параметр weight_dtype:

tensorflowjs_converter \
  --input_format=tf_saved_model \
  --output_format=tfjs_graph_model \
  --weight_dtype=float16 \
  /path/to/saved_model \
  /path/to/web_model
  • weight_dtype=float16: веса будут храниться в формате float16, что уменьшает размер примерно в два раза.
  • Float16 сохраняет относительную точность при использовании на современных GPU и WebGL, где вычисления с половинной точностью поддерживаются аппаратно.
Конвертация с int8

Квантизация до int8 в TensorFlow.js требует дополнительной калибровки с использованием набора данных. Прямого автоматического преобразования int8 при конвертации модели нет, поэтому применяется post-training quantization через TensorFlow Python:

import tensorflow as tf

converter = tf.lite.TFLiteConverter.from_saved_model("saved_model")
converter.optimizations = [tf.lite.Optimize.DEFAULT]

def representative_dataset():
    for _ in range(100):
        yield [input_data_sample]  # input_data_sample — пример входных данных

converter.representative_dataset = representative_dataset
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.uint8
converter.inference_output_type = tf.uint8

tflite_model = converter.convert()

После этого tflite-модель можно конвертировать в TensorFlow.js с помощью tensorflowjs_converter. Квантизация int8 позволяет значительно уменьшить размер модели и ускорить инференс на CPU, но требует проверки точности.


Влияние квантизации на точность

  • Float16 почти не влияет на точность моделей типа CNN, RNN и Transformer. Потери обычно находятся в пределах 1–2%.
  • Int8 может вызывать заметное снижение точности, особенно для сложных моделей с небольшими активациями или узкими диапазонами весов. Для минимизации потерь используется репрезентативный датасет, который помогает правильно масштабировать диапазон значений.

Практические рекомендации

  1. Выбор формата квантизации:

    • Float16 подходит для моделей с большим количеством операций и когда точность критична.
    • Int8 предпочтителен для мобильных и web-приложений с ограниченной памятью и низкой пропускной способностью CPU.
  2. Тестирование модели после квантизации:

    • Проверить точность на контрольном наборе данных.
    • Для int8 использовать несколько подходов к репрезентативной выборке для оптимизации масштабирования весов.
  3. Интеграция в TensorFlow.js:

    • Graph Model (tf.loadGraphModel) лучше подходит для моделей с float16 и int8, особенно если требуется WebGL ускорение.
    • Layers Model (tf.loadLayersModel) поддерживает float16 на этапе конвертации весов, но int8 поддерживается через TFLite → TFJS Pipeline.

Особенности работы с float16 и int8 в браузере

  • Float16: поддерживается WebGL шейдерами. TensorFlow.js автоматически использует ускорение при наличии GPU. Ограничения касаются браузеров без WebGL2.
  • Int8: вычисления выполняются на CPU, так как WebGL не поддерживает целочисленные операции natively. Для ускорения можно использовать WebAssembly Backend (tfjs-backend-wasm), который обеспечивает ускоренные int8 вычисления.

Выводы по оптимизации

  • Квантизация — ключевой инструмент оптимизации моделей для браузера.
  • Float16 балансирует размер и точность, особенно полезен для графических операций.
  • Int8 обеспечивает максимальную экономию памяти и ускорение на CPU, требует тщательной калибровки.
  • В TensorFlow.js квантизация реализуется через конвертер моделей и поддерживается как для графовых, так и для слоевых моделей.

Квантизация является обязательной практикой при переносе больших нейронных сетей в веб-среду, обеспечивая сочетание производительности, компактности и управляемой потери точности.