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

feat(pt): consistent fine-tuning with init-model #3803

Merged
merged 38 commits into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
a08ee08
feat(pt): consistent fine-tuning with init-model
iProzd May 22, 2024
da92310
Merge branch 'devel' into rf_finetune
iProzd May 22, 2024
70531cc
FIx uts
iProzd May 22, 2024
591de3e
Update test_finetune.py
iProzd May 22, 2024
7c909cb
Update test_finetune.py
iProzd May 22, 2024
21b77d6
Merge branch 'devel' into rf_finetune
iProzd May 22, 2024
5850a2f
Merge branch 'devel' into rf_finetune
iProzd May 23, 2024
bc8bdf8
Merge branch 'devel' into rf_finetune
iProzd May 29, 2024
297b5d6
Merge branch 'devel' into rf_finetune
iProzd May 30, 2024
638c369
Merge branch 'devel' into rf_finetune
iProzd May 31, 2024
a67ef2c
Update slim type
iProzd Jun 3, 2024
8270305
Merge branch 'devel' into rf_finetune
iProzd Jun 3, 2024
915707b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 3, 2024
951fb1e
Update main.py
iProzd Jun 3, 2024
c03e90a
rm extra doc
iProzd Jun 3, 2024
aa08e30
update uts
iProzd Jun 3, 2024
ddaa38d
fix uts
iProzd Jun 3, 2024
be1a18e
mv change_energy_bias_lower to tf
iProzd Jun 3, 2024
a394d97
resolve conversation
iProzd Jun 4, 2024
4d09586
update version
iProzd Jun 4, 2024
dfbf01f
Update test_cuda.yml
iProzd Jun 4, 2024
f5ee0ab
Revert "Update test_cuda.yml"
iProzd Jun 4, 2024
5664240
Merge branch 'devel' into rf_finetune
iProzd Jun 4, 2024
9f1d473
Merge branch 'devel' into rf_finetune
iProzd Jun 6, 2024
12788ab
Update deepmd/dpmodel/atomic_model/base_atomic_model.py
iProzd Jun 6, 2024
25909aa
Merge branch 'devel' into rf_finetune
iProzd Jun 6, 2024
fbe8396
Add uts for slim_type_map
iProzd Jun 6, 2024
7316f32
Merge branch 'devel' into rf_finetune
iProzd Jun 7, 2024
7c30b47
support extend type map in finetune
iProzd Jun 8, 2024
ab04399
Merge branch 'devel' into rf_finetune
iProzd Jun 8, 2024
4599213
resolve conversations
iProzd Jun 10, 2024
bf20853
add doc for use-pretrain-script in tf
iProzd Jun 10, 2024
af6c8b2
fix tebd
iProzd Jun 10, 2024
ad838c4
add ut for extend stat
iProzd Jun 11, 2024
9fac36e
Merge branch 'devel' into rf_finetune
iProzd Jun 11, 2024
911b043
Update deepmd/main.py
iProzd Jun 11, 2024
c0d57e9
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 11, 2024
fd64ee5
Update deepmd/utils/finetune.py
iProzd Jun 11, 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
22 changes: 22 additions & 0 deletions deepmd/dpmodel/atomic_model/base_atomic_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
AtomExcludeMask,
PairExcludeMask,
)
from deepmd.utils.finetune import (
get_index_between_two_maps,
map_atom_exclude_types,
map_pair_exclude_types,
)

from .make_base_atomic_model import (
make_base_atomic_model,
Expand Down Expand Up @@ -113,6 +118,23 @@
]
)

def change_type_map(
self, type_map: List[str], model_with_new_type_stat=None
) -> None:
"""Change the type related params to new ones, according to `type_map` and the original one in the model.
If there are new types in `type_map`, statistics will be updated accordingly to `model_with_new_type_stat` for these new types.
"""
remap_index, has_new_type = get_index_between_two_maps(self.type_map, type_map)
self.type_map = type_map
self.reinit_atom_exclude(

Check warning on line 129 in deepmd/dpmodel/atomic_model/base_atomic_model.py

View check run for this annotation

Codecov / codecov/patch

deepmd/dpmodel/atomic_model/base_atomic_model.py#L127-L129

Added lines #L127 - L129 were not covered by tests
map_atom_exclude_types(self.atom_exclude_types, remap_index)
)
self.reinit_pair_exclude(

Check warning on line 132 in deepmd/dpmodel/atomic_model/base_atomic_model.py

View check run for this annotation

Codecov / codecov/patch

deepmd/dpmodel/atomic_model/base_atomic_model.py#L132

Added line #L132 was not covered by tests
map_pair_exclude_types(self.pair_exclude_types, remap_index)
)
self.out_bias = self.out_bias[:, remap_index, :]
self.out_std = self.out_std[:, remap_index, :]

