YOLO Vision 2026:

Архитектура YOLO: объяснение от YOLOv3 до YOLO26#

Каждая модель Ultralytics YOLO состоит из трёх этапов: backbone, который извлекает признаки, neck, который объединяет их в разных масштабах, и head, который предсказывает боксы и классы. В этом руководстве описаны модули каждого этапа и их изменения от YOLOv3 до YOLO26; каждый компонент прослеживается до его определения в конфигурационных файлах в ultralytics/cfg/models/ и классов модулей в ultralytics/nn/modules/.

Каждая модель декларативно определяется в YAML-файле как упорядоченный список слоёв, где каждый слой соответствует формату [from, repeats, module, args]: какие слои подают на него данные, сколько раз повторяется модуль, класс слоя (Conv, C3k2, SPPF, Detect, …) и аргументы его конструктора. В руководстве по конфигурации Model YAML описан этот формат, включая то, как repeats и args масштабируются с учётом множителей глубины и ширины варианта, а также подробно описана система разрешения модулей. Это руководство посвящено самим модулям и их изменениям от версии к версии.

Три этапа#

Каждая модель Ultralytics YOLO последовательно пропускает изображение через три этапа, у каждого из которых своя задача:

ЭтапЗадачаРезультат
BackboneИзвлечение признаков из входного изображения в нескольких разрешенияхКарты признаков со stride 8, 16 и 32 (P3, P4 и P5)
NeckОбъединение признаков в разных масштабах, чтобы и малые, и крупные объекты имели контекстОбъединённые многомасштабные карты признаков
HeadПредсказание ограничивающих боксов и оценок классов на основе объединённых признаковДетекции для каждой опорной точки

Фундаментальная единица — блок Conv (определённый в conv.py): двумерная свёртка, пакетная нормализация и активация SiLU, применяемые последовательно. Каждый более крупный модуль ниже строится композиционно из блоков Conv.

Диаграммы архитектуры#

В каждой версии сохраняется один и тот же каркас backbone → neck → head, но меняются отдельные этапы. Вкладки ниже показывают структуру каждой версии: этапы backbone и neck соответствуют конфигурациям в ultralytics/cfg/models/, а head YOLOv3 и YOLOv5 показаны в исходной anchor-based форме, а не в anchor-free форме head варианта u, которая фактически поставляется в конфигурациях их пакетов. Последовательный просмотр вкладок показывает, что добавила каждая генерация. Если кратко: YOLOv3 — детектор только на основе FPN и anchor-based; YOLOv5 добавляет восходящий путь PAN и SPPF; YOLOv8 переходит на блок C2f с anchor-free head и DFL; YOLO11 добавляет внимание C2PSA и блок C3k2; YOLO26 добавляет остаточную связь SPPF, а head становится свободным от NMS и DFL. Цвета узлов соответствуют принятому в документации стилю диаграмм: зелёный — вход, синий — backbone, серо-синий — пространственное объединение и внимание, оранжевый — neck, фиолетовый — head и выход.

flowchart TD
    IN[Input 640x640]:::start --> ST[Conv stem<br/>5x stride-2 down to P1-P5]:::proc
    ST --> BB[Darknet-53 backbone<br/>stacked Bottleneck]:::proc
    BB --> FPN[Neck FPN only<br/>top-down Upsample + Concat]:::decide
    FPN --> HD[Detect head<br/>3 scales, anchor-based]:::out
    HD --> O[Predictions + NMS]:::out
    classDef start fill:#4CAF50,color:#fff
    classDef proc fill:#2196F3,color:#fff
    classDef decide fill:#FF9800,color:#fff
    classDef out fill:#9C27B0,color:#fff

На диаграммах YOLOv3 и YOLOv5 показан исходный anchor-based head. Пакет ultralytics поставляет anchor-free конфигурации YOLOv3u и YOLOv5u — те же backbone Darknet-53 и C3 с head Detect от YOLOv8; они описаны в разделе Detection Head.

Блоки backbone: Bottleneck → C3 → C2f → C3k2#

Backbone объединяет повторяющийся блок CSP (частичный блок между этапами) между слоями понижения разрешения Conv со stride 2. Именно этот повторяющийся блок сильнее всего менялся между версиями. Все блоки ниже находятся в block.py; c1/c2 — это входные и выходные каналы, а c = 0.5 * c2 — скрытая ширина.

