YOLO26 deep dive: tại sao Ultralytics bỏ DFL sau 4 năm?

YOLO26 deep dive đọc thẳng source code: reg_max=1 thay DFL, end2end NMS-free native, MuSGD optimizer (SGD + Muon hybrid). Cleanup pass cho YOLO modern era. CPU nhanh hơn 43%.

YOLO26 deep dive: tại sao Ultralytics bỏ DFL sau 4 năm?

Hôm qua mình vừa publish bài YOLOv12 deep dive, kết bằng một câu kiểu "v12 là cú nhảy đầu tiên sang attention-centric". Tối qua, một issue trên GitHub Ultralytics nảy lên feed của mình, người ta nói đến yolo26. WTF... 26? 26 là cái số quái gì? Mở docs xem, hoá ra Ultralytics đã release YOLO26 ở YOLO Vision 2025 tại London, tháng 9/2025. Source ship trong ultralytics 8.4.0 (commit f2d3aed, 14/01/2026), đến giờ đã hơn 3 tháng và có gần 40 commit fix bug edge case.

Cái làm mình dừng lại không phải là tên version nhảy từ 13 sang 26 (Ultralytics đặt tên hơi marketing, mình bỏ qua). Cái làm mình dừng là khi mở ultralytics/cfg/models/26/yolo26.yaml ra đọc, ba dòng đầu file:

Lines 7-10 trong yolo26.yaml: end2end: True và reg_max: 1. Hai dòng này đảo ngược 4 năm thiết kế của YOLO modern era.

reg_max: 1. Cái này thay đổi mọi thứ. v8 đến v13 đều dùng reg_max=16, mình vừa giải thích trong bài YOLOv8 deep dive là một trong những thiết kế bền bỉ nhất của YOLO modern era. v26 đặt thẳng về 1, distribution biến mất, regression quay về dạng simple.

Đọc tiếp end2end: True, tức là NMS-free native, không phải dual-assignment hack như v10. Rồi mở ultralytics/optim/muon.py thấy class MuSGD, một optimizer mới hẳn. Mượn từ training LLM.

Thesis của mình sau khi đọc xong code: YOLO26 không phải breakthrough kiến trúc như v12. Nó là một cleanup pass. Ultralytics dọn dẹp những thứ mà 4 năm qua YOLO modern era đã tích lũy như technical debt: DFL phức tạp khi export, NMS hack, optimizer không ổn định ở scale lớn. v26 trừ đi thay vì cộng thêm. Backbone vẫn là YOLOv11. Điểm khác chỉ ở head, loss, và optimizer.

Latency-accuracy trade-off của YOLO26 (đỏ) vs YOLOv5-13 và RT-DETR. Bên trái: T4 inference latency. Bên phải: end-to-end latency vs RT-DETR family

Bài này cùng style với bài v12. Mình giả định bạn đã đọc v12 (hiểu Area Attention, R-ELAN, FlashAttention dependency) và bài v8 (hiểu DFL, anchor-free, decoupled head). Source mình tham chiếu là github.com/ultralytics/ultralytics commit ổn định gần nhất. Mọi claim đều có thể trace bằng git blame hoặc đọc thẳng file.

Backbone: vẫn là YOLOv11, không thay đổi gì

Trước khi nói về phần đổi mới, cần nói rõ phần KHÔNG đổi để tránh hiểu nhầm. Backbone v26 lấy nguyên xi từ v11. Mở YAML đọc thẳng:

backbone:
  - [-1, 1, Conv, [64, 3, 2]]              # 0-P1/2
  - [-1, 1, Conv, [128, 3, 2]]             # 1-P2/4
  - [-1, 2, C3k2, [256, False, 0.25]]
  - [-1, 1, Conv, [256, 3, 2]]             # 3-P3/8
  - [-1, 2, C3k2, [512, False, 0.25]]
  - [-1, 1, Conv, [512, 3, 2]]             # 5-P4/16
  - [-1, 2, C3k2, [512, True]]
  - [-1, 1, Conv, [1024, 3, 2]]            # 7-P5/32
  - [-1, 2, C3k2, [1024, True]]
  - [-1, 1, SPPF, [1024, 5, 3, True]]      # 9
  - [-1, 2, C2PSA, [1024]]                 # 10

C3K2 là block của v11. SPPF có từ v5. C2PSA (CSP với Spatial Attention) cũng là của v11. So với YAML của yolo11.yaml thì gần như identical, chỉ khác vài tham số fine-tune nhẹ.

Điều này đáng nói vì nó loại bỏ một câu chuyện đẹp mà mình đã định viết. Lúc đọc paper review trước, mình đoán v26 sẽ tiếp nối v12, dùng Area Attention thiện hơn hoặc một biến thể attention mới. Sai. Ultralytics quay ngược lại v11, vứt Area Attention của v12 đi cùng với DFL.

Lý do? Mình suy ra hai khả năng:

  1. Area Attention không scale tốt cho deployment. v12 cần FlashAttention (Turing GPU trở lên), không chạy được trên Jetson Nano cũ, không tối ưu cho ARM CPU mobile. Khi v26 nhắm "edge-first", attention bị loại trước.
  2. Gain mAP của v12 attention nhỏ hơn cost. v12 vs v11 chỉ tăng 1-1.2 mAP nhưng training time tăng (600 vs 500 epoch), dependency hardware tăng. Trade-off không đáng cho version production.

Không có cách verify trực tiếp lý do của Ultralytics, nhưng quyết định kỹ thuật thì rõ: v11 backbone đã đủ tốt, không cần thêm. Effort đổ vào head + loss + optimizer thay vì backbone novel.

Một, DFL chết bằng reg_max: 1

Để hiểu vì sao reg_max=1 là một quyết định lớn, cần nhớ DFL làm gì. Trong v8 (2023), bounding box không được predict trực tiếp dưới dạng 4 con số (left, top, right, bottom). Mỗi cạnh được predict như một phân phối xác suất trên 16 bin rời rạc, rồi softmax lấy expected value. Idea từ paper Generalized Focal Loss (Li et al., 2020). Lý do dùng nó là làm gradient mượt hơn ở vùng cạnh object mơ hồ.

DFL hoạt động và trở thành default cho v8, v9, v10, v11, v12, v13. Năm version, không ai dám động vào. Trong bài v12 mình đã viết:

"Loss config y hệt v8. Box gain 7.5, class gain 0.5, DFL gain 1.5. Không một thay đổi. Tức là từ v8 đến v12, đoạn từ feature pyramid output ra prediction về cơ bản đứng yên."

YOLO26 phá điều đó. reg_max: 1 nghĩa là chỉ 1 bin, distribution biến mất, expected value của 1 phân phối 1 bin là chính giá trị đó, regression quay về predict trực tiếp 1 con số cho mỗi cạnh.

Box edge regression: v8-v13 dùng softmax distribution trên 16 bin rồi lấy expected value, v26 đặt reg_max=1 để predict trực tiếp 1 scalar cho mỗi cạnh box

Code DFL trong ultralytics/nn/modules/block.py vẫn còn, không bị xoá hẳn. Nhưng với reg_max=1, layer DFL biến thành identity function. Đây là cách clean để deprecate một feature mà không break interface, checkpoint cũ vẫn load được.

Câu hỏi đầu tiên của mình: tại sao? DFL có gain accuracy mà.

Đào sâu hơn, lý do nằm ở deployment. DFL có 2 vấn đề:

  1. Operation chưa standard. ONNX, CoreML, TFLite không có DFL op native. Khi export model, Ultralytics phải gắn custom plugin hoặc rewrite module thành softmax + matmul tay. Một plugin tốt cho TensorRT có thể không chạy được trên CoreML mà không sửa thêm. Nhân lên 5 framework export, mỗi version đụng hàng tá bug đặc thù. Có thể tự verify bằng cách xem lịch sử commit Ultralytics, search "DFL export", sẽ thấy hàng trăm fix qua các version.
  2. Tốn compute thừa ở edge. DFL thêm một layer 16 channels và softmax cho mỗi cạnh box, mỗi prediction location. Trên T4 GPU thì không đáng kể (compute dư). Trên CPU ARM hoặc Jetson Nano thì cộng dồn lên 5-10% latency, đủ để phá real-time budget.

Ultralytics nhận ra: lợi ích accuracy của DFL nhỏ (paper gốc claim ~0.5 mAP), trong khi cost deployment lớn. Khi v26 nhắm edge-first, vứt đi.

