Model Evaluation Plots

ROC, precision-recall, confusion matrix, calibration, learning curves, feature importance and SHAP — built from a classifier's outputs in one call.

Introduction

CanvasXpress turns the raw outputs of a trained classifier — truth labels, scores, predictions, importances or SHAP values — into render-ready charts. The builders compute the statistics (AUC, average precision, ECE, confusion counts) in the engine itself and return a plain {data, config} spec, so the same figure renders from JavaScript, R (cx_roc, cx_pr, cx_confusion, cx_calibration, cx_learning_curve, cx_importance, cx_shap) and Python. Each static runs before any chart exists — the same standalone pattern as recommend().

ROC & Precision-Recall

CanvasXpress.rocConfig(yTrue, yScore) sweeps the thresholds, computes the trapezoidal AUC and draws the ROC curve with the chance diagonal. prConfig does the precision-recall curve with the average precision and the no-skill baseline. evalPlots returns ROC + PR + confusion in one call.

var b = CanvasXpress.evalPlots(yTrue, yScore, { positive: 1 });
new CanvasXpress("cxRoc", b.roc.data, b.roc.config);   // AUC in the title
new CanvasXpress("cxPr",  b.pr.data,  b.pr.config);    // AP in the title

Confusion Matrix

CanvasXpress.confusionConfig(yTrue, yPred) counts every (actual, predicted) pair over the sorted union of labels and emits a Heatmap with the count printed in each cell.

var cm = CanvasXpress.confusionConfig(yTrue, yPred, { title: "Confusion matrix" });
new CanvasXpress("cxCm", cm.data, cm.config);

Calibration Curve

CanvasXpress.calibrationConfig(yTrue, yProb) bins the predicted probabilities, plots observed frequency against mean predicted probability, draws the perfect-calibration diagonal and reports the expected calibration error (ECE).

var cal = CanvasXpress.calibrationConfig(yTrue, yProb, { bins: 10 });
new CanvasXpress("cxCal", cal.data, cal.config);

Learning Curve

CanvasXpress.learningCurveConfig(sizes, train, val) draws training and validation score as two lines over the training-set size.

var lc = CanvasXpress.learningCurveConfig(sizes, trainScores, valScores);
new CanvasXpress("cxLc", lc.data, lc.config);

Feature Importance & SHAP

CanvasXpress.importanceConfig(features, importances) draws a sorted horizontal bar chart (cap it with {top: N}). shapConfig(shap, values, featureNames) builds a SHAP summary beeswarm: a jittered dotplot grouped by feature, points positioned by SHAP value and coloured by the underlying feature value.

var imp = CanvasXpress.importanceConfig(features, importances, { top: 10 });
new CanvasXpress("cxImp", imp.data, imp.config);

var sh = CanvasXpress.shapConfig(shapMatrix, featureValues, featureNames);
new CanvasXpress("cxShap", sh.data, sh.config);

Where Teams Use These

Framed as who, in what moment, does what — grounded in the builders above and the engine capabilities they ride on.

1. The eval report at the end of a run

Who: an ML engineer finishing a model, in the notebook cell after fitting. What: one evalPlots call emits ROC + PR + confusion as a small interactive panel, with hover-to-read AUC and zoomable cells. The output is reproducible JSON that commits next to the model card and renders identically for anyone who opens it. The everyday on-ramp.

2. Model comparison — which checkpoint ships

Who: a team lead before a go/no-go. What: read ROC/PR curves and a sorted importance bar side by side, with legends that toggle series on click. Shown in a self-contained page you paste into a PR or Slack with no login — not locked inside a dashboard tool.

3. Interpretability deep-dive

Who: a data scientist explaining why the model decides, in a stakeholder or fairness review. What: a SHAP beeswarm with hover showing the actual feature value per point, and a signed top-N importance bar. Hover identity is the payoff — “which record is that outlier” is one mouseover, not a re-plot.

4. Embedding exploration

Who: anyone working with UMAP/t-SNE embeddings (NLP, vision, RAG). What: a Scatter2D/Scatter3D coloured by label or cluster, hover = the actual document/image id, lasso-select a region to inspect. Pairs naturally with these builders for debugging where retrieval or clusters land.

5. Threshold / operating-point tuning

Who: whoever owns the deployed classifier. What: the precision-recall curve or a score-distribution-by-class (Violin/Density) with an annotated threshold decoration line to pick the decision cutoff.

6. The shareable, reproducible model card

Who: regulated or collaborative teams (clinical, pharma, finance). What: a dashboard combining confusion matrix + calibration + importance + a cohort table, published once, git-diffable, re-rendering from JSON months later — where reproducibility plus R/Python/JS parity beats a folder of PNGs.

7. “Plot my model results” via LLM / MCP

Who: someone in an AI assistant or notebook. What: the MCP server generates the eval config from plain English — “evaluate this classifier and show me the plots” — so the assistant reaches for CanvasXpress directly.

Across Languages

Every builder has an instance form (cx.rocConfig(...)) and matching R and Python wrappers that take a data frame and column names, so scientists get the same charts in their own language.

ChartJavaScriptRPython
ROC curveCanvasXpress.rocConfigcx_roc(df, truth, score)cx_roc(df, "truth", "score")
Precision-recallCanvasXpress.prConfigcx_pr(df, truth, score)cx_pr(df, "truth", "score")
Confusion matrixCanvasXpress.confusionConfigcx_confusion(df, truth, pred)cx_confusion(df, "truth", "pred")
CalibrationCanvasXpress.calibrationConfigcx_calibration(df, truth, prob)cx_calibration(df, "truth", "prob")
Learning curveCanvasXpress.learningCurveConfigcx_learning_curve(df, size, train, val)cx_learning_curve(df, "size", "train", "val")
Feature importanceCanvasXpress.importanceConfigcx_importance(df, feature, importance)cx_importance(df, "feature", "importance")
SHAP summaryCanvasXpress.shapConfigcx_shap(shap, values)cx_shap(shap, values)

The Python wrappers (from canvasxpress.eval import cx_roc) take a pandas DataFrame and column names. canvasxpress-python

⇧