Check warning on line 136 in deepmd/dpmodel/atomic_model/base_atomic_model.py

View check run for this annotation

Codecov / codecov/patch

deepmd/dpmodel/atomic_model/base_atomic_model.py#L135-L136

Added lines #L135 - L136 were not covered by tests

def forward_common_atomic(
self,
extended_coord: np.ndarray,
Expand Down
18 changes: 18 additions & 0 deletions deepmd/dpmodel/atomic_model/dp_atomic_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,24 @@
)
return ret

def change_type_map(
self, type_map: List[str], model_with_new_type_stat=None
) -> None:
"""Change the type related params to new ones, according to `type_map` and the original one in the model.
If there are new types in `type_map`, statistics will be updated accordingly to `model_with_new_type_stat` for these new types.
"""
super().change_type_map(

Check warning on line 144 in deepmd/dpmodel/atomic_model/dp_atomic_model.py

View check run for this annotation

Codecov / codecov/patch

deepmd/dpmodel/atomic_model/dp_atomic_model.py#L144

Added line #L144 was not covered by tests
type_map=type_map, model_with_new_type_stat=model_with_new_type_stat
)
self.type_map = type_map
self.descriptor.change_type_map(

Check warning on line 148 in deepmd/dpmodel/atomic_model/dp_atomic_model.py

View check run for this annotation

Codecov / codecov/patch

deepmd/dpmodel/atomic_model/dp_atomic_model.py#L147-L148

Added lines #L147 - L148 were not covered by tests
type_map=type_map,
model_with_new_type_stat=model_with_new_type_stat.descriptor
if model_with_new_type_stat is not None
else None,
)
self.fitting_net.change_type_map(type_map=type_map)

Check warning on line 154 in deepmd/dpmodel/atomic_model/dp_atomic_model.py

View check run for this annotation

Codecov / codecov/patch

deepmd/dpmodel/atomic_model/dp_atomic_model.py#L154

Added line #L154 was not covered by tests

