Переглянути як Markdown

Дистиляція знань

Дистиляція додає другий доданок до функції втрат, який наближає проміжні карти ознак учня до карт замороженого вчителя. LibreYOLO відбирає ознаки за допомогою forward hooks, тому власні голова й функція втрат учителя не залучаються.

Дистиляція з більшої контрольної точки

Установлення distill_model вмикає дистиляцію. Значенням є контрольна точка вчителя, яка завантажується через ту саму фабрику, що й будь-яка інша модель.

Python
from libreyolo import LibreYOLO # Більша контрольна точка того самого сімейства керує навчанням малої.model = LibreYOLO("LibreYOLO9s.pt")model.train(    data="my-dataset.yaml",    epochs=100,    distill_model="LibreYOLO9c.pt",    distill_loss_type="mgd",)
CLI
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, а функція втрат обробляє невідповідність між сіткою патчів і кроком згортки.

Python
from libreyolo import LibreYOLO # Заморожений самокерований ViT керує навчанням одного етапу бекбона.model = LibreYOLO("LibreYOLO9s.pt")model.train(    data="my-dataset.yaml",    epochs=100,    distill_model="dinov2",)
CLI
libreyolo train model=LibreYOLO9s.pt data=my-dataset.yaml \  epochs=100 distill_model=dinov2

distill_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_down28, 16, 32
YOLOv9учень фундаментальної моделіbackbone.elan316
YOLOXучитель або ученьbackbone.C3_p3, backbone.C3_n3, backbone.C3_n48, 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-режимі. Див. розділ Продуктивність навчання.

Пов'язані матеріали

Перевірено з LibreYOLO v1.5.0.