Skip to content

tn_noise_learning.history#

Per-epoch training record.

History dataclass #

History(
    metrics: dict[str, list[float]] = dict(),
    params: list[list[ndarray]] = list(),
    best_epoch: int | None = None,
    num_sites: int | None = None,
)

Metric curves and optional parameter snapshots recorded by Trainer.

PARAMETER DESCRIPTION
metrics

one list per metric name, one value per epoch.

TYPE: dict[str, list[float]] DEFAULT: dict()

params

Kraus tensors after each epoch, filled only when TrainingConfig.snapshot_params is set.

TYPE: list[list[ndarray]] DEFAULT: list()

best_epoch

1-based epoch whose parameters were written back to the model.

TYPE: int | None DEFAULT: None

num_sites

number of qubits, used to draw the trace-preserving reference 2**num_sites.

TYPE: int | None DEFAULT: None

num_epochs property #

num_epochs: int

Number of recorded epochs.

append #

append(
    values: dict[str, Any],
    tensors: list[ndarray] | None = None,
) -> None

Record one epoch.

Source code in src/tn_noise_learning/history.py
54
55
56
57
58
59
def append(self, values: dict[str, Any], tensors: list[np.ndarray] | None = None) -> None:
    """Record one epoch."""
    for name, value in values.items():
        self.metrics.setdefault(name, []).append(float(value))
    if tensors is not None:
        self.params.append([np.asarray(t) for t in tensors])

load classmethod #

load(path: str | Path) -> History

Read a history written by save.

Source code in src/tn_noise_learning/history.py
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
@classmethod
def load(cls, path: str | Path) -> History:
    """Read a history written by [`save`][tn_noise_learning.history.History.save]."""
    group = zarr.open_group(str(path), mode="r")
    metrics = {
        str(name): read_array(group, f"metrics/{name}").tolist() for name in read_attr(group, "metric_names")
    }
    params = []
    if "params" in group:
        params_group = zarr.open_group(str(path), mode="r", path="params")
        for epoch in sorted(params_group.keys(), key=lambda k: int(k.split("_")[1])):
            epoch_group = zarr.open_group(str(path), mode="r", path=f"params/{epoch}")
            sites = sorted(epoch_group.keys(), key=lambda k: int(k.split("_")[1]))
            params.append([read_array(epoch_group, site) for site in sites])
    best = read_attr(group, "best_epoch")
    num_sites = read_attr(group, "num_sites")
    return cls(metrics, params, None if best is None else int(best), None if num_sites is None else int(num_sites))

plot #

plot(path: str | Path | None = None) -> Figure

Plot the metric curves with plot_history.

Source code in src/tn_noise_learning/history.py
89
90
91
92
93
def plot(self, path: str | Path | None = None) -> Figure:
    """Plot the metric curves with [`plot_history`][tn_noise_learning.plotting.plot_history]."""
    from .plotting import plot_history  # noqa: PLC0415  (avoids a circular import)

    return plot_history(self, path)

save #

save(path: str | Path) -> None

Write to a zarr store at path.

Source code in src/tn_noise_learning/history.py
61
62
63
64
65
66
67
68
69
def save(self, path: str | Path) -> None:
    """Write to a zarr store at ``path``."""
    group = zarr.open_group(str(path), mode="w")
    group.attrs.update(best_epoch=self.best_epoch, num_sites=self.num_sites, metric_names=list(self.metrics))
    for name, values in self.metrics.items():
        group.create_array(f"metrics/{name}", shape=(len(values),), dtype="float64")[:] = np.asarray(values)
    for epoch, tensors in enumerate(self.params):
        for site, t in enumerate(tensors):
            group.create_array(f"params/epoch_{epoch}/site_{site}", shape=t.shape, dtype=t.dtype)[:] = t