RetinaNet Detector
RetinaNet pairs a feature pyramid with focal loss, which down-weights easy background boxes so the rare foreground objects steer training.
Why Does This Exist?
In 2017 one-stage detectors trailed two-stage accuracy by several points, and Lin and colleagues diagnosed why: a dense grid produces around 100,000 candidates per image with only a handful of foreground, so easy background boxes dominate the loss. The network spends training getting better at background it already knows.
RetinaNet kept one-stage speed and fixed the learning dynamics with focal loss, matching Faster R-CNN accuracy while staying single-shot. It proved the gap was a loss problem, not an architecture problem.
This page covers the pyramid backbone, the two heads, and the loss math. The loss itself gets its own treatment on the focal loss page.
Think of It Like This
A teacher who stops grading easy quizzes
A teacher with 1,000 trivially correct quizzes and 10 tricky ones learns nothing by re-grading the easy pile. A smart teacher glances at the easy ones and spends grading time where students actually struggled. Focal loss is that triage: easy background boxes get near-zero weight automatically, so each gradient step is driven by the hard, ambiguous cases at the boundary.
The analogy stops at intention. The teacher chooses to triage; focal loss does it through arithmetic, with no notion of which mistakes matter most to you.
How It Actually Works
Backbone plus two subnetworks
A ResNet with a feature pyramid supplies multi-scale maps P3 through P7, so small and large objects each get a level that fits. Two small fully convolutional subnetworks attach to every level: one predicts class scores per anchor (3 scales 3 aspect ratios each spot), the other predicts box offsets. Both heads share weights across all pyramid levels, keeping the parameter count flat while coverage multiplies.
Focal loss mechanics
Focal loss multiplies cross-entropy by with : , where is the model's probability on the true class and is the natural logarithm. When the model is confident and right, is tiny and the example nearly vanishes from the gradient. When it struggles, the factor stays near and the example counts almost fully.
Worked example: easy versus hard
Score two candidates with :
- Easy background at : cross-entropy , focal loss . Down about times.
- Hard case at : cross-entropy , focal loss . Down only about times.
Easy examples nearly leave the gradient while hard ones survive almost intact. That asymmetry is the whole trick: the rare foreground finally steers training instead of drowning in background.
Code
import math
def focal_loss(pt, gamma=2.0): ce = -math.log(pt) # cross-entropy for the true class return ((1.0 - pt) ** gamma) * ce
for pt in (0.9, 0.3): print(pt, f"{-math.log(pt):.4f}", f"{focal_loss(pt):.4f}")# -> 0.9 0.1054 0.0011# -> 0.3 1.2040 0.5899Watch Out For
Gamma left at 2 on every dataset
Gamma fits COCO's extreme imbalance; on milder ratios it over-suppresses and training stalls on merely medium examples. The symptom is a loss that flatlines early with under-confident scores. Treat gamma as a tuned knob, trying to against validation AP.
Initialization that drowns the first epochs
With 100,000-to- imbalance, random initial scores flood training with confident background mistakes before focal loss can help. RetinaNet initializes the final bias so each anchor starts near foreground probability . Skip that bias init and the first epochs diverge.
The Quick Version
- RetinaNet combines a feature pyramid with focal loss in a one-stage design.
- Focal loss scales cross-entropy by , erasing easy background from the gradient.
- Verified effect: about times smaller loss on easy cases, only about times on hard ones.
- Shared heads across pyramid levels P3 to P7 keep parameters flat as coverage multiplies.
- It matched two-stage accuracy in 2017 while keeping single-shot speed.