Inspiration
Pasture management underpins many food systems, rural livelihoods, and carbon cycles. Farmers make frequent, high-stakes grazing decisions—often under uncertainty, time pressure, and with imperfect observations. Traditional methods (visual inspection, fixed rotation schedules) are blunt instruments: they can produce under-utilized grass, overgrazing, soil degradation, and missed opportunities for carbon sequestration.
Inspired to build PastureAI for three converging reasons:
Practical farmer-first impact. A solution must be useful in real field contexts: low-bandwidth, heterogeneous sensors, physical constraints like fencing and water, and most importantly — decision clarity for farmers.
Scientific rigor and auditability. To support carbon accounting, regenerative programs, and enterprise adoption, predictions must be explainable, uncertainty-aware, and auditable.
Engineering maturity. Many agtech prototypes look pretty but fail to scale. Aimed for a system that was research-grade and production-ready (CI/CD, monitoring, drift detection, privacy).
The work is grounded in evidence: combining remote sensing, targeted drone & ground sampling, validated ML, and constrained optimization to produce actionable grazing plans and environmental metrics.
What it does
At a glance, PastureAI:
Estimates biomass (t/ha) at per-tile spatial detail across pastures from multispectral satellite, drone imagery, and ground sensors. Predicts per-pixel/pixel-aggregate biomass values suitable for mapping and visualization.
Quantifies uncertainty via heteroscedastic modeling + MC dropout ensembles, and surfaces per-tile confidence intervals to the user.
Produces temporal forecasts (growth curves) using spatio-temporal ensembles (spatial CNNs + temporal GRU/Transformer) to predict next-day → 30-day biomass trajectories with uncertainty bands.
Maps biomass to carbon using explainable conversion models and calibration from soil samples to produce site-level soil organic carbon (SOC) change estimates and tCO₂e/ha/year signals.
Advises grazing operations by running a multi-pasture optimizer that accounts for herd demand, water availability, fence reconfiguration capacity, labor constraints, and recovery rules, producing a schedule and recovery recommendations.
Provides developer & farm integrations via robust APIs (tile endpoints, per-tile JSON, timeseries & forecast API), SDKs, Webhooks, and Mapbox-ready tiles.
Maintains compliance & audit logs: every prediction includes model hash, source image IDs, training model version, and optional ground truth link. Immutable logs allow traceability for audits and carbon reporting.
Addresses social & sustainability goals: smallholder safety via equity adjustment factors, community benchmarking anonymized, and impact metrics for funders.
User flows:
- Farmer or advisor loads the pasture map in the UI → views biomass heatmap with uncertainty ribbon → opens a tile to see mean/std/drivers → asks “what if we wait 7 days?” counterfactual simulation → gets an optimizer plan accounting for constraints → logs decision and produces an export pack (CSV + PDF) for audits/extension services.
How we built it
This section covers the concrete technical build: architecture, data, models, training, deployment, UI, and ops — with the details engineering reviewers need.
Architecture overview (high level)
Sensors (Satellite/Drone/Ground) -> Ingest Layer -> Preprocessing & Harmonization -> Feature Engineering -> Model Suite (Image2Biomass + Temporal) -> Postprocessing (tile aggregation, uncertainty, carbon) -> Tile & API Serving
⤷ Audit Store, Monitoring, Drift Detector, Retrain Pipeline
⤵
UI / SDK / Optimizer
Key modules:
Ingest: handles bulk & streaming uploads, geo-alignment, provenance tagging.
Preprocessing: radiometric correction, resampling, cloud mask, co-registration.
Feature engineering: NDVI, EVI, RedEdge indices, texture measures, canopy height models (DSM/CHM), lagged temporal features.
Modeling:
- Image2Biomass (fully-convolutional CNN stack based on ResNet34 backbone, modified for multi-band input).
- Temporal ensembles (GRU / Transformer variants) for sequence forecasting.
- Heteroscedastic heads + MC dropout for uncertainty.
Postprocessing: per-tile aggregation, MC ensemble mean/std, conversion to color ramps / GeoTIFF / PNG tiles, and carbon model mapping.
Serving: Map tiles (XYZ), Predict Tile JSON API, timeseries & forecast API, SDKs and Webhooks.
Operationalization: CI/CD pipelines, automated retrain triggers on drift, monitoring (Prometheus + Grafana), immutable audit logs (append-only store for predictions).
Data ingestion & provenance
Sources
Satellite imagery: Sentinel-2 style (multispectral: B, G, R, NIR, RedEdge), 10–30 m resolution, cadence 5–30 days.
Drone surveys: high-resolution orthomosaics & DSM/CHM, 2–10 cm resolution, used for calibration and per-paddock detail.
Ground truth biomass: destructive clip samples (oven-dry weight), ~12k cores across 120 trial sites — used for regression targets and calibration.
Ground sensors: ultrasonic height sensors, optical spot sensors, soil moisture probes (time series).
Weather & climate: station and gridded reanalysis (rainfall, temperature, PET).
Soil & lab: SOC%, bulk density, texture from lab records.
Telemetry & management records: GPS collars and farmer-provided logs (paddock moves, stocking, inputs).
Provenance design
Every ingested asset receives a unique immutable ID plus:
capture timestamp,
sensor metadata (platform, bands, calibration),
preprocessor version,
ingest hash,
ingest location bounds.
These items are persisted and surfaced in per-tile JSON outputs. The audit store stores: prediction event ID, model version hash, inputs list, outputs, and user action (if any).
Preprocessing steps
Cloud mask (Fmask-like) and edge masking.
Radiometric correction to surface reflectance (per sensor).
Geometric co-registration (RTK/photogrammetry corrections for drone).
Resampling to model input grid (tile size 256–512 px depending on sensor).
Per-band normalization: per-band mean/std computed on training set, applied at preprocessing.
Code snippet (pseudocode):
def preprocess(image_path):
img = read_raster(image_path)
img = apply_cloud_mask(img)
img = radiometric_correction(img)
img = co_register(img)
img = resample_to_model_grid(img)
img = normalize_per_band(img)
return img
Modeling
Image2Biomass — spatial model
Design decisions
Use a fully-convolutional backbone so the model accepts arbitrary tile sizes and outputs per-pixel biomass maps.
Replace standard RGB conv1 with Conv2d(in_channels=N_bands, ...).
Use skip connections (encoder–decoder) for high-resolution detail.
Train with per-pixel regression loss against co-registered clip samples that are spatially matched/aggregated.
Architecture (high level)
Encoder: modified ResNet34 (multi-band first conv), stride adjustments for spatial fidelity.
Bottleneck: dilated convolutions for larger receptive field.
Decoder: upsample + skip connections (U-Net style).
Output head: 1×1 conv producing mean prediction and second head producing log-variance (for heteroscedastic modeling).
Loss
- Heteroscedastic Negative Log Likelihood (Gaussian NLL):
[\mathcal{L} = \frac{(y - \mu)^2}{\sigma^2} + \log \sigma^2]
where model predicts (\mu) and (\log \sigma^2). This yields per-pixel uncertainty.
Regularization & training recipe
L2 weight decay (AdamW)
Learning rate schedule (CosineAnnealing or OneCycle)
Data augmentation: spectral noise, random flips, brightness/contrast, small geo transforms
Batch size tuned by GPU memory; use mixed precision (AMP)
Representative config
model:
backbone: resnet34
in_channels: 4 # e.g., RGB + NIR
decoder: unet_decoder
training:
optimizer: AdamW
lr: 1e-4
weight_decay: 1e-5
batch_size: 4
epochs: 60
loss:
heteroscedastic_nll: true
Temporal models — growth forecasting
Motivation: Spatial snapshot alone cannot capture growth dynamics. Temporal sequences (past 14–42 days) of per-tile aggregated biomass + weather + stocking pressure to forecast next-day and 30-day biomass with uncertainty.
Model families
GRU/LSTM baselines (fast, low memory)
Temporal Transformer variants (better for longer lookbacks)
Temporal ensemble combining above with spatial features (concatenate CNN embeddings)
Output
Mean & log-variance for each forecast horizon (enables uncertainty bands)
Optional MC dropout forecasts to capture epistemic uncertainty
Loss & training
Negative log-likelihood combined over forecast horizons
Multi-horizon training with teacher forcing for sequence models
Ensemble & fusion
Weighted blending of multiple models using validation-set based weights.
Ensemble outputs merged via weighted mean and variance combination rules.
Explainability
Use SHAP (DeepSHAP for NN) on per-tile aggregated features for driver attributions (NIR, RedEdge, canopy height, prior biomass).
Produce per-tile driver list used by frontends for popup explanation.
Carbon accumulation & soil recovery models
Approach
Map daily/net biomass growth to carbon flux using conversion factor (biomass → C) and belowground allocation proxies. Conservative IPCC Tier-2 compatible coefficients and site calibration.
Soil carbon modeled with simple state equations: SOC_{t+1} = SOC_t + α·ΔAGB − β·losses where α is conversion efficiency (fraction of above ground biomass becoming SOC via roots & residues) and β accounts for compaction and decomposition losses.
Calibration
Use SOC lab measurements to calibrate α per site/soil type.
Report propagated uncertainty by combining model predictive variance with calibration uncertainty.
Training pipeline & experiments
Dataset splits
Stratified by biome, pasture type, and season.
Training/validation/test with spatial holdout (leave some sites completely out for robust generalization testing).
Metrics
RMSE (t/ha) — primary regression accuracy metric.
MAE (t/ha) — robust central error metric.
R² — variance explained.
Coverage (95% CI) — fraction of ground truth lying within predicted 95% CI.
Calibration — reliability diagrams comparing predicted sigma to empirical errors.
Experimental results (representative)
RMSE ≈ 0.32 t/ha on withheld test set (aggregated tiles).
R ≈ 0.92 on calibration sites used for publications.
95% CI coverage ≈ 0.92 (target ≈ 0.95 — iterated on uncertainty calibration).
Hyperparameter tuning & ablations
Ablation: Remove RedEdge band → error increase ~ 8%
Ablation: Remove temporal features → 12% performance drop for 7-14 day forecasts
Ablation: Use homoscedastic MSE loss instead of heteroscedastic NLL → underestimation of errors in heterogeneous soils
Training infra
Multi-GPU training (NVIDIA A100 or V100 clusters)
Containerized training jobs using Docker + Kubernetes
Artifacts stored in model registry with versioning (model hash, training dataset hash, hyperparams)
Inference, tiling & APIs
Tiling
Per-tile inference performed on tiles sized for efficient GPU batching (e.g., 512×512 px at sensor resolution); overlapping windows with blending to avoid edge artifacts.
Postprocessing produces:
- Tile PNGs (for visualization)
- Cloud-optimized GeoTIFFs with embedded metadata
- Per-tile JSON including biomass_mean, biomass_std, drivers, sources (IDs), model_version
API design (representative)
POST /api/v1/ingest — upload imagery or sensor CSV (multipart)
GET /tiles/{pasture}/{z}/{x}/{y}.png — map tile
GET /api/v1/pastures/{id}/tiles/{z}/{x}/{y}.json — per-tile JSON
GET /api/v1/pastures/{id}/timeseries — historical & forecast series
Webhooks for on_prediction events
Serving stack
Tile serving via cloud optimized storage + CDN (pre-rendered tiles cached).
Prediction API: FastAPI + Uvicorn with TorchScripted models for fast inference.
Caching: Redis for hot tiles; TTLs tuned by expected update cadence.
Frontend + UX integration
Mapbox integration
Vegetation → color ramp mapping consistent with brand palette (soil warm → meadow → pasture moss).
Uncertainty overlay represented by alpha or hatch patterns at low confidence.
Popups display per-tile JSON: mean/std/drivers, last updated, model version, provenance links.
Temporal slider to switch snapshots/dates (calls timeseries API).
Decision UX
Counterfactual modal uses temporal forecast API to show % change and uncertainty when delaying grazing.
Optimizer UI allows constraints (water, labor, fence units), shows selected plan with carbon impact estimates and audit trace.
Accessibility & farmer-first language
All tooltips include human-readable disclaimers.
Color choices tested for color blindness; patterns used where necessary.
Offline export (PDF/CSV) for farmers without reliable connectivity.
MLOps, monitoring & audits
Continuous evaluation & drift detection
Feature distribution monitors (e.g., NDVI_mean drift) using population drift measures (KS statistic, mean shifts).
Output drift monitors track mean biomass predictions shift beyond thresholds.
Alerts trigger pipelines:
- trigger local sampling campaigns (low confidence + drift)
- schedule retrain job
- flag model card for review
Audit store
Each prediction event logs:
- event_id, timestamp
- pasture_id, tile indices
- input_ids, model_version, weights_hash
- predicted_mean, predicted_std
- user_id if human accepted/overrode decision
Immutable storage options: append-only DB (e.g., BigQuery with append), or object store with signed immutability.
CI/CD & governance
All code in monorepo with tests and linting.
Model changes gated by:
- unit tests for data transforms
- performance tests (REQ: validation RMSE must not degrade)
- manual review of model card & dataset changes
Deployment: Docker images, Kaniko build + ECR/GCR, Helm charts for K8s.
Challenges we ran into
- Heterogeneous sensors & alignment.
* Real field data came from satellites, drones (RTK), and low-cost ground devices. Achieving robust co-registration and consistent radiometry across sensors was time-consuming. Implemented per-sensor radiometric pipelines and co-registration with sub-meter accuracy for drone → satellite mapping.
- Ground truth sampling logistics.
* Collecting oven-dry clip samples across biomes (12k cores) required exacting field protocols and double labeling to avoid label noise. Created SOPs and inter-annotator QA (double-label checks) to maintain sample quality and metadata.
- Uncertainty calibration.
* Heteroscedastic modeling reduces overconfident predictions but requires careful training (NLL can be numerically unstable). Combined warm-start training and log-variance clipping; calibration curves and Platt-style scaling were applied to get target 95% coverage.
- Edge inference constraints.
* Many farms have limited connectivity. Designing an edge preprocessing step (denoise, compress) that reduces bandwidth by ~10× while preserving model performance took iterative optimization and a small quantized preprocessing model.
- Operational drift & nonstationarity.
* Seasonal changes and sensor upgrades cause drift. Built a drift detection pipeline that triggers sampling and re-calibration rather than blind retraining, to avoid degrading performance due to temporary domain shifts.
- Explainability without leakage.
* SHAP-style attribution is computationally heavy for per-pixel maps. Compute explainability at tile aggregates / feature groups and show drivers instead of full SHAP heatmaps to avoid confusion and computational cost.
- Delivering farmer-usable recommendations.
* Translating t/ha numbers into operational actions required co-design with farmers. Iterated on the optimizer UI and created conservative defaults for smallholders that prioritize income stability.
- Regulatory readiness for carbon claims.
* Carbon markets require defensible measurement. Designed our pipeline to provide per-tile provenance, calibration logs, and a model card with limitations to prevent overclaiming.
Accomplishments that we're proud of
- High accuracy with uncertainty.
* Achieved RMSE ≈ 0.3–0.35 t/ha across held-out test sites with calibrated 95% CIs, and R ≈ 0.9+, demonstrating both accuracy and reliable uncertainty.
- Productionized per-tile provenance.
* Every map tile includes model version, source image IDs, and sample links — enabling auditability and reproducibility.
- On-farm trials across diverse biomes.
* 120 trial sites across 3 continents and 30 farmer participants with matched controls provided real evidence of environmental and economic benefits.
- Integrating constraint-aware optimization.
* Developed a practical multi-pasture optimizer that considers water, fencing, and labor — moving predictions into operational decisions.
- Robust MLOps & drift management.
* Implemented monitoring, automated alerts, and retrain triggers based on targeted drift tests and sampling campaigns.
- Farmer-first UX and offline exports.
* Map + tooltip UI, counterfactual simulations, and PDF export workflows are usable on low-bandwidth farms.
- Open, defensible carbon pathway.
* The carbon conversion pipeline is explicitly IPCC Tier-2 compatible and includes calibration paths with soil samples.
- Community & equity design.
* Smallholder biasing in recommendations, anonymized benchmarking, and mentorship match modules built into the platform early.
What we learned
- Data quality beats quantity.
* Early iterations with more data but poor labels underperformed compared to smaller curated datasets with strict provenance. Investing in protocols paid dividends.
- Uncertainty is a first-class citizen.
* Displaying and using uncertainty to drive action (local sampling, conservative plans) produced better outcomes and more farmer trust than point estimates.
- Human in the loop is essential.
* Farmers expected advisory control. Automated plans without obvious human decision points were rejected. Tuned UI to emphasize "recommendation" and to make override simple.
- Explainability must be pragmatic.
* Full per-pixel SHAP maps are noisy and hard to interpret. Aggregated driver lists and simple feature bars are more usable.
- Operational constraints determine value.
* The optimizer that respects fencing/labor/water constraints was more valuable than marginal accuracy improvements. Real impact requires operational feasibility.
- Governance matters for scale.
* To participate in carbon programs and enterprise pilots, needed audit trails, model cards, and validation reports — not just a model.
- Design must bridge technical & social modes.
* To win adoption, UX must translate scientific outputs into concise operational advice and social impact narratives.
What's next for PastureAI
Have a clear technical roadmap, prioritized by impact and feasibility:
1) Model & data improvements
Temporal uncertainty bands expansion. Build richer probabilistic time series (quantile ensembles, deep state space models) to better capture long-horizon uncertainty.
More calibrated carbon models. Add root measurements and decomposition experiments to improve SOC mapping per pasture type.
Active learning. Deploy an active sampling scheduler to suggest the minimal number of ground samples to reduce uncertainty in high-impact tiles.
2) Optimization & planning
Full constrained optimizer (MILP). Move from greedy heuristics to mixed integer programming for better optimality with constraints (water, fence, labor, carbon goals).
Multi-objective optimization. Add carbon/sequestration and income as simultaneous objectives (Pareto frontier & UI for tradeoffs).
3) Deployment & scaling
Edge quantized inference (TFLite or ONNX quantized) for low-power on-device inference and next-day offline recommendations.
Auto-retrain pipelines with better data lineage and human gating for production retrains.
4) Product & community
Smallholder program. Tailored interface & subsidy-friendly workflows for small farms, offline & multilingual UX.
Community benchmarking & mentorship. Expand anonymized regional benchmarks and verified practice libraries.
Regulatory integrations. Templates and export formats for government reporting & carbon registries.
5) Research publications & open validation
- Publish model card, validation report, and a reproducible evaluation dataset (sanitized) for the community and external peer review.
Appendices
Below are concrete developer artifacts, sample code, CI steps, model card snippets and API examples to help engineers reproduce and audit work.
Appendix A — Folder structure
/backend
/app
/api
inference.py
tiles.py
timeseries.py
audit.py
/core
config.py
logging.py
/models
image2biomass.py
temporal.py
carbon.py
explainability.py
/pipelines
preprocess.py
inference.py
tiling.py
optimizer.py
/data
datasets.py
provenance.py
/training
train_image2biomass.py
train_temporal.py
losses.py
/tests
Dockerfile
requirements.txt
/frontend
/src
/components
BiomassMap.tsx
TimeSlider.tsx
OptimizerUI.tsx
/api
client.ts
package.json
/infra
/k8s
/helm
/ci
pipeline.yaml
/README.md
Appendix B — Representative training script (PyTorch)
training/train_image2biomass.py (abridged)
import torch
from torch.utils.data import DataLoader
from app.models.image2biomass import Image2Biomass
from app.data.datasets import BiomassDataset
from training.losses import heteroscedastic_nll
device = 'cuda' if torch.cuda.is_available() else 'cpu'
model = Image2Biomass(in_channels=4).to(device)
optimizer = torch.optim.AdamW(model.parameters(), lr=1e-4)
train_ds = BiomassDataset('/data/train')
train_loader = DataLoader(train_ds, batch_size=4, shuffle=True, num_workers=8)
for epoch in range(60):
model.train()
for batch in train_loader:
imgs = batch['image'].to(device)
targets = batch['biomass'].to(device)
mean, logvar = model(imgs)
loss = heteroscedastic_nll(mean, logvar, targets)
optimizer.zero_grad()
loss.backward()
optimizer.step()
print(f"Epoch {epoch} loss {loss.item()}")
torch.save(model.state_dict(), 'models/biomass_vX.pt')
heteroscedastic_nll implemented per standard Gaussian NLL.
Appendix C — Example Predict Tile JSON
GET /api/v1/pastures/PASTURE_07/tiles/14/4823/7618.json
{
"pasture_id": "PASTURE_07",
"tile": {"z":14,"x":4823,"y":7618},
"biomass_mean_t_ha": 2.53,
"biomass_std_t_ha": 0.18,
"drivers": [
{"feature":"NDVI_mean","impact":0.34},
{"feature":"CanopyHeight","impact":0.21}
],
"model_version": "image2bio-v1.2.1",
"sources": [
{"id":"IMG_20260312_S2_001", "sensor":"sentinel2", "bands":["B4","B8","B5"]},
{"id":"DRONE_20260310_07", "sensor":"drone", "rtk":true}
],
"timestamp": "2026-03-12T10:40:00Z"
}
Appendix D — CI / CD pipeline (sketch)
Unit tests on commits (pytest).
Data tests: schema validation, distribution checks (great_expectations).
Model smoke tests: run inference on small sample; assert no NaN and RMSE within threshold.
Build container image (Kaniko).
Deploy to staging (Helm) if all tests pass; manual promote to production after QA review.
Monitoring: rollout canary 5% traffic → metrics check → promote.
Sample ci/pipeline.yaml steps:
lint
test
data_quality
train_smoke
docker_build
push
helm_deploy_staging
integration_test
promote_to_prod (manual)
Appendix E — Model card (abridged)
Model name: Image2Biomass v1.2.1*Intended use:* per-tile biomass estimation for grazing management & carbon reporting.Limitations: snow cover, flooded paddocks, crops that mask grass, extremes of drought outside training distribution.Performance: RMSE 0.32 t/ha; R ≈ 0.92; 95% CI coverage 0.92 on held-out test.Training data: 128k images; 120 trial sites; 12k clip samples.Ethics: human-in-loop; no automated enforcement of actions; conservatism for smallholders.
Appendix F — Ethics, privacy & governance checklist
Consent & data ownership: explicit farm consent docs collected for sample/imagery.
Minimize PII: all exports anonymized; telemetry linked to farm IDs with explicit opt-in.
Smallholder safety: conservative default recommendations with equity biasing.
Auditability: append-only logs, model cards, calibration records.
Explainability: driver lists & simple guides for farmers on interpreting uncertainty.
Responsible claims: climate numbers presented with caveats and confidence intervals.
Closing notes
Built With
- image2biomass
- pytorch

Log in or sign up for Devpost to join the conversation.