uma-finetune-wrapper 0.1.0.dev2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- uma_finetune/__init__.py +6 -0
- uma_finetune/dataset.py +62 -0
- uma_finetune/resources/FAIRChem-LICENSE.md +23 -0
- uma_finetune/resources/NOTICE.md +13 -0
- uma_finetune/resources/configs/uma/finetune/data/uma_conserving_data_task_energy.yaml +89 -0
- uma_finetune/resources/configs/uma/finetune/data/uma_conserving_data_task_energy_force.yaml +100 -0
- uma_finetune/resources/configs/uma/finetune/data/uma_conserving_data_task_energy_force_stress.yaml +107 -0
- uma_finetune/resources/configs/uma/finetune/uma_sm_finetune_template.yaml +118 -0
- uma_finetune/training.py +153 -0
- uma_finetune_wrapper-0.1.0.dev2.dist-info/METADATA +249 -0
- uma_finetune_wrapper-0.1.0.dev2.dist-info/RECORD +16 -0
- uma_finetune_wrapper-0.1.0.dev2.dist-info/WHEEL +5 -0
- uma_finetune_wrapper-0.1.0.dev2.dist-info/licenses/LICENSE +21 -0
- uma_finetune_wrapper-0.1.0.dev2.dist-info/licenses/src/uma_finetune/resources/FAIRChem-LICENSE.md +23 -0
- uma_finetune_wrapper-0.1.0.dev2.dist-info/licenses/src/uma_finetune/resources/NOTICE.md +13 -0
- uma_finetune_wrapper-0.1.0.dev2.dist-info/top_level.txt +1 -0
uma_finetune/__init__.py
ADDED
uma_finetune/dataset.py
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'''Prepare datasets with FAIRChem's existing UMA conversion script.'''
|
|
2
|
+
|
|
3
|
+
import subprocess
|
|
4
|
+
import sys
|
|
5
|
+
from importlib.resources import as_file, files
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def create_dataset(
|
|
10
|
+
train_path,
|
|
11
|
+
val_path,
|
|
12
|
+
output_dir,
|
|
13
|
+
*,
|
|
14
|
+
task='oc25',
|
|
15
|
+
targets='ef',
|
|
16
|
+
base_model=None,
|
|
17
|
+
num_workers=1,
|
|
18
|
+
):
|
|
19
|
+
'''Convert directories of labelled ASE-readable files and return their output path.
|
|
20
|
+
|
|
21
|
+
targets: 'e' (energies), 'ef' (energies and forces), or 'efs' (also stress).
|
|
22
|
+
base_model=None uses FAIRChem's default for the generated configuration.
|
|
23
|
+
output_dir must not already exist. Templates are included in the package.
|
|
24
|
+
Conversion failures raise subprocess.CalledProcessError; logs remain visible.
|
|
25
|
+
'''
|
|
26
|
+
train_path = Path(train_path).expanduser().resolve()
|
|
27
|
+
val_path = Path(val_path).expanduser().resolve()
|
|
28
|
+
output_dir = Path(output_dir).expanduser().resolve()
|
|
29
|
+
|
|
30
|
+
for path in (train_path, val_path):
|
|
31
|
+
if not path.is_dir():
|
|
32
|
+
raise NotADirectoryError(f'Input directory does not exist: {path}')
|
|
33
|
+
|
|
34
|
+
if output_dir.exists():
|
|
35
|
+
raise FileExistsError(f'Output directory already exists: {output_dir}')
|
|
36
|
+
if task not in ('omol', 'omat', 'odac', 'oc20', 'oc25', 'omc'):
|
|
37
|
+
raise ValueError('task must be omol, omat, odac, oc20, oc25, or omc.')
|
|
38
|
+
if targets not in ('e', 'ef', 'efs'):
|
|
39
|
+
raise ValueError('targets must be e, ef, or efs.')
|
|
40
|
+
if type(num_workers) is not int or num_workers < 1:
|
|
41
|
+
raise ValueError('num_workers must be a positive integer.')
|
|
42
|
+
|
|
43
|
+
command = [
|
|
44
|
+
sys.executable,
|
|
45
|
+
'-m', 'fairchem.core.scripts.create_uma_finetune_dataset',
|
|
46
|
+
'--train-dir', str(train_path),
|
|
47
|
+
'--val-dir', str(val_path),
|
|
48
|
+
'--output-dir', str(output_dir),
|
|
49
|
+
'--uma-task', task,
|
|
50
|
+
'--regression-tasks', targets,
|
|
51
|
+
'--num-workers', str(num_workers),
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
if base_model is not None:
|
|
55
|
+
command.extend(['--base-model', base_model])
|
|
56
|
+
|
|
57
|
+
# FAIRChem reads configs/uma/finetune relative to its working directory.
|
|
58
|
+
# Input and output paths are absolute, so only template lookup changes.
|
|
59
|
+
resources = files('uma_finetune').joinpath('resources')
|
|
60
|
+
with as_file(resources) as resource_root:
|
|
61
|
+
subprocess.run(command, check=True, cwd=resource_root)
|
|
62
|
+
return output_dir
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# License
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Copyright (c) Meta, Inc. and its affiliates.
|
|
6
|
+
|
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
in the Software without restriction, including without limitation the rights
|
|
10
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
furnished to do so, subject to the following conditions:
|
|
13
|
+
|
|
14
|
+
The above copyright notice and this permission notice shall be included in all
|
|
15
|
+
copies or substantial portions of the Software.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
23
|
+
SOFTWARE.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# FAIRChem templates
|
|
2
|
+
|
|
3
|
+
The four YAML files under configs/uma/finetune are unmodified copies from
|
|
4
|
+
FAIRChem 2.22.0, supplied from the working source checkout for this project.
|
|
5
|
+
Upstream project: https://github.com/facebookresearch/fairchem
|
|
6
|
+
|
|
7
|
+
Copyright (c) Meta, Inc. and its affiliates.
|
|
8
|
+
These templates are distributed under the MIT license reproduced in
|
|
9
|
+
FAIRChem-LICENSE.md. This notice does not assign a license to the wrapper itself.
|
|
10
|
+
|
|
11
|
+
The conversion script is supplied by the installed fairchem-core dependency;
|
|
12
|
+
it is not copied into this package. Keep these resources matched to the pinned
|
|
13
|
+
FAIRChem version when upgrading.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
dataset_name: ??
|
|
2
|
+
elem_refs: ??
|
|
3
|
+
normalizer_rmsd: ??
|
|
4
|
+
|
|
5
|
+
train_dataset:
|
|
6
|
+
splits:
|
|
7
|
+
train:
|
|
8
|
+
src: ??
|
|
9
|
+
format: ase_db
|
|
10
|
+
transforms:
|
|
11
|
+
common_transform:
|
|
12
|
+
dataset_name: ${data.dataset_name}
|
|
13
|
+
stress_reshape_transform:
|
|
14
|
+
dataset_name: ${data.dataset_name}
|
|
15
|
+
|
|
16
|
+
val_dataset:
|
|
17
|
+
splits:
|
|
18
|
+
val:
|
|
19
|
+
src: ??
|
|
20
|
+
format: ase_db
|
|
21
|
+
transforms:
|
|
22
|
+
common_transform:
|
|
23
|
+
dataset_name: ${data.dataset_name}
|
|
24
|
+
stress_reshape_transform:
|
|
25
|
+
dataset_name: ${data.dataset_name}
|
|
26
|
+
|
|
27
|
+
regress_stress: True
|
|
28
|
+
pass_through_head_outputs: True
|
|
29
|
+
|
|
30
|
+
heads:
|
|
31
|
+
efs:
|
|
32
|
+
module: fairchem.core.models.uma.escn_md.MLP_EFS_Head
|
|
33
|
+
|
|
34
|
+
tasks_list:
|
|
35
|
+
- _target_: fairchem.core.units.mlip_unit.mlip_unit.Task
|
|
36
|
+
name: energy
|
|
37
|
+
level: system
|
|
38
|
+
property: energy
|
|
39
|
+
loss_fn:
|
|
40
|
+
_target_: fairchem.core.modules.loss.DDPMTLoss
|
|
41
|
+
loss_fn:
|
|
42
|
+
_target_: fairchem.core.modules.loss.PerAtomMAELoss
|
|
43
|
+
coefficient: 20
|
|
44
|
+
out_spec:
|
|
45
|
+
dim: [1]
|
|
46
|
+
dtype: float32
|
|
47
|
+
normalizer:
|
|
48
|
+
_target_: fairchem.core.modules.normalization.normalizer.Normalizer
|
|
49
|
+
mean: 0.0
|
|
50
|
+
rmsd: ${data.normalizer_rmsd}
|
|
51
|
+
element_references:
|
|
52
|
+
_target_: fairchem.core.modules.normalization.element_references.ElementReferences
|
|
53
|
+
element_references:
|
|
54
|
+
_target_: torch.DoubleTensor
|
|
55
|
+
_args_:
|
|
56
|
+
- ${data.elem_refs}
|
|
57
|
+
datasets:
|
|
58
|
+
- ${data.dataset_name}
|
|
59
|
+
metrics:
|
|
60
|
+
- mae
|
|
61
|
+
- per_atom_mae
|
|
62
|
+
- _target_: fairchem.core.units.mlip_unit.mlip_unit.Task
|
|
63
|
+
name: forces
|
|
64
|
+
level: atom
|
|
65
|
+
property: forces
|
|
66
|
+
out_spec:
|
|
67
|
+
dim: [3]
|
|
68
|
+
dtype: float32
|
|
69
|
+
normalizer:
|
|
70
|
+
_target_: fairchem.core.modules.normalization.normalizer.Normalizer
|
|
71
|
+
mean: 0.0
|
|
72
|
+
rmsd: ${data.normalizer_rmsd}
|
|
73
|
+
datasets:
|
|
74
|
+
- ${data.dataset_name}
|
|
75
|
+
inference_only: True
|
|
76
|
+
- _target_: fairchem.core.units.mlip_unit.mlip_unit.Task
|
|
77
|
+
name: stress
|
|
78
|
+
level: system
|
|
79
|
+
property: stress
|
|
80
|
+
out_spec:
|
|
81
|
+
dim: [1, 9]
|
|
82
|
+
dtype: float32
|
|
83
|
+
normalizer:
|
|
84
|
+
_target_: fairchem.core.modules.normalization.normalizer.Normalizer
|
|
85
|
+
mean: 0.0
|
|
86
|
+
rmsd: ${data.normalizer_rmsd}
|
|
87
|
+
datasets:
|
|
88
|
+
- ${data.dataset_name}
|
|
89
|
+
inference_only: True
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
dataset_name: ??
|
|
2
|
+
elem_refs: ??
|
|
3
|
+
normalizer_rmsd: ??
|
|
4
|
+
|
|
5
|
+
train_dataset:
|
|
6
|
+
splits:
|
|
7
|
+
train:
|
|
8
|
+
src: ??
|
|
9
|
+
format: ase_db
|
|
10
|
+
transforms:
|
|
11
|
+
common_transform:
|
|
12
|
+
dataset_name: ${data.dataset_name}
|
|
13
|
+
stress_reshape_transform:
|
|
14
|
+
dataset_name: ${data.dataset_name}
|
|
15
|
+
|
|
16
|
+
val_dataset:
|
|
17
|
+
splits:
|
|
18
|
+
val:
|
|
19
|
+
src: ??
|
|
20
|
+
format: ase_db
|
|
21
|
+
transforms:
|
|
22
|
+
common_transform:
|
|
23
|
+
dataset_name: ${data.dataset_name}
|
|
24
|
+
stress_reshape_transform:
|
|
25
|
+
dataset_name: ${data.dataset_name}
|
|
26
|
+
|
|
27
|
+
regress_stress: True
|
|
28
|
+
pass_through_head_outputs: True
|
|
29
|
+
|
|
30
|
+
heads:
|
|
31
|
+
efs:
|
|
32
|
+
module: fairchem.core.models.uma.escn_md.MLP_EFS_Head
|
|
33
|
+
|
|
34
|
+
tasks_list:
|
|
35
|
+
- _target_: fairchem.core.units.mlip_unit.mlip_unit.Task
|
|
36
|
+
name: energy
|
|
37
|
+
level: system
|
|
38
|
+
property: energy
|
|
39
|
+
loss_fn:
|
|
40
|
+
_target_: fairchem.core.modules.loss.DDPMTLoss
|
|
41
|
+
loss_fn:
|
|
42
|
+
_target_: fairchem.core.modules.loss.PerAtomMAELoss
|
|
43
|
+
coefficient: 20
|
|
44
|
+
out_spec:
|
|
45
|
+
dim: [1]
|
|
46
|
+
dtype: float32
|
|
47
|
+
normalizer:
|
|
48
|
+
_target_: fairchem.core.modules.normalization.normalizer.Normalizer
|
|
49
|
+
mean: 0.0
|
|
50
|
+
rmsd: ${data.normalizer_rmsd}
|
|
51
|
+
element_references:
|
|
52
|
+
_target_: fairchem.core.modules.normalization.element_references.ElementReferences
|
|
53
|
+
element_references:
|
|
54
|
+
_target_: torch.DoubleTensor
|
|
55
|
+
_args_:
|
|
56
|
+
- ${data.elem_refs}
|
|
57
|
+
datasets:
|
|
58
|
+
- ${data.dataset_name}
|
|
59
|
+
metrics:
|
|
60
|
+
- mae
|
|
61
|
+
- per_atom_mae
|
|
62
|
+
- _target_: fairchem.core.units.mlip_unit.mlip_unit.Task
|
|
63
|
+
name: forces
|
|
64
|
+
level: atom
|
|
65
|
+
property: forces
|
|
66
|
+
train_on_free_atoms: True
|
|
67
|
+
eval_on_free_atoms: True
|
|
68
|
+
loss_fn:
|
|
69
|
+
_target_: fairchem.core.modules.loss.DDPMTLoss
|
|
70
|
+
loss_fn:
|
|
71
|
+
_target_: fairchem.core.modules.loss.L2NormLoss
|
|
72
|
+
reduction: mean
|
|
73
|
+
coefficient: 2
|
|
74
|
+
out_spec:
|
|
75
|
+
dim: [3]
|
|
76
|
+
dtype: float32
|
|
77
|
+
normalizer:
|
|
78
|
+
_target_: fairchem.core.modules.normalization.normalizer.Normalizer
|
|
79
|
+
mean: 0.0
|
|
80
|
+
rmsd: ${data.normalizer_rmsd}
|
|
81
|
+
datasets:
|
|
82
|
+
- ${data.dataset_name}
|
|
83
|
+
metrics:
|
|
84
|
+
- mae
|
|
85
|
+
- cosine_similarity
|
|
86
|
+
- magnitude_error
|
|
87
|
+
- _target_: fairchem.core.units.mlip_unit.mlip_unit.Task
|
|
88
|
+
name: stress
|
|
89
|
+
level: system
|
|
90
|
+
property: stress
|
|
91
|
+
out_spec:
|
|
92
|
+
dim: [1, 9]
|
|
93
|
+
dtype: float32
|
|
94
|
+
normalizer:
|
|
95
|
+
_target_: fairchem.core.modules.normalization.normalizer.Normalizer
|
|
96
|
+
mean: 0.0
|
|
97
|
+
rmsd: ${data.normalizer_rmsd}
|
|
98
|
+
datasets:
|
|
99
|
+
- ${data.dataset_name}
|
|
100
|
+
inference_only: True
|
uma_finetune/resources/configs/uma/finetune/data/uma_conserving_data_task_energy_force_stress.yaml
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
dataset_name: ??
|
|
2
|
+
elem_refs: ??
|
|
3
|
+
normalizer_rmsd: ??
|
|
4
|
+
|
|
5
|
+
train_dataset:
|
|
6
|
+
splits:
|
|
7
|
+
train:
|
|
8
|
+
src: ??
|
|
9
|
+
format: ase_db
|
|
10
|
+
transforms:
|
|
11
|
+
common_transform:
|
|
12
|
+
dataset_name: ${data.dataset_name}
|
|
13
|
+
stress_reshape_transform:
|
|
14
|
+
dataset_name: ${data.dataset_name}
|
|
15
|
+
|
|
16
|
+
val_dataset:
|
|
17
|
+
splits:
|
|
18
|
+
val:
|
|
19
|
+
src: ??
|
|
20
|
+
format: ase_db
|
|
21
|
+
transforms:
|
|
22
|
+
common_transform:
|
|
23
|
+
dataset_name: ${data.dataset_name}
|
|
24
|
+
stress_reshape_transform:
|
|
25
|
+
dataset_name: ${data.dataset_name}
|
|
26
|
+
|
|
27
|
+
regress_stress: True
|
|
28
|
+
pass_through_head_outputs: True
|
|
29
|
+
|
|
30
|
+
heads:
|
|
31
|
+
efs:
|
|
32
|
+
module: fairchem.core.models.uma.escn_md.MLP_EFS_Head
|
|
33
|
+
|
|
34
|
+
tasks_list:
|
|
35
|
+
- _target_: fairchem.core.units.mlip_unit.mlip_unit.Task
|
|
36
|
+
name: energy
|
|
37
|
+
level: system
|
|
38
|
+
property: energy
|
|
39
|
+
loss_fn:
|
|
40
|
+
_target_: fairchem.core.modules.loss.DDPMTLoss
|
|
41
|
+
loss_fn:
|
|
42
|
+
_target_: fairchem.core.modules.loss.PerAtomMAELoss
|
|
43
|
+
coefficient: 20
|
|
44
|
+
out_spec:
|
|
45
|
+
dim: [1]
|
|
46
|
+
dtype: float32
|
|
47
|
+
normalizer:
|
|
48
|
+
_target_: fairchem.core.modules.normalization.normalizer.Normalizer
|
|
49
|
+
mean: 0.0
|
|
50
|
+
rmsd: ${data.normalizer_rmsd}
|
|
51
|
+
element_references:
|
|
52
|
+
_target_: fairchem.core.modules.normalization.element_references.ElementReferences
|
|
53
|
+
element_references:
|
|
54
|
+
_target_: torch.DoubleTensor
|
|
55
|
+
_args_:
|
|
56
|
+
- ${data.elem_refs}
|
|
57
|
+
datasets:
|
|
58
|
+
- ${data.dataset_name}
|
|
59
|
+
metrics:
|
|
60
|
+
- mae
|
|
61
|
+
- per_atom_mae
|
|
62
|
+
- _target_: fairchem.core.units.mlip_unit.mlip_unit.Task
|
|
63
|
+
name: forces
|
|
64
|
+
level: atom
|
|
65
|
+
property: forces
|
|
66
|
+
train_on_free_atoms: True
|
|
67
|
+
eval_on_free_atoms: True
|
|
68
|
+
loss_fn:
|
|
69
|
+
_target_: fairchem.core.modules.loss.DDPMTLoss
|
|
70
|
+
loss_fn:
|
|
71
|
+
_target_: fairchem.core.modules.loss.L2NormLoss
|
|
72
|
+
reduction: mean
|
|
73
|
+
coefficient: 2
|
|
74
|
+
out_spec:
|
|
75
|
+
dim: [3]
|
|
76
|
+
dtype: float32
|
|
77
|
+
normalizer:
|
|
78
|
+
_target_: fairchem.core.modules.normalization.normalizer.Normalizer
|
|
79
|
+
mean: 0.0
|
|
80
|
+
rmsd: ${data.normalizer_rmsd}
|
|
81
|
+
datasets:
|
|
82
|
+
- ${data.dataset_name}
|
|
83
|
+
metrics:
|
|
84
|
+
- mae
|
|
85
|
+
- cosine_similarity
|
|
86
|
+
- magnitude_error
|
|
87
|
+
- _target_: fairchem.core.units.mlip_unit.mlip_unit.Task
|
|
88
|
+
name: stress
|
|
89
|
+
level: system
|
|
90
|
+
property: stress
|
|
91
|
+
loss_fn:
|
|
92
|
+
_target_: fairchem.core.modules.loss.DDPMTLoss
|
|
93
|
+
loss_fn:
|
|
94
|
+
_target_: fairchem.core.modules.loss.MAELoss
|
|
95
|
+
reduction: mean
|
|
96
|
+
coefficient: 1
|
|
97
|
+
out_spec:
|
|
98
|
+
dim: [1, 9]
|
|
99
|
+
dtype: float32
|
|
100
|
+
normalizer:
|
|
101
|
+
_target_: fairchem.core.modules.normalization.normalizer.Normalizer
|
|
102
|
+
mean: 0.0
|
|
103
|
+
rmsd: ${data.normalizer_rmsd}
|
|
104
|
+
datasets:
|
|
105
|
+
- ${data.dataset_name}
|
|
106
|
+
metrics:
|
|
107
|
+
- mae
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
defaults:
|
|
2
|
+
- data: ??
|
|
3
|
+
- _self_
|
|
4
|
+
|
|
5
|
+
job:
|
|
6
|
+
device_type: CUDA
|
|
7
|
+
scheduler:
|
|
8
|
+
mode: LOCAL
|
|
9
|
+
ranks_per_node: 1
|
|
10
|
+
num_nodes: 1
|
|
11
|
+
debug: True
|
|
12
|
+
run_dir: /tmp/uma_finetune_runs/
|
|
13
|
+
run_name: uma_finetune
|
|
14
|
+
logger:
|
|
15
|
+
_target_: fairchem.core.common.logger.WandBSingletonLogger.init_wandb
|
|
16
|
+
_partial_: true
|
|
17
|
+
entity: example
|
|
18
|
+
project: uma_finetune
|
|
19
|
+
|
|
20
|
+
# refers to a model name that can be retrieved from (huggingface)[https://huggingface.co/facebook/UMA]
|
|
21
|
+
base_model_name: uma-s-1p1
|
|
22
|
+
# 300 is effectively infinite neighbors, but if you are memory strained, using 100 is usually just as good
|
|
23
|
+
max_neighbors: 300
|
|
24
|
+
# choose to either run for integer number of epochs or steps, only 1 can be step, the other must be null
|
|
25
|
+
epochs: 1
|
|
26
|
+
steps: null
|
|
27
|
+
# customize batch size depending on your system
|
|
28
|
+
batch_size: 2
|
|
29
|
+
lr: 4e-4
|
|
30
|
+
weight_decay: 1e-3
|
|
31
|
+
evaluate_every_n_steps: 100
|
|
32
|
+
checkpoint_every_n_steps: 1000
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
train_dataset:
|
|
36
|
+
_target_: fairchem.core.datasets.mt_concat_dataset.create_concat_dataset
|
|
37
|
+
dataset_configs:
|
|
38
|
+
DATASET_NAME: ${data.train_dataset}
|
|
39
|
+
combined_dataset_config: { sampling: {type: temperature, temperature: 1.0} }
|
|
40
|
+
|
|
41
|
+
train_dataloader:
|
|
42
|
+
_target_: fairchem.core.components.common.dataloader_builder.get_dataloader
|
|
43
|
+
dataset: ${train_dataset}
|
|
44
|
+
batch_sampler_fn:
|
|
45
|
+
_target_: fairchem.core.common.data_parallel.BalancedBatchSampler
|
|
46
|
+
_partial_: True
|
|
47
|
+
batch_size: ${batch_size}
|
|
48
|
+
shuffle: True
|
|
49
|
+
seed: 0
|
|
50
|
+
num_workers: 0
|
|
51
|
+
collate_fn:
|
|
52
|
+
_target_: fairchem.core.units.mlip_unit.mlip_unit.mt_collater_adapter
|
|
53
|
+
tasks: ${data.tasks_list}
|
|
54
|
+
|
|
55
|
+
val_dataset:
|
|
56
|
+
_target_: fairchem.core.datasets.mt_concat_dataset.create_concat_dataset
|
|
57
|
+
dataset_configs:
|
|
58
|
+
DATASET_NAME: ${data.val_dataset}
|
|
59
|
+
combined_dataset_config: { sampling: {type: temperature, temperature: 1.0} }
|
|
60
|
+
|
|
61
|
+
eval_dataloader:
|
|
62
|
+
_target_: fairchem.core.components.common.dataloader_builder.get_dataloader
|
|
63
|
+
dataset: ${val_dataset}
|
|
64
|
+
batch_sampler_fn:
|
|
65
|
+
_target_: fairchem.core.common.data_parallel.BalancedBatchSampler
|
|
66
|
+
_partial_: True
|
|
67
|
+
batch_size: ${batch_size}
|
|
68
|
+
shuffle: False
|
|
69
|
+
seed: 0
|
|
70
|
+
num_workers: 0
|
|
71
|
+
collate_fn:
|
|
72
|
+
_target_: fairchem.core.units.mlip_unit.mlip_unit.mt_collater_adapter
|
|
73
|
+
tasks: ${data.tasks_list}
|
|
74
|
+
|
|
75
|
+
runner:
|
|
76
|
+
_target_: fairchem.core.components.train.train_runner.TrainEvalRunner
|
|
77
|
+
train_dataloader: ${train_dataloader}
|
|
78
|
+
eval_dataloader: ${eval_dataloader}
|
|
79
|
+
train_eval_unit:
|
|
80
|
+
_target_: fairchem.core.units.mlip_unit.mlip_unit.MLIPTrainEvalUnit
|
|
81
|
+
job_config: ${job}
|
|
82
|
+
tasks: ${data.tasks_list}
|
|
83
|
+
model:
|
|
84
|
+
_target_: fairchem.core.units.mlip_unit.mlip_unit.initialize_finetuning_model
|
|
85
|
+
checkpoint_location:
|
|
86
|
+
_target_: fairchem.core.calculate.pretrained_mlip.pretrained_checkpoint_path_from_name
|
|
87
|
+
model_name: ${base_model_name}
|
|
88
|
+
overrides:
|
|
89
|
+
backbone:
|
|
90
|
+
otf_graph: True
|
|
91
|
+
max_neighbors: ${max_neighbors}
|
|
92
|
+
regress_stress: ${data.regress_stress}
|
|
93
|
+
always_use_pbc: False
|
|
94
|
+
pass_through_head_outputs: ${data.pass_through_head_outputs}
|
|
95
|
+
heads: ${data.heads}
|
|
96
|
+
optimizer_fn:
|
|
97
|
+
_target_: torch.optim.AdamW
|
|
98
|
+
_partial_: true
|
|
99
|
+
lr: ${lr}
|
|
100
|
+
weight_decay: ${weight_decay}
|
|
101
|
+
cosine_lr_scheduler_fn:
|
|
102
|
+
_target_: fairchem.core.units.mlip_unit.mlip_unit._get_consine_lr_scheduler
|
|
103
|
+
_partial_: true
|
|
104
|
+
warmup_factor: 0.2
|
|
105
|
+
warmup_epochs: 0.01
|
|
106
|
+
lr_min_factor: 0.01
|
|
107
|
+
epochs: ${epochs}
|
|
108
|
+
steps: ${steps}
|
|
109
|
+
print_every: 10
|
|
110
|
+
clip_grad_norm: 100
|
|
111
|
+
max_epochs: ${epochs}
|
|
112
|
+
max_steps: ${steps}
|
|
113
|
+
evaluate_every_n_steps: ${evaluate_every_n_steps}
|
|
114
|
+
callbacks:
|
|
115
|
+
- _target_: fairchem.core.components.callbacks.TrainCheckpointCallback
|
|
116
|
+
checkpoint_every_n_steps: ${checkpoint_every_n_steps}
|
|
117
|
+
max_saved_checkpoints: 5
|
|
118
|
+
- _target_: torchtnt.framework.callbacks.TQDMProgressBar
|
uma_finetune/training.py
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
'''Run UMA fine-tuning with configurable backbone freezing.'''
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import math
|
|
5
|
+
import subprocess
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
import yaml
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def initialize_model(mode='full', freeze_blocks=0, **kwargs):
|
|
13
|
+
'''Initialize UMA and apply the requested parameter-freezing policy.'''
|
|
14
|
+
from fairchem.core.units.mlip_unit.mlip_unit import initialize_finetuning_model
|
|
15
|
+
|
|
16
|
+
model = initialize_finetuning_model(**kwargs)
|
|
17
|
+
|
|
18
|
+
if mode not in ('full', 'head_only', 'partial'):
|
|
19
|
+
raise ValueError('mode must be full, head_only, or partial.')
|
|
20
|
+
if type(freeze_blocks) is not int or freeze_blocks < 0:
|
|
21
|
+
raise ValueError('freeze_blocks must be a nonnegative integer.')
|
|
22
|
+
if mode != 'partial' and freeze_blocks != 0:
|
|
23
|
+
raise ValueError('freeze_blocks is only used with mode=partial.')
|
|
24
|
+
|
|
25
|
+
if mode == 'partial':
|
|
26
|
+
blocks = model.backbone.blocks
|
|
27
|
+
if freeze_blocks > len(blocks):
|
|
28
|
+
raise ValueError(f'freeze_blocks exceeds the {len(blocks)} backbone blocks.')
|
|
29
|
+
|
|
30
|
+
# Keep the heads trainable; control backbone parameters separately.
|
|
31
|
+
for parameter in model.parameters():
|
|
32
|
+
parameter.requires_grad = True
|
|
33
|
+
|
|
34
|
+
if mode in ('head_only', 'partial'):
|
|
35
|
+
for parameter in model.backbone.parameters():
|
|
36
|
+
parameter.requires_grad = False
|
|
37
|
+
|
|
38
|
+
if mode == 'partial':
|
|
39
|
+
for block in blocks[freeze_blocks:]:
|
|
40
|
+
for parameter in block.parameters():
|
|
41
|
+
parameter.requires_grad = True
|
|
42
|
+
print(f'Trainable backbone blocks: {len(blocks) - freeze_blocks}/{len(blocks)}')
|
|
43
|
+
|
|
44
|
+
trainable = sum(p.numel() for p in model.parameters() if p.requires_grad)
|
|
45
|
+
total = sum(p.numel() for p in model.parameters())
|
|
46
|
+
print(f'Trainable parameters: {trainable:,}/{total:,}')
|
|
47
|
+
return model
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def finetune(
|
|
51
|
+
dataset,
|
|
52
|
+
output_dir,
|
|
53
|
+
*,
|
|
54
|
+
model=None,
|
|
55
|
+
mode='full',
|
|
56
|
+
freeze_blocks=0,
|
|
57
|
+
energy_coef=20,
|
|
58
|
+
force_coef=2,
|
|
59
|
+
epochs=30,
|
|
60
|
+
batch_size=4,
|
|
61
|
+
lr=1e-4,
|
|
62
|
+
device='cuda',
|
|
63
|
+
max_neighbors=300,
|
|
64
|
+
max_saved_checkpoints=2,
|
|
65
|
+
):
|
|
66
|
+
'''
|
|
67
|
+
Fine-tune UMA using a directory returned by create_dataset().
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
dataset: Directory containing the generated training YAML and datasets.
|
|
71
|
+
output_dir: Root directory for FAIRChem run outputs.
|
|
72
|
+
model: Pretrained UMA model name; None keeps the generated YAML setting.
|
|
73
|
+
mode: 'full', 'head_only', or 'partial'.
|
|
74
|
+
freeze_blocks: Number of initial backbone blocks frozen in partial mode.
|
|
75
|
+
Other backbone parameters remain frozen; heads stay trainable.
|
|
76
|
+
energy_coef: Energy loss coefficient; None keeps the YAML setting.
|
|
77
|
+
force_coef: Force loss coefficient; None keeps the YAML setting.
|
|
78
|
+
Use None for an energy-only dataset.
|
|
79
|
+
epochs: Total training epochs.
|
|
80
|
+
batch_size: Training and validation batch size.
|
|
81
|
+
lr: Learning rate.
|
|
82
|
+
device: 'cuda' or 'cpu'.
|
|
83
|
+
max_neighbors: Maximum neighbors used by the model.
|
|
84
|
+
max_saved_checkpoints: Checkpoint retention limit.
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
Absolute output root as a Path. FAIRChem creates its run folder inside.
|
|
88
|
+
This function starts a new run; it does not implement checkpoint resume.
|
|
89
|
+
'''
|
|
90
|
+
dataset = Path(dataset).expanduser().resolve()
|
|
91
|
+
output_dir = Path(output_dir).expanduser().resolve()
|
|
92
|
+
config = dataset / 'uma_sm_finetune_template.yaml'
|
|
93
|
+
if not config.is_file():
|
|
94
|
+
raise FileNotFoundError(config)
|
|
95
|
+
if mode not in ('full', 'head_only', 'partial'):
|
|
96
|
+
raise ValueError('mode must be full, head_only, or partial.')
|
|
97
|
+
if type(freeze_blocks) is not int or freeze_blocks < 0:
|
|
98
|
+
raise ValueError('freeze_blocks must be a nonnegative integer.')
|
|
99
|
+
if mode != 'partial' and freeze_blocks != 0:
|
|
100
|
+
raise ValueError('freeze_blocks is only used with mode=partial.')
|
|
101
|
+
device = device.upper()
|
|
102
|
+
if device not in ('CPU', 'CUDA'):
|
|
103
|
+
raise ValueError('device must be cpu or cuda.')
|
|
104
|
+
for name, value in [('epochs', epochs), ('batch_size', batch_size),
|
|
105
|
+
('max_neighbors', max_neighbors),
|
|
106
|
+
('max_saved_checkpoints', max_saved_checkpoints)]:
|
|
107
|
+
if type(value) is not int or value < 1:
|
|
108
|
+
raise ValueError(f'{name} must be a positive integer.')
|
|
109
|
+
if not math.isfinite(lr) or lr <= 0:
|
|
110
|
+
raise ValueError('lr must be finite and positive.')
|
|
111
|
+
|
|
112
|
+
# Invoke the installed FAIRChem entry point with this Python interpreter.
|
|
113
|
+
entry_point = '''from importlib.metadata import distribution
|
|
114
|
+
next(ep for ep in distribution('fairchem-core').entry_points
|
|
115
|
+
if ep.group == 'console_scripts' and ep.name == 'fairchem').load()()
|
|
116
|
+
'''
|
|
117
|
+
command = [
|
|
118
|
+
sys.executable, '-c', entry_point,
|
|
119
|
+
'-c', str(config),
|
|
120
|
+
f'job.device_type={device}',
|
|
121
|
+
'+job.scheduler.distributed_init_method=FILE',
|
|
122
|
+
f'job.run_dir={json.dumps(str(output_dir))}',
|
|
123
|
+
f'epochs={epochs}',
|
|
124
|
+
f'batch_size={batch_size}',
|
|
125
|
+
f'lr={lr}',
|
|
126
|
+
f'max_neighbors={max_neighbors}',
|
|
127
|
+
'runner.train_eval_unit.model._target_=uma_finetune.training.initialize_model',
|
|
128
|
+
f'+runner.train_eval_unit.model.mode={mode}',
|
|
129
|
+
f'+runner.train_eval_unit.model.freeze_blocks={freeze_blocks}',
|
|
130
|
+
f'runner.callbacks.0.max_saved_checkpoints={max_saved_checkpoints}',
|
|
131
|
+
]
|
|
132
|
+
if model is not None:
|
|
133
|
+
command.append(f'base_model_name={json.dumps(model)}')
|
|
134
|
+
|
|
135
|
+
# Find loss positions by property rather than assuming their list order.
|
|
136
|
+
template = yaml.safe_load(config.read_text())
|
|
137
|
+
data_name = next(item['data'] for item in template['defaults']
|
|
138
|
+
if isinstance(item, dict) and 'data' in item)
|
|
139
|
+
data = yaml.safe_load((dataset / 'data' / f'{data_name}.yaml').read_text())
|
|
140
|
+
for property_name, coefficient in [('energy', energy_coef), ('forces', force_coef)]:
|
|
141
|
+
if coefficient is None:
|
|
142
|
+
continue
|
|
143
|
+
if not math.isfinite(coefficient) or coefficient < 0:
|
|
144
|
+
raise ValueError(f'{property_name} coefficient must be finite and nonnegative.')
|
|
145
|
+
index = next((i for i, task in enumerate(data['tasks_list'])
|
|
146
|
+
if task['property'] == property_name
|
|
147
|
+
and not task.get('inference_only', False)), None)
|
|
148
|
+
if index is None:
|
|
149
|
+
raise ValueError(f'No training task for {property_name}; set its coefficient to None.')
|
|
150
|
+
command.append(f'data.tasks_list.{index}.loss_fn.coefficient={coefficient}')
|
|
151
|
+
|
|
152
|
+
subprocess.run(command, check=True, cwd=dataset)
|
|
153
|
+
return output_dir
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: uma-finetune-wrapper
|
|
3
|
+
Version: 0.1.0.dev2
|
|
4
|
+
Summary: A simple Python interface for UMA dataset preparation and fine-tuning with FAIRChem.
|
|
5
|
+
Author: Timmo-hendrik Pukk
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: UMA,FAIRChem,fine-tuning,atomistic,machine-learning
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Science/Research
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
13
|
+
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
15
|
+
Requires-Python: >=3.12
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
License-File: src/uma_finetune/resources/FAIRChem-LICENSE.md
|
|
19
|
+
License-File: src/uma_finetune/resources/NOTICE.md
|
|
20
|
+
Requires-Dist: fairchem-core==2.22.0
|
|
21
|
+
Requires-Dist: PyYAML>=6.0
|
|
22
|
+
Dynamic: license-file
|
|
23
|
+
|
|
24
|
+
# UMA fine-tuning wrapper
|
|
25
|
+
|
|
26
|
+
Prepare a dataset and fine-tune a UMA model through two Python functions:
|
|
27
|
+
`create_dataset()` and `finetune()`.
|
|
28
|
+
|
|
29
|
+
This package wraps FAIRChem's existing dataset-generation and training tools.
|
|
30
|
+
It provides options for backbone freezing, energy and force loss coefficients,
|
|
31
|
+
and basic training settings. The training loop and model implementation remain
|
|
32
|
+
in FAIRChem.
|
|
33
|
+
|
|
34
|
+
The distribution name is **uma-finetune-wrapper**; the Python import is
|
|
35
|
+
**uma_finetune**. This is an independent wrapper, not an official FAIRChem package.
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
Python 3.12 and Linux are the tested development environment. The wrapper pins
|
|
40
|
+
`fairchem-core==2.22.0`; compatibility with other FAIRChem versions has not been
|
|
41
|
+
established.
|
|
42
|
+
|
|
43
|
+
Install a PyTorch build suitable for your hardware first. The tested Tesla V100
|
|
44
|
+
configuration uses:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
python -m pip install 'torch==2.13.0' \
|
|
48
|
+
--index-url https://download.pytorch.org/whl/cu126
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
See the [PyTorch installation instructions](https://pytorch.org/get-started/locally/)
|
|
52
|
+
for other hardware. This CUDA build is not a recommendation for every GPU.
|
|
53
|
+
|
|
54
|
+
Before publication, install from the package source directory:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
python -m pip install .
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
To build and install a wheel instead:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
python -m pip wheel --no-deps --wheel-dir dist .
|
|
64
|
+
python -m pip install dist/uma_finetune_wrapper-0.1.0.dev2-py3-none-any.whl
|
|
65
|
+
python -m pip check
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
The installation command installs the declared dependencies. A separate FAIRChem
|
|
69
|
+
source checkout is not needed: this package includes the required YAML templates.
|
|
70
|
+
You also need access to the chosen UMA model and any authentication required by
|
|
71
|
+
its [model repository](https://huggingface.co/facebook/UMA). Model weights are not
|
|
72
|
+
included in this package.
|
|
73
|
+
|
|
74
|
+
## Quick start
|
|
75
|
+
|
|
76
|
+
Prepare separate training and validation directories containing labelled
|
|
77
|
+
ASE-readable files, such as `.db`, `.traj`, or `.extxyz` files. The labels must be
|
|
78
|
+
readable as ASE calculator results. Split your data before calling the wrapper;
|
|
79
|
+
for related structures, keep the appropriate groups together to avoid leakage.
|
|
80
|
+
|
|
81
|
+
Save this as a Python script and run it in your compute allocation:
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from uma_finetune import create_dataset, finetune
|
|
85
|
+
|
|
86
|
+
if __name__ == '__main__':
|
|
87
|
+
dataset = create_dataset(
|
|
88
|
+
train_path='data/train',
|
|
89
|
+
val_path='data/validation',
|
|
90
|
+
output_dir='data/prepared',
|
|
91
|
+
task='oc25',
|
|
92
|
+
targets='ef',
|
|
93
|
+
base_model='uma-s-1p2',
|
|
94
|
+
num_workers=1,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
output = finetune(
|
|
98
|
+
dataset=dataset,
|
|
99
|
+
output_dir='runs/example',
|
|
100
|
+
mode='head_only',
|
|
101
|
+
energy_coef=20,
|
|
102
|
+
force_coef=2,
|
|
103
|
+
epochs=1,
|
|
104
|
+
batch_size=4,
|
|
105
|
+
lr=1e-4,
|
|
106
|
+
device='cuda',
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
print('Run output root:', output)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`data/prepared` must not already exist. To train again using prepared data, call
|
|
113
|
+
only `finetune(dataset='data/prepared', ...)`. Each call starts a new training run.
|
|
114
|
+
On an HPC cluster, submit training inside a GPU allocation; the wrapper does not
|
|
115
|
+
submit scheduler jobs.
|
|
116
|
+
|
|
117
|
+
## Dataset options
|
|
118
|
+
|
|
119
|
+
`create_dataset(train_path, val_path, output_dir, ...)` accepts directories for
|
|
120
|
+
both inputs and returns the absolute prepared-directory path.
|
|
121
|
+
|
|
122
|
+
| Option | Default | Meaning |
|
|
123
|
+
| --- | --- | --- |
|
|
124
|
+
| `task` | `'oc25'` | UMA task: `omol`, `omat`, `odac`, `oc20`, `oc25`, or `omc` |
|
|
125
|
+
| `targets` | `'ef'` | `e`: energy; `ef`: energy and forces; `efs`: also stress |
|
|
126
|
+
| `base_model` | `None` | Model name for the generated configuration; `None` uses FAIRChem's default |
|
|
127
|
+
| `num_workers` | `1` | Positive number of conversion workers |
|
|
128
|
+
|
|
129
|
+
Use the task corresponding to your data and pretrained model. Dataset conversion,
|
|
130
|
+
normalization, and element-reference fitting are performed by FAIRChem. Its input
|
|
131
|
+
requirements apply; real-data testing of this wrapper has used `targets='ef'`.
|
|
132
|
+
|
|
133
|
+
## Training options
|
|
134
|
+
|
|
135
|
+
`finetune(dataset, output_dir, ...)` uses the generated configuration and returns
|
|
136
|
+
the absolute output root. FAIRChem creates a timestamped run directory inside it.
|
|
137
|
+
|
|
138
|
+
| Option | Default | Meaning |
|
|
139
|
+
| --- | --- | --- |
|
|
140
|
+
| `model` | `None` | Pretrained model name; `None` keeps the dataset configuration's model |
|
|
141
|
+
| `mode` | `'full'` | `full`, `head_only`, or `partial` |
|
|
142
|
+
| `freeze_blocks` | `0` | Number of initial backbone blocks frozen in partial mode |
|
|
143
|
+
| `energy_coef` | `20` | Energy loss coefficient |
|
|
144
|
+
| `force_coef` | `2` | Force loss coefficient |
|
|
145
|
+
| `epochs` | `30` | Total training epochs |
|
|
146
|
+
| `batch_size` | `4` | Training and validation batch size |
|
|
147
|
+
| `lr` | `1e-4` | Learning rate |
|
|
148
|
+
| `device` | `'cuda'` | `cuda` or `cpu` |
|
|
149
|
+
| `max_neighbors` | `300` | Model neighbor limit |
|
|
150
|
+
| `max_saved_checkpoints` | `2` | Retention limit passed to FAIRChem's checkpoint callback |
|
|
151
|
+
|
|
152
|
+
Loss coefficients must be finite and nonnegative. Set either coefficient to
|
|
153
|
+
`None` to keep its YAML setting. For energy-only training, use `force_coef=None`.
|
|
154
|
+
Stress training retains its generated loss coefficient.
|
|
155
|
+
|
|
156
|
+
### Freezing
|
|
157
|
+
|
|
158
|
+
- **full:** all model parameters are trainable.
|
|
159
|
+
- **head_only:** the backbone is frozen; parameters outside it remain trainable.
|
|
160
|
+
- **partial:** the first `freeze_blocks` blocks are frozen; subsequent blocks
|
|
161
|
+
and heads are trainable. Other backbone parameters remain frozen.
|
|
162
|
+
|
|
163
|
+
For example, freeze the first block:
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
output = finetune(
|
|
167
|
+
dataset='data/prepared',
|
|
168
|
+
output_dir='runs/partial',
|
|
169
|
+
mode='partial',
|
|
170
|
+
freeze_blocks=1,
|
|
171
|
+
epochs=1,
|
|
172
|
+
batch_size=1,
|
|
173
|
+
)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
`freeze_blocks` must be between zero and the model's block count. A nonzero value
|
|
177
|
+
is only accepted in partial mode. Partial mode with zero frozen blocks still
|
|
178
|
+
freezes backbone parameters outside the blocks, so it differs from full mode.
|
|
179
|
+
The initializer prints the number of trainable parameters.
|
|
180
|
+
|
|
181
|
+
## Use a trained model
|
|
182
|
+
|
|
183
|
+
After a completed run, find:
|
|
184
|
+
|
|
185
|
+
```text
|
|
186
|
+
<output_dir>/<run_id>/checkpoints/final/inference_ckpt.pt
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Load it through FAIRChem using the same task used for fine-tuning:
|
|
190
|
+
|
|
191
|
+
```python
|
|
192
|
+
from ase.io import read
|
|
193
|
+
from fairchem.core import FAIRChemCalculator
|
|
194
|
+
from fairchem.core.units.mlip_unit import load_predict_unit
|
|
195
|
+
|
|
196
|
+
predictor = load_predict_unit(
|
|
197
|
+
'runs/example/<run_id>/checkpoints/final/inference_ckpt.pt',
|
|
198
|
+
device='cuda',
|
|
199
|
+
)
|
|
200
|
+
atoms = read('data/validation/example.db', index=0)
|
|
201
|
+
atoms.calc = FAIRChemCalculator(predictor, task_name='oc25')
|
|
202
|
+
|
|
203
|
+
energy = atoms.get_potential_energy() # eV
|
|
204
|
+
forces = atoms.get_forces(apply_constraint=False) # eV/angstrom
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Replace `<run_id>` and the input filename with actual paths. The wrapper does
|
|
208
|
+
not currently implement checkpoint resume or automatic best-checkpoint selection.
|
|
209
|
+
|
|
210
|
+
## Validation status
|
|
211
|
+
|
|
212
|
+
The following checks were completed on 17 October 2026:
|
|
213
|
+
|
|
214
|
+
- Dataset conversion with the bundled templates: 2,130 training structures.
|
|
215
|
+
- Head-only GPU training, final checkpoint loading, and finite energy/force
|
|
216
|
+
predictions on a 54-atom validation structure.
|
|
217
|
+
- Partial training with `freeze_blocks=1`, producing a final checkpoint.
|
|
218
|
+
- Fresh-environment wheel installation followed by dataset conversion,
|
|
219
|
+
head-only GPU training, and checkpoint inference without an editable FAIRChem
|
|
220
|
+
checkout.
|
|
221
|
+
|
|
222
|
+
The tested combination was Python 3.12, FAIRChem 2.22.0, PyTorch 2.13.0+cu126,
|
|
223
|
+
and a Tesla V100-SXM2-32GB. Full-mode GPU training, CPU training, other tasks,
|
|
224
|
+
and real-data energy-only/stress training have not been tested for this wrapper.
|
|
225
|
+
These are functionality checks, not evidence of model accuracy or generalization.
|
|
226
|
+
|
|
227
|
+
Lightweight wrapper tests can be run from the source directory:
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
python -m unittest discover -s tests -v
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
For development, install with `python -m pip install -e .`. Keep a snapshot of
|
|
234
|
+
an environment that passed your tests using `python -m pip freeze > requirements-tested.txt`.
|
|
235
|
+
This snapshot records an environment; it does not replace the package's dependency
|
|
236
|
+
metadata or the CUDA-specific installation instructions.
|
|
237
|
+
|
|
238
|
+
## License and attribution
|
|
239
|
+
|
|
240
|
+
The wrapper is distributed under the MIT license; see `LICENSE`.
|
|
241
|
+
The bundled FAIRChem 2.22.0 YAML templates retain their original copyright and
|
|
242
|
+
MIT license in `src/uma_finetune/resources/FAIRChem-LICENSE.md`, with provenance
|
|
243
|
+
in `src/uma_finetune/resources/NOTICE.md`.
|
|
244
|
+
|
|
245
|
+
The wrapper's license does not change the terms for UMA model weights, datasets,
|
|
246
|
+
or other dependencies. Follow the upstream model's terms and citation guidance
|
|
247
|
+
when using it in research.
|
|
248
|
+
|
|
249
|
+
Upstream: [FAIRChem](https://github.com/facebookresearch/fairchem).
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
uma_finetune/__init__.py,sha256=42u-cwQRprTXU_pRLNQPKYrk9YDF9wqzXlhUzrsHAPs,170
|
|
2
|
+
uma_finetune/dataset.py,sha256=s8EoSvie0pA7s-sma2x0474qWfSvgf_ObQ7EW7WF0Gw,2311
|
|
3
|
+
uma_finetune/training.py,sha256=Ei0CkT2TY1ytSvD0zy1BILLjLDmP9DEvY_Bxha7z_tk,6505
|
|
4
|
+
uma_finetune/resources/FAIRChem-LICENSE.md,sha256=PhCCeTiq6eWRZHciyDAGWpWzrych8NfwLzc4abQP6B0,1093
|
|
5
|
+
uma_finetune/resources/NOTICE.md,sha256=BiU7jlt9w5979X4783bfwVzaKPH5pPEsZfEKH0tzME8,622
|
|
6
|
+
uma_finetune/resources/configs/uma/finetune/uma_sm_finetune_template.yaml,sha256=OGQgSaSqvExd6rmpg01IjLx6b6o--ZW4gGDknzGjcq0,3800
|
|
7
|
+
uma_finetune/resources/configs/uma/finetune/data/uma_conserving_data_task_energy.yaml,sha256=BR_7QQvBo_d06MANmvYXrWNAZ-HJKDMOBVOtZUmM_Jo,2041
|
|
8
|
+
uma_finetune/resources/configs/uma/finetune/data/uma_conserving_data_task_energy_force.yaml,sha256=wa6zpC3i5KHOV8swE5dBK4QpdORmDXcaSZkKsqzZ8Q8,2308
|
|
9
|
+
uma_finetune/resources/configs/uma/finetune/data/uma_conserving_data_task_energy_force_stress.yaml,sha256=5IpUVwGBDVR567U3cQZFDlB4UFXTPVETY7DXdWdZPdE,2471
|
|
10
|
+
uma_finetune_wrapper-0.1.0.dev2.dist-info/licenses/LICENSE,sha256=V8T-HymNKX2rCymqfxOzsNgiAkMZ1kVRmG4w8W1Uk5A,1075
|
|
11
|
+
uma_finetune_wrapper-0.1.0.dev2.dist-info/licenses/src/uma_finetune/resources/FAIRChem-LICENSE.md,sha256=PhCCeTiq6eWRZHciyDAGWpWzrych8NfwLzc4abQP6B0,1093
|
|
12
|
+
uma_finetune_wrapper-0.1.0.dev2.dist-info/licenses/src/uma_finetune/resources/NOTICE.md,sha256=BiU7jlt9w5979X4783bfwVzaKPH5pPEsZfEKH0tzME8,622
|
|
13
|
+
uma_finetune_wrapper-0.1.0.dev2.dist-info/METADATA,sha256=7p6Wja0uOaCUulQRiauccXGliC18RhoYwjsOOfZtG28,9332
|
|
14
|
+
uma_finetune_wrapper-0.1.0.dev2.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
15
|
+
uma_finetune_wrapper-0.1.0.dev2.dist-info/top_level.txt,sha256=gKWWMdhx1KrESvpMdYjVKvpvoUJ5HNm52Ijc6AbdJzg,13
|
|
16
|
+
uma_finetune_wrapper-0.1.0.dev2.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Timmo-hendrik Pukk
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
uma_finetune_wrapper-0.1.0.dev2.dist-info/licenses/src/uma_finetune/resources/FAIRChem-LICENSE.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# License
|
|
2
|
+
|
|
3
|
+
MIT License
|
|
4
|
+
|
|
5
|
+
Copyright (c) Meta, Inc. and its affiliates.
|
|
6
|
+
|
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
in the Software without restriction, including without limitation the rights
|
|
10
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
furnished to do so, subject to the following conditions:
|
|
13
|
+
|
|
14
|
+
The above copyright notice and this permission notice shall be included in all
|
|
15
|
+
copies or substantial portions of the Software.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
23
|
+
SOFTWARE.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# FAIRChem templates
|
|
2
|
+
|
|
3
|
+
The four YAML files under configs/uma/finetune are unmodified copies from
|
|
4
|
+
FAIRChem 2.22.0, supplied from the working source checkout for this project.
|
|
5
|
+
Upstream project: https://github.com/facebookresearch/fairchem
|
|
6
|
+
|
|
7
|
+
Copyright (c) Meta, Inc. and its affiliates.
|
|
8
|
+
These templates are distributed under the MIT license reproduced in
|
|
9
|
+
FAIRChem-LICENSE.md. This notice does not assign a license to the wrapper itself.
|
|
10
|
+
|
|
11
|
+
The conversion script is supplied by the installed fairchem-core dependency;
|
|
12
|
+
it is not copied into this package. Keep these resources matched to the pinned
|
|
13
|
+
FAIRChem version when upgrading.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
uma_finetune
|