Yezhen Cong, Samar Khanna, Chenlin Meng, Patrick Liu, Erik Rozi, Yutong He, Marshall Burke, David Lobell, Stefano Ermon (Stanford) — NeurIPS 2022

SatMAE: Masked Autoencoders for Satellite Imagery

The masked autoencoder learned to reconstruct cat photos. Satellites do not photograph cats — they photograph the same patch of Earth across thirteen wavelengths and across months of time. SatMAE asks: what is the right way to mask, embed, and reconstruct that?

Prerequisites: Vision Transformer (patches + attention) + Softmax/MSE + the idea of self-supervised pre-training. We re-derive the rest.
10
Chapters
9
Simulations
2
Code Labs

Chapter 0: Why Satellites Break Plain MAE

You are an analyst at an agriculture ministry. You have petabytes of Sentinel-2 imagery — a European satellite that photographs every point on Earth roughly every five days, in thirteen spectral bands (not three RGB channels, but thirteen wavelengths from deep blue to shortwave infrared). You want a model that can map cropland, predict yields, and flag deforestation. You have almost no labels — labelling a single field requires a person to walk it. But you have an ocean of unlabelled pixels.

This is exactly the setting where self-supervised pre-training wins: learn a good representation from the unlabelled ocean, then fine-tune on the tiny labelled puddle. In natural images, the reigning recipe in 2022 was the Masked Autoencoder (MAE) of He et al.: hide 75% of the image patches, ask a Vision Transformer to reconstruct the missing pixels, and throw the decoder away — the encoder is now a strong feature extractor.

So you take MAE off the shelf and point it at Sentinel-2. It works... poorly. Why? Because MAE was designed for a photograph: one image, three colour channels (R, G, B), one moment in time. Satellite data violates all three assumptions, and the violations are not cosmetic.

A Photograph vs a Satellite Cube

Left: the world MAE was built for — one frame, three channels. Right: a satellite observation — the SAME ground patch stacked across many wavelengths and many revisit dates. Click "Reveal" to peel the cube apart.

A satellite pixel is a cube, not a colour

Consider the three mismatches concretely:

Assumption in plain MAEReality in satellite imageryConsequence if ignored
3 channels (R,G,B), tightly correlated13 bands at very different resolutions (10m, 20m, 60m) and very different physics (visible vs near-IR vs SWIR)Stacking all 13 into one patch embedding forces unrelated wavelengths to share weights — the model averages away the spectral signal that distinguishes water from concrete
One image, one timestampA time series: the same field in March (bare soil), June (green crop), September (harvested)Treating each date as an independent image throws away the temporal structure that is often the most label-relevant signal (phenology)
Random masking over a single 2D gridMasking must decide: do all timestamps share the same mask? do all bands share the same mask?A naive shared mask lets the model "cheat" — copy the visible co-located band/time instead of learning to predict

SatMAE's thesis, in one sentence: keep the MAE recipe, but redesign three things — the input grouping, the positional/temporal embeddings, and the masking strategy — so that the encoder is forced to learn spectral and temporal structure rather than route around it. Everything in this paper is a careful answer to "how should a masked autoencoder treat a band, a timestamp, and a mask?"

The misconception to kill now: "Satellite imagery is just an image with more channels — feed all 13 bands as a 13-channel input and run MAE." The whole paper exists because that does worse than handling the bands well. Bands at 10m and 60m resolution, capturing reflected sunlight vs thermal-adjacent SWIR, are not interchangeable colour planes. SatMAE shows that encoding bands as groups with their own spectral position beats the flat 13-channel input by several points — the structure is not free; you have to build it in.

By the end of this Veanor you will be able to implement SatMAE's two signature mechanisms — spectral group masking and the MAE reconstruction loss on masked patches — from scratch in NumPy (both are Code Labs), and you will understand exactly why each design choice was made.

Why does the standard MAE recipe transfer poorly to multi-spectral, multi-date satellite imagery?

Chapter 1: MAE in 90 Seconds (the part SatMAE keeps)

