=== versions === python 3.12.0 | scikit-learn 1.9.1 | odc-stac 0.5.3 | xarray 2026.9.0 | dask 2026.8.0 | pystac-client 0.9.0 | planetary-computer 1.0.0 | numpy 2.5.4 === STAC search === 68 Sentinel-2 L2A items (tiles ['30UWE', '30UXE']) with < 60% cloud, 07 Mar to 11 Oct 2021 lazy cube: {'y': 1166, 'x': 2356, 'time': 42}, 2.5 GB if loaded in full dropped 0 dates whose tiles mix processing baselines before and after 04.00 SCL read in 3 s; 36 of 42 dates are at least 10% clear spring 18 dates; pixels with no clear view: 0.31% summer 9 dates; pixels with no clear view: 0.69% autumn 9 dates; pixels with no clear view: 0.78% composites built in 47 s === feature stack === 1166 x 2356 pixels of 20 m, 42 features (3 seasons x (10 bands + 4 indices)) pixels with at least one missing feature: 1.56% === ESA WorldCover 2021 (resampled to 20 m with the mode) === 10 Tree cover 27.21 20 Shrubland 0.00 30 Grassland 36.99 40 Cropland 20.87 50 Built-up 14.05 60 Bare / sparse 0.14 80 Water 0.72 90 Herbaceous wetland 0.02 classes used: ['Tree cover', 'Grassland', 'Cropland', 'Built-up', 'Water']; dropped: ['Shrubland', 'Bare / sparse', 'Herbaceous wetland'] === stratified random sample === Tree cover 2000 Grassland 2000 Cropland 2000 Built-up 2000 Water 2000 10000 samples in 288 blocks of 2 km === spatial hold-out test (20% of blocks) === trained on 8050 samples in 0.6 s; tested on 1950 samples overall accuracy 0.977 | macro F1 0.977 | out-of-bag accuracy 0.972 precision recall f1-score support Tree cover 0.959 0.961 0.960 361 Grassland 0.986 0.961 0.973 432 Cropland 0.974 0.974 0.974 387 Built-up 0.969 0.991 0.980 447 Water 1.000 1.000 1.000 323 accuracy 0.977 1950 macro avg 0.978 0.977 0.977 1950 weighted avg 0.977 0.977 0.977 1950 area-weighted accuracy (class recall weighted by WorldCover area share): 0.968 === random vs spatially blocked 5-fold cross-validation === random accuracy 0.973 | macro F1 0.973 | Tree 0.96 Grassland 0.96 Cropland 0.97 Built-up 0.98 Water 1.00 spatial blocks accuracy 0.971 | macro F1 0.971 | Tree 0.96 Grassland 0.96 Cropland 0.97 Built-up 0.97 Water 1.00 random CV overstates accuracy by 0.2 percentage points === feature importance === permutation perm_sd impurity spring_MNDWI 0.0121 0.0007 0.0423 autumn_NDRE 0.0039 0.0016 0.0661 spring_B11 0.0034 0.0013 0.0536 spring_B8A 0.0030 0.0016 0.0624 spring_B08 0.0024 0.0013 0.0436 summer_NDRE 0.0020 0.0010 0.0513 autumn_B11 0.0017 0.0009 0.0209 spring_B06 0.0016 0.0014 0.0333 autumn_B05 0.0015 0.0004 0.0323 summer_B12 0.0011 0.0008 0.0219 spring_B07 0.0010 0.0021 0.0408 spring_B12 0.0009 0.0007 0.0293 impurity importance by season: {'autumn': 0.292, 'spring': 0.39, 'summer': 0.318} === full map prediction === predicted 2,747,096 pixels in 6 s agreement with WorldCover over the classes used: 87.0%; median top-class probability 0.96 per-class F1 against WorldCover over every pixel: Tree 0.82 Grassland 0.89 Cropland 0.90 Built-up 0.85 Water 0.87 WorldCover_ha random_forest_ha Tree cover 29897 26388 Grassland 40651 40093 Cropland 22928 25171 Built-up 15437 17527 Water 796 705 === figures === wrote 6 figures, land_cover_rf_2021.tif and training_samples.csv