Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LLPR improvements #307

Merged
merged 51 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from 45 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
a4ab072
Try to soft reset
frostedoyster Jun 3, 2024
5e8df5b
Eliminate old train file for SOAP-BPNN
frostedoyster Jun 4, 2024
ae7624f
Merge branch 'main' into llpr
frostedoyster Jun 6, 2024
4158747
Merge branch 'main' into llpr
frostedoyster Jun 12, 2024
ea614d1
Merge branch 'main' into llpr
frostedoyster Jun 13, 2024
40f4fa8
Merge branch 'main' into llpr
frostedoyster Jun 13, 2024
aeb2afa
Merge branch 'main' into llpr
frostedoyster Jun 15, 2024
a711829
Update branch
frostedoyster Jun 15, 2024
6c2e803
Escape quotation marks
frostedoyster Jun 15, 2024
b28e270
Merge branch 'main' into llpr
frostedoyster Jun 18, 2024
4578939
Make torchscriptable
frostedoyster Jun 18, 2024
b61635a
Update LLPR example
frostedoyster Jun 25, 2024
a1710c9
Update and document
frostedoyster Jun 26, 2024
cb3eff2
Finish LLPR example
frostedoyster Jun 27, 2024
75c65a7
Merge branch 'main' into llpr
frostedoyster Jun 27, 2024
09a5463
Linter
frostedoyster Jun 27, 2024
d983f9d
Merge branch 'llpr' of https://github.com/lab-cosmo/metatrain into llpr
frostedoyster Jun 27, 2024
767b676
Tests
frostedoyster Jun 27, 2024
5bf6663
Test more
frostedoyster Jun 27, 2024
c836bea
More robust sampler
frostedoyster Jun 27, 2024
20e7beb
Merge branch 'main' into llpr
frostedoyster Jun 27, 2024
190f690
Incorporate comments
frostedoyster Jun 27, 2024
3784433
Merge branch 'llpr' of https://github.com/lab-cosmo/metatrain into llpr
frostedoyster Jun 27, 2024
4cd934e
Set seed for tests
frostedoyster Jun 27, 2024
ab4dfcf
Remove stray copy-paste
frostedoyster Jun 27, 2024
2f732ef
Merge branch 'main' into llpr
frostedoyster Jul 4, 2024
a40e75b
Pseudo-Hessian calculation of the covariance
frostedoyster Jul 4, 2024
f37db86
Fix non-torchscriptable LLPR module
frostedoyster Jul 8, 2024
937bdb6
Remove unnecessary check
frostedoyster Jul 8, 2024
f4e76ef
Clean up after pseudo-Hessian calculation
frostedoyster Jul 11, 2024
e0fc822
Fix some more bugs
frostedoyster Jul 11, 2024
4ca0a52
Detach
frostedoyster Jul 15, 2024
7f00c6c
Merge branch 'llpr-torchscript' into llpr
frostedoyster Jul 15, 2024
e753af6
Add dtypes, lint
frostedoyster Jul 19, 2024
2709d75
Move example
frostedoyster Jul 19, 2024
fc39e45
Fix small issue
frostedoyster Jul 19, 2024
1919dc1
Merge branch 'main' into llpr
frostedoyster Jul 19, 2024
121524e
Revert some changes
frostedoyster Jul 19, 2024
b7893ce
Fix stuff
frostedoyster Jul 19, 2024
b405848
Update to new changes in main
frostedoyster Jul 19, 2024
d6f7c78
Add test for LLPR pseudo-Hessian
frostedoyster Jul 20, 2024
d407a84
Merge branch 'main' into llpr
frostedoyster Jul 22, 2024
d31870f
Merge branch 'main' into llpr
PicoCentauri Jul 24, 2024
7259ce1
Update examples/programmatic/llpr_forces/force_llpr.py
frostedoyster Aug 5, 2024
78cec83
Avoid memory issues when calibrating
frostedoyster Aug 5, 2024
a9a099d
Update examples/programmatic/llpr_forces/force_llpr.py
frostedoyster Aug 5, 2024
bc5137c
Merge branch 'main' into llpr
frostedoyster Oct 3, 2024
19a66fb
More documentation of `parameters` for pseudo-Hessian calculation
frostedoyster Oct 3, 2024
36d0ccd
Update dataset call in LLPR test
frostedoyster Oct 3, 2024
d05bd33
Merge branch 'main' into llpr
frostedoyster Oct 14, 2024
6c82f6e
Merge branch 'main' into llpr
frostedoyster Oct 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/programmatic/llpr_forces/ethanol_reduced_100.xyz
229 changes: 229 additions & 0 deletions examples/programmatic/llpr_forces/force_llpr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
import matplotlib.pyplot as plt
import numpy as np
import torch
from metatensor.torch.atomistic import (
MetatensorAtomisticModel,
ModelEvaluationOptions,
ModelMetadata,
ModelOutput,
load_atomistic_model,
)