SatMAE is a modification of MAE, so we must first nail the base recipe. The Masked Autoencoder is an asymmetric encoder-decoder that learns by filling in the blanks.

Start with an image of resolution H×W. A Vision Transformer chops it into a grid of non-overlapping patches — say 16×16 pixels each — giving N = (H/16)(W/16) patch tokens. For a 224×224 image that is N = 14×14 = 196 patches. Each patch is flattened and linearly projected to a token of dimension D (e.g. D = 1024 for ViT-Large).

N = (H / p)(W / p)    patch tokens, each a vector in ℝD

Now the masking. Choose a high masking ratio ρ (MAE uses ρ = 0.75). Sample a random subset of the N tokens to keep visible; the rest are masked. The numbers matter:

Nvis = (1 − ρ) N     Nmask = ρ N

The asymmetry is the key engineering decision: the encoder sees only the visible tokens. With ρ = 0.75, the encoder processes only Nvis = 0.25N = 49 tokens instead of 196. Attention is O(N2), so processing a quarter of the tokens makes the encoder roughly 16× cheaper — this is why MAE can afford a huge encoder and pre-train fast.

1. Patchify + mask
Image → N tokens; keep 25%, hide 75%
↓ visible tokens only
2. Encoder (big ViT)
Processes ONLY the 25% visible tokens — cheap, deep
↓ encoded visible + [MASK] tokens reinserted at masked positions
3. Decoder (small ViT)
Sees ALL N positions; predicts raw pixels of masked patches
↓ throw the decoder away after pre-training
4. Keep the encoder
Fine-tune it on the tiny labelled set

After the encoder, a shared learned [MASK] token is inserted at every masked position (so the decoder sees a full-length sequence of N tokens again), positional embeddings are added back, and a small, shallow decoder reconstructs the pixels of the masked patches. Then — crucially — the decoder is discarded. Only the encoder survives into fine-tuning.

The 75% Mask, Visibly

A 196-patch grid. Slide the masking ratio ρ and watch how few tokens the encoder actually processes (teal = visible, faded = masked). At ρ=0.75 only ~49 tokens reach the encoder — the source of MAE's speed.

Mask ratio ρ 0.75

Worked example. Take a 96×96 satellite chip with patch size p = 8. Then the grid is (96/8)×(96/8) = 12×12 = 144 patches. With ρ = 0.75: Nvis = 0.25×144 = 36 visible tokens and Nmask = 108 masked tokens. The encoder runs self-attention over 36 tokens (36² = 1296 attention entries) instead of 144 (144² = 20,736) — a 16× reduction. The decoder, by contrast, must process all 144 positions, which is why it is kept deliberately small.

Why mask so aggressively (75%)? Natural images are spatially redundant — a missing patch can often be guessed from its neighbours by interpolation. If you mask only 15% (like BERT does for text), the model solves the task by copying neighbours and learns little. Masking 75% removes the easy local crutch and forces the model to build a holistic understanding of the scene. Satellite imagery is even more redundant (large smooth fields, repeating texture), which is part of why SatMAE keeps the high ratio.

SatMAE inherits this entire skeleton: asymmetric encoder-decoder, high mask ratio, predict-the-masked-pixels objective, discard-the-decoder. What it changes is how the tokens are formed (Chapters 3-4) and how the mask is chosen (Chapter 5). Everything else is MAE.

Why does the MAE encoder run on only the visible tokens (not the full image)?

Chapter 2: The Reconstruction Loss, Derived

The entire learning signal in SatMAE (and MAE) comes from one loss. Get this exactly right and the rest of the paper is plumbing. The objective is a mean squared error between predicted and true pixels, computed on the masked patches only. Let us build it up term by term.

Let the decoder output, for each patch i, a vector of predicted pixel values i ∈ ℝP, where P = p·p·C is the number of pixels-times-channels in a patch (for a 16×16 RGB patch, P = 16·16·3 = 768). Let xi be the true patch pixels. The per-element squared error for patch i is:

i = (1 / P) ∑j=1P ( x̂i,j − xi,j )2

This is just the average squared pixel error for one patch. Now the two design choices that make it the MAE loss rather than a generic autoencoder loss.

