Maminda KCS learning loop: yield forecast and research Kurima Credit Score

Final-year project, Chinhoyi University of Technology: Machine learning-based credit risk assessment model for smallholder farmers using embedded IoT, satellite imagery and computer vision (Mashonaland West, Zimbabwe).

Live demo: Maminda KCS Research Lab

What it does

  1. Inputs for each field and season:
    • a crop-health score from a close-up leaf photo, produced by the Mashonaland crop classifier
    • Sentinel-2 NDVI
    • seven soil-probe readings: moisture, temperature, N, P, K, pH and EC
    • days after planting
  2. Yield head: one XGBoost regressor per crop (maize, potato, tomato) forecasts yield in t/ha.
  3. Repayment head: an XGBoost classifier combines the same inputs with projected cash coverage (forecast yield ร— area ร— price, minus costs and household needs, plus other cash), the due date and repayment history. It outputs the probability of repaying in full by the due date.
  4. Score: the probability is mapped to a 300โ€“850 research KCS. Probability 0.90 maps to 600, and each doubling of the repayment odds adds 50 points. This is a display convention, not a lender-approved policy.

The learning loop (how the model improves as farmers use it)

Photos, NDVI and soil readings are inputs. The model learns only from outcomes: the weighed harvest at season end, and whether each scored loan was repaid by its due date. learning_loop/ contains the code:

  • outcomes.py records harvests and repayments.
    • Each repayment is linked to the exact estimate that scored the loan.
    • Farmer-estimated harvests are stored but never used as labels.
    • Corrections are audited.
  • learning_loop.py retrains the models.
    • Synthetic data as a prior: the synthetic data counts as S real examples. With n real outcomes, the synthetic share of the training weight is S / (S + n).
    • Candidate challengers: recalibrate the current model, or retrain at several prior strengths (S = 0 means real data only).
    • Fair testing: every candidate is scored by grouped cross-validation over farmers, on outcomes the current release never saw.
    • Promotion: the best candidate replaces the champion only if it is better.
    • Versioning: every release is versioned and checksummed in releases/registry.json.

Current release

releases/v0-synthetic-prior is trained on:

  • simulated yields for all three crops
  • ten public US maize field-season means from the Genomes to Fields 2022 dataset (maize only)
  • simulated loan outcomes

It contains no real Mashonaland West outcomes yet. Its credit labels are entirely simulated.

Evidence that the loop works (results/)

Because no real outcomes exist yet, the loop was run against a deliberately different simulator ("field reality": lower smallholder yields, stronger nitrogen and drought limits, harder-hitting disease, side-selling repayment shocks). The test ran for 6 seasons with 140 field-seasons per season, across 3 runs, and was scored on 1,500 unseen farms per crop and 4,500 unseen loans.

Yield MAE (t/ha) Synthetic only Loop after 1 season Real-only after 1 season Loop after 6 seasons Real-only after 6 seasons
Maize 1.28 0.55 0.61 0.53 0.52
Potato 4.27 4.11 4.87 3.95 3.92
Tomato 7.04 6.43 7.46 5.99 6.12
Repayment model Synthetic only Loop after 1 season Real-only after 1 season Loop after 6 seasons Real-only after 6 seasons
Log loss 0.553 0.549 0.617 0.543 0.552
ROC AUC 0.752 0.760 0.672 0.761 0.748

Yield learning curve Repayment learning curve

These results show that the method corrects a mis-specified prior, and that the prior helps while real data is scarce. Both sides of the test are simulators. They say nothing about accuracy on real farms.

Use

from huggingface_hub import snapshot_download
import json, sys
root = snapshot_download('awesomeddiey/Maminda-KCS-Learning-Loop')
active = json.load(open(f'{root}/releases/registry.json'))['active']
sys.path.insert(0, f'{root}/releases/{active}')
from model_core import assess
result = assess({'crop': 'maize', 'features': {
    'sentinel_ndvi_score': 0.62, 'cv_health_score_0_100': 80, 'soil_moisture_vwc_pct': 24,
    'soil_temperature_c': 25, 'soil_n_mg_kg': 90, 'soil_p_mg_kg': 30, 'soil_k_mg_kg': 140,
    'soil_ph': 5.9, 'soil_ec_ms_cm': 0.6, 'days_after_planting': 70}},
    {'area_ha': 1.2, 'farmgate_price_per_tonne': 320, 'remaining_costs_excluding_loan_financed': 60,
     'other_cash_available_by_due': 40, 'household_cash_needed_by_due': 30, 'amount_due': 300,
     'days_until_due': 120, 'currency': 'USD', 'prior_loans_count': None,
     'prior_late_repayments': None, 'prior_defaults': None},
    enable_synthetic_credit=True, root=f'{root}/releases/{active}')
print(result['experimental_yield_t_ha'], result['research_credit_estimate']['kcs_score'])

Requirements: xgboost==3.4.1, numpy, pandas (plus scikit-learn to retrain).

Limits

  • Simulated relationships: the effects of NPK, pH, EC and the crop-health score on yield are learned from simulation. Potato and tomato yield heads are simulation-only.
  • Uncalibrated sensors: probe NPK, pH and EC methods are not calibrated against laboratory measurements. Equal units do not establish equivalence.
  • Synthetic credit labels: repayment probabilities in this release come from simulated loans. They are not established repayment probabilities for real farmers.
  • No lending use: no release is validated for lending. validated_kcs_score is always null.
  • Leaf-level CV score: the crop-health score describes one leaf photo. It does not measure the whole field.

Files

  • releases/: model releases and the registry. The Space serves the active release.
  • learning_loop/: outcome capture, retraining, and the season replay experiment.
  • prior/: the synthetic prior used for retraining (the G2F rows are not redistributed here).
  • results/: the season replay metrics, champion/challenger decisions and figures.
Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. ๐Ÿ™‹ Ask for provider support

Space using awesomeddiey/Maminda-KCS-Learning-Loop 1