Đây là một quyết định ngược chiều xu hướng "thêm complexity, accuracy cao hơn" của 5 năm qua. v9 thêm GELAN, v10 thêm dual-assignment, v11 thêm C3K2 + C2PSA, v12 thêm Area Attention, v13 thêm hypergraph correlation. Mỗi version cộng thêm thứ. v26 lần đầu tiên trừ đi. Mình thấy đây là dấu hiệu mature của framework, đủ nhiều moving parts để cần dọn dẹp.

Hai, NMS-free native với end2end: True

NMS-free không phải mới. v10 (Wang et al. 2024, Tsinghua) đã làm rồi với dual label assignment: train với cả one-to-many head (cho gradient phong phú) và one-to-one head (cho inference NMS-free), ở inference chỉ dùng one-to-one. Cách này hoạt động nhưng có đặc điểm: hai head song song, hai loss tính song song, training graph phức tạp hơn.

NMS-free strategies so sánh: v10 cần dual head (one-to-many cho training, one-to-one cho inference) với dual loss path, v26 dùng một single one-to-one head end-to-end, đơn giản hơn cả v10

v26 làm khác. Trong YAML có flag end2end: True ngay đầu file, không phải optional flag mà là default. Đọc Detect module trong ultralytics/nn/modules/head.py, khi flag này bật, head được trained với one-to-one assignment ngay từ đầu, kết hợp với regularization khiến output "sparse" tự nhiên. Một head, một loss path, không cần NMS post-process.

Hệ quả thực tế: pipeline inference của v26 đơn giản hơn cả v10. Không có NMS function, không có IoU threshold để tune, không có max_det parameter để debate. Output là final luôn. Test thử bằng cách load model trong Python:

from ultralytics import YOLO
model = YOLO('yolo26n.pt')
result = model('image.jpg')
# result.boxes đã là final, không cần result.boxes.cpu().nms()

Trên CPU, đây là chỗ v26 ăn điểm to nhất. NMS thuần CPU là một vòng lặp Python (hoặc C++) không vectorize được dễ, mỗi inference tốn 10-30ms tuỳ số box. Bỏ NMS thật sự (không phải bỏ trên giấy) cộng với bỏ DFL, v26-N giảm CPU latency 43% so với v11/v12 cùng size.

43% là con số nghe hơi marketing, nhưng break down ra: bỏ DFL khoảng 8-10%, bỏ NMS thuần khoảng 25-30%, còn lại đến từ tối ưu graph (BatchNorm folded, layer fusion). Cộng lại đến 43% là đáng tin.

Số liệu cụ thể từ Ultralytics docs (CPU ONNX, 640px):

  • YOLO26n: 38.9ms (so với v11n ~70ms cùng điều kiện)
  • YOLO26s: 87.2ms
  • YOLO26m: 220ms
  • YOLO26l: 286ms
  • YOLO26x: 525ms

Trên T4 GPU (TensorRT FP16), gain nhỏ hơn nhiều vì NMS trên GPU đã được Triton/TensorRT optimize tốt:

  • YOLO26n: 1.7ms (v12n: 1.64ms, gần như nhau)
  • YOLO26s: 2.5ms (v12s: 2.61ms, nhẹ hơn nhẹ)
  • YOLO26x: 11.8ms (v12x: 11.79ms, identical)

Pattern rõ: gain của v26 chủ yếu ở CPU, không ở GPU. Đây là chiến lược có chủ đích. v26 nhắm vào edge devices (smartphone, Jetson Nano CPU mode, Raspberry Pi), không nhắm vào server GPU. Server GPU đã đủ nhanh, người ta không cần thêm 0.1ms.

Ba, MuSGD optimizer mượn từ training LLM

Đây là phần mình thích nhất, không phải vì performance gain, mà vì nó inter-disciplinary.

YOLO modern era luôn dùng SGD hoặc AdamW. SGD với momentum stable cho convergence dài hạn, AdamW nhanh hơn cho ít epoch. Bài optimization-algorithms-gd-sgd-adam của mình đã giải thích trade-off. Cả hai có vấn đề chung: ở scale lớn (model X 60M+ params), training instability bùng lên ở gần cuối, loss landscape gập ghềnh, gradient explode hoặc plateau lâu.