from metatrain.utils.data import Dataset, collate_fn, read_systems, read_targets
from metatrain.utils.llpr import LLPRUncertaintyModel
from metatrain.utils.loss import TensorMapDictLoss
from metatrain.utils.neighbor_lists import get_system_with_neighbor_lists


model = load_atomistic_model("model.pt", extensions_directory="extensions/")
model = model.to("cuda")

train_systems = read_systems("train.xyz")
train_target_config = {
"energy": {
"quantity": "energy",
"read_from": "train.xyz",
"file_format": ".xyz",
"reader": "ase",
"key": "energy",
"unit": "kcal/mol",
"forces": {
"read_from": "train.xyz",
"file_format": ".xyz",
"reader": "ase",
"key": "forces",
},
"stress": {
"read_from": "train.xyz",
"file_format": ".xyz",
"reader": "ase",
"key": "stress",
},
"virial": False,
},
}
train_targets, _ = read_targets(train_target_config)

valid_systems = read_systems("valid.xyz")
valid_target_config = {
"energy": {
"quantity": "energy",
"read_from": "valid.xyz",
"file_format": ".xyz",
"reader": "ase",
"key": "energy",
"unit": "kcal/mol",
"forces": {
"read_from": "valid.xyz",
"file_format": ".xyz",
"reader": "ase",
"key": "forces",
},
"stress": {
"read_from": "valid.xyz",
"file_format": ".xyz",
"reader": "ase",
"key": "stress",
},
"virial": False,
},
}
valid_targets, _ = read_targets(valid_target_config)

test_systems = read_systems("test.xyz")
test_target_config = {
"energy": {
"quantity": "energy",
"read_from": "test.xyz",
"file_format": ".xyz",
"reader": "ase",
"key": "energy",
"unit": "kcal/mol",
"forces": {
"read_from": "test.xyz",
"file_format": ".xyz",
"reader": "ase",
"key": "forces",
},
"stress": {
"read_from": "test.xyz",
"file_format": ".xyz",
"reader": "ase",
"key": "stress",
},
"virial": False,
},
}
test_targets, target_info = read_targets(test_target_config)

requested_neighbor_lists = model.requested_neighbor_lists()
train_systems = [
get_system_with_neighbor_lists(system, requested_neighbor_lists)
for system in train_systems
]
train_dataset = Dataset({"system": train_systems, **train_targets})
valid_systems = [
get_system_with_neighbor_lists(system, requested_neighbor_lists)
for system in valid_systems
]
valid_dataset = Dataset({"system": valid_systems, **valid_targets})
test_systems = [
get_system_with_neighbor_lists(system, requested_neighbor_lists)
for system in test_systems
]
test_dataset = Dataset({"system": test_systems, **test_targets})

train_dataloader = torch.utils.data.DataLoader(
train_dataset,
batch_size=4,
shuffle=False,
collate_fn=collate_fn,
)
valid_dataloader = torch.utils.data.DataLoader(
valid_dataset,
batch_size=4,
shuffle=False,
collate_fn=collate_fn,
)
test_dataloader = torch.utils.data.DataLoader(
test_dataset,
batch_size=4,
shuffle=False,
collate_fn=collate_fn,
)

loss_weight_dict = {
"energy": 1.0,
"energy_positions_grad": 1.0,
"energy_grain_grad": 1.0,
}
loss_fn = TensorMapDictLoss(loss_weight_dict)

llpr_model = LLPRUncertaintyModel(model)

print("Last layer parameters:")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see later comment

