Finding contrails in GOES-16 satellite imagery

Persistent aircraft contrails cause about 1% of human-caused warming, and many are avoidable with small altitude changes. Checking contrail forecasts needs a detector that marks every contrail pixel in a satellite scene. This is that detector, trained on real GOES-16 infrared data and scored with the Kaggle competition's metric.

0.595global Dice, validation (1,856 scenes)
0.597Kaggle private score (hidden test)
+0.047Dice from upsampling the input 2x
8,197training scenes, 40% of the full set

01What worked

Every run uses a U-Net with a ResNet34 encoder, 40 epochs, and is scored on the full validation split with global Dice: intersection and sizes pooled over every pixel of the set, the competition metric.

ModelTrain scenesGlobal Dice
Labelled frame only2,4470.508
+ two neighbouring frames as channels2,4470.461
+ input upsampled 2x inside the network2,4470.555
+ input upsampled 2x, more data8,1970.595
Validation global Dice per epoch for the four runs; the 2x-input run on 8,197 scenes stays highest throughout, the three-frame run lowest.
Validation global Dice per epoch. The 2x-input runs lead from the first epochs; stacking frames lags throughout.

02What it sees

Four validation scenes in ash false colour with the human label and the model prediction side by side. Rows 1, 3 and 4 match closely; row 2 shows a contrail over complex cloud that the model misses.
Ash false colour, human label, prediction. Straight, sharp contrails are caught; the contrail over a complex cloud deck in row 2 is missed entirely, and short fragments in row 3 are dropped.

03Getting 451 GB of data onto a 300 GB disk

The Kaggle archive is 451 GB, and requesting its ~90,000 files one by one triggered the API rate limit, which blocked the account for hours. Two loaders replaced it:

Both keep each scene as an 8-frame ash false-colour composite in uint8: about 1.2 MB instead of 43 MB.

04Caveats