|
14 | 14 | import numpy as np |
15 | 15 | import torch |
16 | 16 |
|
17 | | -from deepmd.entrypoints.test import test as dp_test |
| 17 | +from deepmd.entrypoints.test import test as dp_test, test_ener as dp_test_ener |
18 | 18 | from deepmd.pt.entrypoints.main import ( |
19 | 19 | get_trainer, |
20 | 20 | ) |
21 | 21 | from deepmd.pt.utils.utils import ( |
22 | 22 | to_numpy_array, |
23 | 23 | ) |
| 24 | +from deepmd.infer.deep_eval import DeepEval |
| 25 | +from deepmd.utils.data import DeepmdData |
24 | 26 |
|
25 | 27 | from .model.test_permutation import ( |
26 | 28 | model_property, |
@@ -140,6 +142,97 @@ def setUp(self) -> None: |
140 | 142 | json.dump(self.config, fp, indent=4) |
141 | 143 |
|
142 | 144 |
|
| 145 | +class TestDPTestForceWeight(DPTest, unittest.TestCase): |
| 146 | + def setUp(self) -> None: |
| 147 | + self.detail_file = "test_dp_test_force_weight_detail" |
| 148 | + input_json = str(Path(__file__).parent / "water/se_atten.json") |
| 149 | + with open(input_json) as f: |
| 150 | + self.config = json.load(f) |
| 151 | + self.config["training"]["numb_steps"] = 1 |
| 152 | + self.config["training"]["save_freq"] = 1 |
| 153 | + system_dir = self._prepare_weighted_system() |
| 154 | + data_file = [system_dir] |
| 155 | + self.config["training"]["training_data"]["systems"] = data_file |
| 156 | + self.config["training"]["validation_data"]["systems"] = data_file |
| 157 | + self.config["model"] = deepcopy(model_se_e2_a) |
| 158 | + self.system_dir = system_dir |
| 159 | + self.input_json = "test_dp_test_force_weight.json" |
| 160 | + with open(self.input_json, "w") as fp: |
| 161 | + json.dump(self.config, fp, indent=4) |
| 162 | + |
| 163 | + def _prepare_weighted_system(self) -> str: |
| 164 | + src = Path(__file__).parent / "water/data/single" |
| 165 | + tmp_dir = tempfile.mkdtemp() |
| 166 | + shutil.copytree(src, tmp_dir, dirs_exist_ok=True) |
| 167 | + set_dir = Path(tmp_dir) / "set.000" |
| 168 | + forces = np.load(set_dir / "force.npy") |
| 169 | + forces[0, -3:] += 10.0 |
| 170 | + np.save(set_dir / "force.npy", forces) |
| 171 | + natoms = forces.shape[1] // 3 |
| 172 | + atom_pref = np.ones((forces.shape[0], natoms), dtype=forces.dtype) |
| 173 | + atom_pref[:, -1] = 0.0 |
| 174 | + np.save(set_dir / "atom_pref.npy", atom_pref) |
| 175 | + return tmp_dir |
| 176 | + |
| 177 | + def test_force_weight(self) -> None: |
| 178 | + trainer = get_trainer(deepcopy(self.config)) |
| 179 | + with torch.device("cpu"): |
| 180 | + trainer.get_data(is_train=False) |
| 181 | + model = torch.jit.script(trainer.model) |
| 182 | + tmp_model = tempfile.NamedTemporaryFile(delete=False, suffix=".pth") |
| 183 | + torch.jit.save(model, tmp_model.name) |
| 184 | + dp = DeepEval(tmp_model.name) |
| 185 | + data = DeepmdData( |
| 186 | + self.system_dir, |
| 187 | + set_prefix="set", |
| 188 | + shuffle_test=False, |
| 189 | + type_map=dp.get_type_map(), |
| 190 | + sort_atoms=False, |
| 191 | + ) |
| 192 | + err = dp_test_ener( |
| 193 | + dp, |
| 194 | + data, |
| 195 | + self.system_dir, |
| 196 | + numb_test=1, |
| 197 | + detail_file=None, |
| 198 | + has_atom_ener=False, |
| 199 | + ) |
| 200 | + test_data = data.get_test() |
| 201 | + coord = test_data["coord"].reshape([1, -1]) |
| 202 | + box = test_data["box"][:1] |
| 203 | + atype = test_data["type"][0] |
| 204 | + ret = dp.eval( |
| 205 | + coord, |
| 206 | + box, |
| 207 | + atype, |
| 208 | + fparam=None, |
| 209 | + aparam=None, |
| 210 | + atomic=False, |
| 211 | + efield=None, |
| 212 | + mixed_type=False, |
| 213 | + spin=None, |
| 214 | + ) |
| 215 | + force_pred = ret[1].reshape([1, -1]) |
| 216 | + force_true = test_data["force"][:1] |
| 217 | + weight = test_data["atom_pref"][:1] |
| 218 | + diff = force_pred - force_true |
| 219 | + diff_w = diff * weight |
| 220 | + denom = weight.sum() |
| 221 | + mae_expected = np.sum(np.abs(diff_w)) / denom |
| 222 | + rmse_expected = np.sqrt(np.sum(diff * diff * weight) / denom) |
| 223 | + mae_unweighted = np.sum(np.abs(diff)) / diff.size |
| 224 | + rmse_unweighted = np.sqrt(np.sum(diff * diff) / diff.size) |
| 225 | + np.testing.assert_allclose(err["mae_f"][0], mae_unweighted) |
| 226 | + np.testing.assert_allclose(err["rmse_f"][0], rmse_unweighted) |
| 227 | + np.testing.assert_allclose(err["mae_fw"][0], mae_expected) |
| 228 | + np.testing.assert_allclose(err["rmse_fw"][0], rmse_expected) |
| 229 | + os.unlink(tmp_model.name) |
| 230 | + |
| 231 | + def tearDown(self) -> None: |
| 232 | + super().tearDown() |
| 233 | + shutil.rmtree(self.system_dir) |
| 234 | + |
| 235 | + |
143 | 236 | class TestDPTestPropertySeA(unittest.TestCase): |
144 | 237 | def setUp(self) -> None: |
145 | 238 | self.detail_file = "test_dp_test_property_detail" |
|
0 commit comments