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

API ансамблів

LibreEnsemble запускає кілька детекторів на тому самому зображенні та зливає їхні виявлення в один Results. Злиття відбувається після власного постоброблення кожного учасника, тому учасники зберігають власні розмір вхідних даних, нормалізацію та придушення.

LibreEnsemble

python
LibreEnsemble(
    members,
    *,
    weights=None,
    fusion="wbf",
    fusion_iou=0.55,
    min_votes=1,
)
АргументТипове значенняЗначення
membersДва або більше детекторів
weightsNoneКоефіцієнти довіри для кожного учасника; за відсутності всі дорівнюють 1.0
fusion"wbf""wbf", "wbf_seeded", "nms" або викликаний об'єкт
fusion_iou0.55Поріг IoU для кластеризації під час злиття
min_votes1Залишати лише рамки, підтверджені щонайменше такою кількістю учасників

Учасником може бути шлях до ваг, визначений через фабрику LibreYOLO(), уже створена модель, експортований бекенд або ExternalDetector. Кожен учасник має бути моделлю завдання detect.

Два учасники й типове злиття
from libreyolo import LibreEnsemble, SAMPLE_IMAGE ens = LibreEnsemble(["LibreYOLO9t.pt", "LibreYOLO9s.pt"]) # Джерело з одним зображенням повертає один Results, а не список.result = ens(SAMPLE_IMAGE, conf=0.25) print(result.boxes.xyxy)print(result.speed)
Консенсус і пороги для окремих учасників
from libreyolo import LibreEnsemble, SAMPLE_IMAGE ens = LibreEnsemble(    ["LibreYOLO9t.pt", "LibreYOLO9s.pt"],    weights=[1.0, 2.0],    fusion="wbf",    fusion_iou=0.55,    min_votes=2,)result = ens(SAMPLE_IMAGE, conf=[0.25, 0.4])print(len(result))

Під час створення відхиляються: менше двох учасників, список weights неправильної довжини, недодатна вага, значення min_votes, що не є додатним цілим числом, і min_votes, більше за кількість учасників. fusion="nms" із min_votes > 1 також спричиняє помилку, оскільки NMS відкидає належність до кластера й не може підраховувати голоси.

weights масштабує довіру до кожного учасника. Більша вага наближає злиті координати й оцінки до цього учасника. За домовленістю вони задаються пропорційно до валідаційного mAP.

Простори класів

Учасники з однаковим names проходять без змін. В іншому разі простори класів об'єднуються за назвою, ідентифікатори класів учасників перетворюються через таблиці відповідності, а Results.names після злиття є об'єднанням. Злиття поєднує рамки лише в межах одного об'єднаного класу, тому клас, відомий лише одному учаснику, проходить без злиття. Невідповідність спричиняє попередження під час створення.

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

Виклик ансамблю

python
ens(
    source=None,
    *,
    conf=0.25,
    iou=0.45,
    imgsz=None,
    device=None,
    classes=None,
    max_det=300,
    augment=False,
    save=False,
    output_path=None,
    color_format="auto",
    batch=1,
    stream=False,
    stream_buffer=False,
    vid_stride=1,
    show=False,
    **kwargs,
)

predict є псевдонімом __call__. Повертається звичайний Results, де speed розділяє витрати за учасниками й додає запис fusion. Джерело з одним зображенням повертає один такий об'єкт, список або каталог повертає список, а stream=True повертає генератор.

conf, iou та device транслюються на кожного учасника й також приймають по одному значенню на учасника, тому conf=[0.25, 0.4] задає учаснику 0 поріг 0.25, а учаснику 1 поріг 0.4. imgsz транслюється, коли є цілим числом або кортежем, і застосовується окремо до учасників лише як список. Тому imgsz=(480, 640) задає один прямокутний розмір для всіх, а imgsz=[480, 640] задає 480 для учасника 0 і 640 для учасника 1. Кожен елемент має бути дійсним для сімейства відповідного учасника.

augment транслюється на учасників, які підтримують аугментацію під час тестування, а експортовані бекенди його ігнорують. classes приймає ідентифікатори класів об'єднання, а max_det застосовується до злитого результату, тому учасники працюють із запасом, а ансамбль один раз обрізає результат. batch приймається для узгодженості API; зображення обробляються послідовно.