LLM community có cùng vấn đề ở scale to hơn nhiều. Năm 2024-2025, một loạt optimizer mới ra đời: Muon (Jordan et al., arXiv 2502.16982), Lion, Sophia, Shampoo. Trong đó Muon được dùng để train Kimi K2 của Moonshot AI (LLM Trung Quốc với context 200k+ tokens). Idea: gradient được orthogonal hoá qua Newton-Schulz iterations, làm gradient flow ổn định hơn ở deep network.

YOLO26 mượn idea này về vision domain. Mở ultralytics/optim/muon.py đọc thẳng, không cần đoán:

MuSGD hybrid optimizer: gradient G chia làm hai path song song, SGD path giữ momentum + weight decay, Muon path qua Newton-Schulz x5 để orthogonalize, hai update combine 50/50, fallback AdamW khi iterations < 10000
def zeropower_via_newtonschulz5(G: torch.Tensor, eps: float = 1e-7):
    X = G.bfloat16()
    X /= X.norm() + eps  # ensure top singular value <= 1
    if G.size(0) > G.size(1):
        X = X.T
    for a, b, c in [(3.4445, -4.7750, 2.0315)] * 5:  # 5 iterations fixed
        A = X @ X.T
        B = b * A + c * A @ A
        X = a * X + B @ X
    if G.size(0) > G.size(1):
        X = X.T
    return X

5 lần Newton-Schulz iteration với coefficient cố định (3.4445, -4.7750, 2.0315). Ba số này không phải random, được optimize trong paper Muon gốc để maximize convergence slope tại zero. Output không phải orthogonal matrix chính xác (như SVD), mà là một xấp xỉ "đủ tốt" với singular values rơi vào khoảng Uniform(0.5, 1.5). Empirically work tốt cho NN optimization.

Hàm zeropower_via_newtonschulz5 trong ultralytics/optim/muon.py: 5 lần lặp với cùng coefficient, chỉ vài dòng linear algebra trên bfloat16. Đây là phần "Muon" của MuSGD.

Phần MuSGD thì là wrapper hybrid:

optimizer = MuSGD(param_groups, muon=0.5, sgd=0.5)
# Mỗi parameter group có flag `use_muon: True/False`
# - use_muon=True  → param này nhận cả Muon update + SGD update (50/50)
# - use_muon=False → param này chỉ nhận SGD update (giống v8-v12)

Default 50/50 weight giữa Muon và SGD update. Conv filter 4D được reshape thành (out_channels, in_channels*H*W) rồi mới orthogonalize, sau đó reshape lại. Final update scale thêm sqrt(max(1, dim_out/dim_in)) để cân bằng theo shape parameter.

Có một dòng nhỏ trong engine/trainer.py rất đáng để ý:

Dòng 999 trong engine/trainer.py: optimizer auto-select dựa trên iterations > 10000. Dataset nhỏ tự fallback AdamW.

Tức là MuSGD chỉ kick in khi training dài hơn 10000 iterations. Custom dataset nhỏ (vài trăm ảnh, vài chục epoch) sẽ tự động fallback về AdamW. Đây là chi tiết practical quan trọng. Nó có ý nghĩa: Muon là optimizer tốt cho long horizon (LLM scale), không phải fine-tuning ngắn. Nếu bạn fine-tune v26 trên dataset 500 ảnh 30 epoch, batch 16 thì total ~1000 iter, MuSGD không kick in, gain biến mất.

Lý do mình thấy thú vị: đây là lần đầu tiên YOLO mượn optimizer từ LLM một cách rõ ràng. Trong vài năm qua dòng chảy idea thường là vision → LLM (transformer ban đầu là vision idea trở qua NLP). Lần này thì ngược lại. Điều này phản ánh thực tế là LLM community đầu tư vào optimization research nhiều hơn vision community trong 2 năm gần đây, đơn giản vì ngân sách training của họ lớn hơn vài bậc, mỗi % gain ở optimizer tiết kiệm hàng triệu USD.

Practical impact: Ultralytics docs claim v26 cần ít epoch hơn để converge so với v12 (v12 cần 600 epoch). Theo training recipe guide chính thức, v26 base models train trên COCO ở 640px với batch 128. Với scale đó, MuSGD chắc chắn kick in.

Bốn, ProgLoss và STAL nhắm small object

