Model reference · open weights

UniverSat

Available as managed deployment Embeddings g-astruc · community Image embed 1 variants 515 dl/mo

UniverSat is an open-weight embedding model from g-astruc. AxForge deploys and operates it for you on dedicated EU-owned hardware — with the licence handled where one is required.

Available as managed deployment — configured and operated for you on dedicated EU hardware, quoted per deployment.

What it is

Released byg-astruc
TypeEmbedding models
TaskImage embed
Parameters (lead)201M
Released2026-06-19
Popularity515 downloads / month
LicenceOpen weights

About

What UniverSat is

One set of weights for many sensors, resolutions, scales, and modalities.

UniverSat is a ViT-style Earth Observation backbone built around a Universal Patch Encoder (UPE) that maps patches of arbitrary spatial, spectral, and temporal shape into a shared embedding space — no resampling, no channel selection, no per-sensor encoder. A single model is trained jointly on 13 sensors from 7 datasets spanning ~3 orders of magnitude in resolution, channel count, and revisit frequency, and generalises to unseen sensors within this gamut without input resampling.

  • 📄 Paper (arXiv):
  • 📦 Code / Torch Hub:
  • 🌐 Project page:

Read the full model card

Highlights

  • 🌐 Universal. One weight set processes many modality combinations and arbitrary resolutions — optical, SAR, hyperspectral, and elevation — without channel filtering or resampling.
  • 📏 Resolution-flexible. The output spatial resolution is chosen at inference and decoupled from the input patch size: coarse maps, native resolution, or per-pixel features from the same forward pass.
  • 🔍 Granular. A sub-patch skip cross-attention recovers fine spatial detail (field boundaries, roads) beyond patch-level embeddings.
  • 🧊 Frozen-backbone friendly. Competitive with ~9K-parameter linear probes — strong in low-label regimes.

Usage

The model is published with PyTorchModelHubMixin, so from_pretrained pulls the weights (config.json + model.safetensors) straight from this repo:

from hubconf import UniverSat   # from a local checkout on your path

model = UniverSat.from_pretrained("g-astruc/UniverSat").eval()

Equivalently, through Torch Hub — same weights, same tracked download, no local checkout needed:

import torch

model = torch.hub.load("gastruc/UniverSat", "from_pretrained").eval()

Loading requires huggingface_hub (and safetensors); building the model needs only torch.

Encode any combination of sensors

model.encode(...) looks up per-modality wavelengths, physical resolution, and sub-patch factors automatically from a built-in registry, so you only pass {modality_name: tensor}:

# Snapshot modalities: (B, C, H, W). Time series: (B, T, C, H, W) + a "_dates" tensor.
data = {
    "spot":     torch.randn(2,  3, 360, 360),       # 1 m VHR RGB snapshot
    "s2":       torch.randn(2, 20, 10,  36,  36),   # 10 m Sentinel-2 time series
    "s2_dates": torch.randint(0, 365, (2, 20)),     # day-of-year per timestamp
    "s1":       torch.randn(2, 12,  3,  36,  36),   # 10 m Sentinel-1 (VV, VH, ratio)
    "s1_dates": torch.randint(0, 365, (2, 12)),
    "dsm":      torch.randn(2,  1,  12,  12),       # 30 m elevation snapshot
}

features, _ = model.encode(data, patch_size=40, output_grid=36)
# features: (2, 1296, 768)  ->  a 36×36 dense feature grid (register tokens stripped for you)
  • patch_size — patch size in metres (patch_size=40 → 40 m patches; scale = patch_size / 10 internally).
  • output_gridside G of the output grid (a G×G map, tokens), decoupled from the input patch size. The same model + inputs produce coarse or per-pixel maps just by changing it:
patch, _   = model.encode(data, patch_size=40, output_grid=9)     #   9×9   patch-level
dense, _   = model.encode(data, patch_size=40, output_grid=36)    #  36×36  dense
highres, _ = model.encode(data, patch_size=40, output_grid=180)   # 180×180 high-res

Unseen sensors? Pass the sensor's wavelengths={...} (optical/hyperspectral), polarization codes (SAR), input_res={...}, and subpatches={...} overrides to encode(...). The UPE uses these as positional encodings — no retraining needed.

Inputs should be normalised (per-channel z-score). For the low-level forward(...) API (explicit wavelengths, latent grid, masking), see hubconf.py.

Supported sensors

The encoder accepts any combination of the registered modalities below (and more — see modality_registry.py). Time-series modalities take a 5-D tensor plus a "_dates" companion (day-of-year, Jan 1 = 0).

ModalityTypeChannelsResolution
aerial / aerialflairsnapshotRGB-NiR (4)0.2 m
spotsnapshotRGB (3)1 m
spotRGBNsnapshotRGB-NiR (4)1.6 m
naipsnapshotRGB-NiR (4)1.25 m
rgbneonsnapshotRGB (3)0.1 m
dem / dsm / ndemneonsnapshotDSM / nDEM (1–2)0.2–30 m
s2 (Sentinel-2)time series1010 m
s1 (Sentinel-1)time seriesVV, VH, ratio (3)10 m
l7 / l8 (Landsat)time series6 / 1130 / 10 m
alos (ALOS-2)time seriesHH, HV, ratio (3)30 m
modistime series7250 m
enmap / EO1 / neonsnapshothyperspectral30 m / 30 m / 1 m

Training

UniverSat is pre-trained self-supervised on 13 sensors from 7 datasets with a combination of latent multimodal masked modeling (LM³) and cross-modal contrastive learning under aggressive (~90%) masking across channels, time, space, and modalities.

DatasetSensors used
FLAIR-HubSPOT 6/7 + aerial UHR + Sentinel-1 + Sentinel-2 + DSM + nDEM
PASTIS-HDSPOT 6/7 + Sentinel-1 + Sentinel-2 time series
TreeSatAI-TSaerial UHR + Sentinel-1 + Sentinel-2 time series
PlantedSentinel-1 + Sentinel-2 + Landsat-7/8/9 + ALOS-2 + MODIS
S2NAIP-UrbanNAIP + Landsat-8 + Sentinel-1 + Sentinel-2
HyperGlobalEO-1 Hyperion (175 bands) + Gaofen-5 (150 bands)
EarthView (NEON)NEON RGB/UAV + NIS hyperspectral (396 bands) + nDEM

Combined coverage: spatial resolution 0.1–300 m, temporal depth 1–150 images/year, spectral width 1–396 channels. Fold 1 of PASTIS

From the published model card. Full card on the HuggingFace links in the sidebar.

How it works

How embedding models work

Your textsentence / documentEncodermaps meaningVectorlist of numbersAn embedding model turns text into a vector, so similar meanings sit close together — the basis of search and RAG.

Using it via the API

Call it like any OpenAI endpoint

Once AxForge deploys universat for you, it answers on the OpenAI-compatible API — the same base URL and keys as every other model. (universat below is illustrative; you get the exact model name on deployment.)

$ curl -sS https://api.axforge.ai/v1/embeddings \
  -H "Authorization: Bearer $AXFORGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"universat","input":"text to embed"}'

Create an account — your API key is available in the console. 3M free tokens every 30 days with every new account.

© 2026 AxForge · EU-hosted AI infrastructure Pricing Docs Trust Privacy Terms