Choice 1: Loss on masked patches only

Let M be the set of masked patch indices (|M| = Nmask). The total loss averages ℓi over the masked set, and over no others:

L = (1 / |M|) ∑i ∈ Mi

Why only masked patches? The visible patches were handed to the encoder unchanged — reconstructing them is trivial copying and provides no learning pressure. Including them in the loss would let the model lower its loss by perfecting the easy copy task while neglecting the hard prediction task. MAE found that computing loss on visible patches hurts the learned representation. So the loss looks only where the model had to actually predict.

Choice 2: Normalize the target pixels per patch

MAE (and SatMAE) found that reconstructing normalized pixels gives a better representation. For each patch, compute the mean μi and standard deviation σi of its true pixels, and ask the decoder to predict the standardized target:

i,j = ( xi,j − μi ) / ( σi + ε )

Per-patch normalization makes the target locally contrastive: it strips out each patch's overall brightness and contrast, so the model must predict relative structure (texture, edges) rather than just the average tone. For satellite bands this matters even more — different bands and different scenes have wildly different absolute reflectance ranges, and per-patch standardization equalizes them before the loss.

The subtle bug everyone writes: computing the loss over all N patches, or forgetting the mask entirely. If you average over all patches, the visible patches (which the model can reconstruct near-perfectly) dominate and dwarf the gradient signal from the hard masked patches — the loss drops fast but the representation is weak. The mask is not a detail; it is the supervision. You will implement exactly this masked average in Code Lab 2, and the check will reject the all-patches version.

Worked numerical example

Take a toy with 4 patches, P = 2 pixels each. Suppose patches 1 and 3 are masked (M = {1, 3}), patches 0 and 2 are visible. Predictions and targets (already normalized for simplicity):

Patch imasked?i (pred)i (target)i = mean sq err
0no[0.2, 0.2][0.0, 0.0]0.04 (ignored)
1yes[1.0, 0.0][0.0, 0.0](1²+0)/2 = 0.50
2no[0.9, 0.9][1.0, 1.0]0.01 (ignored)
3yes[0.0, 0.5][0.0, 0.0](0+0.25)/2 = 0.125

The masked-only loss is L = (0.50 + 0.125) / 2 = 0.3125. Note that patch 0's error of 0.04 and patch 2's error of 0.01 are not in the sum at all — the gradient flows only from patches 1 and 3. If we had (wrongly) averaged all four, we would get (0.04+0.50+0.01+0.125)/4 = 0.169 — a smaller, but meaningless, number diluted by the visible patches.

Masked-Only Loss vs All-Patches Loss

Slide the model's "skill" from random to perfect. The teal curve is the correct masked-only loss; the faded curve averages over all patches and is contaminated by the easy visible patches. Watch how the all-patches loss can look low while the model still fails on the masked patches.

Model skill on masked patches 0.30
python
# The MAE / SatMAE reconstruction loss
import torch

def mae_loss(pred, target, mask, norm_pix=True, eps=1e-6):
    """
    pred   : [B, N, P]  decoder output per patch (P = p*p*C)
    target : [B, N, P]  true patch pixels
    mask   : [B, N]     1 = masked (predict it), 0 = visible (ignore)
    """
    if norm_pix:                                  # Choice 2: per-patch standardize
        mu  = target.mean(dim=-1, keepdim=True)
        var = target.var(dim=-1, keepdim=True)
        target = (target - mu) / (var + eps).sqrt()

    se   = (pred - target) ** 2              # [B, N, P]
    per_patch = se.mean(dim=-1)            # [B, N]  -> l_i

    # Choice 1: average over MASKED patches only
    loss = (per_patch * mask).sum() / mask.sum()
    return loss
Why is the MAE/SatMAE reconstruction loss computed on the masked patches only?

Chapter 3: Temporal SatMAE

Now the first satellite-specific contribution. A field is not a single image; it is a time series of images of the same place. SatMAE's temporal variant feeds the model a stack of T timestamps of the same scene and must answer two questions: how do we tell the model when each patch was taken, and how do we mask across time?