Một trong những điểm yếu kéo dài của YOLO là detect small object. COCO benchmark tách riêng AP_small (object < 32×32 pixel) và YOLO luôn underperform ở đó so với DETR-family. Lý do: anchor-free + multi-scale FPN giúp đỡ object trung-lớn, nhưng small object vẫn bị underrepresent trong loss vì chỉ vài positive sample mỗi ảnh.

v26 fix bằng 2 cơ chế, integrated vào loss và assignment:

ProgLoss (Progressive Loss Balancing). Loss components (box, class, obj) thường có weight cố định. v8 dùng box=7.5, cls=0.5, dfl=1.5 từ ngày một. ProgLoss thay weight cố định bằng schedule động: early epochs ưu tiên class loss (model học categorize trước), late epochs ưu tiên box loss (refine localization). Mỗi class cũng có weight riêng được adjust dựa trên frequency và difficulty trong batch.

STAL (Small-Target-Aware Label Assignment). TaskAlignedAssigner của v8 chọn positive sample dựa trên score^α * IoU^β. Với object nhỏ, IoU có thể low (vì box nhỏ, sai 2-3 pixel đã hỏng IoU), khiến small object hiếm khi được assign positive. STAL điều chỉnh α, β dynamic theo object size: object nhỏ giảm trọng số IoU, tăng trọng số confidence. Hệ quả: small object được trained với nhiều positive sample hơn → learn tốt hơn.

STAL label assignment: với TaskAlignedAssigner cũ small object chỉ nhận 1-2 positive sample, với STAL của v26 small object nhận 4-5 positive sample nhờ dynamic alpha/beta theo object size

Cá nhân mình thấy đây là phần thực dụng nhất của v26 cho hackathon UAV (drone bay cao, mọi object nhỏ hết). Nếu bạn đang làm drone perception, thử v26 trước rồi so với v12 trên dataset của bạn. Mình đoán v26 thắng ít nhất 2-3 mAP trên small object subset.

Multi-task: 5 task cùng một backbone

Một feature ít được quảng bá nhưng quan trọng: v26 ship 5 task trên cùng kiến trúc. Ngoài yolo26.yaml còn có yolo26-seg.yaml, yolo26-pose.yaml, yolo26-obb.yaml, yolo26-cls.yaml. Tất cả share backbone + neck, chỉ khác head.

Task Variant Top accuracy T4 latency
Detection YOLO26n→x 40.9 → 57.5 mAP 1.7 → 11.8ms
Segmentation YOLO26n-seg → x-seg 33.9 → 47.0 mask mAP 2.1 → 16.4ms
Pose YOLO26n-pose → x-pose 57.2 → 71.6 mAP 1.8 → 12.2ms
OBB (DOTA v1) YOLO26n-obb → x-obb 52.4 → 56.7 mAP 2.8 → 30.5ms
Classification YOLO26n-cls → x-cls 71.4 → 79.9 Top-1 1.1 → 3.8ms
YOLO26 unified architecture support 5 task: detection, segmentation, pose/keypoints, oriented detection, classification. Cùng backbone, head riêng.

Cho hackathon UAV, mình đặc biệt chú ý đến OBB (Oriented Bounding Box). Drone bay cao chụp ảnh xuống, object thường rotate (xe, container, công trình). YOLO26-l-obb đạt 56.2 mAP trên DOTA v1, 13ms trên T4. So với YOLOv11-OBB cùng size, nhanh hơn ~20%. Đây là thứ thực sự hữu ích cho aerial detection task.

Bốn pillar enhancement, nhìn tổng thể

Bốn enhancement chính của YOLO26: (a) DFL "removal" qua reg_max=1, (b) end-to-end NMS-free, (c) ProgLoss + STAL, (d) MuSGD optimizer

Bốn pillar này đại diện cho ý đồ thiết kế của v26. Hai pillar đầu là về deployment (vứt bỏ overhead). Hai pillar sau là về training quality (small object + convergence). Cả 4 đều phục vụ một mục tiêu: edge-first.

Core architecture YOLO26: input → backbone (kế thừa v11) → multi-scale feature → neck → direct regression head (NMS-free) → quantized export. ProgLoss + STAL ở training, MuSGD ở optimizer.

