File size: 7,253 Bytes
6a4eb73 18ebfc8 6a4eb73 18ebfc8 6a4eb73 b868c30 6a4eb73 b868c30 ff249f5 6a4eb73 a284772 6a4eb73 a284772 6a4eb73 ff249f5 6a4eb73 ff249f5 6a4eb73 ff249f5 5eee133 ff249f5 5eee133 ff249f5 5eee133 ff249f5 5eee133 6a4eb73 ff249f5 5eee133 ff249f5 5eee133 6a4eb73 d386935 6a4eb73 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | ---
license: apache-2.0
pipeline_tag: text-to-image
library_name: safetensors
tags:
- text-to-image
- remote-sensing
- earth-observation
- satellite-imagery
- diffusion
- flow-matching
- diffusion-transformer
---
<div align="center">
# GeoCore-9B
### Towards Geo-Aware Generative Foundation Models in Earth Observation
[Jeonghyeok Do](https://jeonghyeokdo.github.io/) ·
[Munchurl Kim](https://scholar.google.com/citations?user=bGXte_4AAAAJ&hl=en)
Korea Advanced Institute of Science and Technology (KAIST)
[](https://kaist-viclab.github.io/GeoCore-9B_site/)
[](https://github.com/KAIST-VICLab/GeoCore-9B)
[](https://www.apache.org/licenses/LICENSE-2.0)
<img src="teaser.jpg" alt="Text-conditioned generation compared with prior methods" width="100%">
</div>
A 9-billion-parameter generative foundation model for Earth Observation, trained from scratch
exclusively on EO data. GeoCore-9B is a Flow Matching Diffusion Transformer that conditions
generation on text **and** continuous geospatial metadata — ground sample distance (GSD), latitude
and longitude.
> [!NOTE]
> **2026-08-04 — corrected weights.** The initial upload accidentally contained an EMA state that
> was never updated during training (pure initialization weights — see
> [GitHub issue #2](https://github.com/KAIST-VICLab/GeoCore-9B/issues/2)). The current files are the
> final 300K-step training weights, verified to load strictly and denoise correctly. If you
> downloaded the weights before this date, please re-download and check them against `SHA256SUMS`.
## Model details
| | |
|---|---|
| Parameters | 9.24 B |
| Weights | final training weights (non-EMA), bfloat16, sharded safetensors |
| Included | frozen Flux.2 VAE in `vae/` (Apache-2.0, Black Forest Labs) |
| Architecture | Flow Matching DiT — 8 double-stream + 24 single-stream blocks, hidden 4096, 32 heads |
| Conditioning | CLIP + T5 text embeddings, GSD, latitude, longitude |
| Training data | [Git-10M](https://huggingface.co/datasets/lcybuaa/Git-10M) |
| Training | 300K steps, global batch 1024, AdamW lr 1e-4, bf16, DeepSpeed ZeRO-2, 8x B200 |
| Resolution | 256x256 |
Training used a **Geospatial Semantic Alignment (GSA)** loss that aligns intermediate DiT features
(block 8) with a frozen DINOv3-Sat teacher, weighted by `mu = 0.5`. GSA is training-only — the
teacher and projection head are not needed for inference, and the exported weights add no overhead.
## Usage
These weights use a custom `Flux2` architecture, so load them with the model definition from the
GitHub repository rather than a stock `diffusers` pipeline.
```python
import torch
from huggingface_hub import snapshot_download
from models.flux2 import Flux2, GeoCore9BParams
from inference import load_state_dict
path = snapshot_download("JeonghyeokDo/GeoCore-9B")
model = Flux2(GeoCore9BParams()).to("cuda", torch.bfloat16)
model.load_state_dict(load_state_dict(path), strict=True)
model.eval()
```
Sampling, including the Euler flow-matching sampler and classifier-free guidance over both text and
metadata, is provided by `inference.py`:
```bash
python inference.py \
--ckpt /path/to/GeoCore-9B \
--vae /path/to/GeoCore-9B/vae \
--prompt "A satellite view of a highly dense urban city with towering skyscrapers" \
--lon 126.97 --lat 37.56 --res 0.0 \
--num-samples 4 --out samples/
```
### Conditioning inputs
* `res` — resolution index, defined as `17 - z` for Google XYZ tile zoom `z`. `res = 0` is roughly
1.2 m/px at the equator; each `+1` doubles the GSD.
* `lon`, `lat` — degrees.
* Any field set to `-999.0` falls back to the model's learned null embedding for that field, so
metadata is fully optional.
### The frozen VAE is included
`vae/` in this repository holds the frozen Flux.2 autoencoder that encodes and decodes the latents,
so `snapshot_download` gives you everything the model needs:
```bash
python inference.py --ckpt /path/to/GeoCore-9B --vae /path/to/GeoCore-9B/vae ...
```
`models/vae_flux2.py` reads it directly (`load_autoencoder`), and `vae/config.json` is included so
`diffusers >= 0.37` can load it too:
```python
from diffusers import AutoencoderKLFlux2
vae = AutoencoderKLFlux2.from_pretrained("JeonghyeokDo/GeoCore-9B", subfolder="vae")
```
CLIP and T5 text encoders are still downloaded from the Hub at runtime.
> [!IMPORTANT]
> Do **not** substitute `ae.safetensors` from `FLUX.2-dev`. It holds the same autoencoder weights,
> but under the FLUX Non-Commercial License v2.1, whose §4(a)(iii) forbids "surveillance purposes,
> including all research and development related to surveillance" — a clause that Earth-observation
> work should not have to argue about. The copy shipped here is Apache-2.0, and the two were
> verified identical by pairing every tensor on value: 250 of 251 pair one-to-one with a worst
> deviation of 7.802e-03 (bf16 rounding); the odd one out is a BatchNorm step counter. In bf16, the
> precision this model runs in, latents and reconstructions are bit-identical.
## Limitations
* Trained on 256x256 RGB optical imagery; other resolutions and sensor modalities require adaptation.
* Git-10M coverage is uneven across the globe, so generation quality varies by region.
* Geospatial conditioning reflects correlations in the training corpus and is not a substitute for
real observations of a location.
## License and attribution
GeoCore-9B is released under Apache-2.0, and so is every weight needed to run it.
**`model-*.safetensors` (the 9.24B DiT)** — Copyright 2026 Jeonghyeok Do and Munchurl Kim,
Apache-2.0. Trained from scratch on Git-10M; not derived from any FLUX checkpoint.
**`vae/` (the frozen 84M autoencoder)** — Copyright Black Forest Labs, **Apache-2.0**. This is an
**unmodified, byte-identical redistribution** of
[`black-forest-labs/FLUX.2-klein-base-4B`](https://huggingface.co/black-forest-labs/FLUX.2-klein-base-4B)
`vae/diffusion_pytorch_model.safetensors` and its `vae/config.json`, bundled here only so the model
is usable in one download. Verify it against upstream:
```
sha256 ca70d2202afe6415bdbcb8793ba8cd99fd159cfe6192381504d6c4d3036e0f04 vae/diffusion_pytorch_model.safetensors
sha256 0d6dfb69ae95a5e2ac9836284bbb63d8b38ce67b25ba2dff380752b2a10ab948 vae/config.json
```
Those digests are the upstream files' own. A copy of the Apache License 2.0 as distributed with
that model is included as [`LICENSE-FLUX2-VAE.md`](LICENSE-FLUX2-VAE.md). Black Forest Labs neither
endorses nor is affiliated with GeoCore-9B; the attribution above is a statement of origin, not of
sponsorship.
The [Git-10M](https://huggingface.co/datasets/lcybuaa/Git-10M) training corpus is CC BY-NC-ND 4.0,
which restricts (re)training on that data to non-commercial use.
## Citation
```bibtex
@article{do2026geocore,
title = {GeoCore-9B: Towards Geo-Aware Generative Foundation Models in Earth Observation},
author = {Do, Jeonghyeok and Kim, Munchurl},
year = {2026}
}
```
|