A Machine Learning Framework for Automated Anomaly Detection in Precision Agriculture Geospatial Data
Zachary Komarnisky · Felippe H. S. Karp — Olds College of Agriculture & Technology Presented at the 17th International Conference on Precision Agriculture (ICPA) / 11th Brazilian Congress on Precision and Digital Agriculture (ConBAP), 2026.
This is the public repo to the RETA-ML project. It ships the trained models and the framework code — enough to inspect the models, run them on your own sensor data, and build on the work.
On-the-go agriculture sensors are fast and useful but produce errors or include data that is not desirable for further analysis, things like headland turns, overlaps, speed changes, localized and global errors. These quietly reduce the quality in precision-ag maps. Cleaning that data is manual, slow, and different for every sensor. We ask whether one model can learn cleaning once and apply it across sensors, and we measure exactly where that transfer holds and where it breaks.
(a) every expert-labeled point on a held-out field — Clean, Operational, Global
and Local classes. (b) the same field after running it through the shipped
random_forest.joblib: everything the model doesn't predict as Clean is filtered out
(shown faint grey), leaving the value surface behind.
Trained on two sensors, tested on the held-out third, macro-averaged over three folds:
| Class | RF P | RF R | RF F1 | XGB P | XGB R | XGB F1 |
|---|---|---|---|---|---|---|
| Clean | 0.96 | 0.94 | 0.95 | 0.96 | 0.85 | 0.90 |
| Operational | 0.46 | 0.63 | 0.52 | 0.30 | 0.65 | 0.40 |
| Local | 0.44 | 0.24 | 0.30 | 0.32 | 0.38 | 0.34 |
Random Forest macro-accuracy 0.90, XGBoost 0.83. Clean data and operational errors (the kinematic ones) transfer across sensors; local spatial anomalies do not — they look different on every sensor, which motivates a spatially-explicit (graph) model next. (Global-outlier class excluded from reporting: only 14 examples across all fields.)
reta_ml/ the framework — preprocessing, features, models, evaluation
models/ trained models + a model card
app.py Streamlit app to load a field, run a model, and inspect results
requirements.txt / environment.yml dependencies
| File | What it is |
|---|---|
random_forest.joblib |
Random Forest (400 trees, class-balanced), the poster's headline model. joblib.load(...). |
xgboost.json |
XGBoost (400 trees, depth 6). XGBClassifier().load_model(...). |
model_card.json |
Feature list, config, training data, and per-class counts. |
The RF/XGBoost models are trained on all expert-labeled points across the three sensors (49,665 points; the annotated dataset itself is not distributed in this repository) with the locked-in configuration: 13 sensor-agnostic features (field-relative motion + fixed-radius 15/30/45 m spatial z-scores), seed 42, no scaler.
# 1. install
pip install -r requirements.txt # or: conda env create -f environment.yml
# 2. use a trained model in a few lines
python - <<'PY'
import joblib, json
from reta_ml.load import load_table
from reta_ml.preprocess import preprocess_pipeline, recompute_value_stats
from reta_ml.lofo_benchmark import _feature_matrix
feats = json.load(open("models/feature_columns.json"))
rf = joblib.load("models/random_forest.joblib")
raw = load_table("your_field.gpkg", validate=False) # bring your own sensor data
raw["value"] = raw["<your_value_column>"]
proc = preprocess_pipeline(raw, main_variable="value", local_stats_mode="fixedbands")
proc = recompute_value_stats(proc, main_variable="value", local_stats_mode="fixedbands")
pred = rf.predict(_feature_matrix(proc, feats)) # 0=Clean 1=Operational 2=Global 3=Local
print(pred[:20])
PY
# 3. or explore interactively
streamlit run app.py- Features (13, sensor-agnostic): field-relative speed / distance / acceleration, turn & short-segment flags, whole-field z-score, fixed-radius spatial z-scores at 15 / 30 / 45 m, and ratio to the transect mean. Deliberately relative and fixed-radius so the same feature vector is comparable across a soil sensor and a combine.
- Models: Random Forest and XGBoost (class-balanced), with a HeteroGAT graph neural network as the spatially-explicit next step.
- Evaluation: Leave-One-Sensor-Out — train on two sensors, test on the third — the honest test of cross-sensor transfer.
If you use this work, please cite the ICPA/ConBAP 2026 paper (Komarnisky & Karp, 2026).
Released under the MIT License.
https://github.com/Dozer3530/RETA-ML/tree/main
Supported by an NSERC CCI Mobilize Grant (CCMOB-2024-00038), the Olds College Office of Research Services, and the Werklund School of Agriculture Technology.
