GitHub
deepbox/plot

ML Visualizations

Specialized plots for evaluating and understanding machine learning models. These convenience functions combine multiple plot primitives into ready-to-use diagnostic visualizations. All functions draw onto the current axes — call figure() first, then the ML plot function, then saveFig().
plotConfusionMatrix
plotConfusionMatrix(cm: Tensor, labels?: string[], options?: PlotOptions): void

Visualize a confusion matrix as an annotated heatmap. Rows represent true labels, columns represent predicted labels. Cell [i,j] shows how many samples with true label i were predicted as j. Diagonal cells are correct predictions. Off-diagonal cells reveal which classes are being confused. Color intensity is proportional to count. Pass class names via labels for readable axis labels.

Parameters:
cm: Tensor - Confusion matrix [nClasses, nClasses] from confusionMatrix()
labels: string[] - Class names for axis labels (optional)
plotRocCurve
plotRocCurve(fpr: Tensor, tpr: Tensor, auc?: number, options?: PlotOptions): void

Plot the Receiver Operating Characteristic curve — True Positive Rate vs False Positive Rate across all classification thresholds. Includes a dashed diagonal line representing a random classifier (AUC = 0.5). If auc is provided, it is annotated on the plot. A curve hugging the top-left corner indicates strong discrimination ability. Use rocCurve() from deepbox/metrics to compute fpr and tpr.

Parameters:
fpr: Tensor - False positive rates from rocCurve()
tpr: Tensor - True positive rates from rocCurve()
auc: number - Area Under Curve value to annotate (optional)
plotPrecisionRecallCurve
plotPrecisionRecallCurve(precision: Tensor, recall: Tensor, ap?: number, options?: PlotOptions): void

Plot the Precision-Recall curve — Precision vs Recall across all thresholds. More informative than ROC for imbalanced datasets where the positive class is rare. A curve hugging the top-right corner indicates both high precision and high recall. If ap (average precision) is provided, it is annotated on the plot.

Parameters:
precision: Tensor - Precision values from precisionRecallCurve()
recall: Tensor - Recall values from precisionRecallCurve()
ap: number - Average precision score to annotate (optional)
plotLearningCurve
plotLearningCurve(trainSizes: Tensor, trainScores: Tensor, valScores: Tensor, options?: PlotOptions): void

Plot training and validation scores as a function of training set size. The key diagnostic plot for bias-variance tradeoff. If both curves plateau at a low score → high bias (underfitting, need a more complex model). If training score is high but validation score is low → high variance (overfitting, need more data or regularization). Gap between curves = generalization gap.

Parameters:
trainSizes: Tensor - Training set sizes (x-axis)
trainScores: Tensor - Training scores at each size
valScores: Tensor - Validation scores at each size
plotValidationCurve
plotValidationCurve(paramRange: Tensor, trainScores: Tensor, valScores: Tensor, options?: PlotOptions): void

Plot training and validation scores as a function of a single hyperparameter. Shows how the model behaves across different values (e.g., regularization strength C, tree depth, number of neighbors k). The optimal value is where the validation score peaks. Left of peak = underfitting, right of peak = overfitting.

Parameters:
paramRange: Tensor - Hyperparameter values (x-axis)
trainScores: Tensor - Training scores at each param value
valScores: Tensor - Validation scores at each param value
plotDecisionBoundary
plotDecisionBoundary(X: Tensor, y: Tensor, model: { predict: (x: Tensor) => Tensor }, options?: PlotOptions): void

Visualize the decision boundary of a 2D classifier. Creates a dense mesh grid covering the feature space, predicts the class at every grid point, and draws filled contour regions colored by predicted class. Original data points are overlaid as scatter markers. Only works with 2-feature datasets (use PCA to reduce first if needed). The model must have a .predict() method.

Parameters:
X: Tensor - Feature data [nSamples, 2]
y: Tensor - True labels [nSamples]
model: { predict: (x: Tensor) => Tensor } - Any fitted classifier with a predict method
ml-plots.ts
import { figure, plotConfusionMatrix, plotRocCurve, plotDecisionBoundary, saveFig, gca } from "deepbox/plot";import { confusionMatrix, rocCurve, rocAucScore } from "deepbox/metrics";import { tensor, slice } from "deepbox/ndarray";import { KNeighborsClassifier } from "deepbox/ml";import { loadIris } from "deepbox/datasets";// ── Confusion matrix ──const yTrue = tensor([0, 1, 1, 0, 1, 0, 1, 1]);const yPred = tensor([0, 1, 0, 0, 1, 1, 1, 1]);const cm = confusionMatrix(yTrue, yPred);figure();plotConfusionMatrix(cm, ["Negative", "Positive"]);gca().setTitle("Confusion Matrix");await saveFig("confusion_matrix.svg");// ── ROC curve ──const yScore = tensor([0.1, 0.9, 0.4, 0.2, 0.8, 0.6, 0.95, 0.7]);const [fpr, tpr] = rocCurve(yTrue, yScore);const auc = rocAucScore(yTrue, yScore);figure();plotRocCurve(fpr, tpr, auc);gca().setTitle(`ROC Curve (AUC = ${auc.toFixed(3)})`);await saveFig("roc.svg");// ── Decision boundary (2D) ──const { data, target } = loadIris();const X2d = slice(data, null, { start: 0, end: 2 }); // First 2 featuresconst knn = new KNeighborsClassifier({ nNeighbors: 5 });knn.fit(X2d, target);figure({ width: 600, height: 500 });plotDecisionBoundary(X2d, target, knn);gca().setTitle("KNN Decision Boundary (Iris)");await saveFig("decision_boundary.svg");

Output Formats

  • SVG (default) — Lossless vector format, infinitely scalable, embeddable in HTML/Markdown, small file size
  • PNG — Raster bitmap via saveFig('file.png') or show({ format: 'png' }). Requires Node.js. Uses a built-in bitmap font for text rendering.
  • show() returns RenderedSVG { kind: 'svg', svg: string } synchronously, or Promise<RenderedPNG> { kind: 'png', width, height, bytes: Uint8Array }
  • saveFig() writes directly to disk — format is inferred from file extension (.svg or .png) or overridden via opts.format