Zero-Shot Classification
Transformers
Safetensors
English
qwen3_5
feature-extraction
earth-observation
remote-sensing
satellite-imagery
decision-model
multimodal
vision
calibration
lora
custom_code
Instructions to use mx297/EO-Jev with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use mx297/EO-Jev with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("zero-shot-classification", model="mx297/EO-Jev", trust_remote_code=True)# pip install -U transformers accelerate # Load model directly from transformers import AutoProcessor, AutoModel processor = AutoProcessor.from_pretrained("mx297/EO-Jev", trust_remote_code=True) model = AutoModel.from_pretrained("mx297/EO-Jev", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
File size: 8,603 Bytes
4a56d40 d79e10e 4a56d40 75e5101 4a56d40 8afc72d 4a56d40 75e5101 4a56d40 | 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 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | ---
license: apache-2.0
base_model: vllm-sr/d3-flash
base_model_relation: finetune
library_name: transformers
pipeline_tag: zero-shot-classification
language:
- en
tags:
- earth-observation
- remote-sensing
- satellite-imagery
- decision-model
- multimodal
- vision
- calibration
- lora
---
# EO-Jev: Decision Model for Earth Observation
[**Paper (arXiv:2611.03371)**](https://arxiv.org/abs/2611.03371) ·
[**Project page**](https://mbzuai-oryx.github.io/EO-Jev/) ·
[**Code**](https://github.com/mbzuai-oryx/EO-Jev)
EO-Jev answers questions about satellite and aerial images with **a probability for every allowed answer, in a single
forward pass**. It writes no text, so answers come fast and with a confidence you can threshold: accept confident
answers automatically and send uncertain ones to an analyst.
EO-Jev is [d3-flash](https://huggingface.co/vllm-sr/d3-flash) (8.4B parameters, built on Qwen3.5-9B) adapted to Earth
observation. We trained LoRA adapters on public Earth-observation training splits: rank 32 on the text tower, 64 on the
vision merger and 16 on the vision blocks. The adapters are merged into the weights, so EO-Jev has the same
architecture, interface and inference cost as d3-flash.
## Results
On 30 evaluation settings from 23 public Earth-observation benchmarks (details in the paper):
| | |
|---|---|
| **26 / 30** | settings improved significantly over d3-flash: +23.8 points on average where the dataset's training split was used, **+8.0** on 12 settings held out from adaptation |
| **20 / 28** | settings at or above the best open Earth-observation specialist model |
| **21 / 28** | settings with lower expected calibration error than the specialist |
| **6.4×** | median throughput of the best specialist's, each at its best batch size (3.2× with one question per call) |
| **−1.8** | points on general (non-EO) decisions, the cost of adaptation |
## Quickstart
```bash
pip install "transformers==5.17.0" torch torchvision pillow safetensors accelerate
pip install flash-linear-attention # optional: fast GPU kernels for the linear-attention layers
pip install causal-conv1d # optional: fast kernel for the short convolutions in those layers
```
```python
import json
from huggingface_hub import hf_hub_download
from transformers import AutoModel
model = AutoModel.from_pretrained("mx297/EO-Jev", trust_remote_code=True) # on cuda:0 when a GPU is visible
image = hf_hub_download("mx297/EO-Jev", "assets/example_airport.png") # or a local path, URL or PIL image
result = model.system_one(
state="Aerial image, about 0.3 m per pixel.",
images=[image],
questions={
"scene": {
"type": "choice",
"instructions": "What is the main land use in this image?",
"criteria": {"airport": None, "harbor": None, "parking lot": None, "residential area": None, "farmland": None},
},
"airplanes": {
"type": "choice",
"instructions": "How many airplanes are in this image?",
"criteria": {"0": None, "1": None, "2": None, "3": None, "4": None, "5": None, "more than 5": None},
},
"car": {
"type": "noul",
"instructions": "Is there a car in this image?",
},
},
)
print(json.dumps(result["answers"], indent=1))
```
Output (probabilities rounded to three decimals):
```json
{
"scene": {"type": "choice", "choice": "airport",
"probabilities": {"airport": 0.966, "harbor": 0.000, "parking lot": 0.033, "residential area": 0.000, "farmland": 0.000},
"confidence": 0.905},
"airplanes": {"type": "choice", "choice": "5",
"probabilities": {"0": 0.000, "1": 0.001, "2": 0.002, "3": 0.046, "4": 0.440, "5": 0.454, "more than 5": 0.057},
"confidence": 0.463},
"car": {"type": "noul", "noul": 0.978}
}
```
The scene and the car are answered right and with confidence. The image has four airplanes: EO-Jev's count is a near
tie between 4 (0.440) and 5 (0.454), and its low confidence (0.46) marks the answer for review instead of hiding the
mistake. Counting on unfamiliar imagery is one of the limitations below. For `noul` questions, the value is the
probability of "yes".
All questions about the same image or images are answered in one call.
## Asking questions
A request has a **state** (free text: what the image is, its sensor or resolution, any context), one or more
**images**, and a dictionary of **questions**. Each question has a `type`:
| Type | `criteria` | Answer |
|---|---|---|
| `choice` | a dict of options (up to 255); each value is an optional description (`None` is fine) | `choice` (the top option), `probabilities` per option, `confidence` |
| `noul` | none (a yes/no question) | `noul`: the probability of "yes" |
| `score` | an ordered list of 2–10 levels, e.g. `["no damage", "minor damage", "major damage", "destroyed"]` | `score` (the expected level index) and `probabilities` per level |
Several images go into one request, for example a pre- and post-event pair or a time series. Say in the state which is
which:
```python
result = model.system_one(
state="Image 1 is the earlier (pre-disaster) image and Image 2 the later (post-disaster) image of the same area.",
images=["pre.png", "post.png"],
questions={
"damage": {
"type": "score",
"instructions": "How damaged is the building in the centre?",
"criteria": ["no damage", "minor damage", "major damage", "destroyed"],
}
},
)
```
The model also works as a `transformers` pipeline:
`pipeline("decision", model="mx297/EO-Jev", trust_remote_code=True)(state=..., questions=..., images=...)`.
**Tips**
- Keep each answer's wording short and distinct. The probabilities are over the options you give, so include an
option such as "none of these" or "0" when it can be the answer.
- The probabilities are calibrated at the checkpoint's temperature. A per-question threshold on the top probability
decides which answers to accept automatically.
- The code that runs the model (`d3_runtime.py` and the other `d3_*.py` files) is d3-flash's runtime, unchanged.
## Training
- **Base model:** d3-flash, with LoRA adapters on the text tower, the vision merger and the vision blocks (the vision
blocks at 0.2× the learning rate), merged after training.
- **Data:** decision questions built from public Earth-observation training splits: scene and land-use labels, object
presence and counting, visual question answering, multi-temporal change, building damage and disaster type,
geo-localisation. About 20% of every batch replays general decision data with d3-flash's own probabilities as targets,
to keep its general skills. Every training image that duplicates or crops an evaluation image was removed.
- **Loss:** KL divergence to the target distribution: one-hot, soft ordinal labels (SORD) for counts and damage
levels, or d3-flash's own probabilities.
- **Compute:** 20,000 steps of 16 questions on 4 NVIDIA A100 GPUs.
Training and evaluation code: [github.com/mbzuai-oryx/EO-Jev](https://github.com/mbzuai-oryx/EO-Jev).
## Limitations
- Counting on unfamiliar imagery, robustness to the order of answer options, geometric and cross-view reasoning, and
calibration far from the training data remain the hardest cases.
- EO-Jev was trained and evaluated on optical (RGB) imagery; SAR and multispectral inputs were not part of training.
- It answers only with the options you provide. It cannot say that none applies unless such an option is offered.
- Validate it on your own data before relying on it for decisions with consequences.
## License
Apache-2.0 ([LICENSE](LICENSE)), as d3-flash, which is built on
[Qwen/Qwen3.5-9B](https://huggingface.co/Qwen/Qwen3.5-9B) (Apache-2.0); see [NOTICE](NOTICE). The datasets used for
training keep their own licences. The example image is from the UC Merced Land Use dataset (USGS National Map imagery,
public domain).
## Citation
```bibtex
@article{abouelhadid2026eojev,
title = {{EO-Jev}: Decision Model for {Earth} Observation},
author = {Abouelhadid, Mohamed Atef and Abuhani, Diaa Addeen and
Munir, Muhammad Akhtar and Khan, Fahad Shahbaz and Khan, Salman},
journal = {arXiv preprint arXiv:2611.03371},
year = {2026}
}
```
Please also cite d3-flash:
```bibtex
@misc{d3_flash_2026,
title = {{d3-flash}: A Multimodal Foundation Decision Model},
author = {{vLLM Semantic Router Team}},
year = {2026},
howpublished = {\url{https://huggingface.co/vllm-sr/d3-flash}}
}
```
|