Pipeline tổng thể nhìn không khác v11 mấy, vì backbone và neck giống nhau. Khác biệt nằm ở 4 chỗ: head end-to-end, reg_max=1 ở regression, ProgLoss ở training, MuSGD ở optimizer.

YOLO26 vs YOLOv12: bảng so sánh head-to-head

Model mAP T4 TRT CPU ONNX Params
YOLOv12-N 40.6 1.64ms ~70ms* 2.6M
YOLO26-N 40.9 1.7ms 38.9ms 2.4M
YOLOv12-S 48.0 2.61ms ~150ms* 9.3M
YOLO26-S 48.6 2.5ms 87.2ms 9.5M
YOLOv12-M 52.5 4.86ms ~330ms* 20.2M
YOLO26-M 53.1 4.7ms 220.0ms 20.4M
YOLOv12-X 55.2 11.79ms ~900ms* 59.1M
YOLO26-X 57.5 11.8ms 525.8ms 55.7M

*CPU ONNX của v12 mình estimate dựa trên Ultralytics benchmark docs

Đọc bảng có ba quan sát:

  1. GPU latency gần như identical giữa v26 và v12 ở mọi scale. v26 không nhanh hơn trên GPU.
  2. CPU latency v26 thấp hơn ~40-45% ở mọi scale. Đây là gain thực sự.
  3. mAP v26 nhỉnh hơn 0.3-2.3 điểm, gain tăng dần theo scale (X tăng 2.3 điểm là đáng kể).

Tóm lại: nếu bạn deploy GPU server, sự khác biệt giữa v12 và v26 nhỏ. Nếu bạn deploy CPU edge (Jetson Nano CPU mode, smartphone, embedded), v26 thắng đậm.

Steel-man: có thực sự cần switch sang v26?

Để fair, mình thử trình bày case mạnh nhất cho việc không switch:

Argument 1: backbone v26 quay về v11, accuracy gain so với v11 là gì?

So với v11 cùng size: v11n đạt 39.4 mAP, v26n đạt 40.9 → tăng 1.5. v11s 46.9 → v26s 48.6 → tăng 1.7. v11x 54.6 → v26x 57.5 → tăng 2.9. Gain accuracy không đến từ backbone, mà đến từ MuSGD training tốt hơn + ProgLoss/STAL cho small object. Đây là gain "free" không cần thay kiến trúc.

Argument 2: v12 Area Attention có ưu điểm về quality semantic mà v26 không có.

v12 dùng attention thật, có receptive field rộng. v26 quay về CNN thuần. Trên một số dataset có scene phức tạp (relation giữa các object xa nhau), attention vẫn có thể tốt hơn.

Phản biện: v26 đánh bại v12 ở mAP overall (57.5 vs 55.2 cho X). Nếu attention thật sự critical, gap sẽ nhỏ hoặc đảo. Có thể attention chỉ tốt cho một subset task niche. Cần benchmark trên domain riêng để chắc.

Argument 3: ecosystem tooling chưa catch up.

v8, v11, v12 đã có hàng nghìn tutorial, model zoo, integration với Roboflow, Weights & Biases, etc. v26 mới ra, tooling còn thiếu.

Phản biện: Ultralytics framework là cùng một code base. Switch v12 sang v26 là đổi model = YOLO('yolov12n.pt') thành model = YOLO('yolo26n.pt'). Nếu pipeline của bạn dùng Ultralytics API, switch gần như không có cost. Source v26 đã public 4 tháng, đã có nhiều fix bug edge case (RKNN export, OpenVINO INT8, Jetson Orin benchmark), risk thấp hơn nhiều so với lúc paper v12 mới ra.

Steel-man tốt nhất mình tìm được: nếu bạn đang fine-tune dataset rất nhỏ (<10k iter total), MuSGD không kick in, gain training của v26 biến mất, chỉ còn gain inference. Khi đó so sánh v26 với v11 (cùng backbone, không cần switch nhiều) có thể practical hơn.

Kill shot: edge deployment story

Đây là chỗ v26 thực sự nổi trội và là lý do mình tin nó sẽ stick.

Nhớ lại bài v12 mình kết bằng FAQ về Jetson Orin Nano: "v12 chạy được, ~3-4ms cho N variant, nhưng cần FlashAttention, cần Ampere trở lên". Đây là một limitation lớn vì Jetson Nano cũ (2019, Maxwell) và nhiều edge device không support.