Telling the model "when": the temporal embedding

Plain ViT adds a positional embedding to each token so the model knows where a patch is. With multiple dates, the model also needs to know when. SatMAE adds a temporal embedding on top of the spatial position. Crucially, the timestamp is not just an index 0,1,2 — it is the actual acquisition date, because the gap between images is irregular (one image in March, the next in June, the next two weeks later).

SatMAE encodes each component of the date — year, month, and hour/day-of-year — with its own sinusoidal positional encoding (the same sin/cos-at-many-frequencies scheme as the original Transformer), then concatenates them into the temporal embedding. So a token's full embedding is:

token(s,t) = patch_embed(xs,t) + pos_embed(s) + time_embed(datet)

where s indexes spatial position and t indexes the date. The same spatial patch at two different dates gets the same pos_embed(s) but a different time_embed — so the model can line up "this is the same field, three months later." Encoding the real date (not the index) means the model learns calendar structure: it can tell that the gap from March to June is larger than March to April, and that June crops differ from March bare soil.

Why the real date, not a 0/1/2 index? Crop phenology — the green-up and senescence cycle — is tied to the calendar, not to "the 2nd image in this stack." A model that knows the absolute month can learn that band reflectance in a vegetation index should peak around the growing season. An index-only embedding would have to relearn this for every irregularly-sampled stack. Encoding year/month/day-of-year with sinusoids gives a smooth, generalizable representation of time, exactly as sinusoidal position gives a smooth representation of space.

Masking across time: independent, not shared

Here is the second temporal choice, and it mirrors the spectral choice we will see in Chapter 5. Given T frames of the same scene, do we mask the same spatial patches in every frame (shared mask) or different patches in each frame (independent mask)?

SatMAE masks independently across time. If patch (s=12) is masked in the March frame, it might be visible in the June frame. Why? Because a shared mask creates a shortcut: if patch 12 is masked in every frame, the model genuinely has to predict it from spatial neighbours. But that is the easy spatial-interpolation task again. With independent masking, patch 12 is hidden in March but visible in June — so the model can (and is encouraged to) use the temporal neighbour: "what did this field look like at the same location a few months ago?" Independent masking is what forces the encoder to learn temporal correspondence rather than purely spatial inpainting.

Shared vs Independent Temporal Masking

Three frames (dates) of the same 6×6 scene. Toggle between shared masking (the same cells hidden every frame) and independent masking (different cells per frame). Notice: under independent masking a hidden cell in frame 1 is often visible in frame 2 — the model can borrow across time.

Shared: same cells hidden in all frames

Worked example. Suppose a scene has T = 3 frames, each a 12×12 = 144-patch grid, and ρ = 0.75. Under independent masking we draw a fresh 75%-mask per frame, so per frame 36 patches are visible. Across the stack of 3×144 = 432 tokens, 3×36 = 108 are visible to the encoder and 324 are masked. A given ground location (one of the 144 spatial cells) is, on average, visible in 3×0.25 = 0.75 of its 3 frames — so most locations are visible in at least one frame, giving the model a temporal anchor to predict the others. Under a shared mask, a masked location is masked in all 3 frames, destroying that anchor.

Misconception: "Independent masking just means more randomness — it can't matter which one you pick." It matters a great deal. Shared masking accidentally turns the temporal MAE back into 3 copies of a spatial MAE (each frame's masked patches must be guessed from that frame's own neighbours). Independent masking is the one line that makes the task temporal: by leaving a location visible in some frames and hidden in others, it rewards the encoder for learning "same place, different time" correspondences — the phenological signal that downstream tasks care about.
Why does temporal SatMAE mask patches independently across frames instead of using one shared mask for all dates?

Chapter 4: Spectral Band Groups

This is the headline mechanism for multi-spectral SatMAE, and the one most worth your attention. The question: a Sentinel-2 pixel has 13 bands — how should the model ingest them?

The naive baseline: one fat patch

