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

fix: add numb_fparam & numb_aparam to dipole & polar fitting #4405

Merged
merged 2 commits into from
Nov 23, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
49 changes: 49 additions & 0 deletions deepmd/tf/fit/dipole.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
one_layer,
one_layer_rand_seed_shift,
)
from deepmd.utils.data import (
DataRequirementItem,
)
from deepmd.utils.version import (
check_version_compatibility,
)
Expand All @@ -51,6 +54,10 @@ class DipoleFittingSeA(Fitting):
resnet_dt : bool
Time-step `dt` in the resnet construction:
y = x + dt * \phi (Wx + b)
numb_fparam
Number of frame parameters
numb_aparam
Number of atomic parameters
sel_type : list[int]
The atom types selected to have an atomic dipole prediction. If is None, all atoms are selected.
seed : int
Expand All @@ -75,6 +82,8 @@ def __init__(
embedding_width: int,
neuron: list[int] = [120, 120, 120],
resnet_dt: bool = True,
numb_fparam: int = 0,
numb_aparam: int = 0,
sel_type: Optional[list[int]] = None,
seed: Optional[int] = None,
activation_function: str = "tanh",
Expand Down Expand Up @@ -108,6 +117,18 @@ def __init__(
self.mixed_prec = None
self.mixed_types = mixed_types
self.type_map = type_map
self.numb_aparam = numb_fparam
njzjz marked this conversation as resolved.
Show resolved Hide resolved
self.numb_aparam = numb_aparam
if numb_fparam > 0:
raise ValueError("numb_fparam is not supported in the dipole fitting")
if numb_aparam > 0:
raise ValueError("numb_aparam is not supported in the dipole fitting")
self.fparam_avg = None
self.fparam_std = None
self.fparam_inv_std = None
self.aparam_avg = None
self.aparam_std = None
self.aparam_inv_std = None
njzjz marked this conversation as resolved.
Show resolved Hide resolved

def get_sel_type(self) -> int:
"""Get selected type."""
Expand Down Expand Up @@ -372,6 +393,8 @@ def serialize(self, suffix: str) -> dict:
"dim_out": 3,
"neuron": self.n_neuron,
"resnet_dt": self.resnet_dt,
"numb_fparam": self.numb_fparam,
"numb_aparam": self.numb_aparam,
"activation_function": self.activation_function_name,
"precision": self.fitting_precision.name,
"exclude_types": [],
Expand Down Expand Up @@ -412,3 +435,29 @@ def deserialize(cls, data: dict, suffix: str):
suffix=suffix,
)
return fitting

@property
def input_requirement(self) -> list[DataRequirementItem]:
"""Return data requirements needed for the model input."""
data_requirement = []
if self.numb_fparam > 0:
data_requirement.append(
DataRequirementItem(
"fparam", self.numb_fparam, atomic=False, must=True, high_prec=False
)
)
if self.numb_aparam > 0:
data_requirement.append(
DataRequirementItem(
"aparam", self.numb_aparam, atomic=True, must=True, high_prec=False
)
)
return data_requirement

def get_numb_fparam(self) -> int:
"""Get the number of frame parameters."""
return self.numb_fparam

def get_numb_aparam(self) -> int:
"""Get the number of atomic parameters."""
return self.numb_aparam
49 changes: 49 additions & 0 deletions deepmd/tf/fit/polar.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
one_layer,
one_layer_rand_seed_shift,
)
from deepmd.utils.data import (
DataRequirementItem,
)
from deepmd.utils.version import (
check_version_compatibility,
)
Expand All @@ -56,6 +59,10 @@ class PolarFittingSeA(Fitting):
resnet_dt : bool
Time-step `dt` in the resnet construction:
y = x + dt * \phi (Wx + b)
numb_fparam
Number of frame parameters
numb_aparam
Number of atomic parameters
sel_type : list[int]
The atom types selected to have an atomic polarizability prediction. If is None, all atoms are selected.
fit_diag : bool
Expand Down Expand Up @@ -86,6 +93,8 @@ def __init__(
embedding_width: int,
neuron: list[int] = [120, 120, 120],
resnet_dt: bool = True,
numb_fparam: int = 0,
numb_aparam: int = 0,
sel_type: Optional[list[int]] = None,
fit_diag: bool = True,
scale: Optional[list[float]] = None,
Expand Down Expand Up @@ -151,6 +160,18 @@ def __init__(
self.mixed_prec = None
self.mixed_types = mixed_types
self.type_map = type_map
self.numb_fparam = numb_fparam
self.numb_aparam = numb_aparam
if numb_fparam > 0:
raise ValueError("numb_fparam is not supported in the dipole fitting")
if numb_aparam > 0:
raise ValueError("numb_aparam is not supported in the dipole fitting")
self.fparam_avg = None
self.fparam_std = None
self.fparam_inv_std = None
self.aparam_avg = None
self.aparam_std = None
self.aparam_inv_std = None

def get_sel_type(self) -> list[int]:
"""Get selected atom types."""
Expand Down Expand Up @@ -565,6 +586,8 @@ def serialize(self, suffix: str) -> dict:
"dim_out": 3,
"neuron": self.n_neuron,
"resnet_dt": self.resnet_dt,
"numb_fparam": self.numb_fparam,
"numb_aparam": self.numb_aparam,
"activation_function": self.activation_function_name,
"precision": self.fitting_precision.name,
"exclude_types": [],
Expand Down Expand Up @@ -777,3 +800,29 @@ def get_loss(self, loss: dict, lr) -> Loss:
atomic=False,
label_name="polarizability",
)

@property
def input_requirement(self) -> list[DataRequirementItem]:
"""Return data requirements needed for the model input."""
data_requirement = []
if self.numb_fparam > 0:
data_requirement.append(
DataRequirementItem(
"fparam", self.numb_fparam, atomic=False, must=True, high_prec=False
)
)
if self.numb_aparam > 0:
data_requirement.append(
DataRequirementItem(
"aparam", self.numb_aparam, atomic=True, must=True, high_prec=False
)
)
return data_requirement

def get_numb_fparam(self) -> int:
"""Get the number of frame parameters."""
return self.numb_fparam

def get_numb_aparam(self) -> int:
"""Get the number of atomic parameters."""
return self.numb_aparam
32 changes: 32 additions & 0 deletions deepmd/utils/argcheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -1595,6 +1595,8 @@ def fitting_property():

@fitting_args_plugin.register("polar", doc=doc_polar)
def fitting_polar():
doc_numb_fparam = "The dimension of the frame parameter. If set to >0, file `fparam.npy` should be included to provided the input fparams."
doc_numb_aparam = "The dimension of the atomic parameter. If set to >0, file `aparam.npy` should be included to provided the input aparams."
doc_neuron = "The number of neurons in each hidden layers of the fitting net. When two hidden layers are of the same size, a skip connection is built."
doc_activation_function = f'The activation function in the fitting net. Supported activation functions are {list_to_doc(ACTIVATION_FN_DICT.keys())} Note that "gelu" denotes the custom operator version, and "gelu_tf" denotes the TF standard version. If you set "None" or "none" here, no activation function will be used.'
doc_resnet_dt = 'Whether to use a "Timestep" in the skip connection'
Expand All @@ -1609,6 +1611,20 @@ def fitting_polar():
doc_shift_diag = "Whether to shift the diagonal of polar, which is beneficial to training. Default is true."

return [
Argument(
"numb_fparam",
int,
optional=True,
default=0,
doc=doc_only_pt_supported + doc_numb_fparam,
),
Argument(
"numb_aparam",
int,
optional=True,
default=0,
doc=doc_only_pt_supported + doc_numb_aparam,
),
Argument(
"neuron",
list[int],
Expand Down Expand Up @@ -1649,13 +1665,29 @@ def fitting_polar():

@fitting_args_plugin.register("dipole", doc=doc_dipole)
def fitting_dipole():
doc_numb_fparam = "The dimension of the frame parameter. If set to >0, file `fparam.npy` should be included to provided the input fparams."
doc_numb_aparam = "The dimension of the atomic parameter. If set to >0, file `aparam.npy` should be included to provided the input aparams."
doc_neuron = "The number of neurons in each hidden layers of the fitting net. When two hidden layers are of the same size, a skip connection is built."
doc_activation_function = f'The activation function in the fitting net. Supported activation functions are {list_to_doc(ACTIVATION_FN_DICT.keys())} Note that "gelu" denotes the custom operator version, and "gelu_tf" denotes the TF standard version. If you set "None" or "none" here, no activation function will be used.'
doc_resnet_dt = 'Whether to use a "Timestep" in the skip connection'
doc_precision = f"The precision of the fitting net parameters, supported options are {list_to_doc(PRECISION_DICT.keys())} Default follows the interface precision."
doc_sel_type = "The atom types for which the atomic dipole will be provided. If not set, all types will be selected."
doc_seed = "Random seed for parameter initialization of the fitting net"
return [
Argument(
"numb_fparam",
int,
optional=True,
default=0,
doc=doc_only_pt_supported + doc_numb_fparam,
),
Argument(
"numb_aparam",
int,
optional=True,
default=0,
doc=doc_only_pt_supported + doc_numb_aparam,
),
Argument(
"neuron",
list[int],
Expand Down
1 change: 1 addition & 0 deletions doc/model/train-fitting-tensor.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,3 +247,4 @@ During training, at each step when the `lcurve.out` is printed, the system used

To only fit against a subset of atomic types, in the TensorFlow backend, {ref}`fitting_net/sel_type <model[standard]/fitting_net[dipole]/sel_type>` should be set to selected types;
in other backends, {ref}`atom_exclude_types <model/atom_exclude_types>` should be set to excluded types.
The TensorFlow backend does not support {ref}`numb_fparam <model[standard]/fitting_net[dipole]/numb_fparam>` and {ref}`numb_aparam <model[standard]/fitting_net[dipole]/numb_aparam>`.
3 changes: 1 addition & 2 deletions source/tests/consistent/model/test_dipole.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ def data(self) -> dict:
"type": "dipole",
"neuron": [4, 4, 4],
"resnet_dt": True,
# TODO: add numb_fparam argument to dipole fitting
"_numb_fparam": 0,
"numb_fparam": 0,
"precision": "float64",
"seed": 1,
},
Expand Down
3 changes: 1 addition & 2 deletions source/tests/consistent/model/test_polar.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ def data(self) -> dict:
"type": "polar",
"neuron": [4, 4, 4],
"resnet_dt": True,
# TODO: add numb_fparam argument to polar fitting
"_numb_fparam": 0,
"numb_fparam": 0,
"precision": "float64",
"seed": 1,
},
Expand Down
3 changes: 1 addition & 2 deletions source/tests/consistent/model/test_property.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,7 @@ def data(self) -> dict:
"type": "property",
"neuron": [4, 4, 4],
"resnet_dt": True,
# TODO: add numb_fparam argument to property fitting
"_numb_fparam": 0,
"numb_fparam": 0,
"precision": "float64",
"seed": 1,
},
Expand Down
Loading