Ответ
Квантизация — это техника оптимизации, которую я применял для уменьшения размера модели и ускорения ее вывода на CPU или edge-устройствах за счет снижения числовой точности весов и активаций (например, с 32-битных чисел с плавающей запятой до 8-битных целых чисел). Я использовал два основных подхода.
1. Посттренировочная квантизация (Post-Training Quantization, PTQ): Это самый быстрый метод, применяемый после обучения модели. Я использовал его, когда требовалось быстро получить оптимизированную версию без повторного обучения.
- Как это работает: Калибровочный датасет (небольшая часть тренировочных данных) прогоняется через модель для сбора статистик (диапазонов) активаций. На основе этих статистик определяются параметры масштабирования (scale) и сдвига (zero_point) для преобразования float-значений в int8.
- Пример с TensorFlow Lite:
import tensorflow as tf
Загрузка обученной модели
model = tf.keras.models.load_model('my_model.h5') converter = tf.lite.TFLiteConverter.from_keras_model(model)
Включение квантизации
converter.optimizations = [tf.lite.Optimize.DEFAULT] # DEFAULT обычно включает PTQ для весов
Для полной квантизации (веса + активации) нужен representative_dataset
def representative_dataset(): for data in calibration_data.take(100): # 100 примеров для калибровки yield [tf.dtypes.cast(data, tf.float32)] converter.representative_dataset = representative_dataset
Конвертация в квантизованный TFLite формат
quantized_tflite_model = converter.convert()
Сохранение модели
with open('model_quantized.tflite', 'wb') as f: f.write(quantized_tflite_model) print(f"Размер уменьшился с {os.path.getsize('my_model.h5')} до {os.path.getsize('model_quantized.tflite')} байт")
**Плюсы PTQ:** Быстро, не требует повторного обучения. **Минусы:** Может привести к заметной потере точности, особенно если распределение активаций нестабильно.
**2. Квантизация с учетом обучения (Quantization-Aware Training, QAT):**
Я применял этот метод, когда была критически важна минимальная потеря точности. QAT **эмулирует** эффект квантизации прямо во время фазы дообучения (fine-tuning).
* **Как это работает:** В граф модели встраиваются специальные узлы (FakeQuantize), которые во время forward pass округляют значения, как при int8-квантизации, но во время backward pass пропускают градиенты через операцию округления (используя Straight-Through Estimator). Это позволяет модели адаптировать свои веса к будущему квантованию.
* **Пример с PyTorch (torch.ao.quantization):**
```python
import torch
import torch.nn as nn
from torch.ao.quantization import QuantStub, DeQuantStub, prepare_qat, convert
class MyModelWithQuant(nn.Module):
def __init__(self):
super().__init__()
self.quant = QuantStub() # Точка квантизации входов
self.conv1 = nn.Conv2d(3, 16, kernel_size=3)
self.relu = nn.ReLU()
self.dequant = DeQuantStub() # Точка де-квантизации выходов
def forward(self, x):
x = self.quant(x)
x = self.conv1(x)
x = self.relu(x)
x = self.dequant(x)
return x
model = MyModelWithQuant()
model.train()
# 1. Установка конфигурации квантизации (для CPU 'fbgemm', для Mobile 'qnnpack')
model.qconfig = torch.ao.quantization.get_default_qat_qconfig('fbgemm')
# 2. Подготовка модели к QAT (встраивание fake quantization модулей)
torch.ao.quantization.prepare_qat(model, inplace=True)
# 3. Дообучение (fine-tuning) модели с учетом квантизации
# ... (обычно несколько эпох на том же датасете)
optimizer = torch.optim.SGD(model.parameters(), lr=0.001)
for epoch in range(10):
for data, target in train_loader:
optimizer.zero_grad()
output = model(data)
loss = criterion(output, target)
loss.backward()
optimizer.step()
# 4. Конвертация обученной QAT-модели в настоящую квантизованную модель
model.eval()
model_fused = torch.ao.quantization.fuse_modules(model, [['conv1', 'relu']]) # Фьюзинг слоев
model_quantized = convert(model_fused, inplace=False)
# Теперь model_quantized использует целочисленные операции
Выбор подхода: Для прототипирования и быстрого развертывания я использовал PTQ. Для продакшн-моделей, где каждый процент точности на счету (например, в компьютерном зрении для беспилотных автомобилей), я всегда применял QAT.