Квантование модели: статическое и динамическое, int8

Квантование — процесс преобразования весов и активаций модели из формата с высокой точностью (например, float32) в более компактные типы данных, такие как int8. Цель квантования — снизить объем модели и ускорить вычисления без значительной потери точности. В ONNX Runtime Web поддерживаются методы статического и динамического квантования, позволяющие оптимизировать работу модели на клиентской стороне в браузере.

Перед квантованием необходимо:

  • Иметь модель в формате ONNX.
  • Определить точность, которую допускается потерять (обычно минимальная деградация точности — 1–2% для задач классификации).
  • Подготовить данные калибровки для статического квантования (необходимы примеры, отражающие распределение реальных входных данных).

Статическое квантование (Static Quantization)

Статическое квантование подразумевает вычисление статических коэффициентов масштабирования (scale) и смещения (zero-point) для весов и активаций до выполнения инференса. Эти коэффициенты фиксируются в модели, что позволяет браузеру выполнять операции с int8 без дополнительной арифметики преобразования на лету.

Преимущества:

  • Более высокая скорость инференса.
  • Снижение потребления памяти за счет компактного хранения весов.
  • Минимизация накладных расходов на преобразование типов данных во время выполнения.

Основные шаги:

  1. Калибровка на примерах данных: Для каждого тензора активации вычисляются минимальные и максимальные значения, по которым строятся шкалы квантования.

  2. Применение квантования к весам и активациям: Используется формула: [ q = ()] где f — исходное значение float32, q — значение после квантования в int8.

  3. Сохранение коэффициентов в модели ONNX: ONNX Runtime Web может использовать эти коэффициенты напрямую при выполнении инференса.

Пример применения статического квантования через Python (для подготовки модели к вебу):

from onnxruntime.quantization import quantize_static, CalibrationDataReader, QuantType

class DummyDataReader(CalibrationDataReader):
    def __init__(self, data):
        self.data = data
        self.iterator = iter(data)
    def get_next(self):
        try:
            return next(self.iterator)
        except StopIteration:
            return None

quantize_static(
    model_input="model_float.onnx",
    model_output="model_int8.onnx",
    calibration_data_reader=DummyDataReader(calibration_data),
    quant_format=QuantType.QOperator
)

Динамическое квантование (Dynamic Quantization)

Динамическое квантование выполняется на лету во время инференса. Весовые коэффициенты квантуются заранее, а активации преобразуются в int8 по мере прохождения через слои модели. Это снижает необходимость предоставления больших наборов данных для калибровки.

Преимущества:

  • Не требует калибровочного набора данных.
  • Простота интеграции с существующей моделью.
  • Хорошо подходит для моделей с большим количеством линейных слоев (например, NLP-модели).

Недостатки:

  • Меньший прирост скорости по сравнению со статическим квантованием.
  • Некоторая потеря точности может быть выше, чем у статического метода.

Пример Python-кода для подготовки динамического квантования:

from onnxruntime.quantization import quantize_dynamic, QuantType

quantize_dynamic(
    model_input="model_float.onnx",
    model_output="model_dynamic_int8.onnx",
    weight_type=QuantType.QInt8
)

Интеграция квантованной модели в ONNX Runtime Web

ONNX Runtime Web предоставляет API для выполнения инференса квантованных моделей в браузере. Основные шаги:

  1. Подключение библиотеки:
import * as ort from 'onnxruntime-web';
  1. Загрузка модели:
const session = await ort.InferenceSession.create('model_int8.onnx');
  1. Подготовка входных данных:
const inputTensor = new ort.Tensor('float32', inputData, [batchSize, inputSize]);
  1. Запуск инференса:
const feeds = { input: inputTensor };
const results = await session.run(feeds);
console.log(results.output.data);
  1. Оптимизация исполнения: ONNX Runtime Web позволяет выбирать между WebAssembly и WebGL backend для ускорения вычислений квантованной модели.

Рекомендации по выбору метода квантования

  • Для малых и средних моделей в веб-приложениях статическое квантование обеспечивает максимальную производительность.
  • Для крупных моделей NLP или при отсутствии калибровочных данных динамическое квантование — оптимальный выбор.
  • Комбинированный подход (квантование весов статически + активации динамически) часто обеспечивает баланс между точностью и производительностью.

Особенности работы с int8 в ONNX Runtime Web

  • Поддерживаются основные операции: Conv, MatMul, Gemm, Add, Relu и др.
  • Квантованные модели требуют меньше памяти и быстрее загружаются, что критично для мобильных браузеров.
  • При переходе с float32 на int8 стоит контролировать точность предсказаний и при необходимости корректировать коэффициенты калибровки.

Хорошая практика — профилировать производительность модели как до, так и после квантования, чтобы убедиться, что снижение точности находится в допустимых пределах, а ускорение инференса оправдано.