Skip to content

Repository files navigation

Model 2: Behavioural AR and Collections Segmentation

A prototype that segments a CPG client's paying accounts by HOW they pay, using accounts receivable and collections behaviour, and attaches a differentiated collection strategy to each discovered segment. It is the second of two models in a Finance Transformation customer segmentation workstream: Model 1 (separate repository) segments the same customers by who they are as organisations; Model 2 layers payment behaviour on top of the same accounts. Everything here runs on synthetic data; no real client data appears anywhere.

Instead of one long list worked oldest-and-largest first, the collections team gets segments like "prompt reliable payers", "erratic slow payers", and "deduction-heavy payers", each with a playbook, so effort goes where it changes the outcome.

What it does

  • Discovers behavioural segments by unsupervised clustering (k-means primary, k-prototypes as a config fallback), with the number of segments chosen analytically by elbow plus silhouette plus collections-actionability rules, never hardcoded.
  • Profiles each segment in plain language and original units (days, ratios, currency), with machine-readable traits.
  • Maps a collection strategy playbook to each segment AFTER clustering: cadence, channel, tone, escalation, and commercial levers (early-payment discount, credit hold, stop-ship, dispute-resolution routing).
  • Assigns a new account to an existing segment day one, by nearest centroid against persisted artifacts, with a distance-based confidence proxy. No refitting at inference.
  • Validates itself: a mandatory synthetic-data recovery gate before the pipeline, stability across seeds and bootstrap resamples, a Pareto check, a risk-versus-value read per segment, a regression test on a fresh larger synthetic set, and three worked case studies.

The domain rules that shape the model

These come from the AR parameters domain document (reference/) and are enforced in code, not just documented:

  • Collection strategy and the segments themselves are model OUTPUTS, never features. Preprocessing guardrails raise if either leaks into the matrix.
  • Deductions are not delinquency. In CPG, trade spend runs 15 to 25 percent of gross sales, and much apparent past due is unresolved deductions. The deduction rate is a first-class feature and a high-deduction segment gets a dispute-resolution playbook, not dunning.
  • Both the mean AND the standard deviation of days-to-pay are engineered. A customer who always pays ten days late is predictable and low risk; the same average with wild swings is genuinely risky. Variance is the signal.
  • Aging bucket shares use due-date aging, not invoice-date aging.
  • Statement of account and invoice documents enter only as engineered flags.

Pipeline

Modules in build order; each is independently runnable and prints its result.

Module Role
config.py Every tunable: paths, seed, the hidden generator recipe, feature lists, K-selection knobs, thresholds.
data_generation.py Synthetic AR behaviour per account (customer x company code) on the Model 1 customer base, with a hidden source_profile QA tag and a size knob.
validate_dataset.py The mandatory gate: clustering recovery vs the hidden recipe (ARI/NMI in configured bands) before anything is built on the data.
preprocessing.py Fit-then-transform split: impute, log-transform, scale, one-hot; persisted artifacts plus a hash manifest so training and inference cannot drift.
training.py K sweep, combined elbow-plus-silhouette choice with actionability rules, final fit, atomic artifact persistence, manifest written last.
inference.py Nearest-centroid assignment for batches or a single account dict, from persisted artifacts only.
profiling.py Per-segment profiles in original units, traits, and a plain-language label.
strategy.py The output layer: ordered trait rules map each segment to a collection playbook.
output.py Run summary, segment distribution, per-account assignment CSV, single new-account response.
evaluation.py Silhouette, seed and bootstrap stability, Pareto check, risk-versus-value read, recovery QA.
main.py End-to-end orchestration with a held-out day-one account demo.
visuals.py Presentation figure set (segment value map, variance insight, K selection, Pareto, risk-vs-value, deductions, aging) to outputs/figures/.
regression_test.py Applies the persisted model to a fresh 1,000-account set with a different seed; PASS/FAIL.
case_studies.py Three worked accounts: a deductor, an erratic payer, a day-one new account.

Quickstart

Python 3.9 or later.

python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
python main.py            # full pipeline: generate, gate, train, outputs, evaluate
python regression_test.py # generalisation check on a fresh synthetic set
python case_studies.py    # three worked accounts
python visuals.py         # presentation charts to outputs/figures/

Or step by step, in build order:

python data_generation.py
python validate_dataset.py   # must PASS before anything else
python preprocessing.py
python training.py
python inference.py
python profiling.py
python strategy.py
python output.py
python evaluation.py

All results land in outputs/ (untracked; everything regenerates deterministically from the fixed seed).

Results snapshot (seed 42)

  • 236 accounts from 200 customers; validation gate PASS (ARI 0.537, NMI 0.639 against the hidden recipe, inside the configured bands).
  • K = 3 chosen analytically: elbow knee at K=3, silhouette band {3, 4}, tied K closest to the knee.
  • Segments and playbooks:
Segment Share Value share Playbook
Prompt reliable payers 27% 60% light touch, pre-due reminders only
Erratic slow payers, high variance 31% 3% intensive recovery, credit hold, stop-ship
Moderate payers, high deductions 42% 37% dispute resolution, not dunning
  • Stability: ARI 1.000 across 5 seeds, 0.92 mean across 20 bootstrap resamples. Pareto: top 20 percent of accounts hold 89 percent of value.
  • Regression test PASS: fresh 1,000-account set, mean centroid distance ratio 1.03 vs training (limit 1.5).

Reproducibility

  • One fixed, recorded seed (config.RANDOM_SEED) drives generation, training, and evaluation; runs reproduce byte-identically.
  • requirements.txt pins the exact library versions the artifacts were built with.
  • Training writes outputs/artifacts/manifest.json LAST, recording method, chosen K, silhouette, seed, library versions, and a SHA-256 of every artifact. Inference verifies the manifest before scoring and fails loudly on a missing, stale, or mixed artifact set.

Design documents

  • reference/01_model2_design.md: the implementation blueprint this code follows (objective, grain, feature set, synthetic-data spec, method, outputs, build order).
  • reference/AR_Collections_Parameters_3.docx: the domain source defining the eleven AR and collections parameters and their roles.
  • reference/model1_recap.md: the upstream Model 1 context.
  • CLAUDE.md: operating instructions and norms for working on this repository.

Open questions for the engagement mentor (design Section 11) are tracked in the blueprint: whether risk enters as a supplied score or stays a behavioural read, whether the Model 1 segment may join as a weak feature, and confirmation of the playbook contents.

Data disclaimer

All data is synthetic, generated from a hidden recipe for a GENERIC CPG client. The source_profile tag in the generated dataset is internal QA provenance: the model never sees it, and it is never a feature.

License

MIT. See LICENSE.

About

Behavioural accounts-receivable segmentation for a CPG collections team: k-means on synthetic payment-behaviour features, with per-segment collection strategy playbooks and nearest-centroid inference.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages