Дистиляція знань
Дистиляція додає другий доданок до функції втрат, який наближає проміжні карти ознак учня до карт замороженого вчителя. LibreYOLO відбирає ознаки за допомогою forward hooks, тому власні голова й функція втрат учителя не залучаються.
Дистиляція з більшої контрольної точки
Установлення distill_model вмикає дистиляцію. Значенням є контрольна точка вчителя,
яка завантажується через ту саму фабрику, що й будь-яка інша модель.
from libreyolo import LibreYOLO # Більша контрольна точка того самого сімейства керує навчанням малої.model = LibreYOLO("LibreYOLO9s.pt")model.train( data="my-dataset.yaml", epochs=100, distill_model="LibreYOLO9c.pt", distill_loss_type="mgd",)libreyolo train model=LibreYOLO9s.pt data=my-dataset.yaml \ epochs=100 distill_model=LibreYOLO9c.pt distill_loss_type=mgdПрямий прохід учителя виконується в контексті no_grad, а коли ввімкнено AMP,
також у контексті autocast, тому заморожена модель не витрачає ресурси на обчислення
з повною точністю на кожному кроці. Forward hooks захоплюють її карти ознак у названих
точках відбору, функція втрат порівнює їх із картами учня, а результат додається
до функції втрат навчання й повідомляється як компонент distill.
Дистиляція із замороженого фундаментального бекбона
Натомість самокерований ViT може контролювати один етап бекбона учня. Ознаки вчителя надходять із його власного екстрактора ознак, а не з hooks, а функція втрат обробляє невідповідність між сіткою патчів і кроком згортки.
from libreyolo import LibreYOLO # Заморожений самокерований ViT керує навчанням одного етапу бекбона.model = LibreYOLO("LibreYOLO9s.pt")model.train( data="my-dataset.yaml", epochs=100, distill_model="dinov2",)libreyolo train model=LibreYOLO9s.pt data=my-dataset.yaml \ epochs=100 distill_model=dinov2distill_model розпізнає dinov2, що означає DINOv2-base, а також dinov2_vits14,
dinov2_vitb14, dinov2_vitl14, dinov2-small, dinov2-base, dinov2-large
і будь-який необроблений ідентифікатор hub, що починається з facebook/dinov2.
Будь-яке інше значення розглядається як шлях до контрольної точки вчителя.
Цей шлях використовує feat_mse незалежно від distill_loss_type і потребує
встановленого transformers. Якщо під час завантаження вчителя відсутні ключі ваг,
операція припиняється замість дистиляції з частково випадкового бекбона.
Підтримувані сімейства
Підтримка дистиляції є методом моделі-учня, і таких методів два.
get_distill_config() надає багатомасштабні точки відбору, за якими вчитель-детектор
керує учнем. Його реалізують YOLOv9, YOLOX і RF-DETR.
get_backbone_distill_config() надає один етап бекбона, за яким фундаментальний
учитель керує учнем. Його реалізує YOLOv9, єдине сімейство з такою підтримкою.
Будь-який інший варіант породжує помилку замість навчання без функції втрат:
LibreDFINE does not implement get_distill_config(). Distillation is not yet
supported for the 'dfine' family.Foundation-model distillation into the 'yolox' family is not supported yet
(no get_backbone_distill_config()).Точки відбору
Точки відбору фіксуються для сімейства й ролі, тому вчитель і учень не повинні мати однакову архітектуру, але повинні мати однакові кроки ознак.
| Сімейство | Роль | Точки відбору | Кроки |
|---|---|---|---|
| YOLOv9 | учитель або учень | neck.elan_up2, neck.elan_down1, neck.elan_down2 | 8, 16, 32 |
| YOLOv9 | учень фундаментальної моделі | backbone.elan3 | 16 |
| YOLOX | учитель або учень | backbone.C3_p3, backbone.C3_n3, backbone.C3_n4 | 8, 16, 32 |
| RF-DETR | учитель або учень | model.backbone.0.projector.stages.0 | перевіряється під час налаштування |
Невідповідні кроки породжують помилку до початку навчання:
Teacher and student must have matching strides. Teacher: [8, 16, 32],
Student: [16]Ця перевірка пропускається для фундаментальних учителів, оскільки відмінність сіток і є метою їх використання.
Три функції втрат
distill_loss_type вибирає функцію втрат ознак для вчителя-детектора. Фундаментальний
учитель завжди використовує feat_mse.
mgd, masked generative distillation, маскує частину просторових позицій учня
й навчає малий генератор із двох згорток відтворювати повну карту ознак учителя
з решти позицій. distill_mask_ratio задає замасковану частку, типово 0.65.
cwd, channel-wise distillation, перетворює просторові активації кожного каналу
на розподіл імовірностей і мінімізує дивергенцію KL окремо для кожного каналу.
distill_tau є температурою softmax, типово 1.0.
feat_mse вирівнює канали учня з каналами вчителя за допомогою згортки 1x1,
білінійно змінює розмір сітки вчителя до сітки учня й обчислює середньоквадратичну
похибку. distill_normalize=True спочатку L2-нормалізує обидві карти ознак уздовж
виміру каналів, через що зіставлення враховує лише кут і не залежить від масштабу.
Типове значення: False.
dis є глобальною вагою, застосованою зверху. Якщо її не задано, кожна функція втрат
використовує власне опубліковане типове значення: 2e-5 для MGD, 1.0 для CWD і 1.0
для feature MSE. Вони відрізняються на п'ять порядків, тому вага, налаштована для
одного типу функції втрат, не має сенсу для іншого.
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt")model.train( data="my-dataset.yaml", distill_model="LibreYOLO9c.pt", distill_loss_type="cwd", dis=1.0, # глобальна вага дистиляції distill_tau=1.0, # температура softmax для CWD)Параметри distill_mask_ratio, distill_tau і distill_normalize не мають прапорців
CLI. Вони передаються як аргументи Python або ключі YAML у cfg=. Для RF-DETR
дистиляція загалом також доступна лише через Python, оскільки відображення аргументів
CLI цього сімейства не містить ключів дистиляції.
Адаптери, контрольні точки й кілька GPU
Кожна функція втрат створює невеликі навчувані модулі поза учнем: адаптери каналів 1x1 і генератор MGD. Вони отримують власну групу параметрів оптимізатора з ефективною швидкістю навчання запуску.
Ці модулі записуються до контрольної точки під ключем distiller і відновлюються
під час продовження, тому відновлений запуск не починає навчання проєкторів із нуля.
У DDP адаптери перебувають поза обгорнутим учнем, тому редуктор DDP не бачить їхніх градієнтів. Засіб навчання явно виконує їх all-reduce на кожному кроці, тож усі ранги навчають однакові адаптери.
Захоплення графа CUDA недоступне під час запуску з дистиляцією. Передавання
cuda_graph=True записує один рядок у лог і запускає навчання в eager-режимі.
Див. розділ Продуктивність навчання.
Пов'язані матеріали
- Заморожування шарів і донавчання LoRA, жодне з яких не заважає поєднанню з дистиляцією.
- Гіперпараметри описують решту аргументів
train().