YOLOアーキテクチャの解説:YOLOv3からYOLO26まで#
すべてのUltralytics YOLOモデルは、特徴を抽出するbackbone、スケール間で特徴を融合するneck、ボックスとクラスを予測するheadという3つのステージで構成されています。このガイドでは、各ステージを構成するモジュールと、YOLOv3からYOLO26までにそれらがどのように変化したかを説明し、各コンポーネントをultralytics/cfg/models/配下の設定ファイルにある定義およびultralytics/nn/modules/のモジュールクラスまで追跡します。
各モデルは、レイヤーの順序付きリストとしてYAMLファイルに宣言的に定義され、すべてのレイヤーは[from, repeats, module, args]形式に従います。つまり、どのレイヤーが入力を供給するか、モジュールを何回繰り返すか、レイヤークラス(Conv、C3k2、SPPF、Detect、…)、およびコンストラクター引数を指定します。Model YAML Configuration Guideでは、repeatsとargsがバリアントのdepthおよびwidth multiplierに応じてどのようにスケールするかを含め、この形式とモジュール解決システム全体について説明しています。このガイドでは、モジュール自体と、バージョンごとの変化に焦点を当てます。
3つのステージ#
すべてのUltralytics YOLOモデルは、それぞれ異なる役割を持つ3つの連続したステージを通じて画像を処理します。
| ステージ | 役割 | 出力 |
|---|---|---|
| Backbone | 入力画像から複数の解像度で特徴を抽出します | ストライド8、16、32(P3、P4、P5)の特徴マップ |
| Neck | 小さい物体と大きい物体の両方がコンテキストを持てるよう、スケール間で特徴を融合します | マルチスケールで融合された特徴マップ |
| Head | 融合された特徴からバウンディングボックスとクラススコアを予測します | アンカーポイントごとの検出結果 |
基本単位は**Conv**ブロック(conv.pyで定義)です。これは、2D畳み込み、バッチ正規化、SiLUアクティベーションを順番に適用します。以下のより大きな各モジュールは、Convブロックを組み合わせて構築されています。
アーキテクチャ図#
各バージョンは同じbackbone → neck → headという骨格を維持し、特定のステージを変更しています。以下のタブではバージョンごとの構成を示します。backboneとneckのステージはultralytics/cfg/models/の設定に従いますが、YOLOv3とYOLOv5のheadは、パッケージの設定ファイルが実際に提供するアンカーフリーのu-variant headではなく、元のアンカーベース形式で描画されています。タブを順に確認すると、各世代で追加された要素が分かります。要約すると、YOLOv3はFPNのみのアンカーベース検出器、YOLOv5はボトムアップPANパスとSPPFを追加、YOLOv8はC2fブロックとアンカーフリーのDFL headに切り替え、YOLO11はC2PSA attentionとC3k2ブロックを挿入し、YOLO26はSPPF residualを追加してheadをNMS-freeかつDFL-freeにしています。ノードの色はドキュメントの図の規則に従っています。緑は入力、青はbackbone、スレート色は空間プーリングとattention、オレンジは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:#fffYOLOv3とYOLOv5の図は、元のアンカーベースheadを示しています。ultralyticsパッケージはアンカーフリーのYOLOv3uおよびYOLOv5u設定を提供します。これらは、同じDarknet-53とC3 backboneに、YOLOv8のDetect headを組み合わせたもので、Detection Headで説明しています。
Backboneブロック:Bottleneck → C3 → C2f → C3k2#
backboneは、ストライド2のConvダウンサンプリングレイヤーの間に、反復するCSP(クロスステージ・パーシャル)ブロックを積み重ねます。この反復ブロックが、バージョン間で最も大きく変化した部分です。以下のすべてのブロックはblock.pyにあり、c1/c2は入力/出力チャンネル、c = 0.5 * c2はhidden widthです。
Bottleneck(YOLOv3)#
基本単位はBottleneckです。これは2つのConvレイヤー(デフォルトカーネルは(3, 3))で構成され、shortcut=Trueとc1 == c2の場合はオプションでresidual addを行います。YOLOv3のDarknet-53 backboneは、CSP分割なしでこれらを直接積み重ね、3つのスケール(ストライド8、16、32)で検出します。
C3(YOLOv5)#
YOLOv5のC3は、入力を2つの1x1畳み込みに分割します。cv1はn個のBottleneckブロック(カーネルは(1, 1)、続いて(3, 3))に入力し、cv2はそれらをバイパスします。2つのパスを連結し、3つ目の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出力だけが融合convに到達するため、cv3が受け取る特徴マップは2つです。
C2f(YOLOv8)#
YOLOv8のC2f(「2つの畳み込みを持つCSP Bottleneck、高速」)は、融合convに到達する特徴を変更します。
cv1 = Conv(c1, 2 * c, 1)の後、chunk(2)は出力をcチャンネルの2つのテンソルに分割します。n個のBottleneck(c, c)ブロック(カーネルは(3, 3)、(3, 3))が順番に実行され、それぞれが前のブロックの出力を入力として受け取ります。- すべての
n + 2中間テンソルを連結し、cv2 = Conv((2 + n) * c, c2, 1)で融合します。
C3が融合convに2つの特徴マップを渡すのに対し、C2fはn + 2を渡します。つまり、すべての中間bottleneck出力が再利用されます。
C3k2(YOLO11およびYOLO26)#
YOLO11とYOLO26は、C2fのサブクラスであり、反復単位を置き換えるC3k2を使用します。n個の各ブロックは、コンストラクターのフラグに応じて次のいずれかになります。
- 通常の
Bottleneck(デフォルト、c3k=False)、 C3kブロック(c3k=True)。カーネルサイズを設定可能なC3のバリアントです。またはBottleneck+PSABlockのペア(attn=True)。
2番目のYAML引数は、スケールがm、l、xの場合を除き、c3kを設定します。これらの場合はTrueに強制されます。これにより、1つのyolo11.yamlですべての5つのバリアントに対応できます。したがって、[-1, 2, C3k2, [512, False]]はBottleneck内部をnおよびsで構築しますが、C3k内部はm、l、xで構築します。512はスケーリング前のチャンネル数であり、バリアントのwidth multiplierによってnでは128に、xでは768になります。CSPモジュールでは、repeatsフィールド(ここでは2)は、バリアントのdepth multiplierでスケーリングされる前に、個別のモジュールを積み重ねるのではなく、ブロック内部の反復回数になります。
空間プーリング:SPP → SPPF#
backboneの末尾では、spatial-pyramid-poolingブロックがreceptive fieldを広げます。YOLOv5は、元のマルチカーネルSPPを**SPPF**(Spatial Pyramid Pooling - Fast)に置き換えました。これは、1つのMaxPool2d(kernel_size=5, stride=1, padding=2)をn = 3回順番に適用し、入力と3つすべてのプーリング出力を連結して、1x1 Convで融合します。これはSPP(k=(5, 9, 13))と数学的に同等ですが、連鎖した5x5プーリングが大きなカーネルのreceptive fieldをカバーするため、より低コストです。
YOLO26はshortcutフラグ(SPPF, [1024, 5, 3, True])を渡します。最深層のc1 == c2 == 1024であるため、SPPFがresidual connection(return y + x)を追加します。
空間attention:C2PSA(YOLO11以降)#
YOLO11はSPPFの後に**C2PSA**を追加しました。これは、n個のPSABlock(Position-Sensitive Attention)モジュールを積み重ねたactive branchを持つCSPブロックです。cv1 = Conv(c1, 2 * c, 1)が特徴を分割し、片方がPSABlockスタックを通過し、cv2 = Conv(2 * c, c1, 1)が連結結果を融合します。各PSABlockは、multi-head attentionに続いて2層のfeed-forward network(Conv(c, 2 * c, 1) → Conv(2 * c, c, 1))を適用し、それぞれにresidual connectionがあります。YOLO26も同じC3k2 + C2PSA backboneを維持しています。
Neck:FPN + PAN#
neckは、backboneのP3/P4/P5特徴マップを、top-downの特徴ピラミッドネットワーク(FPN)と、それに続くbottom-upのパス集約ネットワーク(PAN)で融合します。YAMLのheadセクションでは、FPNはnn.Upsample + Concat(高解像度へsemantic informationを伝達)であり、PANはストライド2のConv + Concat(上方向へlocalization informationを伝達)です。
# 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]] # 19neckは各世代のbackboneブロックを再利用します。YOLOv5ではC3、YOLOv8ではC2f、YOLO11とYOLO26ではC3k2です。そのため、各merge pointではbackboneと同じモジュールが実行されます。3つの融合出力がheadに入力されます。例外はYOLOv3です。YOLOv3のneckはtop-down FPNのみであり、YAMLのheadにストライド2のダウンサンプリングがないため、YOLOv5が導入したbottom-up PANパスはありません。
Detection Head:アンカーベース → アンカーフリー → NMS-free#
headは、3つの融合特徴マップをdetection taskの予測に変換します。設計はバージョンを重ねるごとに、アンカーベースからアンカーフリー、さらにNMS-freeへと変化しました。
アンカーフリーでdecoupledなDetect#
元のYOLOv3とYOLOv5は、アンカーベースでcoupledなheadを使用していました。事前定義されたanchor boxと、ボックスおよびクラス予測で共有するbranchを使用します。独立したultralytics/yolov3およびultralytics/yolov5リポジトリは、このアンカーベース設計を維持しています。一方、主要なultralyticsパッケージは、アンカーフリーのYOLOv3uおよびYOLOv5uバリアントを提供します。これらは、同じDarknet-53とC3 backboneに、YOLOv8のアンカーフリーDetect headを組み合わせたものです。ここで説明するyolov3.yamlおよびyolov5.yaml設定は、過去の設計ではなく、これらのuバリアントです。
Detect head(head.py)はアンカーフリーでdecoupledです。ピラミッドレベルごとに2つの並列branchを実行し、anchor boxに対してではなく、grid point上で直接予測します。
- Box branch(
cv2):Conv(x, c2, 3)→Conv(c2, c2, 3)→Conv2d(c2, 4 * reg_max, 1)。 - **Class branch(
cv3):**YOLO11とYOLO26では、2つのdepthwise-separableブロック(DWConv+1x1 Conv)→Conv2d(c3, nc, 1)です。YOLOv8ではlegacyバリアントを使用し、2つの3x3 Convレイヤー→Conv2d(c3, nc, 1)となります。
したがって、各anchor pointはno = nc + 4 * reg_max個の出力を生成します。事前定義されたanchorを除去することで、調整が必要なハイパーパラメーターからanchor boxのサイズとアスペクト比がなくなります。
Distribution Focal Loss(DFL)#
YOLOv8とYOLO11は、4つのボックス座標をそれぞれ単一のスカラーではなく、reg_max = 16個のbinにわたる分布として回帰します(Generalized Focal Lossの積分形式)。DFLモジュールは、4 * reg_max個のbox channelを(4, reg_max)にreshapeし、reg_max個のbinに対してsoftmaxを適用し、期待bin indexを予測座標として取得します。つまり、各bin indexにsoftmax確率を重み付けして合計します。これは、重みがbin index arange(reg_max)である固定1x1畳み込みとして実装されるため、加重和は単一のdot productになります。
YOLO26:NMS-free、DFL-free#
YOLO26は、headが直接読み取る2つのYAMLパラメーターを設定します。
end2end: True—Detectはbranchをone-to-one head(one2one_cv2/one2one_cv3)にdeep copyします。このheadは物体ごとに1つの予測を生成し、非最大抑制(NMS)の後処理ステップを除去します。exportと移行の詳細については、End-to-End Detection guideを参照してください。reg_max: 1— binが1つの場合、self.dflはnn.Identity()およびno = nc + 4になります。headは座標を直接回帰し、exportされたONNXグラフにはDFL処理が現れません。
5つのモデルサイズ(n/s/m/l/x)全体で、YOLO26はCOCOにおいて、1.7~11.8 msのT4 TensorRT latencyで40.9~57.5 mAPを達成します。YOLO26 paperの報告値です。
バージョンごとの概要#
| バージョン | Backboneブロック | 空間プーリング | Attention | Detection head | DFL |
|---|---|---|---|---|---|
| YOLOv3 | Darknet-53(Bottleneck) | 基本設定にはなし | なし | 元の構成:アンカーベース、uバリアント:アンカーフリー | なし / あり(u) |
| YOLOv5 | C3(CSP) | SPPF | なし | 元の構成:アンカーベース、uバリアント:アンカーフリー | なし / あり(u) |
| YOLOv8 | C2f | SPPF | なし | アンカーフリー、decoupled | あり(reg_max=16) |
| YOLO11 | C3k2 | SPPF | C2PSA | アンカーフリー、decoupled | あり(reg_max=16) |
| YOLO26 | C3k2 | SPPF + shortcut | C2PSA | アンカーフリー、NMS-free(end2end) | 削除(reg_max=1) |
モデルごとの詳細、性能表、使用例については、YOLOv3、YOLOv5、YOLOv8、YOLO11、YOLO26の各ページを参照してください。
アーキテクチャを自分で確認する#
model.info()メソッドは、レイヤー、パラメーター、FLOPsの概要を出力し、解析済みのモジュールリストはmodel.model.modelで確認できます。
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)このスニペットを3つの世代で実行すると、変化を数値で確認できます。これらはultralyticsパッケージから取得した実際のfused modelの出力であり、各model pageに掲載されているパラメーター数とFLOPs数に一致します。
| モデル | レイヤー数 | パラメーター数 | GFLOPs | reg_max | end2end | DFLレイヤー |
|---|---|---|---|---|---|---|
| YOLOv8n | 72 | 3,151,904 | 8.7 | 16 | False | DFL |
| YOLO11n | 100 | 2,616,248 | 6.5 | 16 | False | DFL |
| YOLO26n | 122 | 2,408,932 | 5.5 | 1 | True | Identity |
YOLO26nはreg_max=1、end2end=True、およびIdentityのDFLレイヤーを報告します。これは、NMS-freeかつDFL-free headというアーキテクチャ上の特徴です。
パラメーター数とFLOPs数は、各Convとそのバッチ正規化レイヤーを統合するfusedモデル(model.fuse())について報告されています。これは公開されている仕様と一致します。新しく読み込んだcheckpointでは、fuse前のため、やや高い値が報告されます。
まとめ#
バージョンを重ねるごとに、YOLOアーキテクチャは一度に1つのステージを変更してきました。backboneはDarknet-53から、CSPベースのC3、C2f、C3k2ブロックとC2PSA attentionへ移行しました。neckはFPN + PAN構造を維持しながら、SPPがSPPFになりました。headはアンカーベースからアンカーフリーへ、さらにYOLO26のNMS-free、DFL-freeなend-to-end設計へ移行しました。
カスタムアーキテクチャを定義するには、Model YAML Configuration Guideを参照するか、model pagesでモデルを比較してください。質問がある場合は、GitHubまたはDiscordでお問い合わせください。
FAQ#
YOLOモデルには、ストライド8、16、32で画像から特徴を抽出するbackbone、FPNとPANでそれらの特徴をスケール間で融合するneck、バウンディングボックスとクラススコアを予測するheadがあります。YOLOv3からYOLO26まで、すべてのUltralytics YOLOモデルがこの3ステージ設計に従っています。
C2f(YOLOv8)は、融合用の畳み込み処理の前に、すべての内部Bottleneck—n + 2特徴マップの出力を連結するCSPブロックです。一方、以前のC3は2つ בלבדを通過させます。C3k2(YOLO11およびYOLO26)はC2fのサブクラスであり、c3kフラグが設定されている場合、各BottleneckをC3kブロック(設定可能なカーネルサイズを持つC3のバリエーション)に置き換えられます。どちらもblock.pyで定義されています。YOLO11では、YOLOv8に対して3つの構造上の変更が加えられています。
C2fバックボーンおよびネックブロックをC3k2に置き換え、SPPFの後にC2PSAセルフアテンションブロックを挿入し、ヘッドの分類ブランチをより軽量な深さ方向分離可能畳み込みに切り替えています。どちらも、reg_max=16DFL回帰を備えた、同じアンカーフリーかつ分離型のDetectヘッドを維持しています。そのため、検出インターフェースを再設計するのではなく、パラメーター数とFLOPs数を削減しながら精度を向上させています。最新のUltralytics YOLOモデルはアンカーフリーです。YOLOv8、YOLO11、YOLO26は、ボックス回帰と分類用に分離されたブランチを持つ、アンカーフリーかつ分離型の
Detectヘッドを使用します。元のYOLOv3とYOLOv5はアンカーベースでしたが、Ultralyticsでは YOLOv3u および YOLOv5u バリエーションとして提供しており、これらの設定ではYOLOv8と同じアンカーフリーヘッドを使用します。はい。YOLO26 では
end2end=Trueが設定されるため、Detectはオブジェクトごとに1つの予測を生成する一対一のヘッドを使用します。これにより、以前のモデルで必要だったNon-Maximum Suppressionの後処理ステップが不要になります。詳しくは End-to-End Detectionガイド をご覧ください。DFLでは、各ボックス座標を
reg_max個のビンにわたるsoftmax分布(YOLOv8およびYOLO11ではデフォルトで16個)として回帰し、単一のスカラーを予測する代わりに、その期待値を座標として使用します。YOLO26ではreg_max=1が設定されるため、DFLレイヤーは恒等演算になり、ヘッドは座標を直接回帰します。その結果、エクスポートされたONNXまたはTensorRTグラフにはDFL演算が現れません。Pythonでモデルを読み込み、
model.info()を呼び出すと、レイヤー、パラメーター、GFLOPsの概要を確認できます。解析されたレイヤーはmodel.model.modelに格納されています。たとえば、model.model.model[-1]はDetectヘッドであり、reg_maxやend2endなどの属性を公開しています。アーキテクチャ全体は、モデルの YAML設定ファイル で定義されています。