ai_learning/modules/10_computer_vision/notes/04_architecture_selection.md

11 KiB
Raw Blame History

Выбор архитектуры под качество, данные, latency и память

Лучшая модель — не самая глубокая, а самая дешёвая модель, которая устойчиво выполняет требования на целевом оборудовании.

Мотивация

Accuracy на исследовательском GPU не описывает production-систему. Мобильное приложение ограничено размером пакета, RAM, энергией и p95 latency; сервер — throughput и стоимостью; маленький датасет — переобучением. Выбор архитектуры является многокритериальной задачей.

Формализация требований

Пусть Q(\mathcal{M}) — качество модели, T_{95} — p95 latency, M_{\mathrm{peak}} — пиковая память, S — размер весов, C — стоимость. Практическая задача:


\max_{\mathcal{M}} Q(\mathcal{M})
\quad\text{при}\quad
T_{95}\le T_{\max},\
M_{\mathrm{peak}}\le M_{\max},\
S\le S_{\max},\
C\le C_{\max}.

Если единого порога нет, ищут Pareto frontier: модель доминируется, если другая не хуже по всем критериям и лучше хотя бы по одному.

Метрики качества

Accuracy подходит только при примерно равной цене ошибок и сбалансированных классах. Иначе используют macro-F1, ROC-AUC/PR-AUC, sensitivity при заданной specificity, calibration. Для detection — mAP, для segmentation — IoU/Dice.

Сначала фиксируют бизнес-ограничение, затем метрику и порог. Иначе архитектуру оптимизируют под удобное, но нецелевое число.

Данные определяют режим

  • Мало данных, близкий домен: небольшой предобученный backbone, frozen/partial fine-tuning.
  • Много разнообразных данных: более ёмкая модель и full fine-tuning либо обучение с нуля могут окупиться.
  • Сильный domain shift: профильное предобучение, self-supervised learning или более глубокая адаптация.
  • Шумные labels: аудит данных часто ценнее увеличения модели.
  • Высокое разрешение/мелкие объекты: стоимость растёт квадратично по линейному размеру, но ранний resize может уничтожить сигнал.

Learning curves отделяют ограничение данными от ограниченной ёмкости. Если train и validation плохи — возможен underfitting или ошибка pipeline; если train хорош, validation заметно хуже — overfitting/domain mismatch.

Глубину нельзя оценивать отдельно от масштаба сигнала. Для ReLU-слоёв He-инициализация выбирает дисперсию весов порядка 2/\mathrm{fan\_in}, чтобы дисперсии активаций и градиентов не систематически затухали по слоям. Это переносит принцип из модуля 09 на свёртки, где \mathrm{fan\_in}=C_{\mathrm{in}}K_hK_w. Хорошая инициализация облегчает обучение с нуля, но не компенсирует недостаток данных и не заменяет предобучение.

Стоимость: параметры, операции и активации

Для Conv2d приблизительное число multiply-accumulate:


\mathrm{MACs}=
H_{\mathrm{out}}W_{\mathrm{out}}
C_{\mathrm{out}}C_{\mathrm{in}}K_hK_w.

Параметров:


P=C_{\mathrm{out}}(C_{\mathrm{in}}K_hK_w+1).

Но MACs не равны latency. Depthwise convolution имеет мало операций, но на конкретном устройстве может быть ограничена memory bandwidth или плохо оптимизирована. Latency измеряют после warm-up, нужным batch size, на целевом runtime и устройстве.

Память inference включает веса, активации и workspace kernels. При обучении добавляются градиенты, optimizer states и сохранённые активации. Adam часто хранит два дополнительных момента на параметр.

Разобранный пример

Требование. Android CPU, batch 1, p95 не более 50 мс, пакет до 20 МБ, macro-F1 не ниже 0.90.

Кандидаты после одинакового fine-tuning:

  • A: F1 0.913, p95 82 мс, 18 МБ;
  • B: F1 0.905, p95 41 мс, 14 МБ;
  • C: F1 0.898, p95 25 мс, 8 МБ.

Решение. A нарушает latency, C — качество. B — единственная допустимая. Более высокая accuracy A не делает её лучшей для задачи.

Проверка. Измерение повторяют на слабейшем поддерживаемом устройстве, с реальным preprocessing и thermal throttling.

Семейства и inductive bias

  • ResNet-18/34 — понятные сильные baseline, часто удобны на сервере.
  • MobileNet/EfficientNet-lite — depthwise/inverted bottlenecks для мобильных ограничений.
  • EfficientNet — согласованное масштабирование глубины, ширины и разрешения.
  • Vision Transformer — слабее локальный CNN bias, часто требует сильного предобучения; эффективность зависит от реализации.

Название семейства не гарантирует скорость. Поддержка операторов runtime важнее теоретических FLOPs.

Практический протокол

  1. Зафиксировать split, метрику, допустимую деградацию и оборудование.
  2. Создать дешёвый baseline, например предобученную ResNet-18 или MobileNet.
  3. Проверить данные, leakage, дисбаланс и ошибки по подгруппам.
  4. Сравнить 2–3 кандидата при одинаковом training budget.
  5. Экспортировать в целевой runtime и измерить end-to-end, включая decode/resize.
  6. При необходимости применить mixed precision/quantization, pruning или distillation.
  7. Выбрать простейшую модель на допустимой части Pareto frontier.

Оптимизации после выбора baseline

  • FP16/BF16 уменьшают память и могут ускорить GPU.
  • INT8 quantization уменьшает размер и ускоряет поддерживаемое железо, но требует calibration или quantization-aware training и проверки качества.
  • Pruning полезен только если runtime эффективно использует полученную разреженность.
  • Knowledge distillation обучает компактного student имитировать soft targets teacher.
  • Batching повышает throughput, но часто ухудшает latency одного запроса.

Оптимизировать модель до корректного baseline рискованно: ошибка preprocessing не лечится quantization.

Runnable PyTorch: параметры и latency

import time
import torch
from torchvision.models import resnet18

model = resnet18(weights=None).eval()
x = torch.randn(1, 3, 224, 224)
parameters = sum(p.numel() for p in model.parameters())

with torch.inference_mode():
    for _ in range(10):           # warm-up
        model(x)
    samples = []
    for _ in range(30):
        start = time.perf_counter()
        model(x)
        samples.append((time.perf_counter() - start) * 1000)

samples.sort()
p95 = samples[int(0.95 * (len(samples) - 1))]
print("parameters:", parameters)
print("p95 milliseconds:", round(p95, 2))

На CUDA перед и после замера нужна torch.cuda.synchronize(), иначе измеряется постановка асинхронной операции в очередь. Этот микротест не включает чтение изображения и preprocessing.

Типичные ошибки и ограничения

  • Сравнивают модели на разных split или с разным tuning budget.
  • Выбирают по среднему latency вместо p95/p99.
  • Приравнивают FLOPs к реальному времени.
  • Считают только размер файла, игнорируя RAM активаций.
  • Измеряют batch 32, хотя production использует batch 1.
  • Увеличивают глубину при проблеме качества данных.

Краткое резюме

  • Выбор архитектуры — constrained multi-objective optimization.
  • Данные, метрика и целевое устройство должны быть известны до сравнения.
  • Параметры и MACs полезны, но не заменяют end-to-end benchmark.
  • Выбирают простейшую допустимую модель, а не абсолютный максимум качества.

Связанные материалы