Оптимизация производительности и скорости моделей компьютерного зрения

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

1. Прунинг нейронных сетей: удаление избыточных весов и фильтров

Прунинг нейронных сетей: удаление избыточных весов и фильтров

На предыдущих этапах нашего курса мы разобрали архитектуры детекции объектов, такие как YOLO и Faster R-CNN, и научились обучать их на собственных данных. Вы получили точную модель, которая отлично находит объекты на тестовых изображениях. Однако при попытке запустить эту модель на мобильном телефоне, дроне или камере видеонаблюдения вы, скорее всего, столкнетесь с проблемой: алгоритм работает слишком медленно и потребляет слишком много оперативной памяти.

Современные сверточные нейронные сети содержат десятки и сотни миллионов параметров. Для работы в реальном времени (что критично для автопилотов и систем безопасности) модель должна быть не только точной, но и легкой. Здесь на помощь приходит прунинг (pruning) — один из самых эффективных методов оптимизации производительности.

Что такое прунинг и зачем он нужен

В переводе с английского pruning означает «обрезка ветвей». В биологии существует понятие синаптического прунинга: по мере взросления мозг человека удаляет редко используемые нейронные связи, делая работу нервной системы более эффективной.

В контексте глубокого обучения прунинг — это процесс принудительного удаления части параметров (весов) обученной нейронной сети, которые вносят наименьший вклад в итоговый результат.

> Прунинг базируется на гипотезе о том, что нейронные сети сильно перепараметризованы. Это означает, что для решения задачи им требуется гораздо меньше весов, чем заложено в их изначальной архитектуре.

Давайте рассмотрим пример с числами. Допустим, ваша модель YOLOv4 имеет около 60 миллионов параметров. Каждый параметр — это число с плавающей точкой (обычно формата FP32), занимающее 4 байта памяти.

Размер модели = 60 000 000 × 4 байта = 240 мегабайт.

Если мы сможем без потери точности удалить 50% наименее важных параметров, размер модели уменьшится до 120 мегабайт, а количество математических операций при инференсе (предсказании) сократится, что потенциально ускорит работу алгоритма.

Неструктурированный прунинг: точечная обрезка

Самый базовый подход называется неструктурированным прунингом (unstructured pruning). При этом методе мы рассматриваем каждый отдельный вес в сети независимо от остальных.

Как понять, какой вес важен, а какой нет? Самый популярный критерий — абсолютное значение веса (его магнитуда). Если вес близок к нулю, значит, сигнал, проходящий через это соединение, умножается на очень маленькое число и почти не влияет на активацию следующего нейрона.

Математически это записывается через пороговое значение :

Где: * — новое значение веса после прунинга; * — исходное значение веса; * — абсолютное значение (модуль) веса; * — заданный порог отсечения.

Пример из практики: Представьте слой нейронной сети, содержащий 10 000 весов. Мы сортируем все веса по их абсолютному значению и решаем удалить 30% наименьших. Мы находим значение веса, которое находится на 30-м процентиле (например, это число 0,0015). Мы устанавливаем порог . Все веса в слое, модуль которых меньше 0,0015, приравниваются к нулю.

Проблема аппаратного ускорения

Неструктурированный прунинг позволяет убрать до 80-90% весов сети почти без потери точности. Матрицы весов становятся разреженными (состоят в основном из нулей).

Однако здесь кроется главный подвох: стандартные графические процессоры (GPU) не умеют эффективно пропускать нули при умножении плотных матриц. Видеокарта все равно выполнит операцию , потратив на это такт процессора и электроэнергию. Чтобы получить реальное ускорение от неструктурированного прунинга, требуются специализированные аппаратные ускорители или сложные форматы хранения разреженных матриц, которые не всегда поддерживаются мобильными устройствами.

Структурированный прунинг: удаление фильтров

Чтобы получить реальное ускорение на любом оборудовании, в компьютерном зрении применяется структурированный прунинг (structured pruning). Вместо удаления отдельных связей мы удаляем целые структурные блоки: нейроны, каналы или сверточные фильтры.

В сверточных нейронных сетях (CNN), на которых базируются детекторы объектов, основным строительным блоком является фильтр. Каждый фильтр отвечает за поиск определенного паттерна на изображении (например, вертикальной линии или текстуры шерсти).

!Сравнение неструктурированного и структурированного прунинга

Если мы удалим целый фильтр, мы физически уменьшим размер матрицы весов.

Пример с числами: Допустим, у нас есть сверточный слой, который принимает на вход 64 канала и применяет 128 фильтров размером 3×3. Размер тензора весов этого слоя: параметров.

Если мы с помощью структурированного прунинга удалим 32 наименее важных фильтра, в слое останется 96 фильтров. Новый размер тензора: параметров.

Матрица стала физически меньше. Любой процессор выполнит умножение меньшей матрицы быстрее. Мы получили реальное ускорение инференса.

Как выбрать фильтр для удаления?

