Training at scale
Datasets on disk, made by many processes at once, and the training sets of the model built on them; see Training at scale on a SLURM cluster for the SLURM pipeline that uses them.
Shards
Datasets on disk, in shards made by any number of processes.
The training sets of the surrogates grow to millions of waveforms, more than a process makes in a walltime or
holds in memory. A ShardedStore keeps one in a directory:
config.json what the items are (a frozen dataclass with
n_binaries, shard_size and seed)
shards/00000.npz items 0 ... shard_size - 1, and so on
shards/00000.json when, where and how fast it was made
locks/00000.lock a shard being made: by whom, refreshed while it is
Each shard is a function of the configuration and of its index alone (its
items drawn from the seed sequence (seed, index)), so shards can be made
in any order, by any process on any machine sharing the filesystem: a
process claims one by creating its lock file exclusively (taking over a lock
not refreshed for a while, whose owner died), and writes it atomically. A
shard lost is made again, identically. The first N items are a uniform
sample for every N, so the training sets of a learning curve are nested.
Subclasses say what a shard holds (ShardedStore._make()) and may keep
derived shards next to the base ones, under other source names, which replace some
fields (ShardedStore.overlay_fields) of the base shards.
The processes making them run as batch jobs with a walltime: on SIGTERM
or SIGUSR1 (which SLURM sends before the walltime) they abandon the shard
they are making (stop_on_signals()) and exit with EXIT_REQUEUE,
for the job to be run again.
- class ShardedStore(directory: str)[source]
A dataset on disk, in shards; see the module docstring. Open one with
Store(directory), make one withcreate().Subclasses set
config_class(a frozen dataclass withn_binaries,shard_sizeandseed,to_jsonandfrom_json) and implement_make(); those with derived shards alsosource_directory()andoverlay_fields.- chunks(n: int | None = None, fields: Sequence[str] | None = None, source: str = 'base', select: Callable[[ndarray], ndarray] | None = None) Iterator[Dict[str, ndarray]][source]
The
fields(all, by default; andindex, the items’ positions in the dataset) of its firstnvalid items (all, by default), a shard at a time; of those whose indices passselect(a mask) if given. Theoverlay_fieldsare those ofsource.
- classmethod create(directory: str, config)[source]
Make the dataset
configindirectory, or open it if it is there: the same, or with fewer items and a full last shard (then it is grown).
- generate(n_jobs: int = -1, max_seconds: float | None = None, stale_seconds: float = 600.0, **kwargs) bool[source]
Make the shards not yet there (see
work_through()), each withn_jobsprocesses; whether all are there.
- load(n: int | None = None, fields: Sequence[str] | None = None, source: str = 'base', select=None) Dict[str, ndarray][source]
chunks(), concatenated.
- overlay_fields: Sequence[str] = ()
Fields of the base shards which those of the other sources replace.
- work_through(source: str, work: Callable[[int], None], max_seconds: float | None = None, stale_seconds: float = 600.0, poll_seconds: float = 30.0) bool[source]
Claim and
work(index)the shards ofsourcenot yet there, until there are none (waiting for those others are making), ormax_secondshave passed: whether all are there.
- class ShardLock(filename: str, stale_seconds: float)[source]
An exclusive claim on a shard, a lock file refreshed by a thread while held; one not refreshed for
stale_secondswas left by a process that died, and is taken over. Two processes taking over the same stale lock both make the shard, identically.
- write_atomically(filename: str, write: Callable) None[source]
write(file)to a temporary file next tofilename, synced, then renamed over it: a reader sees all of it or none.
- stop_on_signals() None[source]
Raise
StoppedonSIGTERMandSIGUSR1: what is being made is abandoned (its lock released), what is made is kept.
- EXIT_REQUEUE = 75
The exit status of a command stopped before it finished, to be run again.
The modes model
Training sets of the modes surrogate (Model) at scale.
Model.generate makes a training set
in one process and holds it in memory; ShardedModesDataset keeps
one on disk, in shards, made by any number of processes on any number of
machines (see mlgw_bns.sharding), and trains models on the first
N waveforms of it a shard at a time. A dataset is a directory:
config.json what the waveforms are (ModesDatasetConfig)
downsampling.npz the downsampling indices of every mode
shards/00000.npz waveforms 0 ... shard_size - 1, and so on
pca/<n>.npz the principal components of the first n waveforms
A shard holds, for each waveform, its parameters (the five of
ParameterSet.parameter_array) and the
amplitude (single precision) and phase residuals of every mode at its
downsampling indices, as Model._multimode_mode_residuals gives them from one EOB
call: about 36 kB a waveform for the seven modes of hom7_big, and a
second of TEOBResumS. The downsampling indices are trained first, once
(ShardedModesDataset.train_downsampling()), and must be the same for
a validation set and the training set it validates
(ShardedModesDataset.copy_downsampling()).
Training a model (ShardedModesDataset.train()) fits the principal
components on the first pca_size waveforms (once,
ShardedModesDataset.principal_components()), reduces the residuals of
the first N shard by shard, and fits a regressor of each mode on them
(ModeModel.fit_nn), saving
each as it is done: a training interrupted resumes from the modes it had
finished, and from the checkpoint of the one it was training if that is a
JaxMLPNetwork.
- class ModesDatasetConfig(n_binaries: int, shard_size: int = 1024, seed: int = 1, modes: tuple = ((2, 2), (2, 1), (3, 1), (3, 2), (3, 3), (4, 3), (4, 4)), initial_frequency_hz: float = 5.0, srate_hz: float = 4096.0, reference_amplitude: bool = True, parameter_ranges: ParameterRanges = <factory>)[source]
What the waveforms of a
ShardedModesDatasetare, and theModelthey train.- Parameters:
n_binaries (int) – How many; a dataset whose last shard is full can be grown.
shard_size (int, optional) – Waveforms a shard.
Default:1024seed (int, optional) – The parameters of shard
kare drawn from the seed sequence(seed, k): datasets with different seeds are independent.Default:1modes (optional) – Of the
Model; the defaults are those ofhom7_big(make_hom7_dataset.py).Default:((2, 2), (2, 1), (3, 1), (3, 2), (3, 3), (4, 3), (4, 4))initial_frequency_hz (optional) – Of the
Model; the defaults are those ofhom7_big(make_hom7_dataset.py).Default:5.0srate_hz (optional) – Of the
Model; the defaults are those ofhom7_big(make_hom7_dataset.py).Default:4096.0reference_amplitude (optional) – Of the
Model; the defaults are those ofhom7_big(make_hom7_dataset.py).Default:Trueparameter_ranges (optional) – Of the
Model; the defaults are those ofhom7_big(make_hom7_dataset.py).Default:<factory>- model(filename: str | None = None, **kwargs) Model[source]
A
Modelof these settings (not trained);kwargsof its modes’ModeModel, such asnn_kind.
- same_waveforms(other: ModesDatasetConfig) bool[source]
Whether
otherhas waveforms of the same model (if not the same ones): what a validation set and its training set share.
- class ShardedModesDataset(directory: str)[source]
A training (or validation) set of a
Modelon disk; see the module docstring. Open one withShardedModesDataset(directory), make one withcreate().- config_class
alias of
ModesDatasetConfig
- copy_downsampling(other: ShardedModesDataset) None[source]
Use the downsampling indices of
other(of waveforms of the same model): those of the training set, for a validation set.
- generate(n_jobs: int = -1, max_seconds: float | None = None, stale_seconds: float = 600.0) bool[source]
Make the shards not yet there (see
work_through()), each withn_jobsprocesses; whether all are there. The downsampling indices must be there.
- load_residuals(n: int | None = None) tuple[source]
The parameters
(n, 5)of the firstnvalid waveforms andmode -> Residualsof every mode.
- model(filename: str | None = None, **kwargs) Model[source]
A
Modelof this dataset (seeModesDatasetConfig.model()), with its downsampling indices if they are there.
- parameters(index: int) list[source]
The
WaveformParametersof shardindex.
- principal_components(n: int, n_components: int = 30) dict[source]
mode -> PrincipalComponentDataof the firstnvalid waveforms, fitted once (asModeModel.generatedoes) and kept inpca/<n>.npz.
- reduced(model: Model, mode: Mode, n: int) tuple[source]
The parameters
(n, 5)of the firstnvalid waveforms, the principal components of their residuals ofmodein themodel’s basis, and their power weights (Nonefor a mode not weighted; seeModeModel._training_power_weights), reduced a shard at a time.
- residuals(mode: Mode, n: int | None = None, select: Callable | None = None) Iterator[tuple][source]
(parameters, Residuals)ofmodefor the firstnvalid waveforms (all, by default), a shard at a time.
- train(n: int, filename: str, nn_kind: type | ~typing.Mapping[~mlgw_bns.pn_modes.Mode, type] = <class 'mlgw_bns.neural_network.KernelRidgeNetwork'>, hyperparameters: ~typing.Callable[[~mlgw_bns.pn_modes.Mode, int], ~mlgw_bns.neural_network.Hyperparameters] | None = None, pca_size: int | None = None, modes: ~typing.Sequence | None = None, checkpoint: str | None = None, sizes: ~typing.Mapping[~mlgw_bns.pn_modes.Mode, int] | None = None) Model | None[source]
Train a
Modelon the firstnvalid waveforms and save it asfilename(without its training data, like the packaged one).- Parameters:
n (int) – Training waveforms.
filename (str) – Base filename of the model (its files are
{filename}_l2_m2_nn.pkland so on).nn_kind (type or mapping, optional) – Of the regressors, or of the regressor of each mode (kernel ridge for those not in it).
Default:<class 'mlgw_bns.neural_network.KernelRidgeNetwork'>hyperparameters (callable, optional) –
(mode, n) -> Hyperparameters; by default those ofModeModel.default_hyperparameters.Default:Nonepca_size (int, optional) – The principal components are those of the first
pca_sizewaveforms (principal_components());nby default.Default:Nonemodes (sequence, optional) – Train only the regressors of these modes (each saved as it is done, skipped if it is there): for trainings split in jobs. The model is saved once those of all the modes are there.
Default:Nonecheckpoint (str, optional) – Base filename of the checkpoints of the training of each mode (
{checkpoint}_l2_m2.joblib), for the regressors that keep one (JaxMLPNetwork).Default:Nonesizes (mapping, optional) – Train the regressors of these modes on the first this many waveforms instead of
n.Default:None- Returns:
The model, once all of it is trained.
- Return type:
Model, optional
- train_downsampling(size: int = 64, n_jobs: int = 1) None[source]
Train the downsampling indices of every mode on
sizewaveforms each (Model.train_downsampling), unless they are there.
- load_model(dataset: ShardedModesDataset, filename: str) Model[source]
The model saved as
filenamebyShardedModesDataset.train().