The obvious move is to treat the 13 bands like 13 colour channels: a 16×16 patch becomes a vector of 16·16·13 = 3328 numbers, projected by a single learned matrix to a token. This is the "flat 13-channel MAE." It is simple, and it is what you'd do first. But it has a structural flaw: every band shares the same projection and the same positional embedding. The model is told nothing about which dimension is the deep-blue band vs the shortwave-infrared band. The wildly different physics of those bands are forced through one undifferentiated embedding, and the model must disentangle them with no help.

SatMAE's answer: group the bands, embed each group with its own spectral position

SatMAE partitions the 13 bands into spectral groups of bands that share similar physical character and ground resolution. For Sentinel-2 the paper uses three groups, roughly:

GroupBands (Sentinel-2)CharacterNative resolution
g0 — visible/RGB+NIR (10m)B2, B3, B4, B8Blue, Green, Red, near-IR — the sharp bands10 m
g1 — red-edge / NIR (20m)B5, B6, B7, B8A, B11, B12Vegetation red-edge + shortwave-IR20 m
g2 — atmospheric (60m)B1, B9, B10Coastal aerosol, water vapour, cirrus — coarse60 m

Each group is patchified and projected separately, and — the crucial part — each group gets its own learned spectral positional encoding, a vector eg added to every token in group g. So a token's embedding now carries three position signals:

token(s, g) = patch_embedg(xs,g) + pos_embed(s) + spec_embed(g)

The spectral embedding spec_embed(g) plays the same role for "which band group am I?" that the positional embedding plays for "where in the image am I?" It lets attention treat the deep-blue token and the SWIR token as distinct kinds of thing, even at the same spatial location. The model can now learn band-specific structure: that the red-edge group is the one that lights up over healthy vegetation, that the SWIR group separates bare soil from water.

Flat 13-Channel vs Grouped Spectral Embedding

Top: all 13 bands crushed into one token with one positional code — the model can't tell blue from SWIR. Bottom: SatMAE groups the bands; each group gets its own projection and its own spectral position code (coloured). Click a group to highlight which bands it owns.

g0: visible + NIR, the 10m sharp bands

Why grouping beats both extremes

There are two extremes and SatMAE sits between them deliberately:

Worked example of the token count. Take a 96×96 chip, patch p = 8, so 12×12 = 144 spatial positions. Flat 13-channel: 144 tokens (each of input dim 8·8·13 = 832). Grouped into 3 groups: 3×144 = 432 tokens (each of input dim 8·8·|bands in group|, e.g. 8·8·4 = 256 for g0). Grouping multiplies the sequence length by the number of groups — that is the cost — but in exchange each band group gets a clean, dedicated representation and its own spectral position, which is what buys the accuracy.

Concept + realization: the spectral group embedding is a tiny learned table of shape [G, D] — one D-dimensional row per group. At forward time you look up row g and add it to every token in group g, exactly like a positional embedding lookup. That is the entire mechanism. Its power is not complexity; it is that it injects the band-identity prior the model would otherwise have to discover from scratch.
What does the spectral group embedding give SatMAE that the flat 13-channel input cannot?

Chapter 5: Independent Group Masking

We have grouped the bands and given each group a spectral code. Now the masking question returns, in spectral form: given the same spatial location across G band groups, do we mask the same patches in every group, or mask independently per group? This is the spectral twin of Chapter 3's temporal masking choice — and it is the core mechanism you will implement in Code Lab 1.

The shortcut a shared mask hands the model

Bands are correlated. The red band and the green band at the same pixel move together; the red-edge bands track vegetation jointly. If you mask the same spatial patch in every group, then to reconstruct group g's masked patch the model truly has to predict it from spatial neighbours. But there is a sneakier failure: with a shared mask, the visible band groups at a location are also all masked at the masked locations, so the model never sees the easy cross-band correlation. SatMAE instead masks independently within each group — a fresh 75% mask drawn per group.

With independent group masking, a spatial location might be masked in group g0 (visible bands) but visible in group g1 (red-edge bands). Now the model can — and must learn to — exploit the strong cross-band correlation: "I can see the red-edge reflectance here; predict the masked visible-band reflectance from it." This is the spectral analogue of borrowing across time. It forces the encoder to learn the inter-band relationships that carry the physical signal (e.g. NDVI-like contrasts), instead of treating each band group as an isolated spatial inpainting problem.