Для оценки важности целого фильтра чаще всего используют -норму (сумму абсолютных значений всех его весов).

Формула оценки важности -го фильтра:

Где: * — итоговая оценка важности фильтра (score); * — общее количество весов внутри одного фильтра; * — конкретный вес с индексом внутри фильтра ; * — абсолютное значение этого веса.

Если сумма модулей всех весов фильтра мала, это означает, что фильтр генерирует очень слабые карты признаков (feature maps), которые почти не влияют на итоговую детекцию объекта. Такой фильтр можно смело удалять.

| Характеристика | Неструктурированный прунинг | Структурированный прунинг | | :--- | :--- | :--- | | Что удаляется | Отдельные веса (числа) | Целые фильтры или каналы | | Вид матрицы | Разреженная (много нулей) | Плотная, но меньшего размера | | Степень сжатия | Очень высокая (до 90-95%) | Средняя (обычно 30-50%) | | Ускорение на GPU | Требует спец. библиотек | Работает «из коробки» | | Падение точности | Минимальное | Более заметное, требует аккуратности |

Итеративный процесс прунинга

Нельзя просто взять обученную модель YOLO, отрезать от нее половину фильтров и ожидать, что она продолжит хорошо находить объекты. Удаление большой части архитектуры вызывает шок у модели, и ее точность (например, метрика mAP) резко падает.