val() і export() спричиняють NotImplementedError. Валідуйте й експортуйте учасників окремо.

ExternalDetector

python
ExternalDetector(fn: Callable, names: dict[int, str])

Адаптує будь-який викликаний детектор до учасника. fn приймає зображення PIL і повертає (boxes, scores, labels), де рамки задано як xyxy у пікселях початкового зображення, а мітки є ідентифікаторами класів, дійсними в names. Працюють тензори, масиви та вкладені списки. LibreYOLO нічого не імпортує із зовнішнього коду.

Адаптер перевіряє повернене значення: воно має бути 3-кортежем, рамки повинні мати форму (N, 4), три масиви повинні мати однакову довжину, а кожен ідентифікатор класу має бути в names. Виявлення з conf або нижче відкидаються перед злиттям.

Операції злиття

Примітиви злиття є окремими операціями torch у libreyolo.ops. Вони не залежать від моделі й можуть імпортуватися окремо, тому їх експортовано окремо від ансамблю.

Операція злиття без моделі
import torchfrom libreyolo.ops import weighted_boxes_fusion boxes = torch.tensor([[10.0, 10.0, 50.0, 50.0], [12.0, 11.0, 51.0, 49.0]])scores = torch.tensor([0.9, 0.8])labels = torch.tensor([0, 0])model_ids = torch.tensor([0, 1]) fused = weighted_boxes_fusion(    boxes, scores, labels, model_ids, num_models=2, iou_thr=0.55)print(fused)

Усі три приймають ті самі позиційні аргументи boxes, scores, labels, model_ids і повертають (boxes, scores, labels).

ОпераціяКлюч реєструПоведінка
weighted_boxes_fusionwbfПослідовне зважене злиття рамок із точним дотриманням статті
wbf_seededwbf_seededПаралельний однопрохідний варіант того самого зведення
nms_fusionnmsОб'єднання всіх даних із застосуванням NMS з урахуванням класів

FUSIONS зіставляє три ключі реєстру з викликаними об'єктами, а LibreEnsemble шукає там значення fusion=.

python
weighted_boxes_fusion(
    boxes, scores, labels, model_ids,
    *,
    weights=None,
    num_models=None,
    iou_thr=0.55,
    skip_box_thr=0.0,
    conf_type="avg",
    min_votes=1,
    models_per_label=None,
    label_weights=None,
)

wbf_seeded має ідентичну сигнатуру. nms_fusion приймає ті самі аргументи, крім conf_type, і спричиняє ValueError, коли min_votes > 1.

У weighted_boxes_fusion виявлення розглядаються в порядку спадання впевненості, масштабованої за вагою. Кожне виявлення або приєднується до наявного кластера, з поточною злитою рамкою якого має найбільше перекриття, за IoU вище iou_thr і тієї самої мітки, або починає новий кластер. Злита рамка кластера є середнім координат його учасників, зваженим за впевненістю, а його оцінка є зваженим середнім або максимумом їхньої впевненості, масштабованим так, щоб рамки, підтверджені меншою кількістю моделей, мали нижчі оцінки.

wbf_seeded вибирає початкові елементи кластерів через NMS з урахуванням класів за iou_thr, призначає кожне виявлення початковому елементу тієї самої мітки з найбільшим IoU, а потім так само зводить кожен кластер. Форми кластерів не змінюються посеред проходу, тому вся операція є тензорною математикою з фіксованою формою. Два варіанти збігаються, коли кластери однозначні, і можуть трохи відрізнятися в ланцюжках перекривних кластерів.

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

Власне злиття

fusion= також приймає викликаний об'єкт із тією самою сигнатурою, що й операції вище. Його назва записується в ens.fusion або як "custom", коли назви немає. Повернене значення перевіряється: воно має бути трійкою (boxes, scores, labels) з узгодженими формами.

Сигнатури й типові значення взято з libreyolo/ensemble/model.py та libreyolo/ops/fusion.py у v1.5.0. Проєктний задум взято з docs/adr/0004-model-ensembling.md.