Independent Group Masking, Visibly

Three band groups over the same 6×6 location grid. Each group draws its OWN 75% mask. Click a location: see how it is hidden in some groups but visible in others — the visible groups become the evidence for predicting the hidden ones (cross-band inference).

Click a cell to trace cross-group visibility

How the mask is actually drawn (the algorithm)

For each band group independently, take the N spatial patch indices, shuffle them, keep the first Nvis = (1−ρ)N as visible and mark the rest masked. The shuffle is the whole trick — it is how you draw a uniform random subset without replacement, and doing it per group with a fresh shuffle is what makes the masks independent. This is exactly the argsort(random) idiom MAE uses, applied once per group.

python
# Independent per-group random masking (the SatMAE spectral mechanism)
import numpy as np

def group_random_mask(N, G, mask_ratio, rng):
    """Return mask[G, N]: 1 = masked, 0 = visible. A FRESH random
       subset per group -> the masks are independent across groups."""
    n_vis = int(round((1 - mask_ratio) * N))
    mask = np.ones((G, N))
    for g in range(G):
        order = rng.permutation(N)        # fresh shuffle per group
        mask[g, order[:n_vis]] = 0      # first n_vis kept visible
    return mask

Worked example. N = 8 spatial patches, G = 3 groups, ρ = 0.5 so Nvis = 4 per group. Group 0 might keep visible {1,3,4,6}, group 1 {0,2,4,7}, group 2 {2,3,5,6}. Look at spatial location 4: visible in g0 and g1, masked in g2. So to reconstruct location 4's group-2 bands, the model has its group-0 and group-1 bands as evidence — cross-band inference is available because the masks differ. Under a shared mask, location 4 would be all-visible or all-masked, and that evidence channel would never exist.

The bug the Code Lab catches: reusing one mask for all groups (or worse, one global np.random draw applied identically). It looks like masking, the shapes are right, the loss runs — but the model is learning per-group spatial inpainting, not the cross-band physics that makes SatMAE work. The check verifies that the per-group visible sets actually differ across groups, and that each group keeps exactly Nvis patches.
What does independent group masking force the encoder to learn that shared masking does not?

Chapter 6: End-to-End Data Flow (tensor shapes)

Let us trace a single multi-spectral SatMAE forward pass with explicit shapes, so you could implement it. We use a concrete config: input chip 96×96, patch p = 8, so N = 144 spatial patches; G = 3 band groups; embedding dim D = 768 (ViT-Base scale); mask ratio ρ = 0.75.

Input cube
[B, 13, 96, 96] — B images, 13 bands, 96×96 pixels
↓ split into 3 band groups
Per-group patchify + project
group g → [B, 144, D]; concat groups → [B, 3·144, D] = [B, 432, D]
↓ add pos_embed(s) + spec_embed(g)
Independent group mask
keep 25% per group → 3·36 = 108 visible tokens: [B, 108, D]
↓ encoder sees ONLY visible
ViT encoder (deep)
self-attention over 108 tokens → [B, 108, D]
↓ reinsert [MASK] tokens at 324 masked slots
ViT decoder (shallow)
all 432 positions → predict pixels → [B, 432, P]
↓ MSE on the 324 masked tokens (Ch.2 loss)
Loss
scalar — backprop — keep encoder, drop decoder

Read the shapes carefully — they encode the whole design:

Sequence-Length Cost of Each Design Knob

How the encoder's visible-token count grows with the number of band groups G, the number of timestamps T, and the mask ratio ρ. The encoder cost is roughly quadratic in this count — drag the sliders and watch the tradeoff that SatMAE balances.

Groups G 3
Timesteps T 1
Mask ratio ρ 0.75

