Machine Learning

Random forests, Segment Anything and U-Nets on satellite imagery: training data, spatially honest validation and inference on full scenes.

Two habitat maps of the Dark Peak side by side. Left: the rule-based map from Sentinel-2, with purple blanket bog and lilac heath on the Kinder and Bleaklow plateaux, orange bracken on the valley sides, green grassland and woodland in the valleys and blue reservoirs in the Derwent valley. Right: Living England 2022-23 for the same area, with smoother patches of the same classes.

Tutorial Python Part 1 of 5

Habitat mapping with Sentinel-2 in Python: spectral index rules and an honest accuracy assessment

Map blanket bog, heath, bracken, grassland, woodland, water and built-up land in the Peak District from 2023 Sentinel-2 seasonal composites with an eight-rule spectral index classifier, then assess it properly: a confusion matrix, user's and producer's accuracy, kappa and its caveats, block-bootstrap confidence intervals, and why a random train/test split overstates accuracy.

Beginner 19 min read

Three habitat maps of the Dark Peak side by side. Left: the noisy Part 1 rule-based map. Centre: the LightGBM map, with smooth purple blanket bog on the Kinder and Bleaklow plateaux, lilac heath around them, orange bracken on the valley sides, yellow semi-natural grassland in the south, green grassland and woodland in the valleys and blue reservoirs. Right: Living England 2022-23, which the LightGBM map closely resembles.

Tutorial Python Part 2 of 5

Habitat classification with LightGBM in Python: Sentinel-2, Sentinel-1 and terrain fusion

Classify nine upland habitats in the Peak District with LightGBM on 77 multi-temporal features: seasonal Sentinel-2 bands and indices, Sentinel-1 VV and VH backscatter and Copernicus DEM terrain. Tune with spatial-fold cross-validation and class weights, run an S2 / S2+S1 / S2+S1+terrain ablation, explain the model with TreeSHAP and permutation importance, and compare it with a random forest and the Part 1 rules on the same test blocks.

Intermediate 21 min read

Two habitat maps of the Dark Peak side by side. Left: the map from AlphaEarth embeddings and logistic regression, with large purple blanket bog areas on Kinder Scout and Bleaklow, lilac heath around them, orange bracken on the valley sides, yellow and light green grassland in the south and west, and blue reservoirs in the Derwent valley. Right: Living England 2022-23 for the same area, with very similar patterns.

Tutorial Python Part 5 of 5

AlphaEarth satellite embeddings in Python: few-shot habitat mapping, uncertainty and area estimates

Use Google DeepMind's AlphaEarth Foundations satellite embeddings, a geospatial foundation model, in Python without a login. Classify nine Peak District habitats with a linear model, compare a few-shot learning curve against raw Sentinel-2 bands, map uncertainty, check calibration, simulate active learning, and estimate habitat areas with confidence intervals from a stratified random sample (Olofsson et al. 2014).

Advanced 24 min read

Four panels of the same 4 by 3 km area of the Edale valley and the southern edge of Kinder Scout. Top left: a true colour Sentinel-2 image of green fields and brown moorland. Top right: a pixel-based habitat map speckled with isolated pixels of other classes. Bottom left: the object-based map, with the same habitats in clean patches that follow field boundaries. Bottom right: the Living England reference map.

Tutorial Python Part 3 of 5

Object-based image analysis in Python: OBIA habitat classification with Sentinel-2

Segment 2023 Sentinel-2 seasonal composites of the Peak District into image objects with scikit-image SLIC and Felzenszwalb, tune the segment size against Living England boundaries, compute per-object statistics, shape and GLCM texture with NumPy, classify the objects with LightGBM and compare OBIA with a pixel-based classifier on accuracy, salt-and-pepper noise and patch counts. Then export the habitat objects as GeoPackage polygons.

Advanced 21 min read

Two habitat maps of the Dark Peak side by side. Left: the TempCNN time-series map at 10 m, with purple blanket bog on the Kinder and Bleaklow plateaux, lilac heath around it, orange bracken on valley sides, yellow and green grassland in the south and west, dark green conifers and blue reservoirs in the Derwent valley. Right: Living England 2022-23 for the same area, which looks very similar but has more heath.

Tutorial Python Part 4 of 5

Satellite image time series classification with deep learning: TempCNN and L-TAE in PyTorch on a CPU

Classify habitats from a full year of cloudy, irregular Sentinel-2 observations with two temporal neural networks in PyTorch: a 1D convolutional TempCNN and a lightweight temporal attention encoder (L-TAE) with day-of-year positional encoding. Compare masking with gap-filling, test against a LightGBM baseline on spatial blocks, read which dates matter from attention and occlusion, and predict a wall-to-wall 10 m map on a CPU.

Advanced 24 min read

Two land cover maps of a 30 km square around Leicester side by side: the U-Net prediction on the left and the reference labels on the right. Both show the city in grey and red in the centre, surrounded by farmland in pale green, woods in dark green and reservoirs in blue. The prediction's city is smoother, with fewer separate red buildings.

Tutorial Python Part 3 of 3

Deep learning inference on large rasters: sliding-window prediction, COGs and polygons in Python

Run a trained PyTorch U-Net over a whole Sentinel-2 scene of a city it has never seen: tiled sliding-window inference on a large GeoTIFF with overlapping, blended windows, a georeferenced Cloud Optimised GeoTIFF of classes and confidence, raster-to-vector polygons with rasterio.features.shapes in a GeoPackage, and an honest check against reference labels.

Advanced 13 min read

Four rows of Sentinel-2 test chips. Each row shows the image, the reference labels, the U-Net prediction and the disagreement in magenta. The prediction matches rivers, woods and fields closely, but in the city centre it draws buildings as blobs instead of separate roofs.

Tutorial Python Part 2 of 3

U-Net satellite image segmentation in PyTorch: a TorchGeo and Sentinel-2 tutorial on a CPU

Train a U-Net to segment Sentinel-2 imagery into buildings, built-up land, trees, grass and water with PyTorch, segmentation_models_pytorch and TorchGeo's Sentinel-2 pretrained ResNet-18 weights, on a CPU in five minutes. Real loss curves, per-class IoU and F1, a confusion matrix and an honest look at what limits accuracy.

Advanced 12 min read

Six 128 by 128 pixel Sentinel-2 image chips of Nottingham, each shown above the same chip with its label mask overlaid: a city centre with red buildings and grey streets, a suburb, a forest, farmland, flooded gravel pits in blue and an industrial estate.

Tutorial Python Part 1 of 3

Training data for deep learning on satellite imagery: Sentinel-2 image chips in Python

Build a labelled deep learning dataset from free data: stream a Sentinel-2 L2A composite from the Planetary Computer, rasterise Overture building footprints over ESA WorldCover, cut georeferenced image chips, split them by spatial block so the test set does not leak, check the class balance and load it all as a TorchGeo dataset.

Intermediate 13 min read

Tutorial Python

Segment Anything on satellite and aerial imagery in Python: a samgeo tutorial

Run Meta's Segment Anything Model on high-resolution aerial imagery with segment-geospatial (samgeo), on a CPU. Generate masks automatically, vectorise them to a GeoPackage, filter them by area, shape and NDVI to find buildings, and prompt SAM with points and boxes, checked against OpenStreetMap.

Intermediate 14 min read