Bottleneck (YOLOv3)#

Базовая единица — Bottleneck: два слоя Conv (ядра по умолчанию (3, 3)) с необязательным добавлением остаточной связи, если shortcut=True и c1 == c2. Backbone Darknet-53 в YOLOv3 непосредственно объединяет эти блоки без разделения CSP и выполняет детекцию в трёх масштабах (stride 8, 16 и 32).

C3 (YOLOv5)#

C3 в YOLOv5 разделяет вход между двумя свёртками 1x1: cv1 передаёт данные в n последовательных блоков Bottleneck (ядра (1, 1), затем (3, 3)), а cv2 обходит их. Два пути объединяются и сливаются третьей свёрткой 1x1 Conv:

def forward(self, x):
    # C3: bottleneck path m(cv1(x)) concatenated with bypass cv2(x), then fused by cv3
    return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), 1))

До свёртки слияния доходит только выход последнего bottleneck, поэтому cv3 получает 2 карты признаков.

C2f (YOLOv8)#

C2f в YOLOv8 ("CSP Bottleneck with 2 convolutions, faster") изменяет набор признаков, поступающих в свёртку слияния:

  1. cv1 = Conv(c1, 2 * c, 1), затем chunk(2) разделяет выход на два тензора с c каналами.
  2. Блоки n Bottleneck(c, c) (ядра (3, 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#

В конце backbone блок пространственного пирамидального объединения расширяет рецептивное поле. YOLOv5 заменил исходный многоканальный SPP на SPPF (Spatial Pyramid Pooling - Fast): одна MaxPool2d(kernel_size=5, stride=1, padding=2), применённая последовательно n = 3 раз, причём вход и все три объединённых результата объединяются и сливаются свёрткой 1x1 Conv. Математически это эквивалентно SPP(k=(5, 9, 13)), но требует меньше вычислений, поскольку последовательные операции pooling 5x5 покрывают рецептивные поля более крупных ядер.

YOLO26 передаёт флаг shortcut (SPPF, [1024, 5, 3, True]); поскольку c1 == c2 == 1024 находится на самом глубоком слое, SPPF добавляет остаточную связь (return y + x).

Пространственное внимание: C2PSA (YOLO11+)#

YOLO11 добавил C2PSA после SPPF. Это блок CSP, активная ветвь которого представляет собой стек из n модулей PSABlock (Position-Sensitive Attention): cv1 = Conv(c1, 2 * c, 1) разделяет признаки, одна половина проходит через стек PSABlock, а cv2 = Conv(2 * c, c1, 1) объединяет конкатенацию. Каждый PSABlock применяет multi-head внимание, за которым следует двухслойная полносвязная сеть (Conv(c, 2 * c, 1)Conv(2 * c, c, 1)); оба этапа имеют остаточную связь. YOLO26 сохраняет тот же backbone C3k2 + C2PSA.

Neck: FPN + PAN#

Neck объединяет карты признаков P3/P4/P5 из backbone с нисходящей сетью пирамиды признаков (FPN), за которой следует восходящая сеть агрегации путей (PAN). В разделе head YAML-файла FPN — это nn.Upsample + Concat (передача семантической информации к более высоким разрешениям), а PAN — это Conv + Concat со stride 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

Neck повторно использует блок backbone своей версии — C3 в YOLOv5, C2f в YOLOv8, C3k2 в YOLO11 и YOLO26, — поэтому в каждой точке слияния выполняется тот же модуль, что и в backbone. Три объединённых выхода передаются в head. YOLOv3 — исключение: его neck содержит только нисходящий FPN (в его YAML head отсутствует понижение разрешения со stride 2), без восходящего пути PAN, который появился в YOLOv5.

Detection Head: Anchor-Based → Anchor-Free → NMS-Free#

Head преобразует три объединённые карты признаков в предсказания для задачи детекции. Его архитектура менялась от версии к версии: от anchor-based к anchor-free, а затем к NMS-free.

Anchor-free, раздельный Detect#

Исходные YOLOv3 и YOLOv5 использовали anchor-based head со связанными ветвями: заранее заданными anchor-боксами и общей ветвью для предсказания боксов и классов. Отдельные репозитории ultralytics/yolov3 и ultralytics/yolov5 сохраняют эту anchor-based архитектуру. Основной пакет ultralytics, напротив, поставляет anchor-free варианты YOLOv3u и YOLOv5u — те же backbone Darknet-53 и C3 с anchor-free head Detect от YOLOv8; конфигурации yolov3.yaml и yolov5.yaml, описанные здесь, относятся именно к этим вариантам u, а не к исторической архитектуре.

Head Detect (head.py) является anchor-free и раздельным: на каждом уровне пирамиды он запускает две параллельные ветви и выполняет предсказания непосредственно на узлах сетки, а не относительно anchor-боксов.

  • Ветвь боксов (cv2): Conv(x, c2, 3)Conv(c2, c2, 3)Conv2d(c2, 4 * reg_max, 1).
  • Ветвь классов (cv3): в YOLO11 и YOLO26 два depthwise-separable блока (DWConv + 1x1 Conv) → Conv2d(c3, nc, 1); YOLOv8 использует устаревший вариант: два слоя 3x3 ConvConv2d(c3, nc, 1).

Таким образом, каждая опорная точка выдаёт no = nc + 4 * reg_max выходов. Удаление заранее заданных anchors исключает размеры и соотношения сторон anchor-боксов из гиперпараметров, которые нужно настраивать.

Distribution Focal Loss (DFL)#

YOLOv8 и YOLO11 регрессируют каждую из 4 координат бокса как распределение по reg_max = 16 бинам, а не как единственное скалярное значение (интегральная форма из Generalized Focal Loss). Модуль DFL изменяет форму 4 * reg_max каналов бокса на (4, reg_max), применяет softmax по reg_max бинам и получает ожидаемый индекс бина — каждый индекс взвешивается его вероятностью softmax, после чего результаты суммируются — как предсказанную координату. Это реализовано в виде свёртки 1x1 с фиксированными весами, равными индексам бинов arange(reg_max), поэтому взвешенная сумма вычисляется одним скалярным произведением.

YOLO26: NMS-free, DFL-free#

YOLO26 задаёт два параметра YAML, которые head считывает напрямую:

  • end2end: TrueDetect глубоко копирует свои ветви в head один-к-одному (one2one_cv2/one2one_cv3), который выдаёт одно предсказание на объект, устраняя этап постобработки подавления немаксимумов (NMS). Подробности экспорта и миграции см. в руководстве по сквозной детекции.
  • reg_max: 1 — при одном бине self.dfl превращается в nn.Identity() и no = nc + 4; head напрямую регрессирует координаты, и в экспортированном графе ONNX отсутствует операция DFL.

Во всех пяти вариантах размера модели (n/s/m/l/x) YOLO26 достигает 40,9–57,5 mAP на COCO при задержке TensorRT 1,7–11,8 мс на T4, как указано в статье о YOLO26.

Сводка по версиям#

ВерсияБлок backboneПространственное объединениеВниманиеHead детекцииDFL
YOLOv3Darknet-53 (Bottleneck)отсутствует в базовой конфигурацииотсутствуетИсходный: anchor-based; вариант u: anchor-freeнет / да (u)
YOLOv5C3 (CSP)SPPFотсутствуетИсходный: anchor-based; вариант u: anchor-freeнет / да (u)
YOLOv8C2fSPPFотсутствуетAnchor-free, раздельныйда (reg_max=16)
YOLO11C3k2SPPFC2PSAAnchor-free, раздельныйда (reg_max=16)
YOLO26C3k2SPPF + shortcutC2PSAAnchor-free, NMS-free (end2end)удалён (reg_max=1)

Подробности по каждой модели, таблицы производительности и примеры использования см. на отдельных страницах YOLOv3, YOLOv5, YOLOv8, YOLO11 и YOLO26.

Изучи архитектуру самостоятельно#

Метод model.info() выводит сводку по слоям, параметрам и FLOPs, а список разобранных модулей доступен в model.model.model.

Изучение архитектуры модели YOLO
from ultralytics import YOLO

# Load a pretrained model
model = YOLO("yolo11n.pt")

# Fuse Conv + BatchNorm layers so counts match the published specs
model.fuse()

# Print a summary: layers, parameters, gradients, GFLOPs
model.info()

# Inspect the detection head (the last module in the network)
head = model.model.model[-1]
print(type(head).__name__, "| reg_max:", head.reg_max, "| end2end:", head.end2end)

Запуск этого фрагмента для трёх поколений показывает изменения в числах. Это реальные результаты для объединённых моделей из пакета ultralytics, соответствующие опубликованным значениям параметров и FLOPs на каждой странице модели:

МодельСлоиПараметрыGFLOPsreg_maxend2endСлой DFL
YOLOv8n723,151,9048.716FalseDFL
YOLO11n1002,616,2486.516FalseDFL
YOLO26n1222,408,9325.51TrueIdentity

YOLO26n сообщает reg_max=1, end2end=True и слой DFL Identity — архитектурный признак его NMS-free и DFL-free head.

Объединённые и необъединённые значения

Значения параметров и FLOPs приводятся для объединённой модели (model.fuse()), в которой каждый Conv объединён со своим слоем пакетной нормализации. Это соответствует опубликованным спецификациям; только что загруженный checkpoint показывает немного большие значения до объединения.

Заключение#

В разных версиях архитектура YOLO менялась поэтапно: backbone перешёл от Darknet-53 к блокам C3, C2f и C3k2 на основе CSP с вниманием C2PSA; neck сохранил структуру FPN + PAN, а SPP превратился в SPPF; head прошёл путь от anchor-based к anchor-free, а затем к сквозной архитектуре YOLO26 без NMS и DFL.

Чтобы определить собственные архитектуры, см. руководство по конфигурации Model YAML или сравни модели на страницах моделей. Если у тебя есть вопросы, обратись к сообществу в GitHub или Discord.

Часто задаваемые вопросы#

  • У модели YOLO есть backbone, который извлекает признаки из изображения со stride 8, 16 и 32, neck, который объединяет эти признаки в разных масштабах с помощью FPN и PAN, и head, который предсказывает ограничивающие боксы и оценки классов. Каждая модель Ultralytics YOLO от YOLOv3 до YOLO26 соответствует этой трёхэтапной архитектуре.

  • C2f (YOLOv8) — это блок CSP, который конкатенирует выходы всех внутренних карт признаков Bottleneckn + 2 перед своей свёрткой слияния, тогда как более старый C3 передаёт только 2. C3k2 (YOLO11 и YOLO26) — это подкласс C2f, который может заменять каждый Bottleneck блоком C3k (вариантом C3 с настраиваемым размером ядра), если установлен флаг c3k. Оба определены в block.py.

  • YOLO11 вносит три структурных изменения по сравнению с YOLOv8: заменяет блок C2f в backbone и neck на C3k2, добавляет блок C2PSA с self-attention после SPPF и заменяет классификационную ветвь head на более лёгкие depthwise-separable свёртки. В обеих моделях сохраняется одна и та же безанкорная раздельная head Detect с регрессией reg_max=16 DFL, поэтому эти изменения уменьшают количество параметров и FLOPs, одновременно повышая точность, а не меняя интерфейс детектирования.

  • Современные модели Ultralytics YOLO работают без якорей. YOLOv8, YOLO11 и YOLO26 используют безанкорную раздельную head Detect с отдельными ветвями для регрессии bbox и классификации. Исходные YOLOv3 и YOLOv5 использовали якоря, но Ultralytics выпускает их варианты YOLOv3u и YOLOv5u, конфигурации которых используют ту же безанкорную head, что и YOLOv8.

  • Да — YOLO26 устанавливает end2end=True, благодаря чему Detect использует head с соответствием один к одному, выдающую одно предсказание для каждого объекта и устраняющую этап постобработки подавления немаксимумов, необходимый предыдущим моделям. Подробнее см. в руководстве End-to-End Detection.

  • DFL регрессирует каждую координату bbox как распределение softmax по reg_max бинам (по умолчанию 16 в YOLOv8 и YOLO11) и использует математическое ожидание в качестве координаты вместо предсказания одного скалярного значения. YOLO26 устанавливает reg_max=1, поэтому слой DFL становится тождественной операцией, head регрессирует координаты напрямую, а в экспортированных графах ONNX или TensorRT операция DFL отсутствует.

  • Загрузи модель в Python и вызови model.info(), чтобы получить сводку по слоям, параметрам и GFLOPs. Распознанные слои находятся в model.model.model — например, model.model.model[-1] — это head Detect, предоставляющая такие атрибуты, как reg_max и end2end. Полная архитектура определена в YAML-файле конфигурации модели.

Участники

Комментарии