Поэтому в индустрии применяется итеративный прунинг — пошаговый процесс с дообучением (fine-tuning).

  • Обучение базовой модели: Сначала мы обучаем полную, большую модель на нашем датасете до максимальной точности.
  • Оценка важности: Алгоритм рассчитывает -норму для всех фильтров сети.
  • Обрезка (Pruning): Мы удаляем небольшую часть самых «слабых» фильтров (например, 10-15%). Точность модели при этом немного снижается.
  • Дообучение (Fine-tuning): Мы снова запускаем процесс обучения обрезанной модели на несколько эпох с небольшим шагом обучения (learning rate). Оставшиеся веса адаптируются, чтобы компенсировать отсутствие удаленных фильтров. Точность восстанавливается.
  • Повторение: Шаги 2-4 повторяются несколько раз, пока мы не достигнем нужного баланса между скоростью работы и точностью детекции.
  • Этот процесс можно сравнить с реабилитацией после травмы: мы убираем часть системы, даем организму время перестроить нейронные связи для компенсации потери, а затем повторяем процедуру.

    Гипотеза лотерейного билета

    Говоря о прунинге, нельзя не упомянуть знаменитую «Гипотезу лотерейного билета» (Lottery Ticket Hypothesis), предложенную исследователями из MIT в 2018 году.

    Она гласит: внутри любой большой, случайно инициализированной нейронной сети существует небольшая подсеть («выигрышный билет»), которая при обучении с нуля способна достичь той же точности, что и исходная большая сеть, за то же количество итераций.

    Проблема в том, что мы не можем найти этот «выигрышный билет» до начала обучения. Нам приходится создавать огромную сеть (покупать миллионы лотерейных билетов), обучать ее, находить те связи, которые реально выполнили работу (выигрышный билет), а затем с помощью прунинга выбрасывать все остальные (проигрышные билеты).

    Внедрение прунинга в ваш пайплайн разработки моделей компьютерного зрения — это обязательный шаг перед релизом продукта. Удалив избыточные фильтры из архитектур вроде YOLO или SSD, вы сможете запускать детекцию объектов в реальном времени даже на слабых процессорах, экономя заряд батареи и вычислительные ресурсы.

    2. Квантование моделей: снижение разрядности вычислений от FP32 до INT8

    Квантование моделей: снижение разрядности вычислений от FP32 до INT8

    На предыдущем этапе оптимизации мы разобрали прунинг — физическое удаление избыточных весов и фильтров из архитектуры нейронной сети. Модель стала меньше, но оставшиеся параметры по-прежнему хранятся в формате высокой точности. Чтобы добиться максимальной скорости работы детектора объектов на мобильных устройствах или краевых вычислениях (edge devices), нам необходимо изменить сам формат представления чисел.

    Этот процесс называется квантованием (quantization). Он позволяет радикально снизить потребление памяти и ускорить математические операции почти без потери качества детекции.

    Проблема избыточной точности

    По умолчанию фреймворки глубокого обучения (PyTorch, TensorFlow) обучают модели и хранят их веса в формате FP32 — 32-битных числах с плавающей точкой (Single-Precision Floating-Point).

    Формат FP32 позволяет хранить числа с огромной точностью, вплоть до седьмого знака после запятой (например, ). Для научных симуляций или расчета траектории космического аппарата такая точность критически важна. Но нейронные сети обладают удивительным свойством: они крайне устойчивы к шуму и небольшим искажениям весов.

    Для того чтобы модель YOLO поняла, что перед ней находится автомобиль, ей не нужно знать, что вес конкретного нейрона равен . Ей вполне достаточно округленного значения .

    > Квантование — это процесс преобразования непрерывных значений (или значений высокой точности, таких как FP32) в дискретный набор значений более низкой точности, чаще всего в 8-битные целые числа (INT8).

    Переход от 32 бит к 8 битам дает два колоссальных преимущества:

  • Сжатие памяти в 4 раза. Каждый параметр теперь занимает 1 байт вместо 4 байт. Модель размером 200 МБ мгновенно «худеет» до 50 МБ, что позволяет загрузить ее в кэш процессора, минуя медленную оперативную память.
  • Ускорение вычислений. Процессоры выполняют целочисленные операции (сложение и умножение INT8) значительно быстрее и с меньшими затратами энергии, чем операции с плавающей точкой.
  • Пример из жизни: Представьте, что вы работаете кассиром. Формат FP32 — это расчеты, где цены указаны с точностью до сотых долей копейки (154 рубля 33,45 копейки). Вам нужно складывать эти числа в уме. Формат INT8 — это округление всех цен до целых рублей (154 рубля). Вы посчитаете итоговую сумму в несколько раз быстрее, а итоговый чек будет отличаться лишь на незначительную долю процента.

    Математика квантования: Scale и Zero-point

    Главная задача квантования — отобразить диапазон дробных чисел (весов или активаций сети) в ограниченный диапазон целых чисел. Для формата INT8 со знаком этот диапазон составляет от до (всего 256 значений).

    Для этого используется линейное (аффинное) преобразование. Формула перевода числа из формата FP32 в INT8 выглядит так:

    Где: * — итоговое квантованное целое число (INT8); * — исходное вещественное число (FP32); (Scale*) — масштабный множитель, шаг квантования; (Zero-point*) — нулевая точка, целое число, которое соответствует вещественному нулю; * — математическая операция округления до ближайшего целого.

    !Схема линейного квантования: отображение непрерывного диапазона в дискретные шаги

    Как вычисляются Scale и Zero-point

    Чтобы найти и , нам нужно знать минимальное () и максимальное () значения в тензоре весов конкретного слоя нейронной сети.

    Шаг квантования рассчитывается путем деления длины исходного диапазона на длину целевого диапазона:

    Для INT8 целевой диапазон равен .

    Нулевая точка гарантирует, что реальный ноль () будет точно представлен целым числом. Это критически важно для сверточных сетей, так как операции padding (добавление нулей по краям изображения) не должны вносить искажения в вычисления.

    Практический расчет: Допустим, мы проанализировали веса одного сверточного слоя YOLO. Самый маленький вес , а самый большой .

  • Вычисляем масштаб:
  • Вычисляем нулевую точку (упрощенно):
  • Теперь квантуем конкретный вес, например, : .

    Так как 160 выходит за пределы , в реальности используются беззнаковые целые числа (UINT8) с диапазоном , либо диапазоны сдвигаются. Главное — мы превратили дробное число в целое число , сохранив пропорции относительно других весов.

    Два подхода к квантованию на практике

    Перевод модели в INT8 неизбежно вносит ошибку округления. Если просто округлить все веса, точность детекции (метрика mAP) может катастрофически упасть. Чтобы этого избежать, инженеры используют два основных метода.

    1. Post-Training Quantization (PTQ)

    Квантование после обучения — самый быстрый и популярный метод. Вы берете уже полностью обученную модель (например, в формате .pt или .onnx) и конвертируете ее.

    Чтобы правильно вычислить параметры и для активаций (выходов каждого слоя), алгоритму нужно знать, какие значения там появляются. Для этого используется процесс калибрации:

  • Через обученную FP32 модель пропускают небольшой набор репрезентативных данных (например, 100-500 картинок из обучающего датасета).
  • Алгоритм собирает статистику: фиксирует и на выходе каждого слоя.
  • На основе этой статистики рассчитываются и , после чего модель конвертируется в INT8.
  • PTQ занимает несколько минут и не требует видеокарт для переобучения. Однако для сложных архитектур детекции падение точности может составить 2-5% mAP, что иногда неприемлемо.

    2. Quantization-Aware Training (QAT)

    Обучение с учетом квантования — более сложный, но эффективный метод. Идея в том, чтобы заставить нейронную сеть адаптироваться к ошибкам округления еще на этапе обучения.

    В граф вычислений добавляются специальные узлы «фейкового квантования» (Fake Quantization). Во время прямого прохода (forward pass) веса и активации округляются до INT8, а затем сразу переводятся обратно в FP32.

    Сеть «чувствует» боль от потери точности и в процессе обратного распространения ошибки (backpropagation) корректирует свои веса так, чтобы минимизировать влияние этого округления.

    | Характеристика | PTQ (Post-Training) | QAT (Quantization-Aware) | | :--- | :--- | :--- | | Время выполнения | Минуты | Часы / Дни (требует обучения) | | Сложность внедрения | Низкая (пара строк кода) | Высокая (изменение пайплайна) | | Требования к данным | 100-500 изображений | Полный обучающий датасет | | Падение точности | Заметное (1-5%) | Минимальное (< 1%) |

    Аппаратное ускорение: почему INT8 работает быстрее

    Снижение разрядности имеет смысл только в том случае, если ваше «железо» умеет с ним работать.

    Современные мобильные процессоры (Apple Neural Engine, Qualcomm Hexagon) и специализированные ускорители (Google Coral Edge TPU) физически спроектированы для матричного умножения в формате INT8. Они содержат тысячи крошечных АЛУ (арифметико-логических устройств), которые за один такт процессора могут перемножить десятки 8-битных чисел.

    Более того, узким местом при инференсе больших моделей часто является не процессор, а пропускная способность памяти (Memory Bandwidth). Процессор простаивает, ожидая, пока данные загрузятся из RAM. Поскольку INT8-модель весит в 4 раза меньше, данные передаются по шине памяти в 4 раза быстрее, устраняя этот «бутылочный горлышко».

    Внедрение квантования — это финальный штрих в подготовке модели к продакшену. В связке с прунингом оно позволяет запускать тяжеловесные архитектуры вроде YOLOv8 на обычных смартфонах или камерах видеонаблюдения с частотой 30+ кадров в секунду.

    3. Дистилляция знаний: передача опыта от тяжелой модели к компактной

    Дистилляция знаний: передача опыта от тяжелой модели к компактной

    На предыдущих этапах оптимизации мы разобрали методы физического и математического сжатия нейронных сетей. Прунинг позволил нам удалить «лишние» нейроны и фильтры, а квантование — перевести вычисления из тяжеловесного формата FP32 в быстрый INT8. В результате мы получили компактную и быструю архитектуру, идеально подходящую для мобильных устройств и краевых вычислений.

    Однако возникает новая проблема: если взять эту маленькую, урезанную архитектуру (например, YOLOv8 Nano) и обучить ее с нуля на стандартном датасете, ее точность детекции будет значительно ниже, чем у большой версии (YOLOv8 Extra Large). Маленькой сети просто не хватает параметров (емкости), чтобы выучить все сложные закономерности визуального мира.

    Здесь на помощь приходит дистилляция знаний (Knowledge Distillation, KD) — элегантный метод машинного обучения, который позволяет передать «опыт» от большой и точной модели к маленькой и быстрой.

    Концепция Учителя и Ученика

    Метод дистилляции строится на понятной жизненной аналогии. Представьте университетского профессора и студента-первокурсника.

    Профессор обладает огромным багажом знаний, он прочитал тысячи книг и понимает тончайшие взаимосвязи между предметами. Студент не может прочитать все эти книги за один семестр (у него не хватает «емкости памяти»). Но если профессор будет не просто давать студенту сухие факты, а объяснять логику, приводить примеры и показывать скрытые связи, студент усвоит материал гораздо быстрее и глубже, чем если бы учился по учебникам самостоятельно.

    В компьютерном зрении роли распределяются так: Модель-Учитель (Teacher Model*) — тяжелая, глубокая нейронная сеть с высокой точностью. Она обучается долго, требует мощных GPU и не подходит для работы в реальном времени на слабых устройствах. Модель-Ученик (Student Model*) — компактная, легкая сеть. Наша цель — сделать так, чтобы Ученик работал так же быстро, как обычно, но выдавал точность, близкую к Учителю.

    !Архитектура дистилляции знаний: процесс передачи информации от большой модели-учителя к компактной модели-ученику.

    Темные знания: почему Учитель учит лучше датасета

    Как обычно обучается нейронная сеть для классификации или детекции? Мы показываем ей картинку и даем правильный ответ из разметки датасета. Этот правильный ответ называется жесткой меткой (Hard Target).

    Жесткая метка представляет собой вектор, где правильный класс равен 1, а все остальные — 0 (так называемое One-Hot Encoding).

    Например, если на фото изображена собака, жесткая метка выглядит так: * Собака: 1.0 (100%) * Кошка: 0.0 (0%) * Автомобиль: 0.0 (0%)

    Проблема жестких меток в том, что они скрывают информацию о сходстве объектов. Для сети ошибка «перепутать собаку с кошкой» математически равна ошибке «перепутать собаку с автомобилем».

    Но обученная Модель-Учитель видит мир иначе. Когда Учитель смотрит на фото собаки, он выдает не абсолютные нули и единицы, а распределение вероятностей — мягкие метки (Soft Targets): * Собака: 0.85 (85%) * Кошка: 0.14 (14%) * Автомобиль: 0.01 (1%)

    > Темные знания (Dark Knowledge) — это скрытая информация в предсказаниях обученной модели, показывающая взаимосвязи между классами. Тот факт, что собака визуально на 14% похожа на кошку и только на 1% на автомобиль, несет огромную обучающую ценность.

    Обучая Ученика предсказывать не жесткие нули и единицы из датасета, а повторять эти дробные вероятности за Учителем, мы передаем ему понимание структуры данных.

    | Характеристика | Жесткие метки (Hard Targets) | Мягкие метки (Soft Targets) | | :--- | :--- | :--- | | Источник | Разметка человека (датасет) | Предсказания Модели-Учителя | | Формат | Только 1 и 0 | Дробные вероятности (от 0.0 до 1.0) | | Информативность | Низкая (только факт принадлежности) | Высокая (показывает сходство классов) | | Сложность обучения | Требует большой емкости сети | Позволяет обучить компактную сеть |

    Математика дистилляции: Температура Softmax

    Чтобы получить вероятности классов, нейронные сети используют функцию активации Softmax на самом последнем слое. Softmax берет сырые числа, которые выдает сеть (они называются логитами, logits), и превращает их в вероятности, сумма которых равна 1.

    В классической дистилляции знаний, предложенной Джеффри Хинтоном, в функцию Softmax добавляется специальный параметр — Температура ().

    Формула Softmax с температурой выглядит так:

    Где: * — итоговая вероятность для класса ; * — логит (сырое предсказание сети) для класса ; * — параметр температуры (число больше или равное 1); * — экспоненциальная функция; * — сумма по всем возможным классам.

    Как работает Температура

    При стандартном обучении . Функция Softmax очень «агрессивна»: она берет самый большой логит и делает его вероятность близкой к 100%, а остальные логиты превращает в значения, близкие к нулю (например, ). Из-за этого «темные знания» теряются, так как вероятности неправильных классов становятся слишком маленькими для эффективного обучения.

    Когда мы искусственно повышаем температуру (например, или ), мы заставляем Softmax работать мягче. Распределение вероятностей сглаживается.

    Пример с числами: Допустим, логиты сети для трех классов (Собака, Кошка, Автомобиль) равны: . * При вероятности будут: . Собака доминирует, остальные классы почти не видны. * При логиты делятся на 5, становясь . После Softmax вероятности станут: .

    Теперь Ученик четко видит, что Кошка — это второй по вероятности вариант, и может учиться на этой информации.

    !Интерактивный калькулятор Softmax с температурой — наглядно показывает, как параметр T 'размывает' вероятности, выявляя скрытые знания модели.

    Как происходит процесс обучения

    Обучение Ученика с помощью дистилляции — это балансирование между двумя целями. Ученик должен одновременно слушать Учителя и смотреть в учебник (датасет).

    Для этого используется комбинированная функция потерь (Loss Function), которая состоит из двух частей:

  • Distillation Loss (Потеря дистилляции): Измеряет разницу между мягкими метками Учителя и предсказаниями Ученика (оба используют одинаковую высокую температуру ). Это заставляет Ученика копировать логику Учителя.
  • Student Loss (Стандартная потеря): Измеряет разницу между предсказаниями Ученика (при стандартной температуре ) и настоящими жесткими метками из датасета. Это гарантирует, что Ученик все еще учится предсказывать правильный класс.
  • Итоговая формула потерь выглядит как взвешенная сумма:

    Где — это коэффициент (от 0 до 1), который определяет, кому Ученик должен доверять больше: Учителю или датасету. На практике часто устанавливают высоким (например, или ), отдавая приоритет знаниям Учителя.

    Дистилляция в задачах детекции объектов

    В задачах классификации изображений дистилляция работает прямолинейно, так как сеть выдает только один вектор вероятностей. Но в детекции объектов (например, в архитектурах YOLO или SSD) задача сложнее. Модель должна не только распознать класс, но и предсказать координаты ограничивающей рамки (bounding box).

    Поэтому для детекции применяются продвинутые методы дистилляции:

    Дистилляция признаков (Feature-based KD): Ученика заставляют копировать не только финальный ответ, но и промежуточные карты признаков (feature maps*) Учителя. Грубо говоря, Ученик учится «смотреть» на те же участки изображения, на которые обращает внимание Учитель (копирует карты внимания). * Дистилляция локализации: Учитель передает Ученику свои предсказания координат рамок. Даже если рамка Учителя немного неточная, она служит отличным ориентиром для Ученика на ранних этапах обучения.

    Место дистилляции в пайплайне оптимизации

    Дистилляция знаний — это мощный инструмент, который идеально дополняет другие методы оптимизации. Классический пайплайн подготовки модели к продакшену выглядит так:

  • Обучение огромной, максимально точной модели (Учитель).
  • Создание компактной архитектуры (Ученик) — либо проектирование с нуля, либо получение путем прунинга Учителя.
  • Обучение Ученика с использованием дистилляции знаний от Учителя.
  • Квантование обученного Ученика в формат INT8 для финального ускорения на устройстве.
  • Используя этот подход, инженеры компьютерного зрения умудряются запускать сложные детекторы объектов на смартфонах, дронах и камерах видеонаблюдения, сохраняя точность, которая еще несколько лет назад была доступна только на серверных видеокартах.

    4. Ускорение инференса с помощью графовых оптимизаций в ONNX и TensorRT

    Ускорение инференса с помощью графовых оптимизаций в ONNX и TensorRT

    На предыдущих этапах мы разобрали методы изменения самой архитектуры и математики нейронной сети. Прунинг позволил удалить лишние веса, квантование снизило разрядность чисел, а дистилляция передала знания от тяжелой модели к легкой. В результате мы получили компактную и точную модель детекции объектов.

    Однако остается последний барьер перед запуском модели в продакшен (например, на камере беспилотного автомобиля или сервере видеонаблюдения). Этот барьер — среда выполнения. Фреймворки вроде PyTorch или TensorFlow созданы для удобного обучения, но они катастрофически неэффективны для инференса (процесса предсказания на новых данных). Чтобы выжать максимум скорости из железа, применяются графовые оптимизации и специализированные движки, такие как ONNX и TensorRT.

    Анатомия вычислительного графа

    Любая нейронная сеть под капотом представляет собой вычислительный граф (Computational Graph). Это математическая структура, состоящая из узлов и ребер: * Узлы (Nodes): Математические операции (свертка, сложение, умножение матриц, функции активации). * Ребра (Edges): Данные, которые передаются от одной операции к другой в виде многомерных массивов — тензоров.

    Когда мы пишем код в PyTorch, фреймворк строит этот граф динамически при каждом проходе данных. Это невероятно удобно для исследователя: можно на лету менять архитектуру, ставить условия if/else и выводить промежуточные значения на экран.

    Но для видеокарты (GPU) динамический граф — это кошмар. Процессор тратит драгоценное время на то, чтобы понять, какую операцию запускать следующей, вместо того чтобы просто считать математику.

    > Динамический граф в PyTorch похож на приготовление блюда, когда повар читает рецепт по одной строчке, каждый раз бегая в кладовку за новым ингредиентом. Оптимизированный статический граф — это конвейерная лента, где все ингредиенты заранее нарезаны и подаются строго в нужный момент.

    ONNX: Универсальный язык нейросетей

    Чтобы оторвать модель от тяжеловесного PyTorch и превратить ее в статический граф, был создан формат ONNX (Open Neural Network Exchange). Это открытый стандарт, который позволяет сохранять обученные модели в универсальном виде.

    Перевод модели в ONNX дает два главных преимущества:

  • Кроссплатформенность: Модель, обученную в PyTorch, можно запустить на C++, Java или JavaScript без установки самого PyTorch.
  • Базовые графовые оптимизации: При экспорте ONNX автоматически анализирует граф и упрощает его.
  • Процесс экспорта модели детекции (например, YOLO) выглядит как простая функция:

    Свертка констант (Constant Folding)

    Первая базовая оптимизация, которую делает ONNX — это свертка констант. Если в графе есть операции, результат которых зависит только от фиксированных весов (и не зависит от входной картинки), ONNX вычисляет их один раз на этапе конвертации и заменяет узлы на готовое число.

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

    Слияние операторов: Магия объединения узлов

    Самая мощная графовая оптимизация — это слияние операторов (Operator Fusion).

    В современных сверточных сетях (CNN) слои почти всегда идут стандартными блоками. Самый частый паттерн:

  • Conv (Свертка) — ищет визуальные признаки.
  • BatchNorm (Пакетная нормализация) — стабилизирует числа.
  • ReLU (Функция активации) — добавляет нелинейность.
  • В неоптимизированном графе это три отдельных узла. Видеокарта должна загрузить данные из памяти, выполнить свертку, сохранить результат в память. Затем снова загрузить его, выполнить нормализацию, сохранить. И так далее. Чтение и запись в память GPU (VRAM) — самый медленный процесс, он занимает больше времени, чем сами вычисления.

    !Схема слияния операторов в вычислительном графе нейронной сети.

    Оптимизатор объединяет эти три шага в один математический мега-узел. Особенно элегантно происходит слияние свертки и пакетной нормализации (Conv + BN).

    Во время инференса пакетная нормализация — это просто линейное преобразование (умножение на одно число и прибавление другого). Математически мы можем заранее изменить веса самой свертки так, чтобы она сразу выдавала нормализованный результат.

    Формула пересчета новых весов свертки выглядит так:

    Где: * и — новые веса и смещение объединенного слоя; * и — оригинальные веса и смещение слоя свертки; * (масштаб), (сдвиг), (среднее) и (дисперсия) — обученные параметры слоя BatchNorm.

    Благодаря этой формуле узел BatchNorm полностью удаляется из графа. Сеть становится меньше в размере и работает быстрее, при этом выдавая математически идентичный результат. Если отдельное выполнение Conv, BN и ReLU занимало 4 миллисекунды, то объединенный узел может выполниться за 2.2 миллисекунды, экономя почти половину времени.

    TensorRT: Экстремальное ускорение на GPU

    ONNX делает граф чистым и логичным. Но ONNX не знает, на какой именно видеокарте будет запускаться модель. Здесь в игру вступает TensorRT — специализированный движок инференса от компании NVIDIA.

    TensorRT берет ONNX-модель и компилирует ее под конкретную архитектуру GPU (например, под RTX 4090 для сервера или под Jetson Orin для дрона).

    | Характеристика | PyTorch | ONNX | TensorRT | | :--- | :--- | :--- | :--- | | Главная цель | Обучение и исследования | Кроссплатформенный обмен | Максимальная скорость инференса | | Тип графа | Динамический | Статический | Статический, аппаратно-зависимый | | Привязка к железу | Нет | Нет | Да (компилируется под конкретный GPU) | | Скорость работы | Низкая | Средняя | Экстремально высокая |

    Автоматическая настройка ядер (Kernel Auto-Tuning)

    Видеокарта состоит из тысяч маленьких процессоров (CUDA-ядер). Для выполнения одной и той же операции (например, умножения матриц) существует несколько десятков различных алгоритмов на уровне железа. Какой из них сработает быстрее, зависит от размера матриц и архитектуры конкретного чипа.

    TensorRT проводит процесс профилирования: он берет вашу модель, прогоняет фиктивные данные через каждый слой, пробуя все доступные алгоритмы (ядра), и замеряет время. Для слоя A он может выбрать алгоритм Winograd, а для слоя B — алгоритм GEMM. В итоге собирается уникальный «движок» (engine), который идеально ложится на транзисторы вашей видеокарты.

    Динамическое управление памятью

    При стандартном выполнении каждый тензор (промежуточный результат между слоями) требует выделения памяти. TensorRT анализирует жизненный цикл всех тензоров в графе. Если тензор X использовался на первом слое и больше не нужен, TensorRT не будет очищать память, а просто перезапишет поверх него тензор Y с пятого слоя. Это называется переиспользованием памяти (Memory Aliasing).

    Такой подход критически важен для моделей детекции объектов высокого разрешения. Обработка 4K-видео в реальном времени требует огромной пропускной способности памяти, и минимизация операций выделения/очистки памяти спасает систему от зависаний.

    Внедрение графовых оптимизаций ONNX и компиляция через TensorRT — это финальный аккорд в пайплайне подготовки модели. В сочетании с квантованием до INT8, TensorRT способен ускорить инференс тяжелой модели YOLO в 5–10 раз по сравнению с базовым кодом на PyTorch, делая возможным создание надежных систем автономного вождения и видеоаналитики реального времени.

    5. Аппаратная оптимизация: адаптация моделей детекции для работы на Edge-устройствах

    Аппаратная оптимизация: адаптация моделей детекции для работы на Edge-устройствах

    На предыдущих этапах мы проделали колоссальную работу над самой нейронной сетью. Мы удалили лишние связи с помощью прунинга, сжали веса до 8-битных целых чисел через квантование и превратили динамический код в монолитный статический граф с помощью ONNX и TensorRT. Модель стала легкой и невероятно быстрой.

    Однако до сих пор мы неявно предполагали, что наша модель будет работать на мощном сервере с видеокартой размером с кирпич и блоком питания на 1000 Ватт. В реальном мире компьютерное зрение чаще всего нужно там, где нет ни розеток, ни кондиционеров: на борту летящего дрона, в умной камере на перекрестке или в смартфоне. Перенос моделей в такие суровые условия требует понимания аппаратной оптимизации и концепции Edge Computing.

    Парадигма Edge Computing: почему облака недостаточно

    Edge Computing (граничные вычисления) — это архитектурный подход, при котором обработка данных происходит прямо на устройстве, которое эти данные собирает, а не на удаленном сервере в дата-центре. Устройство, выполняющее вычисления на «краю» сети, называется Edge-устройством.

    Исторически разработчики шли по простому пути: камера снимает видео, отправляет его по Wi-Fi или 4G на мощный облачный сервер, сервер прогоняет тяжелую модель YOLO и возвращает обратно координаты найденных объектов.

    Почему этот подход больше не работает для современных задач?

  • Задержка сети (Latency): Передача видео в облако и ожидание ответа занимает от 100 до 500 миллисекунд. Для беспилотного автомобиля, движущегося со скоростью 100 км/ч, задержка в полсекунды означает, что машина проедет 14 метров вслепую. Это недопустимо.
  • Пропускная способность: Потоковая передача 4K-видео с десятков камер видеонаблюдения мгновенно перегрузит любую локальную сеть.
  • Приватность и безопасность: Отправка видео из умного дома или медицинской палаты на сторонние серверы создает огромные риски утечки личных данных.
  • Автономность: Сельскохозяйственный дрон, инспектирующий посевы в поле, может вообще не иметь доступа к интернету.
  • !Схема архитектуры: Облачные вычисления против Edge-устройств

    Перенос инференса (процесса предсказания) прямо на камеру решает все эти проблемы. Модель работает локально, анализирует кадры за миллисекунды и отправляет в сеть только текстовый результат: «Обнаружен пешеход, координаты X, Y», что занимает байты, а не мегабайты.

    Анатомия аппаратных ускорителей: NPU и TPU

    Запуск нейросети на смартфоне или камере сталкивается с жестким физическим ограничением: батареей. Обычный центральный процессор (CPU) универсален, он умеет делать всё, но делает это крайне неэффективно с точки зрения затрат энергии. Графический процессор (GPU) отлично справляется с параллельными вычислениями, но потребляет слишком много электричества.

    Чтобы решить эту проблему, инженеры создали специализированные чипы: NPU (Neural Processing Unit) и TPU (Tensor Processing Unit).

    В отличие от CPU, который постоянно читает инструкции из памяти, NPU спроектирован аппаратно под одну конкретную задачу — умножение огромных матриц. В основе таких чипов лежит архитектура систолических массивов (Systolic Arrays).

    > Систолический массив работает как конвейер на заводе. Данные загружаются в чип один раз и протекают через сетку вычислительных блоков, передавая промежуточные результаты от соседа к соседу. Процессору не нужно каждую микросекунду обращаться к оперативной памяти, что экономит до 90% энергии.

    Яркий пример из жизни: технология FaceID в смартфонах Apple работает мгновенно и не разряжает батарею именно потому, что за распознавание лица отвечает не основной процессор, а выделенный аппаратный блок Neural Engine (фирменное название NPU от Apple).

    Энергоэффективность и тепловой пакет (TDP)

    При выборе Edge-устройства для продакшена инженеры смотрят не на чистую производительность, а на энергоэффективность. Главная метрика в мире аппаратного ускорения нейросетей — это TOPS/W (Tera Operations Per Second per Watt), то есть количество триллионов операций в секунду, выполняемых на один затраченный Ватт энергии.

    Формула энергоэффективности выглядит так:

    Где: * — энергоэффективность (TOPS/W); * — пиковая производительность чипа (TOPS); * — потребляемая мощность (Ватт).

    Если чип выдает 4 TOPS и потребляет 2 Вт, его эффективность равна 2 TOPS/W. Чем выше этот показатель, тем дольше проработает устройство от батареи.

    С потреблением энергии неразрывно связано выделение тепла. У Edge-устройств (например, у камер видеонаблюдения) обычно нет активного охлаждения — вентиляторы ломаются от пыли и влаги. Охлаждение происходит только за счет металлического корпуса (радиатора).

    Если модель слишком тяжелая, чип начинает выделять больше тепла, чем корпус может рассеять. Температура растет. Чтобы не сгореть, процессор включает термальный троттлинг (Thermal Throttling) — принудительно снижает свою тактовую частоту.

    На практике это выглядит катастрофически: дрон взлетает, первые 5 минут модель детекции выдает стабильные 30 кадров в секунду (FPS). Затем чип перегревается на солнце, включается троттлинг, и FPS падает до 5 кадров в секунду. Дрон теряет способность быстро реагировать на препятствия и врезается в дерево.

    Синергия методов: от PyTorch до кремния

    Именно из-за жестких ограничений по теплу и батарее все методы оптимизации, которые мы изучили ранее, становятся не просто «желательными», а строго обязательными для Edge-устройств.

    Давайте сравним серверную видеокарту и популярный Edge-ускоритель Google Coral TPU:

    | Характеристика | Сервер (NVIDIA RTX 4090) | Edge (Google Coral TPU) | | :--- | :--- | :--- | | Потребление энергии | 450 Вт | 2 Вт | | Охлаждение | 3 огромных вентилятора | Пассивное (без вентилятора) | | Поддерживаемая математика | FP32, FP16, INT8 | Только INT8 | | Объем памяти | 24 ГБ | 8 МБ (внутренняя SRAM) |

    Обратите внимание на две последние строки. Edge-ускорители физически не умеют работать с дробными числами (FP32). Если вы попытаетесь запустить на Coral TPU модель без предварительного квантования до INT8, чип просто передаст вычисления на слабый центральный процессор, и модель будет работать со скоростью 1 кадр в секунду.

    Кроме того, объем сверхбыстрой памяти на самом чипе крайне мал (всего несколько мегабайт). Если веса модели не помещаются в этот объем, чипу придется постоянно гонять данные из внешней оперативной памяти, что убьет всю энергоэффективность. Здесь на помощь приходит прунинг и дистилляция знаний, которые физически уменьшают размер файла модели с 50 МБ до 3-4 МБ.

    Пайплайн подготовки модели к продакшену на Edge-устройстве выглядит так:

  • Обучение тяжелой модели YOLO на сервере (PyTorch).
  • Дистилляция знаний в компактную версию YOLO-Nano.
  • Прунинг (удаление 30% наименее важных фильтров).
  • Квантование весов и активаций из FP32 в INT8.
  • Экспорт в статический граф и компиляция под конкретный чип (например, через формат TensorFlow Lite для TPU или TensorRT для NVIDIA Jetson).
  • Только пройдя все эти шаги, алгоритм компьютерного зрения превращается из неповоротливого исследовательского кода в стремительный, холодный и энергоэффективный продукт, готовый к работе в реальном мире.