phenofield-e98 / README.md
dcher95's picture
Upload README.md with huggingface_hub
e9f6568 verified
|
Raw History Blame Contribute Delete
2.49 kB
---
license: other
tags: [phenology, ecology, species-distribution]
---
# PhenoField e98 (`e98_large_specdrop_dyn4l`)
Frozen phenology field encoder (CrossModalVAE, AdaLN-DiT dynamic branch, species dropout).
Image-free interface: `forward_field(species_id, prism_window, alphaearth_emb)` →
`(z_static [576], z_dynamic [192])`. The dynamic encoder consumes only the 365×7 trailing PRISM
window and the 64-d AlphaEarth embedding (no doy / lat-lon / climplicit weights exist in this
checkpoint) — season enters through the PRISM window alone.
## Files
| file | what |
|---|---|
| `last.ckpt` | Lightning checkpoint (weights + full training config in `hyper_parameters`) |
| `hparams.yaml` | same config, human-readable |
| `models/*.py` | the exact model code (`CrossModalVAE`, `AdaLNDynamicEncoder`) — self-contained, relative imports only |
| `species_embeddings_v2.pt` | BioCLIP text matrix [6825, 768]; the constructor loads it via `config['species_embedding_path']` |
| `species_vocab.json` | species name → id (indexes rows of the embedding matrix) |
| `inputs/prism_weekly.npz` | climatological per-(cell, week) 365×7 PRISM windows for the CONUS 0.5° grid |
| `inputs/alphaearth_2017.parquet` | per-point AlphaEarth 64-d embeddings (nearest-cell lookup) |
| `inputs/grid_centroids_0.5deg.csv`, `inputs/plant_flowering_events.parquet` | grid definition + plant flowering observations |
## Loading
```python
import sys, torch
from huggingface_hub import snapshot_download
from omegaconf import OmegaConf
d = snapshot_download('dcher95/phenofield-e98')
sys.path.insert(0, d)
from models.cross_modal_vae import CrossModalVAE
ckpt = torch.load(f'{d}/last.ckpt', map_location='cpu', weights_only=False)
cfg = OmegaConf.to_container(OmegaConf.create(ckpt['hyper_parameters']).model, resolve=True)
cfg['species_embedding_path'] = f'{d}/species_embeddings_v2.pt'
model = CrossModalVAE(cfg)
state = {k[len('model.'):]: v for k, v in ckpt['state_dict'].items() if k.startswith('model.')}
missing, unexpected = model.load_state_dict(state, strict=False)
assert not missing and not unexpected # this models/ copy loads clean
model.eval()
```
Do **not** load this checkpoint with the `models/` in dcher95/PhenoField's top level — that class
silently drops `dynamic_encoder.null_species_emb` (the parameter species dropout trains).
Use the `models/` shipped here (a copy of `vendor/bwei_ppe`).
Downstream pipeline: `pipelines/` in the ANTHEIA repo (Summer-2026-CfE project).