Архитектура YOLO: от YOLOv3 до YOLO26#
Каждая модель Ultralytics YOLO состоит из трёх этапов: магистрали, которая извлекает признаки, шейки, которая объединяет их на разных масштабах, и головы, которая предсказывает рамки и классы. В этом руководстве описаны модули каждого этапа и их изменения от YOLOv3 до YOLO26: для каждого компонента указано его определение в файлах конфигурации в ultralytics/cfg/models/ и в классах модулей в ultralytics/nn/modules/.
Каждая модель декларативно описывается в YAML-файле как упорядоченный список слоёв, где каждый слой соответствует формату [from, repeats, module, args]: какие слои подают на него данные, сколько раз повторяется модуль, класс слоя (Conv, C3k2, SPPF, Detect, …) и аргументы конструктора. В руководстве по конфигурации YAML модели описан этот формат, в том числе масштабирование repeats и args с учётом множителей глубины и ширины варианта, а также подробно разобрана система разрешения модулей. Здесь основное внимание уделено самим модулям и их изменениям от версии к версии.
Три этапа#
Каждая модель Ultralytics YOLO последовательно обрабатывает изображение в три этапа, у каждого из которых своя задача:
| Этап | Задача | Результат |
|---|---|---|
| Магистраль | Извлекает признаки из входного изображения в нескольких разрешениях | Карты признаков с шагами 8, 16 и 32 (P3, P4 и P5) |
| Шейка | Объединяет признаки на разных масштабах, чтобы контекст учитывался и для маленьких, и для крупных объектов | Объединённые карты признаков нескольких масштабов |
| Голова | Предсказывает ограничивающие рамки и оценки классов на основе объединённых признаков | Детекции для каждой опорной точки |
Базовая единица — блок Conv (определённый в conv.py): двумерная свёртка, пакетная нормализация и активация SiLU, применяемые последовательно. Все более крупные модули ниже составлены из блоков Conv.
Диаграммы архитектуры#
В каждой версии сохраняется одна и та же схема основная сеть → шея → голова, но меняются отдельные этапы. На вкладках ниже показана структура каждой версии: этапы основной сети и шеи соответствуют конфигам в ultralytics/cfg/models/, а головы YOLOv3 и YOLOv5 показаны в исходном варианте с якорями, а не в безъякорном варианте головы u, который фактически поставляется с их пакетами. Переключаясь между вкладками, ты увидишь, что добавлялось в каждом поколении. Кратко: YOLOv3 — детектор только с FPN, использующий якоря; YOLOv5 добавляет восходящий путь PAN и SPPF; YOLOv8 переходит на блок C2f с безъякорной головой DFL; YOLO11 добавляет механизм внимания C2PSA и блок C3k2; YOLO26 добавляет остаточную связь SPPF, убирает DFL и добавляет необязательную голову без NMS.
На диаграммах YOLOv3 и YOLOv5 показана исходная голова с опорными якорями. Пакет ultralytics поставляется с конфигурациями YOLOv3u и YOLOv5u без якорей: в них используются те же магистрали Darknet-53 и C3, но голова Detect из YOLOv8, как описано в разделе «Голова детектора».
Блоки магистрали: Bottleneck → C3 → C2f → C3k2#
Магистраль состоит из повторяющегося блока CSP (Cross-Stage Partial) между слоями понижения разрешения Conv с шагом 2. Именно этот повторяющийся блок сильнее всего менялся от версии к версии. Все блоки ниже находятся в block.py; c1/c2 обозначают входное/выходное число каналов, а c = 0.5 * c2 — скрытую ширину.
Bottleneck (YOLOv3)#
Базовая единица — Bottleneck: два слоя Conv (размеры ядер по умолчанию — (3, 3)) с необязательным остаточным сложением, если shortcut=True и c1 == c2. Магистраль Darknet-53 в YOLOv3 напрямую соединяет такие блоки, без разделения CSP, а детекция выполняется на трёх масштабах (шаги 8, 16 и 32).
C3 (YOLOv5)#
C3 в YOLOv5 разделяет входные данные между двумя свёртками 1x1: cv1 направляет данные в n последовательных блоков Bottleneck (ядра (1, 1), затем (3, 3)), а cv2 обходит их. Два пути конкатенируются и объединяются третьим 1x1 Conv:
def forward(self, x):
# C3: путь bottleneck m(cv1(x)) конкатенируется с обходным путём cv2(x), затем объединяется с помощью cv3
return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), 1))До свёртки объединения доходит только выход последнего блока bottleneck, поэтому cv3 получает 2 карты признаков.
C2f (YOLOv8)#
В C2f из YOLOv8 изменено то, какие признаки поступают на свёртку объединения («CSP Bottleneck с 2 свёртками, более быстрый»):
- Сначала выполняется
cv1 = Conv(c1, 2 * c, 1), затемchunk(2)разделяет выходной тензор на два тензора сcканалами. - Блоки
nBottleneck(c, c)(ядра(3, 3),(3, 3)) выполняются последовательно; на вход каждого следующего блока подаётся выход предыдущего. - Все промежуточные тензоры
n + 2конкатенируются и объединяются с помощьюcv2 = Conv((2 + n) * c, c2, 1).
В C3 на свёртку объединения подаются 2 карты признаков, а в C2f — n + 2: используется выход каждого промежуточного блока bottleneck.
C3k2 (YOLO11 и YOLO26)#
В YOLO11 и YOLO26 используется C3k2 — подкласс C2f, в котором заменён повторяющийся блок. В зависимости от флагов конструктора каждый блок n становится:
- обычным
Bottleneck(по умолчанию,c3k=False), - блоком
C3k(c3k=True) — вариантомC3с настраиваемым размером ядра, или - парой
Bottleneck+PSABlock(attn=True).
Второй аргумент YAML задаёт c3k, если только масштаб не равен m, l или x: в этих случаях значение принудительно устанавливается в True. Благодаря этому один yolo11.yaml подходит для всех пяти вариантов. Поэтому [-1, 2, C3k2, [512, False]] создаёт внутренние блоки Bottleneck с n и s, но внутренние блоки C3k — с m, l и x; значение 512 — это число каналов до масштабирования, которое множитель ширины варианта преобразует в 128 для n и 768 для x. Для модулей CSP поле repeats — здесь это 2 до масштабирования множителем глубины варианта — задаёт число повторений внутри блока, а не число отдельных последовательно расположенных модулей.
Пространственный пулинг: SPP → SPPF#
В конце магистрали блок пространственного пирамидального пулинга расширяет рецептивное поле. В YOLOv5 исходный многоканальный по ядрам SPP заменили на SPPF (быстрый пространственный пирамидальный пулинг): один MaxPool2d(kernel_size=5, stride=1, padding=2) применяется последовательно n = 3 раз, после чего вход и все три результата пулинга конкатенируются и объединяются с помощью 1x1 Conv. Это математически эквивалентно SPP(k=(5, 9, 13)), но работает быстрее, поскольку цепочка операций пулинга 5x5 охватывает рецептивные поля более крупных ядер.
В YOLO26 передаётся флаг shortcut (SPPF, [1024, 5, 3, True]); поскольку c1 == c2 == 1024 находится на самом глубоком слое, SPPF добавляет остаточное соединение (return y + x).
Пространственное внимание: C2PSA (YOLO11 и новее)#
В YOLO11 после SPPF добавили C2PSA. Это блок CSP с активной ветвью, состоящей из стека модулей n PSABlock (внимание с учётом позиции): cv1 = Conv(c1, 2 * c, 1) разделяет признаки, одна половина проходит через стек PSABlock, а cv2 = Conv(2 * c, c1, 1) объединяет конкатенированные данные. Каждый PSABlock выполняет многоголовое внимание, а затем пропускает данные через двухслойную полносвязную сеть (Conv(c, 2 * c, 1) → Conv(2 * c, c, 1)); после каждой операции используется остаточное соединение. В YOLO26 используется та же магистраль C3k2 + C2PSA.
Шейка: FPN + PAN#
Шейка объединяет карты признаков P3/P4/P5 магистрали: сначала с помощью идущей сверху вниз сети пирамиды признаков (Feature Pyramid Network, FPN), затем — идущей снизу вверх сети агрегации путей (Path Aggregation Network, PAN). В секции head YAML-файла FPN соответствует nn.Upsample + Concat (передача семантической информации на более высокие разрешения), а PAN — операциям Conv + Concat с шагом 2 (передача информации о локализации обратно на более низкие разрешения):
# YOLO11 head (FPN top-down, then PAN bottom-up)
- [-1, 1, nn.Upsample, [None, 2, "nearest"]]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 2, C3k2, [512, False]] # 13
# ... second upsample + concat to P3 ...
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4 (PAN)
- [-1, 2, C3k2, [512, False]] # 19В шейке повторно используется блок магистрали соответствующего поколения: C3 в YOLOv5, C2f в YOLOv8 и C3k2 в YOLO11 и YOLO26. Поэтому в каждой точке объединения выполняется тот же модуль, что и в магистрали. Три объединённых выхода подаются на голову. YOLOv3 — исключение: её шейка использует только FPN, идущую сверху вниз (в её YAML-секции head нет понижения разрешения с шагом 2), без пути PAN снизу вверх, который появился в YOLOv5.
Голова детектора: с опорными якорями → без якорей → без NMS#
Голова преобразует три объединённые карты признаков в предсказания для задачи детекции. В разных версиях её устройство менялось: от варианта с опорными якорями к варианту без якорей, а затем к варианту без NMS.
Голова Detect без якорей с разделёнными ветвями#
В исходных YOLOv3 и YOLOv5 использовалась голова с опорными якорями и общей ветвью для предсказания рамок и классов. В отдельных репозиториях ultralytics/yolov3 и ultralytics/yolov5 сохранена эта архитектура с опорными якорями. Вместо неё основной пакет ultralytics поставляется с вариантами YOLOv3u и YOLOv5u без якорей: в них используются те же магистрали Darknet-53 и C3, но голова Detect из YOLOv8 без якорей. Описанные здесь конфигурации yolov3.yaml и yolov5.yaml — это варианты u, а не историческая архитектура.
Голова Detect (head.py — без якорей и с разделёнными ветвями: на каждом уровне пирамиды она запускает две параллельные ветви и предсказывает непосредственно в точках сетки, а не относительно опорных якорей.
- Ветвь рамок (
cv2):Conv(x, c2, 3)→Conv(c2, c2, 3)→Conv2d(c2, 4 * reg_max, 1). - Ветвь классов (
cv3): в YOLO11 и YOLO26 используются два блока с разделяемыми свёртками (DWConv+1x1 Conv) →Conv2d(c3, nc, 1); в YOLOv8 применяется устаревший вариант: два слоя3x3 Conv→Conv2d(c3, nc, 1).
Таким образом, каждая опорная точка выдаёт no = nc + 4 * reg_max значений. При отказе от заранее заданных якорей размеры и соотношения сторон опорных рамок больше не нужно настраивать в гиперпараметрах.
Distribution Focal Loss (DFL)#
В YOLOv8 и YOLO11 каждая из 4 координат рамки регрессируется как распределение по reg_max = 16 бинам, а не как одно скалярное значение (интегральная форма из обобщённой фокальной функции потерь). Модуль DFL преобразует 4 * reg_max каналов рамки в (4, reg_max), применяет softmax по reg_max бинам и берёт математическое ожидание индекса бина в качестве предсказанной координаты: каждый индекс умножается на свою вероятность после softmax, а затем полученные значения суммируются. Это реализовано с помощью фиксированной свёртки 1x1, веса которой — индексы бинов arange(reg_max), поэтому взвешенная сумма вычисляется одним скалярным произведением.
YOLO26: без NMS и DFL#
YOLO26 задаёт два параметра YAML, которые напрямую использует голова:
end2end: True—Detectсоздаёт глубокие копии ветвей для головы один-к-одному (one2one_cv2/one2one_cv3), которая учится выдавать одно предсказание на объект. Эта настройка YAML создаёт обе головы для обучения; во время выполненияnms=Falseвыбирает голову один-к-одному и удаляет этап постобработки — подавление немаксимумов (NMS). Подробности инференса и экспорта см. в руководстве по сквозной детекции.reg_max: 1— при одном бинеself.dflстановитсяnn.Identity()иno = nc + 4; голова напрямую регрессирует координаты, и в экспортированном графе ONNX нет операции DFL.
Во всех пяти размерах модели YOLO26 (n/s/m/l/x) достигает 40.9–57.5 mAP на COCO при задержке 1.7–11.8 мс на T4 с TensorRT, как указано в статье о YOLO26.
Сводка по версиям#
| Версия | Блок магистрали | Пространственный пулинг | Внимание | Голова детектора | DFL |
|---|---|---|---|---|---|
| YOLOv3 | Darknet-53 (Bottleneck) | в базовой конфигурации отсутствует | отсутствует | Исходный вариант: с опорными якорями; вариант u: без якорей | нет / да (u) |
| YOLOv5 | C3 (CSP) | SPPF | отсутствует | Исходный вариант: с опорными якорями; вариант u: без якорей | нет / да (u) |
| YOLOv8 | C2f | SPPF | отсутствует | Без якорей, с разделёнными ветвями | да (reg_max=16) |
| YOLO11 | C3k2 | SPPF | C2PSA | Без якорей, с разделёнными ветвями | да (reg_max=16) |
| YOLO26 | C3k2 | SPPF + shortcut | C2PSA | Без якорей, две головы; опционально без NMS | удалено (reg_max=1) |
Подробности о каждой модели, таблицы производительности и примеры использования см. на отдельных страницах YOLOv3, YOLOv5, YOLOv8, YOLO11 и YOLO26.
Изучи архитектуру самостоятельно#
Метод model.info() выводит сводку по слоям, параметрам и FLOPs, а список разобранных модулей доступен в model.model.model.
from ultralytics import YOLO
# Загрузи предварительно обученную модель
model = YOLO("yolo11n.pt")
# Объедини слои Conv + BatchNorm, чтобы число параметров совпадало с опубликованными спецификациями
model.fuse()
# Выведи сводку: слои, параметры, градиенты, GFLOPs
model.info()
# Изучи голову детектора (последний модуль сети)
head = model.model.model[-1]
print(type(head).__name__, "| reg_max:", head.reg_max, "| DFL layer:", type(head.dfl).__name__)Запуск фрагмента кода для трёх поколений наглядно показывает численные изменения. Это реальные результаты для объединённых моделей из пакета ultralytics, совпадающие с опубликованными значениями числа параметров и FLOPs на страницах моделей:
| Модель | Слои | Параметры | GFLOPs | reg_max | Слой DFL |
|---|---|---|---|---|---|
| YOLOv8n | 72 | 3,151,904 | 8.7 | 16 | DFL |
| YOLO11n | 100 | 2,616,248 | 6.5 | 16 | DFL |
| YOLO26n | 120 | 2,408,932 | 5.5 | 1 | Identity |
Для YOLO26n указаны reg_max=1 и слой DFL Identity. По умолчанию для предсказаний и валидации используется схема один-ко-многим с NMS; чтобы выполнять инференс без NMS, задай nms=False. Обе головы обучаются.
Значения количества параметров и FLOPs указаны для объединённой модели (model.fuse()), в которой каждый Conv объединён со своим слоем пакетной нормализации. Это соответствует опубликованным характеристикам; у только что загруженного чекпойнта значения до объединения немного выше.
Заключение#
От версии к версии архитектура YOLO менялась поэтапно: основная сеть перешла от Darknet-53 к основанным на CSP блокам C3, C2f и C3k2 с механизмом внимания C2PSA; шея сохранила структуру FPN + PAN, а SPP превратился в SPPF; голова прошла путь от варианта с якорями к безъякорному, а затем — к архитектуре YOLO26 без DFL и с необязательной сквозной головой без NMS.
Чтобы определить собственные архитектуры, ознакомься с руководством по настройке YAML модели или сравни модели на страницах моделей. Если возникнут вопросы, обратись к нам на GitHub или Discord.
Часто задаваемые вопросы#
Модель YOLO состоит из backbone, который извлекает признаки изображения с шагами 8, 16 и 32, neck, который объединяет эти признаки на разных масштабах с помощью FPN и PAN, и head, который предсказывает ограничивающие рамки и оценки классов. Все модели Ultralytics YOLO от YOLOv3 до YOLO26 используют эту трёхэтапную архитектуру.
C2f(YOLOv8) — это CSP-блок, который перед свёрткой объединения конкатенирует выходы всех внутренних карт признаковBottleneck—n + 2, тогда как более старыйC3передаёт только 2.C3k2(YOLO11 и YOLO26) — подклассC2f, способный заменять каждыйBottleneckблокомC3k(вариантомC3с настраиваемым размером ядра), если включён флагc3k. Оба блока определены вblock.py.В YOLO11 внесены три структурных изменения по сравнению с YOLOv8: блок backbone и neck
C2fзаменён наC3k2, послеSPPFдобавлен блок self-attentionC2PSA, а в классификационной ветви head используются более лёгкие глубинные разделимые свёртки. В обеих моделях используется одна и та же anchor-free, разделённая на ветви головаDetectс регрессией DFLreg_max=16, поэтому изменения сокращают количество параметров и FLOPs и повышают точность, не меняя интерфейс детекции.Современные модели Ultralytics YOLO не используют якоря. В YOLOv8, YOLO11 и YOLO26 применяется разделённая на ветви anchor-free-голова
Detectс отдельными ветвями регрессии рамок и классификации. В исходных YOLOv3 и YOLOv5 использовались якоря, но Ultralytics выпускает их варианты YOLOv3u и YOLOv5u, в конфигурациях которых используется та же anchor-free-голова, что и в YOLOv8.Да — в YOLO26 есть голова one-to-one, поддерживающая инференс без NMS с
nms=False. В стандартном пути инференса one-to-many используется NMS, а обе головы получают обучающие сигналы во время обучения. Подробнее см. в руководстве по сквозной детекции.DFL регрессирует каждую координату рамки как распределение softmax по
reg_maxбинам (по умолчанию 16 в YOLOv8 и YOLO11) и использует математическое ожидание в качестве координаты вместо предсказания одного скалярного значения. В YOLO26 заданоreg_max=1, поэтому слой DFL становится тождественной операцией, голова напрямую регрессирует координаты, а в экспортированных графах ONNX или TensorRT нет операций DFL.Загрузи модель в Python и вызови
model.info(), чтобы получить сводку по слоям, параметрам и GFLOPs. Разобранные слои находятся вmodel.model.model— например,model.model.model[-1]— это головаDetectс такими атрибутами, какreg_maxиdfl. Полная архитектура описана в файле конфигурации YAML модели.