Skip to content

Commit 2e822db

Browse files
authored
Merge branch 'develop' into bubble_net
2 parents efc5cdd + 3e1d0ad commit 2e822db

File tree

7 files changed

+149
-12
lines changed

7 files changed

+149
-12
lines changed

docs/zh/examples/volterra_ide.md

+12
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,18 @@
1414
python volterra_ide.py mode=eval EVAL.pretrained_model_path=https://paddle-org.bj.bcebos.com/paddlescience/models/volterra_ide/volterra_ide_pretrained.pdparams
1515
```
1616

17+
=== "模型导出命令"
18+
19+
``` sh
20+
python volterra_ide.py mode=export
21+
```
22+
23+
=== "模型推理命令"
24+
25+
``` sh
26+
python volterra_ide.py mode=infer
27+
```
28+
1729
| 预训练模型 | 指标 |
1830
|:--| :--|
1931
| [volterra_ide_pretrained.pdparams](https://paddle-org.bj.bcebos.com/paddlescience/models/volterra_ide/volterra_ide_pretrained.pdparams) | loss(L2Rel_Validator): 0.00023 <br> L2Rel.u(L2Rel_Validator): 0.00023 |

examples/ide/conf/volterra_ide.yaml

+17
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,20 @@ EVAL:
6161
pretrained_model_path: null
6262
eval_with_no_grad: true
6363
npoint_eval: 100
64+
65+
INFER:
66+
pretrained_model_path: https://paddle-org.bj.bcebos.com/paddlescience/models/volterra_ide/volterra_ide_pretrained.pdparams
67+
export_path: ./inference/volterra_ide
68+
pdmodel_path: ${INFER.export_path}.pdmodel
69+
pdpiparams_path: ${INFER.export_path}.pdiparams
70+
device: gpu
71+
engine: native
72+
precision: fp32
73+
onnx_path: ${INFER.export_path}.onnx
74+
ir_optim: true
75+
min_subgraph_size: 10
76+
gpu_mem: 4000
77+
gpu_id: 0
78+
max_batch_size: 64
79+
num_cpu_threads: 4
80+
batch_size: 16

examples/ide/volterra_ide.py

+67-1
Original file line numberDiff line numberDiff line change
@@ -254,14 +254,80 @@ def u_solution_func(in_) -> np.ndarray:
254254
plt.savefig(osp.join(cfg.output_dir, "./Volterra_IDE.png"), dpi=200)
255255

256256

257+
def export(cfg: DictConfig):
258+
# set model
259+
model = ppsci.arch.MLP(**cfg.MODEL)
260+
261+
# initialize solver
262+
solver = ppsci.solver.Solver(
263+
model,
264+
pretrained_model_path=cfg.INFER.pretrained_model_path,
265+
)
266+
# export model
267+
from paddle.static import InputSpec
268+
269+
input_spec = [
270+
{
271+
key: InputSpec([None, 1], "float32", name=key)
272+
for key in cfg.MODEL.input_keys
273+
},
274+
]
275+
solver.export(input_spec, cfg.INFER.export_path)
276+
277+
278+
def inference(cfg: DictConfig):
279+
from deploy.python_infer import pinn_predictor
280+
281+
predictor = pinn_predictor.PINNPredictor(cfg)
282+
283+
# set geometry
284+
geom = {"timedomain": ppsci.geometry.TimeDomain(*cfg.BOUNDS)}
285+
286+
input_data = geom["timedomain"].uniform_points(cfg.EVAL.npoint_eval)
287+
input_dict = {"x": input_data}
288+
289+
output_dict = predictor.predict(
290+
{key: input_dict[key] for key in cfg.MODEL.input_keys}, cfg.INFER.batch_size
291+
)
292+
293+
# mapping data to cfg.INFER.output_keys
294+
output_dict = {
295+
store_key: output_dict[infer_key]
296+
for store_key, infer_key in zip(cfg.MODEL.output_keys, output_dict.keys())
297+
}
298+
299+
def u_solution_func(in_) -> np.ndarray:
300+
if isinstance(in_["x"], paddle.Tensor):
301+
return paddle.exp(-in_["x"]) * paddle.cosh(in_["x"])
302+
return np.exp(-in_["x"]) * np.cosh(in_["x"])
303+
304+
label_data = u_solution_func({"x": input_data})
305+
output_data = output_dict["u"]
306+
307+
# save result
308+
plt.plot(input_data, label_data, "-", label=r"$u(t)$")
309+
plt.plot(input_data, output_data, "o", label=r"$\hat{u}(t)$", markersize=4.0)
310+
plt.legend()
311+
plt.xlabel(r"$t$")
312+
plt.ylabel(r"$u$")
313+
plt.title(r"$u-t$")
314+
plt.savefig("./Volterra_IDE_pred.png", dpi=200)
315+
316+
257317
@hydra.main(version_base=None, config_path="./conf", config_name="volterra_ide.yaml")
258318
def main(cfg: DictConfig):
259319
if cfg.mode == "train":
260320
train(cfg)
261321
elif cfg.mode == "eval":
262322
evaluate(cfg)
323+
elif cfg.mode == "export":
324+
export(cfg)
325+
elif cfg.mode == "infer":
326+
inference(cfg)
263327
else:
264-
raise ValueError(f"cfg.mode should in ['train', 'eval'], but got '{cfg.mode}'")
328+
raise ValueError(
329+
f"cfg.mode should in ['train', 'eval', 'export', 'infer'], but got '{cfg.mode}'"
330+
)
265331

266332

267333
if __name__ == "__main__":

ppsci/data/__init__.py

+12-7
Original file line numberDiff line numberDiff line change
@@ -82,16 +82,21 @@ def build_dataloader(_dataset, cfg):
8282
sampler_cfg["batch_size"] = cfg["batch_size"]
8383
batch_sampler = getattr(io, batch_sampler_cls)(_dataset, **sampler_cfg)
8484
else:
85-
if cfg["batch_size"] != 1:
86-
raise ValueError(
87-
f"`batch_size` should be 1 when sampler config is None, but got {cfg['batch_size']}."
85+
batch_sampler_cls = "BatchSampler"
86+
if world_size > 1:
87+
batch_sampler_cls = "DistributedBatchSampler"
88+
logger.warning(
89+
f"Automatically use 'DistributedBatchSampler' instead of "
90+
f"'BatchSampler' when world_size({world_size}) > 1."
8891
)
89-
logger.warning(
90-
"`batch_size` is set to 1 as neither sampler config nor batch_size is set."
91-
)
92-
batch_sampler = io.BatchSampler(
92+
batch_sampler = getattr(io, batch_sampler_cls)(
9393
_dataset,
9494
batch_size=cfg["batch_size"],
95+
shuffle=False,
96+
drop_last=False,
97+
)
98+
logger.message(
99+
"'shuffle' and 'drop_last' are both set to False in default as sampler config is not specified."
95100
)
96101

97102
# build collate_fn if specified

ppsci/utils/misc.py

+26
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,11 @@ class Timer(ContextDecorator):
210210
... w = sum(range(0, 10))
211211
>>> func() # doctest: +SKIP
212212
213+
>>> timer = misc.Timer("cost_of_func", auto_print=False)
214+
>>> timer.start()
215+
>>> func()
216+
>>> timer.end()
217+
>>> print(f"time cost of 'cost_of_func' is {timer.interval:.2f}")
213218
"""
214219

215220
interval: float # Time cost for code within Timer context
@@ -220,10 +225,31 @@ def __init__(self, name: str = "Timer", auto_print: bool = True):
220225
self.auto_print = auto_print
221226

222227
def __enter__(self):
228+
paddle.device.synchronize()
223229
self.start_time = time.perf_counter()
224230
return self
225231

226232
def __exit__(self, type, value, traceback):
233+
paddle.device.synchronize()
234+
self.end_time = time.perf_counter()
235+
self.interval = self.end_time - self.start_time
236+
if self.auto_print:
237+
logger.message(f"{self.name}.time_cost = {self.interval:.2f} s")
238+
239+
def start(self, name: str = "Timer"):
240+
"""Push a new timer context.
241+
242+
Args:
243+
name (str, optional): Name of code block to be clocked. Defaults to "Timer".
244+
"""
245+
paddle.device.synchronize()
246+
self.start_time = time.perf_counter()
247+
248+
def end(self):
249+
"""
250+
End current timer context and print time cost.
251+
"""
252+
paddle.device.synchronize()
227253
self.end_time = time.perf_counter()
228254
self.interval = self.end_time - self.start_time
229255
if self.auto_print:

ppsci/utils/save_load.py

+12-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,18 @@ def load_checkpoint(
146146
equation_dict = paddle.load(f"{path}.pdeqn")
147147

148148
# set state dict
149-
model.set_state_dict(param_dict)
149+
missing_keys, unexpected_keys = model.set_state_dict(param_dict)
150+
if missing_keys:
151+
logger.warning(
152+
f"There are missing keys when loading checkpoint: {missing_keys}, "
153+
"and corresponding parameters will be initialized by default."
154+
)
155+
if unexpected_keys:
156+
logger.warning(
157+
f"There are redundant keys: {unexpected_keys}, "
158+
"and corresponding weights will be ignored."
159+
)
160+
150161
optimizer.set_state_dict(optim_dict)
151162
if grad_scaler is not None:
152163
grad_scaler.load_state_dict(scaler_dict)

ppsci/utils/symbolic.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@
101101
sp.sign: paddle.sign,
102102
sp.ceiling: paddle.ceil,
103103
sp.floor: paddle.floor,
104-
# NOTE: sp.Add and sp.Mul is not included here for un-alignment with sympy
104+
# NOTE: sp.Add and sp.Mul is not included here for un-alignment with paddle
105105
# and are implemented manually in 'OperatorNode._add_operator_func' and
106106
# 'OperatorNode._mul_operator_func'
107107
}
@@ -711,15 +711,15 @@ def lambdify(
711711
such as 'momentum_x'. Defaults to None.
712712
create_graph (bool, optional): Whether to create the gradient graphs of
713713
the computing process. When it is True, higher order derivatives are
714-
supported to compute; when it is False, the gradient graphs of the
714+
supported to compute. When it is False, the gradient graphs of the
715715
computing process would be discarded. Defaults to True.
716716
retain_graph (Optional[bool]): Whether to retain the forward graph which
717717
is used to calculate the gradient. When it is True, the graph would
718718
be retained, in which way users can calculate backward twice for the
719719
same graph. When it is False, the graph would be freed. Defaults to None,
720720
which means it is equal to `create_graph`.
721721
fuse_derivative (bool, optional): Whether to fuse the derivative nodes.
722-
for example, if `expr` is 'Derivative(u, x) + Derivative(u, y)'
722+
For example, if `expr` is 'Derivative(u, x) + Derivative(u, y)'
723723
It will compute grad(u, x) + grad(u, y) if fuse_derivative=False,
724724
else will compute sum(grad(u, [x, y])) if fuse_derivative=True as is more
725725
efficient in backward-graph. Defaults to False, as it is experimental so not

0 commit comments

Comments
 (0)