orbit2vec / README.md
jgalego's picture
Upload folder using huggingface_hub
68d76fc verified
|
Raw History Blame Contribute Delete
5.43 kB
---
datasets:
- jgalego/orbit2vec-windows
- juliensimon/space-track-tle-history
- juliensimon/space-track-satcat
- RhynoWu/starlink-maneuver-db
library_name: pytorch
license: mit
model_name: orbit2vec
pipeline_tag: feature-extraction
tags:
- space
- satellites
- tle
- embeddings
- contrastive-learning
- weird2vec
---
# orbit2vec
<p align="center"><img src="assets/logo.svg" alt="Orbit2Vec logo: a satellite on a rainbow orbit around Earth, on a dark tile" width="200"></p>
Embeddings for satellite orbit histories. Two windows of the same object, a month apart, should land close together; other objects should land apart. Part of Weird2Vec, embedding models for data nobody embeds.
> [!NOTE]
> **What is a TLE?** A two-line element set is the public record of an orbit: mean motion, eccentricity, inclination, node, perigee and drag, at one epoch. Space-Track publishes them for every tracked object, several times a day. A month of them is a trajectory, including its manoeuvres and decay.
![Three orbital shells, at 550 km and 53.0°, 570 km and 70.0°, and 560 km and 97.6°](assets/shells.svg)
Satellites in the same shell fly almost the same orbit, which is what makes telling them apart hard.
## 🚀 Usage
The repo holds the script that trained the model, so one command embeds the last 32 days of a TLE file (oldest first, one object) and names the nearest catalogued objects:
```
uv run https://huggingface.co/jgalego/orbit2vec/resolve/main/orbit2vec.py embed --tle history.txt
```
It prints the nearest objects, a guess for regime, constellation or object type and owner, inclination and altitude drift, and the 256-dimensional embedding.
## 🛰️ Data
[jgalego/orbit2vec-windows](https://huggingface.co/datasets/jgalego/orbit2vec-windows): daily mean elements from [juliensimon/space-track-tle-history](https://huggingface.co/datasets/juliensimon/space-track-tle-history), grouped by constellation and owner with [juliensimon/space-track-satcat](https://huggingface.co/datasets/juliensimon/space-track-satcat). Repeated epochs are collapsed to the latest TLE per UTC day. Windows are 32 days long; training pairs are adjacent windows of one object, 10% of the objects are held out, and the test pair is the two windows from 2026-02-28 to 2026-05-02. Manoeuvre labels come from [RhynoWu/starlink-maneuver-db](https://huggingface.co/datasets/RhynoWu/starlink-maneuver-db) and are used for evaluation only.
## 🏋️ Training
Each day becomes 11 features: altitude, its change within the window, eccentricity, inclination and its change, the node and perigee angles as sine and cosine, drag and its rate. Days without a TLE are masked. A transformer encodes the window and a contrastive loss pulls two augmented views (random crop, dropped days) of adjacent windows of the same object together against the rest of the batch. Most of a batch shares one window, so satellites of the same shell compete. Small heads predict regime, constellation, owner, inclination and drift, weighted 0.3.
| | |
|---|---|
| Parameters | 3,314,479 (4 layers, width 256) |
| Steps | 20000, 512 objects (two views each) per step |
| Learning rate | 0.0003, cosine; temperature 0.05 |
| Training pairs | 302,056 from 45,261 objects |
| Final loss | 0.4862 (contrastive 0.2473) |
| Hardware | NVIDIA A10G, 17 min |
## 📊 Results
Each object's later test window is matched against the earlier windows of all 28230 test objects. *Seen* objects were in training, in other months; *unseen* objects never were. The baseline matches the mean of the standardized inputs.
| Objects | n | Top-1 | Top-5 | Baseline top-1 | Regime | Group | Owner | Inclination MAE | Drift MAE |
|---|---|---|---|---|---|---|---|---|---|
| seen | 25441 | 0.423 | 0.585 | 0.059 | 0.998 | 0.861 | 0.82 | 0.78 | 0.058 |
| unseen | 2789 | 0.439 | 0.598 | 0.057 | 0.998 | 0.848 | 0.808 | 0.76 | 0.059 |
Chance top-1 is 3.5e-05.
Two harder checks:
- **Shell mates.** Top-1 among earlier windows of the same group within 5 km of altitude and 0.5° of inclination, for the 21510 objects with at least five such mates: 0.378 (baseline 0.074).
- **Manoeuvres.** Embedding distance between the 10 days before and after a labelled Starlink manoeuvre, against quiet days: AUC 0.763 on 270 manoeuvres and 553 quiet days (a plain altitude-jump baseline: 0.845).
![Test windows' embeddings flattened with UMAP, coloured by group](results/map.png)
### Auxiliary weight
The same model trained with four auxiliary weights, each on its own branch (`aux0`, `aux0.1`, `aux0.3`, `aux1`). `main` is `aux0.3`. Without the auxiliary heads the embedding still retrieves as well, but it does not carry group, owner or inclination.
| Aux weight | Seen top-1 | Unseen top-1 | Shell mates | Group | Owner | Inclination MAE | Manoeuvre AUC |
|---|---|---|---|---|---|---|---|
| 0 | 0.419 | 0.435 | 0.377 | 0.04 | 0.05 | 21.8 | 0.752 |
| 0.1 | 0.419 | 0.427 | 0.374 | 0.85 | 0.80 | 0.89 | 0.791 |
| 0.3 | 0.423 | 0.439 | 0.378 | 0.86 | 0.82 | 0.78 | 0.763 |
| 1 | 0.415 | 0.422 | 0.372 | 0.87 | 0.83 | 0.77 | 0.750 |
Hard pairs do not collapse at any weight. The manoeuvre AUC rests on 26 objects, so differences there are noise.
## ⚠️ Limitations
- Mean elements from public TLEs only; accuracy is a few km and classified objects are missing.
- Windows are 32 days, so slow decay and long manoeuvre campaigns look like noise.
- Manoeuvre labels cover Starlink only.