Skip to content
top-2 of 4 experts

A sparse mixture of experts for Ultralytics YOLO

One call to add it to official ultralytics, a router loss that reaches backward(), and a run record behind every number on this site.

router picks 2 of 4 per image
  • One call to add itequip grafts the block into a config, renumbers layer references and wires the loss, on seven official generations from YOLOv5 to YOLO26 and on YOLO-Master's fork.
  • The aux loss reaches backward()An esmoe_aux column in the training log, asserted by unit tests and by ten real-training checks in scripts/verify.py.
  • Acts the same as YOLO-Master's blockOne yolo-master-n, one protocol: the block adds +0.0104 on the fork and +0.0095 on official ultralytics with this package (FP32, 3/3 each), and the gap between the two is equivalent.
142full-protocol runs, 600 card-hours
7official generations, plus yolo-master-n
335tests, including numerical parity with upstream and the paper
11pre-registrations committed before their results

Open the quick start in Colab: install, equip, train and watch the esmoe_aux column, all on a free GPU.

Install

pip install esmoe

The distribution, the import and the CLI are all esmoe.

Use

import esmoe

model = esmoe.equip("yolo11n.yaml", weight=0.01)   # register + graft + build + wire
model.train(data="coco8.yaml", epochs=10)

The separate steps, the CLI and the hand-written config are covered in the tutorial.

Compatibility

backbone build + forward grafted config aux loss in training protocol runs
YOLOv5 yes yes yes yes
YOLOv8 yes yes yes yes
YOLOv9 yes yes yes yes
YOLOv10 yes yes yes yes
YOLO11 yes yes yes yes
YOLO12 yes yes yes yes
YOLO26 yes yes yes yes
YOLO-Master (fork) yes yes yes no

Verified by tests/test_ultralytics.py on ultralytics 8.4.101 and the latest release (the CI matrix), which report loss items in two different shapes; both are handled. The training column is backed by real 1-epoch VisDrone runs on four generations and by the 120-epoch protocol runs on all seven, each logging a non-zero train/esmoe_aux; graft and forward run on every row in CI. The YOLO-Master row runs against the fork's vendored ultralytics: scripts/fork_smoke.py grafts their yolo-master-n.yaml, trains one epoch with a non-zero esmoe_aux, and builds their own ES_MOE config alongside ours. The same-configuration comparison trains upstream's own blocks on the fork and trains yolo-master-n with this package's blocks on official ultralytics, hence the last column.

Default configuration

ESMoE(num_experts=4, top_k=2) with attach_aux_loss(weight=0.01). Under one budget of a 25% train split, 640 px and 20 epochs, it beat the 2-expert, 8-expert, top-1 and aux-off variants; on the full VisDrone training set, at the same 20 epochs and 640 px, three seeds confirmed it: 3/3 paired wins, +0.0021 mAP50, and 10.4% more parameters on YOLOv8n. Under the protocol budget (800 px, 120 epochs) the default wiring on YOLOv8n is +0.0025, 2/3. The argument is on Selection.