import maidr
from maidr.keras import plot_history
# What `history = model.fit(..., validation_split=0.2)` holds in
# `history.history`; pass `history` itself just the same.
history = {
"loss": [0.69, 0.52, 0.41, 0.35, 0.31, 0.29, 0.27, 0.26],
"accuracy": [0.55, 0.74, 0.82, 0.86, 0.88, 0.89, 0.90, 0.91],
"val_loss": [0.62, 0.47, 0.40, 0.37, 0.36, 0.36, 0.37, 0.39],
"val_accuracy": [0.66, 0.79, 0.83, 0.85, 0.86, 0.86, 0.85, 0.85],
}
maidr.show(plot_history(history))Keras Accessible Chart Examples
Keras Examples
maidr draws the training curves of a Keras model. Pass what model.fit returns to maidr.keras.plot_history(), and hand the figure to maidr.show(), maidr.render() or maidr.save_html(): each metric can then be read from the keyboard, as sound, as text and in braille. To follow a model while it trains, pass maidr.keras.MaidrCallback to model.fit. To walk the model’s layers themselves, pass the model to maidr.keras.plot_model(). For the curves TensorBoard logs, see the TensorBoard page.
Keras support is experimental. What it draws, and how, may change without a deprecation period: see Plot Type Stability.
import maidr does not load Keras: import maidr.keras when you use it. plot_history() also reads the plain history.history dictionary, and plot_model() a model’s config or JSON, so both work on what was saved to disk, with no Keras installed.
Training Curves from model.fit
One chart per metric, the loss first, each with a training and a validation line along the epochs, counted from 1 as Keras counts them. The left and right arrow keys move along the epochs, up and down move to the other line, and Page Up and Page Down move between the charts. A metric logged without a validation value, such as the learning rate, is one line named for itself.
The validation loss stops falling after the fifth epoch and starts to rise while the training loss keeps falling: the model has begun to overfit. metrics= keeps only the metrics you name, in that order, such as plot_history(history, metrics=["loss"]).
Confusion Matrix
maidr.keras.plot_confusion_matrix() draws what a classifier got right and wrong as a heatmap: the true class down the rows, the predicted class across the columns, so the diagonal is the correct answers. Move across a row to hear where one class’s samples went. It takes class indices or what model.predict returns, and normalize="true" reads each cell as a share of its true class.
import numpy as np
from maidr.keras import plot_confusion_matrix
y_true = np.array([0] * 20 + [1] * 20 + [2] * 20)
y_pred = np.array([0] * 17 + [1] * 3 + [1] * 15 + [2] * 5 + [2] * 18 + [0] * 2)
maidr.show(plot_confusion_matrix(y_true, y_pred, labels=["cat", "dog", "bird"]))A confusion matrix logged to TensorBoard as an image carries no numbers a screen reader can read; drawn from the predictions, it keeps them.
PR Curve
maidr.keras.plot_pr_curve() draws a binary classifier’s precision against its recall, one point per decision threshold, from the labels and what model.predict returns: a sigmoid output, or two-class softmax rows. The line is named with its average precision and the precision a classifier guessing at random would reach, the share of positives, drawn as a dashed line, so you hear at once how far above chance the model is. Pass several models’ predictions by name to compare them, a line each.
from maidr.keras import plot_pr_curve
rng = np.random.default_rng(0)
y_true = rng.random(300) < 0.3
good = np.clip(y_true * 0.6 + 0.2 + rng.normal(scale=0.15, size=300), 0, 1)
poor = np.clip(y_true * 0.6 + 0.2 + rng.normal(scale=0.45, size=300), 0, 1)
maidr.show(plot_pr_curve(y_true, {"good": good, "poor": poor}))Following a Model While It Trains
MaidrCallback writes an accessible page of the same charts every every epochs, and a last time when training ends. Open the page while the model trains and reload it to hear how far it has come; the page is replaced in one step, so a reload never meets a half-written file. With no path, the charts are shown in the notebook when training ends.
from maidr.keras import MaidrCallback
model.fit(
x, y,
validation_split=0.2,
epochs=50,
callbacks=[MaidrCallback("training.html", every=5)],
)The callback records the epoch of every value, so validation run only every few epochs (validation_freq=) is placed on the epochs it was run on, which plot_history() cannot tell from a History.
Model Graph [experimental]
maidr.keras.plot_model() draws a model’s layers as a directed graph, top to bottom from the inputs, with an arrow from each layer to the layers called on its output, as keras.utils.plot_model draws it. Left and right walk the layers in the order data flows through them, and the Inputs and Outputs rotor units follow the arrows, so a skip connection is heard as a layer with two inputs. Each layer is announced with its type and, where its config has them, its units and activation; a built model adds its output shape and number of parameters.
With expand_nested=True, a model used as a layer, here a Sequential residual block, is drawn as its own layers in a frame named for it: Down opens it and Up closes it again.
from maidr.keras import plot_model
# `model.to_json()` of a small functional model; pass the model itself just
# the same.
with open("keras-model.json") as f:
maidr.show(plot_model(f.read(), expand_nested=True))The graph is read from the model’s config alone, in Keras 3’s format or Keras 2’s (tf.keras), so a model saved with model.to_json() is drawn with no Keras installed. A directed graph is an experimental plot type, and reading one needs a maidr.js release that carries the directed_graph trace. For the graph Keras’s TensorBoard callback logs, see maidr.read_tensorboard_graph().