YOLO26 không có limitation đó. Vì backbone là CNN thuần (C3K2 + SPPF + C2PSA, không có Area Attention của v12), không cần FlashAttention. Chạy được trên:

  • Jetson Nano cũ (Maxwell 2019): được, không như v12.
  • Jetson Xavier (Volta): được.
  • Jetson Orin Nano/NX (Ampere): tốt nhất, dùng INT8 Tensor Core.
  • Smartphone (ARM CPU + NPU): được, TFLite INT8 ổn định nhờ không có attention nhạy precision.
  • Raspberry Pi 4/5 (ARM CPU): được, v26-N ~150-200ms ở 640px là practical cho 5fps streaming.

Lần đầu tiên trong mấy năm, một YOLO state-of-the-art có deployment story sạch trên gần như mọi device. v8/v11 vốn cũng deploy được khắp nơi nhưng accuracy thấp hơn. v12 cao accuracy nhưng kén GPU. v26 fix gap đó.

So sánh CPU latency cho YOLO26-N trên các target (estimate từ Ultralytics docs):

  • T4 GPU TRT FP16: 1.7ms
  • Jetson Orin Nano (Ampere INT8): ~5-6ms
  • iPhone 15 Pro (Neural Engine): ~10ms
  • Raspberry Pi 5 (ARM Cortex-A76, 4 core): ~150ms
  • Smartphone mid-range (ARM Cortex-A78, 4 core): ~200ms

Nếu bạn đang làm IoT với Pi hoặc smart camera nhúng, v26 là lần đầu tiên một SOTA YOLO thực sự practical. Trước đây bạn phải dùng v8-n quantize hoặc compromise mạnh. Giờ v26-n cho 40.9 mAP với 150ms trên Pi 5, đủ cho 5-7fps real-time monitoring.

FAQ

YOLO26 có gì khác YOLOv12? Khác chính ở deployment philosophy. v12 attention-centric với Area Attention + R-ELAN, accuracy tốt nhưng cần FlashAttention (Turing GPU trở lên) và DFL phức tạp khi export. v26 quay về CNN-centric với backbone v11 nguyên xi, đặt reg_max=1 để tắt DFL, end2end=True để NMS-free native, và optimizer mới MuSGD. CPU latency v26 nhanh hơn v12 ~40-45%, GPU latency tương đương. Accuracy v26 nhỉnh hơn 0.3-2.3 mAP ở các scale. Switch là đổi 1 dòng code Ultralytics API.

Tại sao Ultralytics bỏ DFL sau 4 năm? Không phải vì DFL kém accuracy. DFL gain nhỏ (~0.5 mAP) nhưng cost deployment lớn: ONNX/CoreML/TFLite không có DFL native op, cần custom plugin riêng cho mỗi framework. CPU edge devices tốn 5-10% latency cho DFL softmax. Khi v26 nhắm edge-first, lợi ích < cost, nên đặt reg_max=1 để effectively kill DFL mà không break checkpoint cũ.

MuSGD optimizer là gì? Hybrid SGD + Muon. SGD lo conv backbone (generalize tốt cho vision), Muon-style lo các layer còn lại (orthogonal gradient updates qua 5 lần Newton-Schulz iteration). Default weight 50/50 giữa hai update. Muon là optimizer mới từ LLM community (arXiv 2502.16982), được dùng để train Kimi K2 của Moonshot AI. Lần đầu YOLO mượn optimizer từ LLM domain.

ProgLoss và STAL là gì? ProgLoss = Progressive Loss Balancing, weight các component loss thay đổi theo training progress thay vì cố định. Early epoch ưu tiên class loss, late epoch ưu tiên box loss. STAL = Small-Target-Aware Label Assignment, điều chỉnh dynamic α và β trong TaskAlignedAssigner để small object được assign nhiều positive sample hơn. Cộng lại cải thiện đáng kể accuracy small object, hữu ích cho UAV và aerial detection.

v26 có chạy được trên Jetson Nano cũ không? Có. Khác với v12 cần FlashAttention (Turing GPU trở lên), v26 không có dependency đó vì backbone là CNN thuần. Chạy được trên Maxwell (Jetson Nano 2019), Pascal (Jetson TX2), Volta (Xavier), Ampere (Orin). Đây là điểm v26 vượt v12 mạnh nhất về reach hardware.

