I build machine learning systems, then try to break them. In 2026 I audited my own flood model, found that its headline metric was circular, retracted it, and rebuilt the whole system from real satellite data under strict leakage control. The rebuild is public, released as v2.0.0, and every number below can be re-derived from files in the repository.
I came to ML from physics and geophysics: B.Sc. Physics and Mathematics (Moi University), a geophysics attachment at KenGen Olkaria, then seven years in Kenyan insurance and investment distribution. Everything here was built on an Android phone with Termux and Google Colab, over mobile data.
What I do
- 🛰️ Build end-to-end systems, from raw satellite data to a live API and dashboard.
- 🧪 Validate honestly: event-based cross-validation, sealed test sets, and public retractions of my own results.
- 📦 Ship reproducibly: ONNX models verified by SHA-256, hash-locked Docker images, CI gates on data and claims.
- 🛡️ Add LLMs safely: output guards and deterministic fallbacks.
- 📐 Use physics as a prior: monotonic constraints and physical baselines.
Gain over elevation alone: 95% interval 0.019 to 0.061, pooled over 50 events. Sealed test: 27 held-out events, scored once. Data: 35 Sentinel-1 scene dates.
An open-source system that ranks flood susceptibility across five wards of the Nyando basin in Kenya.
| What | Result |
|---|---|
| Data | Copernicus GFM labels and Google Earth Engine features. No synthetic data. |
| Sealed test | 27 held-out flood events, scored once under rules fixed in advance |
| Ranking skill | Per-event mean AUC 0.971, against 0.939 for ranking by elevation alone |
| Where it does not hold | Not shown under a 1 km spatial buffer or an out-of-time split. The model card says so. |
- Model: gradient boosting with monotonic constraints, chosen against logistic, XGBoost and a PyTorch physics-constrained neural network. The network violated the constraints, so I did not ship it.
- Serving: custom ONNX exporter (parity 3.3e-16), FastAPI service that verifies the model's SHA-256 before loading, rate limiting, security headers, hash-locked Docker image.
- Engineering: GitHub Actions gates for data, manifests and README claims, CodeQL, MLflow tracking on DagsHub, and a deviation register that tests enforce.
- LLM layer: an advisory service (Gemini, Groq fallback, deterministic template) behind an output guard, plus an MCP server and a LangGraph pipeline. One model passed my guard 6 of 6 times yet named the correct drivers 0 of 6, so driver text now comes only from the template.
Scores are rankings from a case-control sample. They are not flood probabilities, forecasts or official warnings.
|
🏦 Loan Default Risk Credit-default model on German Credit data (GradientBoosting). Cost-optimised threshold 0.22 from a 5:1 false-negative cost matrix. Test ROC-AUC 0.791, Gini 0.582, recall 0.833. I corrected my own overstated README metrics to these verified values. Code | App |
💰 AfriSalaries Salary-band classifier across 8 African markets (FastAPI, XGBoost, TF-IDF, SHAP). 1,526 real records, 59.5% band accuracy. Two regression designs rejected on validation grounds. Code | App |
|
🥇 Kenya at Gold Open dataset and API on Kenya's 39 Olympic golds, with a four-dimension governance framework (FastAPI, SQLite). Code MIT, data CC-BY 4.0. Code | Dashboard |
🏢 ChurchOS Multi-tenant church management SaaS: JWT auth, 5-role access control, finance audit log, M-Pesa and Flutterwave integration. Phase 1 live. Code | App |
|
🧩 SegmentIQ K-Means customer segmentation, 5 segments, CSV batch upload (FastAPI, React). Code | App |
🚢 Titanic Survival Leak-free scikit-learn pipeline, hold-out ROC-AUC 0.8661 with bootstrap 95% intervals. Code | DOI |
- Building Sokoni, a WhatsApp AI sales agent for Kenyan SMEs. The backend is scaffolded and the agent logic is not built yet.
- Learning retrieval-augmented generation and model fine-tuning. Nothing shipped yet.
- Open to remote Machine Learning Engineer, MLOps and Applied Scientist roles.
- B.Sc. Physics and Mathematics, Moi University, 2012
- Machine Learning using Python, Google Developers Launchpad (Certificate of Excellence), 2025
- Python Basics, Programiz, 2025
I came into ML from geophysics, where a wrong model can mean a wrong drilling decision. That is why every model I ship comes with what its number means, and what it does not.