Worked example. With G = 3, T = 1, ρ = 0.75 and N = 144 per (group,time): total tokens = 3·1·144 = 432; visible = 0.25·432 = 108. Bump to T = 3 dates: tokens = 3·3·144 = 1296; visible = 324. The encoder attention cost scales like (visible)², so going from 108 to 324 visible tokens is ~9× more encoder compute — which is why SatMAE keeps ρ high (to claw back the multiplicative cost of groups and time) and keeps the decoder shallow.

The asymmetry pays for the structure. Each satellite-specific knob — band groups, timestamps — multiplies the token count. A symmetric autoencoder (encoder = decoder size, both seeing all tokens) would make this prohibitively expensive. MAE's asymmetry — deep encoder on the visible 25%, shallow decoder on the full set — is precisely what makes SatMAE's richer tokenization affordable. The design choices compose: high mask ratio + asymmetric encoder is what licenses band-grouping + temporal stacking.
After grouping a 13-band chip into 3 spectral groups (N=144 spatial patches each), how many tokens does the deep encoder actually process at mask ratio 0.75?

Chapter 7: Experiments & Ablations

A method paper lives or dies on whether the design choices actually help. SatMAE pre-trains a ViT-Large encoder with the MAE objective on a large corpus of unlabelled satellite imagery (the fMoW — Functional Map of the World — dataset, in both RGB and full Sentinel-2 multi-spectral form), then evaluates two regimes: fine-tuning on the same domain and transfer learning to other remote-sensing tasks.

Headline results

Against the strongest prior self-supervised baselines for satellite imagery, SatMAE reports:

SettingResult (vs prior SOTA)What it shows
Supervised fine-tuning on benchmark datasetsup to about +7%The pre-trained representation transfers within the satellite domain better than prior pre-training
Transfer to land-cover classificationup to about +14%Features generalize to a downstream task the model never trained on
Transfer to semantic segmentationconsistent gainsThe encoder is useful for dense prediction, not just classification

The transfer numbers are the more important story. A +14% jump on land cover from better pre-training alone — same labelled data, same fine-tuning budget — is the kind of result that says the representation, not the classifier head, is doing the work. This is the promise of self-supervision realized: the unlabelled ocean paid off.

Ablations: which choice mattered?

The paper isolates each design decision. The qualitative verdict (the directions, which is what you should remember):

AblationFindingWhy it makes sense
Flat 13-channel input vs spectral band groupsGrouping with spectral position helpsDistinct band physics get distinct representations instead of being averaged
Shared vs independent group maskingIndependent masking helpsForces cross-band inference instead of per-group inpainting
Index time embedding vs real-date temporal embeddingEncoding the actual acquisition date helpsCaptures calendar/phenology structure of irregular revisit times
Pixel reconstruction without vs with per-patch normalizationNormalized targets help (inherited from MAE)Forces predicting relative structure, not absolute brightness
Ablation: Stacking the Design Choices

A stylized accuracy ladder (illustrative, showing the direction of each ablation, not exact paper numbers). Toggle each SatMAE design choice on; watch the downstream accuracy climb as the satellite-specific structure is added on top of the plain-MAE baseline.

Baseline: plain MAE on 13 stacked channels

Reading the ablation correctly. The choices are not redundant — each addresses a different failure of plain MAE. Band groups fix the spectral averaging failure; independent masking fixes the cheat-via-correlated-bands failure; the real-date embedding fixes the lost phenology failure. Because they target different failures, they stack: the full SatMAE is meaningfully above any single addition. This is the hallmark of a well-decomposed paper — orthogonal contributions that compose.

What to take to an interview: SatMAE's contribution is not a new architecture (the backbone is a vanilla ViT and the objective is vanilla MAE). It is three carefully-justified input and masking modifications, each empirically validated by ablation, that make a general recipe respect the structure of satellite data. The lesson generalizes: when you bring a foundation-model recipe to a new modality, the leverage is usually in tokenization, positional/identity embeddings, and the masking/augmentation, not in reinventing the transformer.
SatMAE's ablations show its three main design choices stack (combine additively). Why?

Chapter 8: The SatMAE Explorer

This is the payoff. Everything we have built — band groups, independent per-group masking, the encoder seeing only visible tokens, and the masked-only reconstruction loss — is wired into one interactive pre-training step you can drive. There is no quiz; the simulation is the test. If you can predict what each control does before you move it, you understand SatMAE.

