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).
Этот процесс можно сравнить с реабилитацией после травмы: мы убираем часть системы, даем организму время перестроить нейронные связи для компенсации потери, а затем повторяем процедуру.
Гипотеза лотерейного билета
Говоря о прунинге, нельзя не упомянуть знаменитую «Гипотезу лотерейного билета» (Lottery Ticket Hypothesis), предложенную исследователями из MIT в 2018 году.
Она гласит: внутри любой большой, случайно инициализированной нейронной сети существует небольшая подсеть («выигрышный билет»), которая при обучении с нуля способна достичь той же точности, что и исходная большая сеть, за то же количество итераций.
Проблема в том, что мы не можем найти этот «выигрышный билет» до начала обучения. Нам приходится создавать огромную сеть (покупать миллионы лотерейных билетов), обучать ее, находить те связи, которые реально выполнили работу (выигрышный билет), а затем с помощью прунинга выбрасывать все остальные (проигрышные билеты).
Внедрение прунинга в ваш пайплайн разработки моделей компьютерного зрения — это обязательный шаг перед релизом продукта. Удалив избыточные фильтры из архитектур вроде YOLO или SSD, вы сможете запускать детекцию объектов в реальном времени даже на слабых процессорах, экономя заряд батареи и вычислительные ресурсы.