def serialize(self) -> dict:
dd = super().serialize()
dd.update(
Expand Down
17 changes: 17 additions & 0 deletions deepmd/dpmodel/atomic_model/linear_atomic_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,23 @@
"""Get the type map."""
return self.type_map

def change_type_map(
self, type_map: List[str], model_with_new_type_stat=None
) -> None:
"""Change the type related params to new ones, according to `type_map` and the original one in the model.
If there are new types in `type_map`, statistics will be updated accordingly to `model_with_new_type_stat` for these new types.
"""
super().change_type_map(

Check warning on line 113 in deepmd/dpmodel/atomic_model/linear_atomic_model.py

View check run for this annotation

Codecov / codecov/patch

deepmd/dpmodel/atomic_model/linear_atomic_model.py#L113

Added line #L113 was not covered by tests
type_map=type_map, model_with_new_type_stat=model_with_new_type_stat
)
for ii, model in enumerate(self.models):
model.change_type_map(

Check warning on line 117 in deepmd/dpmodel/atomic_model/linear_atomic_model.py

View check run for this annotation

Codecov / codecov/patch

deepmd/dpmodel/atomic_model/linear_atomic_model.py#L116-L117

Added lines #L116 - L117 were not covered by tests
type_map=type_map,
model_with_new_type_stat=model_with_new_type_stat.models[ii]
if model_with_new_type_stat is not None
else None,
)

def get_model_rcuts(self) -> List[float]:
"""Get the cut-off radius for each individual models."""
return [model.get_rcut() for model in self.models]
Expand Down
6 changes: 6 additions & 0 deletions deepmd/dpmodel/atomic_model/make_base_atomic_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,12 @@
def deserialize(cls, data: dict):
pass

@abstractmethod
def change_type_map(
self, type_map: List[str], model_with_new_type_stat=None
) -> None:
pass

Check warning on line 147 in deepmd/dpmodel/atomic_model/make_base_atomic_model.py

View check run for this annotation

Codecov / codecov/patch

deepmd/dpmodel/atomic_model/make_base_atomic_model.py#L147

Added line #L147 was not covered by tests
iProzd marked this conversation as resolved.
Show resolved Hide resolved

def make_atom_mask(
self,
atype: t_tensor,
Expand Down
12 changes: 12 additions & 0 deletions deepmd/dpmodel/atomic_model/pairtab_atomic_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,18 @@
"""Returns whether the atomic model has message passing."""
return False

def change_type_map(
self, type_map: List[str], model_with_new_type_stat=None
) -> None:
"""Change the type related params to new ones, according to `type_map` and the original one in the model.
If there are new types in `type_map`, statistics will be updated accordingly to `model_with_new_type_stat` for these new types.
"""
assert type_map == self.type_map, (

Check warning on line 144 in deepmd/dpmodel/atomic_model/pairtab_atomic_model.py

View check run for this annotation

Codecov / codecov/patch

deepmd/dpmodel/atomic_model/pairtab_atomic_model.py#L144

Added line #L144 was not covered by tests
"PairTabAtomicModel does not support changing type map now. "
"This feature is currently not implemented because it would require additional work to change the tab file. "
"We may consider adding this support in the future if there is a clear demand for it."
)
iProzd marked this conversation as resolved.
Show resolved Hide resolved

def serialize(self) -> dict:
dd = BaseAtomicModel.serialize(self)
dd.update(
Expand Down
34 changes: 34 additions & 0 deletions deepmd/dpmodel/descriptor/descriptor.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,37 @@ def call(
@abstractmethod
def has_message_passing(self) -> bool:
"""Returns whether the descriptor block has message passing."""


def extend_descrpt_stat(des, type_map, des_with_stat=None):
r"""
Extend the statistics of a descriptor block with types from newly provided `type_map`.

After extending, the type related dimension of the extended statistics will have a length of
`len(old_type_map) + len(type_map)`, where `old_type_map` represents the type map in `des`.
The `get_index_between_two_maps()` function can then be used to correctly select statistics for types
from `old_type_map` or `type_map`.
Positive indices from 0 to `len(old_type_map) - 1` will select old statistics of types in `old_type_map`,
while negative indices from `-len(type_map)` to -1 will select new statistics of types in `type_map`.

Parameters
----------
des : DescriptorBlock
The descriptor block to be extended.
type_map : List[str]
The name of each type of atoms to be extended.
des_with_stat : DescriptorBlock, Optional
The descriptor block has additional statistics of types from newly provided `type_map`.
If None, the default statistics will be used.
Otherwise, the statistics provided in this DescriptorBlock will be used.

"""
if des_with_stat is not None:
extend_davg = des_with_stat["davg"]
extend_dstd = des_with_stat["dstd"]
else:
extend_shape = [len(type_map), *list(des["davg"].shape[1:])]
extend_davg = np.zeros(extend_shape, dtype=des["davg"].dtype)
extend_dstd = np.ones(extend_shape, dtype=des["dstd"].dtype)
des["davg"] = np.concatenate([des["davg"], extend_davg], axis=0)
des["dstd"] = np.concatenate([des["dstd"], extend_dstd], axis=0)
wanghan-iapcm marked this conversation as resolved.
Show resolved Hide resolved
43 changes: 41 additions & 2 deletions deepmd/dpmodel/descriptor/dpa1.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
from deepmd.utils.data_system import (
DeepmdDataSystem,
)
from deepmd.utils.finetune import (
get_index_between_two_maps,
map_pair_exclude_types,
)
from deepmd.utils.path import (
DPPath,
)
Expand All @@ -49,6 +53,7 @@
)
from .descriptor import (
DescriptorBlock,
extend_descrpt_stat,
)


Expand Down Expand Up @@ -194,8 +199,6 @@
Whether to use electronic configuration type embedding.
type_map: List[str], Optional
A list of strings. Give the name to each type of atoms.
Only used if `use_econf_tebd` is `True` in type embedding net.

spin
(Only support None to keep consistent with other backend references.)
(Not used in this version. Not-none option is not implemented.)
Expand Down Expand Up @@ -327,6 +330,10 @@
"""Returns the number of element types."""
return self.se_atten.get_ntypes()

def get_type_map(self) -> List[str]:
"""Get the name to each type of atoms."""
return self.type_map

Check warning on line 335 in deepmd/dpmodel/descriptor/dpa1.py

View check run for this annotation

Codecov / codecov/patch

deepmd/dpmodel/descriptor/dpa1.py#L335

Added line #L335 was not covered by tests
iProzd marked this conversation as resolved.
Show resolved Hide resolved
iProzd marked this conversation as resolved.
Show resolved Hide resolved

def get_dim_out(self) -> int:
"""Returns the output dimension."""
ret = self.se_atten.get_dim_out()
Expand Down Expand Up @@ -382,9 +389,41 @@
mean: np.ndarray,
stddev: np.ndarray,
) -> None:
"""Update mean and stddev for descriptor."""
self.se_atten.mean = mean
self.se_atten.stddev = stddev

def get_stat_mean_and_stddev(self) -> Tuple[np.ndarray, np.ndarray]:
"""Get mean and stddev for descriptor."""
return self.se_atten.mean, self.se_atten.stddev

def change_type_map(
self, type_map: List[str], model_with_new_type_stat=None
) -> None:
"""Change the type related params to new ones, according to `type_map` and the original one in the model.
If there are new types in `type_map`, statistics will be updated accordingly to `model_with_new_type_stat` for these new types.
"""
assert (
self.type_map is not None
), "'type_map' must be defined when performing type changing!"
remap_index, has_new_type = get_index_between_two_maps(self.type_map, type_map)
obj = self.se_atten
obj.ntypes = len(type_map)
self.type_map = type_map
self.type_embedding.change_type_map(type_map=type_map)
obj.reinit_exclude(map_pair_exclude_types(obj.exclude_types, remap_index))
if has_new_type:
# the avg and std of new types need to be updated
extend_descrpt_stat(
obj,
type_map,
des_with_stat=model_with_new_type_stat.se_atten
if model_with_new_type_stat is not None
else None,
)
obj["davg"] = obj["davg"][remap_index]
obj["dstd"] = obj["dstd"][remap_index]

def call(
self,
coord_ext,
Expand Down
70 changes: 69 additions & 1 deletion deepmd/dpmodel/descriptor/dpa2.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
from deepmd.utils.data_system import (
DeepmdDataSystem,
)
from deepmd.utils.finetune import (
get_index_between_two_maps,
map_pair_exclude_types,
)
from deepmd.utils.path import (
DPPath,
)
Expand All @@ -42,6 +46,9 @@
from .base_descriptor import (
BaseDescriptor,
)
from .descriptor import (
extend_descrpt_stat,
)
from .dpa1 import (
DescrptBlockSeAtten,
)
Expand Down Expand Up @@ -353,7 +360,6 @@
Whether to use electronic configuration type embedding.
type_map : List[str], Optional
A list of strings. Give the name to each type of atoms.
Only used if `use_econf_tebd` is `True` in type embedding net.

Returns
-------
Expand Down Expand Up @@ -501,6 +507,10 @@
"""Returns the number of element types."""
return self.ntypes

def get_type_map(self) -> List[str]:
"""Get the name to each type of atoms."""
return self.type_map

Check warning on line 512 in deepmd/dpmodel/descriptor/dpa2.py

View check run for this annotation

Codecov / codecov/patch

deepmd/dpmodel/descriptor/dpa2.py#L512

Added line #L512 was not covered by tests
iProzd marked this conversation as resolved.
Show resolved Hide resolved

def get_dim_out(self) -> int:
"""Returns the output dimension of this descriptor."""
ret = self.repformers.dim_out
Expand Down Expand Up @@ -542,6 +552,47 @@
"""
raise NotImplementedError

def change_type_map(
self, type_map: List[str], model_with_new_type_stat=None
) -> None:
"""Change the type related params to new ones, according to `type_map` and the original one in the model.
If there are new types in `type_map`, statistics will be updated accordingly to `model_with_new_type_stat` for these new types.
"""
assert (
self.type_map is not None
), "'type_map' must be defined when performing type changing!"
remap_index, has_new_type = get_index_between_two_maps(self.type_map, type_map)
self.type_map = type_map
self.type_embedding.change_type_map(type_map=type_map)
self.exclude_types = map_pair_exclude_types(self.exclude_types, remap_index)
self.ntypes = len(type_map)
repinit = self.repinit
repformers = self.repformers
if has_new_type:
# the avg and std of new types need to be updated
extend_descrpt_stat(
repinit,
type_map,
des_with_stat=model_with_new_type_stat.repinit
if model_with_new_type_stat is not None
else None,
)
extend_descrpt_stat(
repformers,
type_map,
des_with_stat=model_with_new_type_stat.repformers
if model_with_new_type_stat is not None
else None,
)
repinit.ntypes = self.ntypes
repformers.ntypes = self.ntypes
repinit.reinit_exclude(self.exclude_types)
repformers.reinit_exclude(self.exclude_types)
repinit["davg"] = repinit["davg"][remap_index]
repinit["dstd"] = repinit["dstd"][remap_index]
repformers["davg"] = repformers["davg"][remap_index]
repformers["dstd"] = repformers["dstd"][remap_index]

iProzd marked this conversation as resolved.
Show resolved Hide resolved
iProzd marked this conversation as resolved.
Show resolved Hide resolved
@property
def dim_out(self):
return self.get_dim_out()
Expand All @@ -555,6 +606,23 @@
"""Update mean and stddev for descriptor elements."""
raise NotImplementedError

def set_stat_mean_and_stddev(
self,
mean: List[np.ndarray],
stddev: List[np.ndarray],
) -> None:
"""Update mean and stddev for descriptor."""
for ii, descrpt in enumerate([self.repinit, self.repformers]):
descrpt.mean = mean[ii]
descrpt.stddev = stddev[ii]

def get_stat_mean_and_stddev(self) -> Tuple[List[np.ndarray], List[np.ndarray]]:
"""Get mean and stddev for descriptor."""
return [self.repinit.mean, self.repformers.mean], [
self.repinit.stddev,
self.repformers.stddev,
]

def call(
self,
coord_ext: np.ndarray,
Expand Down
Loading