The grid shows a small scene's spatial patches stacked across the G band groups you select. Drive the controls and watch: which tokens reach the encoder, which become [MASK], and where the reconstruction loss is actually measured. The "cross-band evidence" overlay lights up the visible band groups that a hovered masked patch can borrow from — the mechanism from Chapter 5 made literal.

Live SatMAE Forward Pass

Each row is a band group; each column a spatial location. Teal = visible (goes to encoder), faded = masked (reinserted as [MASK], scored by the loss). Toggle shared vs independent masking and click a masked cell to see which co-located groups remain as cross-band evidence. The readout tracks visible-token count and encoder cost.

Band groups G 3
Mask ratio ρ 0.75
Independent mask — click a masked cell

Things to try, and what they reveal:

Read the readout as a researcher would. The "encoder cost" bar is proportional to (visible tokens)² — it is what you actually pay per pre-training step. SatMAE's design is a balancing act: groups and timestamps push token count up (richer signal), the high mask ratio and asymmetric encoder push the encoder's working set back down (affordable). Every knob in this explorer is a real lever in the paper's config file.

Chapter 9: Limits & Connections

SatMAE is a clean, influential result, but no paper is the last word. Knowing its limits is how you know what came next.

Limitations

Where SatMAE sits in the lineage

ViT (Dosovitskiy 2020)
Patches + attention — the backbone SatMAE uses unchanged
↓ self-supervised masking
MAE (He 2021)
Mask 75%, reconstruct pixels, asymmetric encoder/decoder
↓ respect satellite structure
SatMAE (Cong 2022) — you are here
Band groups + spectral position + temporal embed + independent group masking
↓ add multi-scale / GSD
SatMAE++, Scale-MAE, ...
Multi-scale pre-training, resolution awareness

Related lessons on this site

The cheat sheet

ConceptOne-line summary
Base recipeMAE: mask 75% of patches, deep encoder on visible only, shallow decoder reconstructs masked pixels, keep encoder
Reconstruction lossMSE on the masked patches only, with per-patch pixel normalization
Spectral band groupsPartition the 13 bands into physically-similar groups; each group gets its own projection + learned spectral position embedding
Independent group maskingDraw a fresh random mask per band group → locations visible in some groups, masked in others → forces cross-band inference
Temporal embeddingEncode the real acquisition date (year/month/day) with sinusoids; mask independently across time too
Why it worksInjects spectral/temporal identity the model would otherwise have to discover; independent masking prevents the cheap-copy shortcut
ResultsUp to ~+7% fine-tuning, ~+14% transfer on land cover, gains on segmentation — from pre-training alone
BackboneVanilla ViT-Large; objective is vanilla MAE — the novelty is tokenization + masking, not architecture
The one sentence to remember: SatMAE shows that adapting a foundation-model recipe to a new modality is mostly about tokenization, identity embeddings, and the masking strategy — respect the structure of the data (bands of different physics, irregular dates) in how you form and hide tokens, and a vanilla transformer + vanilla MAE objective will do the rest.

"What I cannot create, I do not understand." — and you can now create both of SatMAE's signature mechanisms in NumPy, from the two Code Labs above.

References

  1. Cong, Khanna, Meng, Liu, Rozi, He, Burke, Lobell, Ermon. "SatMAE: Pre-training Transformers for Temporal and Multi-Spectral Satellite Imagery." NeurIPS, 2022. arXiv:2207.08051
  2. He, Chen, Xie, Li, Dollár, Girshick. "Masked Autoencoders Are Scalable Vision Learners." CVPR, 2022. arXiv:2111.06377
  3. Dosovitskiy et al. "An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale." ICLR, 2021. arXiv:2010.11929
  4. Vaswani et al. "Attention Is All You Need." NeurIPS, 2017. arXiv:1706.03762
  5. Noman et al. "Rethinking Transformers Pre-training for Multi-Spectral Satellite Imagery (SatMAE++)." CVPR, 2024. arXiv:2403.05419