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

Донавчання LoRA

LoRA заморожує важкі попередньо навчені частини моделі та навчає поруч із ними невеликі низькорангові адаптери разом із шарами, які мають залишатися щільними. У LibreYOLO весь загальнодоступний інтерфейс зводиться до одного логічного значення.

Встановлення

LoRA працює на необов'язковій залежності peft.

pip
pip install "libreyolo[lora]"

Без неї lora=True спричиняє ImportError із назвою цієї команди, а не випадково запускає повне донавчання.

Використання

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreRFDETRs.pt")model.train(data="my-dataset.yaml", epochs=50, lora=True)
CLI
libreyolo train model=LibreRFDETRs.pt data=my-dataset.yaml \  epochs=50 lora=true

lora=True, це весь інтерфейс. Ранг, alpha, dropout і цільові модулі зафіксовано для кожного сімейства відповідно до upstream-реалізації, і користувач не може їх налаштовувати.

Сімейство без підтримки LoRA спричиняє помилку під час налаштування, а не ігнорує прапорець:

LoRA fine-tuning (lora=True) is not supported for yolo9. LoRA targets
transformer components with nn.Linear layers (e.g. RF-DETR, D-FINE, DEIM).

CLI відхиляє його раніше, ще до побудови моделі, використовуючи власний дозвільний список тих самих дев'яти сімейств.

Підтримувані сімейства

RF-DETR, D-FINE, DEIM, DEIMv2, RT-DETR v1, v2 і v4, EC та ConvNeXt. Умовою є атрибут supports_lora класу тренера кожного сімейства, а CLI має відповідний дозвільний список.

Покриття задач вужче за покриття сімейств. D-FINE і EC підтримують лише виявлення, а їхні шляхи сегментації та пози спричиняють помилку. Семантичний шлях RF-DETR також спричиняє помилку. ConvNeXt виконує класифікацію.

Усі інші варіанти спричиняють помилку. Часткового або прихованого режиму немає.

Дія кожного рецепта

Рецепти відрізняються через відмінності архітектур, а рецепту, який працює для бекбона ViT, немає до чого приєднатися в згортковому бекбоні.

RF-DETR використовує DoRA, LoRA з розкладеними вагами, із рангом 16 і alpha 16 для проєкцій уваги query, key і value бекбона DINOv2 відповідно до еталона RF-DETR. Бекбон ViT заморожується, а проєктор, декодер і голова виявлення навчаються як звичайно.

D-FINE, DEIM і RT-DETR v1, v2 та v4 поєднують згортковий бекбон із гібридним енкодером-трансформером і деформованим декодером, тому межа зміщується. Згортковий бекбон повністю заморожується, що також пропускає його зворотний прохід. Блоки трансформера заморожують базові ваги й навчають звичайні адаптери LoRA з тим самим рангом 16 і alpha 16 на лінійних шарах: feed-forward linear1 і linear2, gate та проєкції деформованої уваги. Усе інше, згорткове злиття енкодера, вхідні проєкції, голови передбачення й ембединги запитів, навчається щільно.

Дві деталі цього рецепта навмисні. Самоувага декодера залишається замороженою без адаптерів, оскільки nn.MultiheadAttention PyTorch читає out_proj.weight безпосередньо й непомітно обходила б вставлений адаптер. Використовується звичайна LoRA, а не DoRA, оскільки кілька лінійних шарів декодера навмисно ініціалізовано нулями, а нормалізація величини DoRA ділить на норму ваг.

DEIMv2 використовує той самий рецепт із feed-forward шарами SwiGLU w12 і w3 як цілями. Її розміри S, M, L і X також мають бекбон ViT DINOv3, базова частина якого заморожується, а злиті шари уваги qkv отримують адаптери; водночас згорткова піраміда Spatial Tuning Adapter продовжує навчатися як аналог проєктора. Ці адаптери qkv додаються навіть тоді, коли конфігурація вже постачала заморожений ViT, оскільки сенс полягає саме в адаптації замороженого бекбона. Розміри менші за S мають згортковий бекбон і використовують звичайний рецепт.

EC, це DETR із бекбоном ViT, оточеним згортковою пірамідою проєктора, яка навчається. Базова частина ViT заморожується, а її шари qkv отримують адаптери; блоки трансформера використовують спільний рецепт, а проєктор і голови залишаються щільними.

Блоки ConvNeXt мають лінійні MLP із каналами в останньому вимірі, fc1 і fc2, які отримують звичайні адаптери. Глибинні згортки, нормалізації та параметри масштабу шарів заморожуються. Голова класифікації залишається щільною, щоб працювала власна кількість класів.

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

Контрольні точки та експорт

best.pt і last.pt зберігають тензори адаптерів, тому запуск LoRA відновлюється й перевіряється як будь-який інший. Для завантаження однієї з цих контрольних точок потрібна встановлена додаткова залежність lora, оскільки завантажувач повторює вставлення адаптерів для узгодження ключів.

export() зливає адаптери в щільні ваги, тому експортований артефакт не залежить від peft. Таке саме злиття доступне безпосередньо для моделі в пам'яті.

Експорт зливає адаптери
from libreyolo import LibreYOLO model = LibreYOLO("runs/train/exp/weights/best.pt")model.export(format="onnx")
Злиття на місці
from libreyolo import LibreYOLOfrom libreyolo.training.lora import merge_lora_adapters model = LibreYOLO("runs/train/exp/weights/best.pt")merged = merge_lora_adapters(model.model) print(f"{merged} adapter layers folded into dense weights")

Після злиття дерево модулів повністю щільне, а друге злиття нічого не робить.

Що заощаджується, а що ні

LoRA зменшує пам'ять оптимізатора й градієнтів, а в сімействах, що повністю заморожують бекбон, також пропускає його зворотний прохід.

Пам'ять активацій не змінюється. Активації прямого проходу й далі потрібно зберігати для всіх частин, що навчаються, і саме вони зазвичай визначають пікове споживання. За найсуворішого обмеження VRAM також зменште batch або imgsz.

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

  • Заморожування шарів для іншого способу навчати підмножину ваг, який працює з кожним сімейством і не потребує додаткової залежності. freeze і lora=True поєднуються: параметри адаптерів залишаються доступними для навчання, навіть коли їхню батьківську групу бекбона заморожено.
  • Гіперпараметри для batch, imgsz і решти аргументів train().

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