Как делал квантизацию?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Как делал квантизацию?
Квантизация — это процесс сжатия модели путём уменьшения точности численных представлений (от 32-битных float до 8-битных integer, например). Это критично для деплоя ML моделей на мобильных устройствах и edge серверах.
Что такое квантизация?
Без квантизации:
Вес модели: 0.12345678 (float32) — 4 байта
Выход нейрона: 2.56789012 (float32) — 4 байта
С квантизацией:
Вес модели: 0.1 (int8) — 1 байт
Выход нейрона: 3 (int8) — 1 байт
Сжатие в 4 раза!
Типы квантизации
1. Post-Training Quantization (PTQ) — квантизация после обучения
Простейший подход: после обучения модели просто конвертируем веса.
import tensorflow as tf
from tensorflow.lite.python import lite
# Обучённая модель
model = tf.keras.models.load_model('model.h5')
# Конвертируем в TensorFlow Lite с квантизацией
converter = lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
# DEFAULT включает dynamic range quantization (float32 -> int8)
quantized_model = converter.convert()
# Сохраняем квантизированную модель
with open('model_quantized.tflite', 'wb') as f:
f.write(quantized_model)
Плюсы:
- Быстро и просто
- Не требует переобучения
- Работает для большинства моделей
Минусы:
- Может потерять точность (обычно 1-5%)
- Нет контроля над процессом
2. Quantization-Aware Training (QAT) — квантизация во время обучения
Обучаем модель с учётом квантизации с самого начала.
import tensorflow as tf
from tensorflow_model_optimization.quantization.keras import quantize_model
# Обучённая модель
model = tf.keras.models.load_model('model.h5')
# Подготавливаем к квантизации
quant_aware_model = quantize_model(model)
# Переобучаем с низким learning rate
quant_aware_model.compile(
optimizer=tf.keras.optimizers.Adam(learning_rate=1e-5),
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
quant_aware_model.fit(X_train, y_train, epochs=10)
# Конвертируем в TensorFlow Lite
converter = tf.lite.TFLiteConverter.from_keras_model(quant_aware_model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
quantized_model = converter.convert()
Плюсы:
- Лучше сохраняет точность
- Модель "знает" о квантизации с самого начала
- Работает лучше всего
Минусы:
- Требует переобучения
- Дольше по времени
Практический пример: Квантизация XGBoost
import xgboost as xgb
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
# Загружаем данные
X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
# Обучаем обычную модель
model = xgb.XGBClassifier(max_depth=5, n_estimators=100)
model.fit(X_train, y_train)
original_pred = model.predict(X_test)
original_accuracy = np.mean(original_pred == y_test)
print(f"Original accuracy: {original_accuracy:.4f}")
# Квантизируем модель (сохраняем как JSON с низкой точностью)
import json
feature_names = ['f' + str(i) for i in range(X.shape[1])]
tree_dicts = []
for i, estimator in enumerate(model.estimators_):
tree_dict = estimator.get_booster().get_dump(dump_format='json')[0]
tree_dicts.append(json.loads(tree_dict))
# Квантизируем: округляем threshold до 2 знаков
def quantize_tree(tree_dict, precision=2):
if 'children' in tree_dict:
tree_dict['threshold'] = round(tree_dict.get('threshold', 0), precision)
for child in tree_dict['children']:
quantize_tree(child, precision)
return tree_dict
quantized_trees = [quantize_tree(t) for t in tree_dicts]
# Проверяем, что предсказания остались примерно одинаковыми
quantized_pred = model.predict(X_test) # В реальности пришлось бы пересчитать
quantized_accuracy = np.mean(quantized_pred == y_test)
print(f"Quantized accuracy: {quantized_accuracy:.4f}")
print(f"Accuracy loss: {(original_accuracy - quantized_accuracy) * 100:.2f}%")
Пример: Квантизация PyTorch модели
import torch
import torch.nn as nn
from torch.quantization import quantize_dynamic
# Создаём простую модель
model = nn.Sequential(
nn.Linear(784, 256),
nn.ReLU(),
nn.Linear(256, 128),
nn.ReLU(),
nn.Linear(128, 10)
)
print(f"Original model size: {sum(p.numel() for p in model.parameters())} params")
# Динамическая квантизация (самая простая)
quantized_model = quantize_dynamic(
model,
{nn.Linear}, # квантизируем только Linear слои
dtype=torch.qint8
)
print(f"Quantized model size: {sum(p.numel() for p in quantized_model.parameters())} params")
# Сравниваем скорость
import time
X = torch.randn(1000, 784)
# Обычная модель
model.eval()
start = time.time()
with torch.no_grad():
_ = model(X)
original_time = time.time() - start
# Квантизированная модель
quantized_model.eval()
start = time.time()
with torch.no_grad():
_ = quantized_model(X)
quantized_time = time.time() - start
print(f"Original inference time: {original_time:.4f}s")
print(f"Quantized inference time: {quantized_time:.4f}s")
print(f"Speedup: {original_time / quantized_time:.2f}x")
Методы квантизации
1. Symmetric Quantization
int8_value = round(float_value * scale)
scale = 127 / max(|weights|)
2. Asymmetric Quantization
int8_value = round(float_value * scale) + zero_point
scale = 255 / (max - min)
zero_point = -min * scale
Asymmetric лучше сохраняет точность, потому что использует весь диапазон int8 (-128 до 127).
Калибровка при квантизации
import tensorflow as tf
def representative_data_gen():
"""Генерирует репрезентативные данные для калибровки"""
for _ in range(100):
yield [tf.random.normal([1, 28, 28, 1])]
converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
# Полная целочисленная квантизация
converter.target_spec.supported_ops = [
tf.lite.OpsSet.TFLITE_BUILTINS_INT8
]
converter.inference_input_type = tf.int8
converter.inference_output_type = tf.int8
# Используем калибровочные данные
converter.representative_dataset = representative_data_gen
quantized_model = converter.convert()
Где квантизация нужна?
1. На мобильных устройствах (iOS, Android)
Оригинальная модель: 100 MB
Квантизированная: 25 MB
Увеличение батареи: 20-30%
2. На edge устройствах (Raspberry Pi, NVIDIA Jetson)
Делает инференс возможным на слабых железках
Уменьшает задержку (latency)
3. На production серверах
Уменьшает использование памяти
Увеличивает throughput (больше запросов в секунду)
Снижает затраты на инфраструктуру
Потеря точности
В зависимости от типа квантизации и модели:
- 8-bit quantization: потеря 0.5-2% точности
- 4-bit quantization: потеря 2-5%
- 2-bit (binary) quantization: потеря 5-15%
Для боевых проектов:
# Проверяем потерю точности
from sklearn.metrics import accuracy_score
# Тестируем оригинальную модель
original_predictions = original_model.predict(X_test)
original_accuracy = accuracy_score(y_test, original_predictions)
# Тестируем квантизированную
quantized_predictions = quantized_model.predict(X_test)
quantized_accuracy = accuracy_score(y_test, quantized_predictions)
# Проверяем, что потеря приемлема (обычно до 2%)
assert abs(original_accuracy - quantized_accuracy) < 0.02, \
"Too much accuracy loss after quantization"
Вывод
Квантизация — это:
- Post-Training Quantization (PTQ) — быстро, просто, но меньше точности
- Quantization-Aware Training (QAT) — медленнее, но лучше сохраняет точность
- Используй калибровку на репрезентативных данных
- Проверяй потерю точности перед деплоем
- Сжатие 4x-10x с потерей точности 1-5%
Это критический шаг для production ML систем, особенно на мобильных и edge устройствах.