Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Weight classes

TinyBrains groups entries by the size of the two files you submit. Your class is assigned automatically at admission; it is not a field you choose when submitting. Every active entry also participates in the Open ladder.

The classes are the season’s

A season declares its own size limits, so read them from the season you are entering rather than from this page. The API returns them on every season it reports — GET /v1/games/{game} and GET /v1/games/{game}/seasons both carry a weight_classes table — and the site shows them on the home page and beside your entry. A season may also offer only some of the classes: a focused season might run Nano alone, and a model measuring into a class it is not running is rejected CLASS_NOT_OFFERED — which is not the same refusal as being too large for every class there is.

These are the limits the platform started with, and the default a new season inherits from the season before it:

ClassMaximum measured size
Nano (nano)16 KiB = 16,384 bytes
Micro (micro)128 KiB = 131,072 bytes
Mini (mini)1 MiB = 1,048,576 bytes
Small (small)8 MiB = 8,388,608 bytes
Large (large)64 MiB = 67,108,864 bytes

Limits are inclusive. Under the table above an entry measuring exactly 16,384 bytes is Nano and 16,385 bytes is Micro; an entry over the largest class the season offers is too large for that season.

Size is the only thing your class limits. There is no compute cap: a class does not ration how much arithmetic your graph may do. What bounds that is the game’s turn deadline — 1,000 ms for Ants, yours alone, since each seat is its own call — and a graph too slow to answer in it misses the turn and takes a strike. Admission measures and reports your inference time on the reference set; it does not reject you for it.

Because the size limits belong to the season, a class result is comparable within its season and not necessarily across seasons. Two seasons that ran different Nano limits produced two different competitions, and the standings say which limits they were played under.

How many parameters that actually is

The metric is the file’s bytes, so what fits depends on the dtype you export in — directly, with no compression in between:

Initializer dtypeBytes per parameterRelative capacity
float3241.00x
float1622.00x
int814.00x

Exporting float16 weights doubles the model your class holds, and costs nothing you would notice: keep the graph’s compute in float32 by casting each initializer back at its use, and the runtime folds that cast away when it optimises the plan. The operator set does not change — Cast is allowed — and in a measured comparison the float16 graph chose the same move as the float32 one on every ant of three matches.

Subtract your manifest first. The baselines’ is 930 bytes, which is 6% of a Nano budget and nothing at all above that.

Two worked examples, which are the platform’s own baselines:

Parametersmodel.onnxmanifest.jsonS'Of its cap
nano-bc3,00611,35093012,28075% of Nano
micro-bc24,07753,49593154,42642% of Micro

The deadline, not the class, is what limits a big model

The table above is generous at the top and the turn is not. Your seat owns the whole turn — 1,000 ms, one model_infer call per seat with its own deadline — which is thirty times what it owned when a wave of sixteen matches divided one call between them.

That is a real loosening, and the structural point survives it: a fully convolutional network over the largest Ants board still runs out of turn well before it runs out of bytes. Filling Mini and above means spending parameters where they cost less per turn — at a reduced resolution, or in a lookup that is read rather than multiplied — not simply making the same network wider.

The reason is worth stating plainly, because it is structural rather than a tuning problem. In a convolution every parameter is applied at every cell, so bytes and arithmetic are locked together: one parameter costs 2 × cells multiply-accumulates, and nothing about the kernel size, the grouping or the dtype changes that ratio. A class cap is a budget in bytes; the turn is a budget in arithmetic; and the two run out at different sizes.

Admission reports your measured inference time and never rejects you for it. The rejection, if it comes, comes later and looks like a strike.

How your class is decided

The size metric is bytes(model.onnx) + bytes(manifest.json). Admission chooses the smallest class whose size limit contains that total in the season you submitted to. That is the whole rule — there is no second check, and no class is chosen for you to give you more compute, because compute is not what a class rations.

Measure the pair rather than estimating from parameter count. Graph metadata, an exporter’s node names and the manifest’s own length all count. A larger manifest can move an otherwise unchanged network into the next class.

The Open ladder

Open compares models across all sizes. It is an additional rating, not a sixth size class, and has no separate submission artifact.

A match whose competitors all share a class updates that class and Open. A mixed-class match updates Open only. Ratings from different class ladders are not directly comparable; use Open to compare entries of different sizes.

Choosing what to enter

Begin with a model you can train, inspect, and run reliably. Measure size early, leave operation-budget headroom for larger observations, watch your inference time against the turn deadline, and verify every basic board — the game’s limits — before optimizing for a boundary.

There is no automatic score bonus for unused bytes within a class. Smaller size is the constraint and engineering challenge; ranking still comes from game results. Compare revisions using both their measured size and their match performance.