v26 nhanh hơn v12 bao nhiêu? Tuỳ hardware. Trên T4 GPU TensorRT FP16: gần như identical (1.7ms vs 1.64ms cho N). Trên CPU ONNX: v26 nhanh hơn ~40-45% (38.9ms vs ~70ms cho N). Gain chính nằm ở CPU vì bỏ DFL + bỏ NMS. v26 ưu thế rõ rệt cho edge và mobile, không có ưu thế trên server GPU.

v26 size nào nên dùng? N (40.9 mAP, 1.7ms T4, 38.9ms CPU) cho mobile, Pi 5, smart camera. S (48.6 mAP, 2.5ms T4) sweet spot cho hầu hết case. M (53.1 mAP, 4.7ms T4) khi cần accuracy cao. L/X chỉ khi server GPU và không quan tâm size. Rule: bắt đầu S, scale theo accuracy gap.

v26 có train nhanh hơn v12 không? Tuỳ scale training. MuSGD trong code chỉ kích hoạt khi iterations > 10000, dưới ngưỡng đó tự fallback AdamW. Nghĩa là gain tốc độ training của v26 chỉ áp dụng cho training dài (COCO scale, batch 128, vài chục epoch trở lên). Nếu fine-tune custom dataset 500 ảnh trong 30 epoch, bạn không hưởng lợi gì từ MuSGD, gain duy nhất còn lại là inference.

Vài thứ để mang theo

YOLO26 là một version đặc biệt vì nó không thêm gì kiến trúc đáng kể, mà chủ yếu trừ đi. Bỏ DFL qua reg_max=1. Bỏ NMS hack qua end2end=True. Đơn giản hoá pipeline export. Hai thứ thêm vào (ProgLoss + STAL) là incremental improvement, MuSGD là port từ LLM domain. So với v12 thêm Area Attention và R-ELAN hoàn toàn mới, v26 có vẻ ít "innovation" hơn.

Nhưng nhìn rộng hơn, đây là cú chuyển hướng có chủ đích. Ultralytics nhận ra YOLO modern era đã accumulate quá nhiều technical debt qua 5 version. v9 thêm GELAN. v10 thêm dual-assignment. v11 thêm C3K2 + C2PSA. v12 thêm Area Attention. v13 thêm hypergraph. Mỗi cái cải thiện accuracy 0.5-1 mAP, cộng vào latency và export complexity. Đến lúc cần một pass dọn dẹp.

v26 là pass đó. Nó có thể không phải breakthrough nghiên cứu, nhưng là một product release đẹp. Edge-first philosophy đúng với hướng đi của ngành (mobile AI, IoT, agriculture robotics, smart camera). 43% nhanh hơn trên CPU không phải con số marketing, đó là sự khác biệt giữa "chạy được trên Pi 5" và "phải mua Jetson".

Cho hackathon UAV: nếu deployment hardware đã chốt là Jetson Orin Nano, mình vẫn dùng v12 vì có Area Attention + experience tích lũy từ bài tuần trước. Nếu hardware còn flexible hoặc target Pi 5/smartphone, switch sang v26-S ngay.

Cho project edge thực tế: v26 là first-choice từ giờ trở đi. Lý do duy nhất giữ v12 là khi bạn cần global semantic reasoning thật sự (object-relation tasks, scene graph), v26 CNN thuần có thể yếu hơn. Còn 95% use case detection, v26 đủ và rẻ hơn.

Bài tiếp theo có thể là một benchmark thực tế, train v8m, v11m, v12m, v26m trên dataset drone của mình ở 4 độ cao khác nhau, ghi lại mAP trên small/medium/large object subset. Đây là loại test mà đọc code không thay được. Sẽ chạy trong tuần và viết note lại.

Nếu bạn có experience deploy v26 sớm hơn mình, đặc biệt phần MuSGD training stability hay INT8 quantization accuracy trên thiết bị edge thực, mình muốn nghe. Nếu có chỗ nào trong bài này bạn nghĩ mình đọc code sai (đặc biệt phần Newton-Schulz orthogonalization và conv reshape), càng muốn nghe hơn.

Phòng làm việc của team Research AI trên Hoà Lạc năm 2018

Bình.