parameters = []
for name, param in llpr_model.named_parameters():
if "last_layers" in name:
parameters.append(param)
print(name)

llpr_model.compute_covariance_as_pseudo_hessian(
train_dataloader, target_info, loss_fn, parameters
)
llpr_model.compute_inverse_covariance()
llpr_model.calibrate(valid_dataloader)

exported_model = MetatensorAtomisticModel(
llpr_model.eval(),
ModelMetadata(),
llpr_model.capabilities,
)

evaluation_options = ModelEvaluationOptions(
length_unit="angstrom",
outputs={
"mtt::aux::last_layer_features": ModelOutput(per_atom=False),
"mtt::aux::energy_uncertainty": ModelOutput(per_atom=False),
"energy": ModelOutput(per_atom=False),
},
selected_atoms=None,
)

force_errors = []
force_uncertainties = []

for batch in test_dataloader:
systems, targets = batch
systems = [system.to("cuda", torch.float64) for system in systems]
for system in systems:
system.positions.requires_grad = True
targets = {name: tmap.to("cuda", torch.float64) for name, tmap in targets.items()}

outputs = exported_model(systems, evaluation_options, check_consistency=True)
energy = outputs["energy"].block().values
energy_sum = torch.sum(energy)
energy_sum.backward(retain_graph=True)

predicted_forces = -torch.concatenate(
[system.positions.grad.flatten() for system in systems]
)
true_forces = targets["energy"].block().gradient("positions").values.flatten()
frostedoyster marked this conversation as resolved.
Show resolved Hide resolved

force_error = (predicted_forces - true_forces) ** 2
force_errors.append(force_error.detach().clone().cpu().numpy())

last_layer_features = outputs["mtt::aux::last_layer_features"].block().values
last_layer_features = torch.sum(last_layer_features, dim=0)
ll_feature_grads = []
for ll_feature in last_layer_features.reshape((-1,)):
ll_feature_grad = torch.autograd.grad(
ll_feature.reshape(()),
[system.positions for system in systems],
retain_graph=True,
)
ll_feature_grad = torch.concatenate(
[ll_feature_g.flatten() for ll_feature_g in ll_feature_grad]
)
ll_feature_grads.append(ll_feature_grad)
ll_feature_grads = torch.stack(ll_feature_grads, dim=1)

force_uncertainty = torch.einsum(
"if, fg, ig -> i",
ll_feature_grads,
exported_model._module.inv_covariance,
ll_feature_grads,
)
force_uncertainties.append(force_uncertainty.detach().clone().cpu().numpy())

force_errors = np.concatenate(force_errors)
force_uncertainties = np.concatenate(force_uncertainties)


plt.scatter(force_uncertainties, force_errors, s=1)
plt.xscale("log")
plt.yscale("log")
plt.xlabel("Predicted variance")
plt.ylabel("Squared error")

plt.savefig("figure.pdf")
35 changes: 35 additions & 0 deletions examples/programmatic/llpr_forces/options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
seed: 42

architecture:
name: experimental.soap_bpnn
training:
batch_size: 8
num_epochs: 100
log_interval: 1

training_set:
systems:
read_from: train.xyz
length_unit: angstrom
targets:
energy:
key: energy
unit: eV

validation_set:
systems:
read_from: valid.xyz
length_unit: angstrom
targets:
energy:
key: energy
unit: eV

test_set:
systems:
read_from: test.xyz
length_unit: angstrom
targets:
energy:
key: energy
unit: eV
4 changes: 4 additions & 0 deletions examples/programmatic/llpr_forces/readme.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
This is a small example of how to calculate force uncertainties with the LLPR.
In order to run it, it is sufficient to split the ethanol dataset with `python split.py`.
Then train a model with `mtt train options.yaml`, and finally run the example
with `python force_llpr.py`.
13 changes: 13 additions & 0 deletions examples/programmatic/llpr_forces/split.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import ase.io
import numpy as np


structures = ase.io.read("ethanol_reduced_100.xyz", ":")
np.random.shuffle(structures)
train = structures[:50]
valid = structures[50:60]
test = structures[60:]

ase.io.write("train.xyz", train)
ase.io.write("valid.xyz", valid)
ase.io.write("test.xyz", test)
Loading