← All Posts
From Scratch · C++ · Machine Learning · Explainability

Explainability from Scratch in C++

This series implements the core ideas from Machine Learning · Explainability in plain C++. The focus is not on matching every feature of production libraries. The focus is on the mechanics: how to perturb data, query a black-box predictor, fit a weighted surrogate, and turn coefficients into explanations.

Implementation Roadmap

Permutation Importance

The baseline sanity check: shuffle one column, re-score the model, and measure how much performance drops.

LIME from Scratch

Generate local perturbations, weight them by distance, and solve weighted least squares for a local surrogate.

Kernel SHAP from Scratch

Sample coalition masks, query the model on masked rows, and fit weighted coalition regression to estimate attributions.

Tree SHAP from Scratch

Use tree structure for exact row-level explanations instead of black-box mask sampling.

Shared Predictor Interface

Every post assumes a callable predictor:

using Vector = vector<double>;
using Matrix = vector<vector<double>>;
using Predictor = function<double(const Vector&)>;
Model-agnostic means callable. The explainer does not need tree nodes, neural-network layers, or coefficients from the original model. It only needs feature rows and a function that returns predictions.