Skip to content

ML Domain

For machine learning inference, data preparation, and model management. Folia is the data preparation and inference layer - not a training platform. The ML ecosystem has mature training tools (TorchGeo, InstaGeo, TerraTorch); folia fills the gap between trained models and deployed predictions with provenance.

Decided in ADR-0006

Schema Extension

The ml: block on a layer declares machine learning metadata. It applies to three layer variants: model layers (a trained model), prediction layers (inference output), and embedding layers (foundation model representations).

FieldTypeRequiredDescription
taskstringYesML task: classification, segmentation, detection, regression, embedding
architecturestringNoModel architecture family (e.g., unet, vit, resnet)
foundation_modelstringNoBase foundation model if fine-tuned (e.g., prithvi-100m, clay-v1)
model_refstringNoReference to model artifact URI (on prediction layers)
formatstringNoModel format: onnx, torchscript, safetensors
input_bandslistNoExpected input bands (e.g., [B02, B03, B04, B08])
input_shapelistNoExpected input tensor shape ([C, T, H, W] or [C, H, W])
output_classeslistNoClass definitions: [{id: 0, name: background}, ...]
embedding_dimintegerNoEmbedding vector dimensionality
metricsobjectNoEvaluation metrics (e.g., {miou: 0.61, accuracy: 0.83})
param_countintegerNoNumber of model parameters
training_datastringNoURI of training dataset
distilled_fromstringNoURI of teacher model (if distilled)
compression_rationumberNoSize reduction vs. teacher model

Model Layer

A trained model stored as a versioned artifact:

yaml
layers:
  models/crop-segmentation:
    type: model
    uri: catalog://models/crop-segmentation-sentinel2@v3

    ml:
      task: segmentation
      architecture: unet
      foundation_model: prithvi-100m
      input_bands: [B02, B03, B04, B08]
      input_shape: [4, 6, 224, 224]
      output_classes:
        - { id: 0, name: background }
        - { id: 1, name: corn }
        - { id: 2, name: soybean }
        - { id: 3, name: wheat }
      metrics:
        miou: 0.61
        accuracy: 0.83
      format: onnx

    geo:
      bbox: [-10.0, 35.0, 30.0, 60.0]
    temporal:
      range: [2024-01-01, 2024-12-31]

Prediction Layer

Output of running inference - a computed layer like any other:

yaml
layers:
  predictions/crop-type-iowa:
    type: raster
    compute:
      op: predict
      inputs:
        imagery: { layer: imagery/hls-iowa }
      params:
        model: catalog://models/crop-segmentation-sentinel2@v3

    ml:
      model_ref: catalog://models/crop-segmentation-sentinel2@v3
      task: segmentation

    style:
      palette: categorical
      legend: true

Embedding Layer

Precomputed embeddings from a foundation model - an intermediate representation for lightweight downstream tasks:

yaml
layers:
  embeddings/prithvi-conus-2024:
    type: raster
    uri: catalog://embeddings/prithvi-conus-2024@v1

    ml:
      task: embedding
      foundation_model: prithvi-100m
      embedding_dim: 768
      input_bands: [B02, B03, B04, B05, B06, B07]

    geo:
      bbox: [-125, 24, -66, 50]
    temporal:
      range: [2024-01-01, 2024-12-31]

Operation Categories

The ML domain organizes operations into 5 categories:

CategoryOperationsDescription
preparechip, temporal_composite, label_rasterize, train_test_split, cloud_filterTransform raw imagery into ML-ready training data
inferencepredict, predict_batchRun model inference on imagery
embedcompute_embeddings, linear_probeGenerate and use foundation model embeddings
distilldistillCompress models via knowledge distillation
evaluateevaluate, confusion_matrixAssess model predictions against ground truth

Key Operations

OperationTypeDescription
predictraster + model -> rasterRun model inference on input imagery
predict_batchraster + model + region -> rasterBatch inference over a large region (tiled)
compute_embeddingsraster -> rasterGenerate embeddings from a foundation model encoder
chipraster + labels -> raster chipsCut imagery into fixed-size patches for ML training
evaluateraster + raster -> tableCompute metrics (mIoU, accuracy, per-class F1) against ground truth
distillmodel + raster -> modelTask-specific knowledge distillation (teacher -> student)
linear_probeembeddings + labels -> modelTrain lightweight classifier on cached embeddings

Data Preparation Pipeline

The primary gap both InstaGeo and the GeoML library survey identify: going from raw satellite imagery to training-ready chips. Expressed as a folia pipeline:

yaml
layers:
  source/imagery:
    type: raster
    source:
      connector: stac
      params:
        catalog: https://cmr.earthdata.nasa.gov/stac
        collection: HLSL30.v2.0
        temporal: 2024-01-01/2024-12-31

  prepare/filtered:
    type: raster
    compute:
      op: cloud_filter
      inputs:
        imagery: { layer: source/imagery }
      params:
        max_cloud_cover: 0.2

  prepare/chips:
    type: raster
    compute:
      op: chip
      inputs:
        imagery: { layer: prepare/filtered }
      params:
        size: 224
        stride: 112
        temporal_steps: 6
        min_valid_fraction: 0.8

Compute

ML operations run across three backends, selected automatically by model format:

BackendOperationsUse Case
onnxruntimepredict, predict_batchPrimary inference backend. Runs ONNX models on CPU, CUDA, CoreML.
torchgeopredict, compute_embeddings, distill, linear_probeOperations requiring PyTorch (gradients, embedding extraction).
sklearnevaluate, confusion_matrix, linear_probeLightweight eval metrics. No GPU needed.

Backend Resolution

predict op ->
  model format is ONNX         -> onnxruntime
  model format is torchscript   -> torchgeo
  explicit backend: override    -> use that
  no model format metadata      -> error

ONNX is the preferred interchange format: it decouples training framework from inference runtime, runs on CPU/CUDA/CoreML/DirectML, and has a smaller runtime dependency than full PyTorch.

Local-First Inference

The same predict operation runs locally or in cloud batch. The distillation bridge makes this practical:

TierModelLatency
Workbench / localDistilled model (46M params, ONNX)Seconds, interactive
Cloud batchFull model (389M params)Hours, high quality

Model layers declare runtime_hints that inform scheduling:

yaml
ml:
  format: onnx
  param_count: 16_000_000
  runtime_hints:
    min_memory: 2Gi
    gpu_preferred: false
    batch_latency: 200ms

Positioning

What folia does and doesn't do

Folia doesFolia doesn't
Prepare training data (STAC -> chips with labels)Train models from scratch
Run inference with pretrained/fine-tuned modelsHyperparameter search
Store models as versioned artifacts with provenanceHost training infrastructure
Compress models via distillation for local inferenceCompete with MLflow or W&B
Compute and cache embeddings from foundation modelsBuild foundation models
Evaluate predictions against ground truthResearch novel architectures

Where folia sits

Research / Training (TorchGeo, InstaGeo, TerraTorch)
        |  model weights, ONNX exports
        v
Folia ML Domain (data prep, inference, artifacts)
        |  predictions, embeddings
        v
Serving / Workbench (tiles, maps, charts)

Model and Data Cards

Published model and embedding artifacts can include structured metadata cards for interoperability with HuggingFace Hub and the geospatial ML community. See Cards for the model card and data card specifications.

Example: End-to-End Crop Mapping

yaml
layers:
  # 1. Source imagery
  imagery/hls-iowa:
    type: raster
    source:
      connector: stac
      params:
        catalog: https://cmr.earthdata.nasa.gov/stac
        collection: HLSL30.v2.0
        bbox: [-96.6, 40.4, -90.1, 43.5]
        temporal: 2025-06-01/2025-09-30
    geo:
      bbox: [-96.6, 40.4, -90.1, 43.5]

  # 2. Run inference
  predictions/crop-type:
    type: raster
    compute:
      op: predict
      inputs:
        imagery: { layer: imagery/hls-iowa }
      params:
        model: catalog://models/crop-segmentation-sentinel2@v3
    ml:
      model_ref: catalog://models/crop-segmentation-sentinel2@v3
      task: segmentation
    style:
      palette: categorical
      legend: true

  # 3. Evaluate
  evaluation/accuracy:
    type: table
    compute:
      op: evaluate
      inputs:
        predictions: { layer: predictions/crop-type }
        ground_truth: { layer: labels/cdl-iowa-2025 }
      params:
        task: segmentation
    style:
      table:
        columns:
          - { field: metric, label: Metric }
          - { field: value, label: Value, format: ".3f" }

Licensed under CC-BY-4.0