Command line: seamm-al#
seamm-al chooses which candidate frames to label next, by query by committee: a
committee of models (typically five, each trained on four fifths of the data) is run
on every candidate, and the frames where the members disagree most are labelled.
Environments#
score, train, check and engine need torch and xnn; use the MLFF
environment SEAMM itself uses, the one named in the xnn.ini and lammps.ini of
the installation, with xnn 0.13 or later. Training requires 0.13; scoring, checking and
the engine give the same results with older releases, but a committee trained with 0.13
can only be read by 0.13 or later. select needs neither torch nor xnn and runs in
any SEAMM environment. Without installing the package, run python -m
active_learning_step.cli with the repository on PYTHONPATH.
On a CPU, torch uses --threads threads when given, otherwise OMP_NUM_THREADS
(which SEAMM, PBS and most launchers set from the job’s allocation), otherwise as many
as the CPUs the process may run on, which a scheduler’s cpuset or taskset limits.
No scheduler is assumed, so the same commands work under Slurm, PBS, SEAMM’s own
JobServer or none.
Scoring#
seamm-al score needs torch and xnn, so run it in an MLFF environment (see
Environments):
seamm-al score -m m0/best.pt m1/best.pt m2/best.pt m3/best.pt m4/best.pt \
-o scores.csv --carry temperature pool.extxyz
The pools are extxyz files or SDF files written by SEAMM, either of them
optionally gzipped (trajectory.extxyz.gz). scores.csv has one row
per frame:
column |
meaning |
|---|---|
file, index, configuration |
where the frame is (index from 0 in its file) |
kind |
|
n_atoms, formula |
the frame’s size and Hill formula |
total_charge, n_molecules |
the charge given to the models; molecules of a cell |
rho_energy |
committee standard deviation of the energy / sqrt(N), eV |
rho_forces |
RMS over atoms of the per-atom force spread, eV/Å |
rho_forces_max_atom |
the largest per-atom force spread, eV/Å |
rho_pressure |
spread of the atomic pressure, atm (cells) |
rho_pressure_molecular |
spread of the molecular pressure, atm (cells) |
energy_mean, pressure_mean |
the committee average; also pressure_molecular_mean |
Molecules are found with SEAMM’s own rule, that of molsystem’s perceive_bonds:
atoms closer than 1.2 times the sum of their (Pyykkö) covalent radii are bonded, the
alkali and alkaline-earth metals never are, and a hydrogen has at most one bond. The
rule is applied to the coordinates, so it gives the same molecules as SEAMM without
needing SEAMM; for a SEAMM structure that has bonds of its own, those are used. The
total charge is read from total_charge in the extxyz info or from SEAMM’s net
charge in an SDF. By default the dispersion the checkpoints record
as subtracted is not added back (--dispersion false): it is the same in every
member and adds nothing to the spreads. --atoms frames.extxyz writes every frame
with its per-atom force spread.
The models are served in the dtype of their weights, usually float32. Float32 reductions on CPUs are not reproducible from run to run: the
same frame scored twice can differ by about 1e-5 relative in the pressure spreads (and
much less in the energy and force spreads), which cannot change a ranking.
--dtype float64 gives reproducible numbers at about twice the cost.
Training a committee#
seamm-al train trains the k members of a committee in an MLFF environment:
seamm-al train -c recipe.yaml -o committee labelled.extxyz [more.extxyz ...] \
-k 5 --cell-share 0.15 --steps 52950 [--member 2]
The recipe is an ordinary xnn YAML config (model, loss weights, optimiser, epochs and
the dispersion subtracted from the labels); seamm-al supplies the data, the folds,
the seeds and the batching. The labelled frames are cut into k folds with the data
seed (--data-seed, default 0), splitting clusters and cells separately so that
every fold holds out its share of each (--stratify kind, the default; within a
stratum the folds’ counts differ by at most one). --stratify-column liquid adds an
info key to the strata, and --stratify none is a plain k-fold.
Member l trains on the other folds, validates on
fold l and is initialised from seed 1000 + l (--init-seed). Batches never
mix clusters and cells: clusters use the recipe’s data.batch_size and cells
--cell-batch-size (default 4). --cell-share makes cell batches that share of
every epoch whatever the selection holds, and --steps trains every member for the
same number of optimiser steps, so committees trained on different selections differ
only in their data. avg_num_neighbors: auto in the recipe uses the mean neighbour
count of each member’s training set.
The committee’s directory holds manifest.json (the folds, the seeds, the data files
and their SHA-256, a hash of the ordered frames, the recipe, the batching and the code
versions), frames.csv (every frame’s fold) and one directory per member with
best.pt, last.pt, history.json and member.json. Members can be trained
in separate jobs (--member): each checks the manifest, a directory holding a
different plan is refused, and a member that has finished is skipped.
Training needs xnn 0.13 or later, which chooses best.pt, drives the plateau
learning rate and logs on dataset-averaged epoch metrics, and tells the batch samplers
the epoch every pass. score, check and engine work with older releases on
checkpoints those releases wrote, but a checkpoint trained with xnn 0.13 can only be
read by 0.13 or later (its pickled config), so a committee trained here is scored,
checked and run in an xnn 0.13 environment.
Each member’s epochs are recorded in its history.json through an xnn callback, and
the recipe’s trainer section (loggers, early stopping, checkpoints every n epochs)
applies as in xnn train.
Selecting#
seamm-al select needs neither torch nor xnn:
seamm-al select scores.csv --budget 75000 \
--cost cell:EC=2800 --cost cell:FEC=3900 --group-column liquid \
--cap temperature=6 --exclude labelled.txt
By default cells are ranked by the sum of their ranks in rho_pressure_molecular
and rho_forces, clusters by rho_forces (change with --rank), and frames are
taken in that order until the next would exceed the budget (--fill skips it and
keeps going). --threshold rho_forces=0.0106 limits the candidates to frames whose
spread reaches a threshold. The output is selection.csv, with the reason, the
running cost and the frame’s rank within its kind (rank_in_kind of n_in_kind)
for every frame chosen; the command also reports where the budget cut fell, and
--rejected rejected.csv lists every frame not chosen with its rank and why, and the chosen frames copied byte for byte from
the pool files into selected.extxyz and/or selected.sdf, ready for labelling.
Round 0: a random draw#
Before any committee exists, score --no-models lists a pool (identity and
--carry columns only, no torch or xnn needed) and select --random SEED draws
from it in a seeded random order, with the same costs, budget, caps, --exclude and
--max-frames, and the same verbatim output:
seamm-al score --no-models --carry source --carry salt -o pool.csv clusters.extxyz
seamm-al select pool.csv --random 1 --stratify-column source --stratify-column salt \
--cost cluster=4 --max-frames 50
--stratify-column spreads the draw evenly over the values of the columns: one frame
from each stratum in turn, the strata in a shuffled order. selection.csv records
the seed, each frame’s stratum and its place in the draw.
Checking a committee#
seamm-al check asks whether the committee’s spread predicts its real error, on
labelled frames:
seamm-al check committee labelled.extxyz --tag-key frame \
--calibrate rho_forces:0.14 --calibrate rho_pressure_molecular:1500:0.9
For each frame it gives the spreads and the out-of-fold errors: the error of the one
member that held the frame out, or the mean over the members for a frame none trained
on (a common validation or test set); frames every member trained on are left out. The
errors are the force RMSE, the energy per atom and, for cells, the atomic and molecular
pressures (the label’s molecular pressure from its stress and forces). The command
prints, and --summary writes, the Spearman correlation of each spread with its error
per kind, over all out-of-fold frames and the held-out ones only.
The committee directory is one made by seamm-al train (frames matched by
configuration name) or one with a fold_manifest.json per member listing tags under
held_out, validation and test; --tag-key names the info key of the tags.
Labels are read from REF_energy, REF_forces and REF_stress (a 9-vector, a
Voigt 6-vector or a matrix) unless --*-key says otherwise.
check also judges every member. For each it reports the final and best validation
loss (from the member’s history.json when there is one), its mean error on the
frames it held out and on the common validation and test frames, and the median
leave-one-out ratio of each spread: the spread with the member over the spread
without it, so a member that inflates the spreads stands out. A member more than
--flag-factor (default 1.5) times the median of the others on any of these is
flagged — as a note only, except for the final validation loss, which is the gate. A
member that trailed the others for a while (validation losses smoothed over 9 epochs,
at least 5 epochs above the factor) and then recovered is noted, not flagged. The
table is written to <out>_members.csv. --drop-member K
(repeatable) leaves member m<K> out, in check and in score (where K
counts the --models from 0); the members used and dropped are recorded in the
summary and in scores.csv.json.
--calibrate NAME:FAIL_LEVEL[:CAPTURE] calibrates a threshold as Smith et al.
(fig. 1): the largest spread that still catches CAPTURE (default 0.98) of the
frames whose worst-member error exceeds FAIL_LEVEL (eV/A for forces, atm for
pressures, eV per sqrt(atom) for energies), with what it separates. Fewer than 10
failures earn a warning: such a threshold is not to be trusted.
Committee molecular dynamics#
seamm-al engine serves the committee’s mean to an MDI driver such as LAMMPS
(fix mdi/qm) as one potential: the mean of the members’ short-range energies, with
the dispersion the checkpoints record added once on top, differentiated once for the
forces and stress. It takes the place of xnn mdi in an MDI pair:
mpirun --bind-to none \
-np 1 seamm-al engine --members m0/best.pt m1/best.pt m2/best.pt m3/best.pt \
m4/best.pt --device cuda:0 --eeq-reuse --spreads spreads.csv --every 10 \
--flag rho_forces=0.05 --flagged flagged.extxyz \
-mdi "-role ENGINE -name xnn -method MPI" \
: -np 1 lmp -mdi "-role DRIVER -name LAMMPS -method MPI" -in input.dat
With --spreads the engine also evaluates every member on its own every --every
force evaluations and appends the committee spreads (rho_energy, rho_forces,
rho_forces_max_atom and, for periodic systems, rho_pressure and
rho_pressure_molecular) to the CSV, with the committee-mean energy and max_dF,
the largest difference between the forces served and the mean of the members’ forces
(rounding only, without dispersion). --flag NAME=VALUE writes the frames whose
spread reaches a value to --flagged with their step, spreads and per-atom force
spread, ready for seamm-al score or labelling; --frames writes every frame
recorded. --drop-member K leaves a member out and --no-dispersion serves the
energy without the dispersion the checkpoints record as subtracted from their labels.
LAMMPS runs the engine with atom_style atomic, which reads only the Atoms,
Velocities, Masses and pair-coefficient sections of a data file. Check a data
file before submitting, and strip what it cannot read (a Molecules or Bonds
section, bond counts in the header) into a copy:
seamm-al data water512.data # exit status 1 on a problem
seamm-al data water512.data --strip water512_atomic.data
On a CPU (8 threads, 64 waters, five MACE members) the mean costs five times one model, and spreads every 10 steps add about 11 %.