diff --git a/docs/zh/examples/deephpms.md b/docs/zh/examples/deephpms.md index a39369673..9be5e6d77 100644 --- a/docs/zh/examples/deephpms.md +++ b/docs/zh/examples/deephpms.md @@ -2,6 +2,29 @@ AI Studio快速体验 +=== "模型训练命令" + + ``` sh + wget https://paddle-org.bj.bcebos.com/paddlescience/datasets/DeepHPMs/burgers_sine.mat -O ./datasets/DeepHPMs/burgers_sine.mat + wget https://paddle-org.bj.bcebos.com/paddlescience/datasets/DeepHPMs/burgers.mat -O ./datasets/DeepHPMs/burgers.mat + # windows + # curl https://paddle-org.bj.bcebos.com/paddlescience/datasets/DeepHPMs/burgers_sine.mat --output ./datasets/DeepHPMs/burgers_sine.mat + # curl https://paddle-org.bj.bcebos.com/paddlescience/datasets/DeepHPMs/burgers.mat --output ./datasets/DeepHPMs/burgers.mat + python burgers.py + ``` + +=== "模型评估命令" + + ``` sh + # linux + wget https://paddle-org.bj.bcebos.com/paddlescience/datasets/DeepHPMs/burgers_sine.mat -O ./datasets/DeepHPMs/burgers_sine.mat + wget https://paddle-org.bj.bcebos.com/paddlescience/datasets/DeepHPMs/burgers.mat -O ./datasets/DeepHPMs/burgers.mat + # windows + # curl https://paddle-org.bj.bcebos.com/paddlescience/datasets/DeepHPMs/burgers_sine.mat --output ./datasets/DeepHPMs/burgers_sine.mat + # curl https://paddle-org.bj.bcebos.com/paddlescience/datasets/DeepHPMs/burgers.mat --output ./datasets/DeepHPMs/burgers.mat + python burgers.py mode=eval EVAL.pretrained_model_path=https://paddle-org.bj.bcebos.com/paddlescience/models/DeepHPMs/burgers_pretrained.pdparams + ``` + ## 1. 背景简介 求解偏微分方程(PDE) 是一类基础的物理问题,在过去几十年里,以有限差分(FDM)、有限体积(FVM)、有限元(FEM)为代表的多种偏微分方程组数值解法趋于成熟。随着人工智能技术的高速发展,利用深度学习求解偏微分方程成为新的研究趋势。PINNs(Physics-informed neural networks) 是一种加入物理约束的深度学习网络,因此与纯数据驱动的神经网络学习相比,PINNs 可以用更少的数据样本学习到更具泛化能力的模型,其应用范围包括但不限于流体力学、热传导、电磁场、量子力学等领域。 @@ -39,9 +62,9 @@ $$ 运行本问题代码前请下载 [模拟数据集1](https://paddle-org.bj.bcebos.com/paddlescience/datasets/DeepHPMs/burgers_sine.mat) 和 [模拟数据集2](https://paddle-org.bj.bcebos.com/paddlescience/datasets/DeepHPMs/burgers.mat), 下载后分别存放在路径: -``` py linenums="55" +``` yaml linenums="26" --8<-- -examples/deephpms/burgers.py:55:56 +examples/deephpms/conf/burgers.yaml:26:27 --8<-- ``` @@ -57,9 +80,9 @@ Net1 通过数据驱动的方式,使用输入的某种模拟情况 1 下的少 因为训练中后一个阶段网络需要使用前一个阶段网络的前向推理值,因此本问题使用 Model List 来实现,上式中 $f_1,f_2,f_3$ 分别为一个 MLP 模型,三者共同构成了一个 Model List,用 PaddleScience 代码表示如下 -``` py linenums="68" +``` py linenums="99" --8<-- -examples/deephpms/burgers.py:68:71 +examples/deephpms/burgers.py:99:100 --8<-- ``` @@ -69,25 +92,25 @@ examples/deephpms/burgers.py:68:71 对于 Net1,输入为 $(x, t)$ 本来不需要 transform,但由于训练中根据数据的定义域对输入数据进行了数值变换,因此同样需要transform,同样,Net3 也需要对输入进行数值变换的 transform -``` py linenums="73" +``` py linenums="72" --8<-- -examples/deephpms/burgers.py:73:79 +examples/deephpms/burgers.py:72:77 --8<-- ``` 对于 Net2,因为它的输入为 $u, u_x, u_{xx}$ 而 $u$ 为其他两个网络的输出,只要进行 Net2 的前向推理,就需要 transform,因此需要两种 transform。同时,在训练 Net3 之前,需要重新注册 transform -``` py linenums="81" +``` py linenums="88" --8<-- -examples/deephpms/burgers.py:81:94 +examples/deephpms/burgers.py:88:92 --8<-- ``` 然后依次注册 transform 后,将3 个 MLP 模型组成 Model List -``` py linenums="96" +``` py linenums="100" --8<-- -examples/deephpms/burgers.py:96:102 +examples/deephpms/burgers.py:95:100 --8<-- ``` @@ -95,7 +118,7 @@ examples/deephpms/burgers.py:96:102 ``` py linenums="243" --8<-- -examples/deephpms/burgers.py:243:244 +examples/deephpms/burgers.py:236:237 --8<-- ``` @@ -105,17 +128,17 @@ examples/deephpms/burgers.py:243:244 我们需要指定问题相关的参数,如数据集路径、输出文件路径、定义域的值等 -``` py linenums="53" +``` yaml linenums="26" --8<-- -examples/deephpms/burgers.py:53:66 +examples/deephpms/conf/burgers.yaml:26:33 --8<-- ``` 同时需要指定训练轮数和学习率等超参数 -``` py linenums="104" +``` yaml linenums="57" --8<-- -examples/deephpms/burgers.py:104:107 +examples/deephpms/conf/burgers.yaml:57:61 --8<-- ``` @@ -123,9 +146,9 @@ examples/deephpms/burgers.py:104:107 本问题提供了两种优化器,分别为 Adam 优化器和 LBFGS 优化器,训练时只选择其中一种,需要将另一种优化器注释掉。 -``` py linenums="109" +``` py linenums="103" --8<-- -examples/deephpms/burgers.py:109:118 +examples/deephpms/burgers.py:103:111 --8<-- ``` @@ -135,9 +158,9 @@ examples/deephpms/burgers.py:109:118 无监督仍然可以采用监督约束 `SupervisedConstraint`,在定义约束之前,需要给监督约束指定文件路径等数据读取配置,因为数据集中没有标签数据,因此在数据读取时我们需要使用训练数据充当标签数据,并注意在之后不要使用这部分“假的”标签数据,例如 -``` py linenums="180" +``` py linenums="115" --8<-- -examples/deephpms/burgers.py:180:188 +examples/deephpms/burgers.py:115:123 --8<-- ``` @@ -147,9 +170,9 @@ examples/deephpms/burgers.py:180:188 第一阶段对 Net1 的训练是纯监督学习,此处采用监督约束 `SupervisedConstraint` -``` py linenums="121" +``` py linenums="125" --8<-- -examples/deephpms/burgers.py:121:138 +examples/deephpms/burgers.py:125:131 --8<-- ``` @@ -173,9 +196,9 @@ examples/deephpms/burgers.py:121:138 第二阶段对 Net2 的训练是无监督学习,但仍可采用监督约束 `SupervisedConstraint`,要注意上述提到的给定“假的”标签数据 -``` py linenums="179" +``` py linenums="144" --8<-- -examples/deephpms/burgers.py:179:199 +examples/deephpms/burgers.py:144:151 --8<-- ``` @@ -187,9 +210,9 @@ examples/deephpms/burgers.py:179:199 第三阶段 Net3 的训练复杂,包含了对部分初始点的监督学习、与 PDE 有关的无监督学习以及与边界条件有关的无监督学习,这里仍采用监督约束 `SupervisedConstraint`,同样要注意给定“假的”标签数据,各参数含义同上 -``` py linenums="246" +``` py linenums="183" --8<-- -examples/deephpms/burgers.py:246:303 +examples/deephpms/burgers.py:183:192 --8<-- ``` @@ -203,9 +226,9 @@ examples/deephpms/burgers.py:246:303 评价指标 `metric` 为 `L2` 正则化函数 -``` py linenums="140" +``` py linenums="205" --8<-- -examples/deephpms/burgers.py:140:158 +examples/deephpms/burgers.py:205:215 --8<-- ``` @@ -213,9 +236,9 @@ examples/deephpms/burgers.py:140:158 评价指标 `metric` 为 `FunctionalMetric`,这是 PaddleScience 预留的自定义 metric 函数类,该类支持编写代码时自定义 metric 的计算方法,而不是使用诸如 `MSE`、 `L2` 等现有方法。自定义 metric 函数代码请参考下一部分 [自定义 loss 和 metric](#38)。 -``` py linenums="201" +``` py linenums="268" --8<-- -examples/deephpms/burgers.py:201:222 +examples/deephpms/burgers.py:268:291 --8<-- ``` @@ -223,9 +246,9 @@ examples/deephpms/burgers.py:201:222 因为第三阶段评价时只需要对训练得到的点的值进行评价,而不需要对边界条件满足程度或 PDE 满足程度进行评价,因此评价指标 `metric` 为 `L2` 正则化函数 -``` py linenums="305" +``` py linenums="309" --8<-- -examples/deephpms/burgers.py:305:325 +examples/deephpms/burgers.py:309:318 --8<-- ``` @@ -237,25 +260,25 @@ examples/deephpms/burgers.py:305:325 与 PDE 相关的自定义 loss 函数为 -``` py linenums="25" +``` py linenums="28" --8<-- -examples/deephpms/burgers.py:25:27 +examples/deephpms/burgers.py:28:30 --8<-- ``` 与 PDE 相关的自定义 metric 函数为 -``` py linenums="30" +``` py linenums="33" --8<-- -examples/deephpms/burgers.py:30:35 +examples/deephpms/burgers.py:33:38 --8<-- ``` 与边界条件相关的自定义 loss 函数为 -``` py linenums="38" +``` py linenums="41" --8<-- -examples/deephpms/burgers.py:38:49 +examples/deephpms/burgers.py:41:52 --8<-- ``` @@ -265,25 +288,25 @@ examples/deephpms/burgers.py:38:49 第一阶段训练、评估 -``` py linenums="160" +``` py linenums="154" --8<-- -examples/deephpms/burgers.py:160:176 +examples/deephpms/burgers.py:154:169 --8<-- ``` 第二阶段训练、评估 -``` py linenums="224" +``` py linenums="218" --8<-- -examples/deephpms/burgers.py:224:240 +examples/deephpms/burgers.py:218:233 --8<-- ``` 第三阶段训练、评估 -``` py linenums="327" +``` py linenums="321" --8<-- -examples/deephpms/burgers.py:327:343 +examples/deephpms/burgers.py:321:336 --8<-- ``` diff --git a/examples/deephpms/burgers.py b/examples/deephpms/burgers.py index f1019be17..b062ffe77 100644 --- a/examples/deephpms/burgers.py +++ b/examples/deephpms/burgers.py @@ -12,13 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. +from os import path as osp + +import hydra import paddle import paddle.nn.functional as F +from omegaconf import DictConfig import ppsci from ppsci.autodiff import hessian from ppsci.autodiff import jacobian -from ppsci.utils import config from ppsci.utils import logger @@ -49,26 +52,21 @@ def boundary_loss_func(output_dict, *args): return losses -if __name__ == "__main__": - args = config.parse_args() - ppsci.utils.misc.set_random_seed(42) - DATASET_PATH = "./datasets/DeepHPMs/burgers_sine.mat" - DATASET_PATH_SOL = "./datasets/DeepHPMs/burgers.mat" - OUTPUT_DIR = "./output_burgers/" if args.output_dir is None else args.output_dir - +def train(cfg: DictConfig): + ppsci.utils.misc.set_random_seed(cfg.seed) # initialize logger - logger.init_logger("ppsci", f"{OUTPUT_DIR}/train.log", "info") + logger.init_logger("ppsci", osp.join(cfg.output_dir, f"{cfg.mode}.log"), "info") # initialize burgers boundaries - t_lb = paddle.to_tensor([0.0]) - t_ub = paddle.to_tensor([10.0]) - x_lb = paddle.to_tensor([-8.0]) - x_ub = paddle.to_tensor([8.0]) + t_lb = paddle.to_tensor(cfg.T_LB) + t_ub = paddle.to_tensor(cfg.T_UB) + x_lb = paddle.to_tensor(cfg.X_LB) + x_ub = paddle.to_tensor(cfg.T_UB) # initialize models - model_idn = ppsci.arch.MLP(("t", "x"), ("u_idn",), 4, 50, "sin") - model_pde = ppsci.arch.MLP(("u_x", "du_x", "du_xx"), ("f_pde",), 2, 100, "sin") - model_sol = ppsci.arch.MLP(("t", "x"), ("u_sol",), 4, 50, "sin") + model_idn = ppsci.arch.MLP(**cfg.MODEL.idn_net) + model_pde = ppsci.arch.MLP(**cfg.MODEL.pde_net) + model_sol = ppsci.arch.MLP(**cfg.MODEL.sol_net) # initialize transform def transform_u(_in): @@ -101,28 +99,23 @@ def transform_f_sol(_in): # initialize model list model_list = ppsci.arch.ModelList((model_idn, model_pde, model_sol)) - # set training hyper-parameters - ITERS_PER_EPOCH = 1 - EPOCHS = 50000 if args.epochs is None else args.epochs # set 1 for LBFGS - # MAX_ITER = 50000 # for LBFGS - # initialize optimizer # Adam - optimizer_idn = ppsci.optimizer.Adam(1e-3)(model_idn) - optimizer_pde = ppsci.optimizer.Adam(1e-3)(model_pde) - optimizer_sol = ppsci.optimizer.Adam(1e-3)(model_sol) + optimizer_idn = ppsci.optimizer.Adam(cfg.TRAIN.learning_rate)(model_idn) + optimizer_pde = ppsci.optimizer.Adam(cfg.TRAIN.learning_rate)(model_pde) + optimizer_sol = ppsci.optimizer.Adam(cfg.TRAIN.learning_rate)(model_sol) # LBFGS - # optimizer_idn = ppsci.optimizer.LBFGS(max_iter=MAX_ITER)((model_idn, )) - # optimizer_pde = ppsci.optimizer.LBFGS(max_iter=MAX_ITER)((model_pde, )) - # optimizer_sol = ppsci.optimizer.LBFGS(max_iter=MAX_ITER)((model_sol, )) + # optimizer_idn = ppsci.optimizer.LBFGS(max_iter=cfg.TRAIN.max_iter)((model_idn, )) + # optimizer_pde = ppsci.optimizer.LBFGS(max_iter=cfg.TRAIN.max_iter)((model_pde, )) + # optimizer_sol = ppsci.optimizer.LBFGS(max_iter=cfg.TRAIN.max_iter)((model_sol, )) # stage 1: training identification net # manually build constraint(s) train_dataloader_cfg_idn = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH, + "file_path": cfg.DATASET_PATH, "input_keys": ("t", "x"), "label_keys": ("u_idn",), "alias_dict": {"t": "t_train", "x": "x_train", "u_idn": "u_train"}, @@ -141,7 +134,7 @@ def transform_f_sol(_in): eval_dataloader_cfg_idn = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH, + "file_path": cfg.DATASET_PATH, "input_keys": ("t", "x"), "label_keys": ("u_idn",), "alias_dict": {"t": "t_star", "x": "x_star", "u_idn": "u_star"}, @@ -161,12 +154,12 @@ def transform_f_sol(_in): solver = ppsci.solver.Solver( model_list, constraint_idn, - OUTPUT_DIR, + cfg.output_dir, optimizer_idn, None, - EPOCHS, - ITERS_PER_EPOCH, - eval_during_train=False, + cfg.TRAIN.epochs, + cfg.TRAIN.iters_per_epoch, + eval_during_train=cfg.TRAIN.eval_during_train, validator=validator_idn, ) @@ -180,7 +173,7 @@ def transform_f_sol(_in): train_dataloader_cfg_pde = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH, + "file_path": cfg.DATASET_PATH, "input_keys": ("t", "x"), "label_keys": ("du_t",), "alias_dict": {"t": "t_train", "x": "x_train", "du_t": "t_train"}, @@ -202,7 +195,7 @@ def transform_f_sol(_in): eval_dataloader_cfg_pde = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH, + "file_path": cfg.DATASET_PATH, "input_keys": ("t", "x"), "label_keys": ("du_t",), "alias_dict": {"t": "t_star", "x": "x_star", "du_t": "t_star"}, @@ -225,12 +218,12 @@ def transform_f_sol(_in): solver = ppsci.solver.Solver( model_list, constraint_pde, - OUTPUT_DIR, + cfg.output_dir, optimizer_pde, None, - EPOCHS, - ITERS_PER_EPOCH, - eval_during_train=False, + cfg.TRAIN.epochs, + cfg.TRAIN.iters_per_epoch, + eval_during_train=cfg.TRAIN.eval_during_train, validator=validator_pde, ) @@ -247,7 +240,7 @@ def transform_f_sol(_in): train_dataloader_cfg_sol_f = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH_SOL, + "file_path": cfg.DATASET_PATH_SOL, "input_keys": ("t", "x"), "label_keys": ("du_t",), "alias_dict": {"t": "t_f_train", "x": "x_f_train", "du_t": "t_f_train"}, @@ -256,7 +249,7 @@ def transform_f_sol(_in): train_dataloader_cfg_sol_init = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH_SOL, + "file_path": cfg.DATASET_PATH_SOL, "input_keys": ("t", "x"), "label_keys": ("u_sol",), "alias_dict": {"t": "t0", "x": "x0", "u_sol": "u0"}, @@ -265,7 +258,7 @@ def transform_f_sol(_in): train_dataloader_cfg_sol_bc = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH_SOL, + "file_path": cfg.DATASET_PATH_SOL, "input_keys": ("t", "x"), "label_keys": ("x",), "alias_dict": {"t": "tb", "x": "xb"}, @@ -306,7 +299,7 @@ def transform_f_sol(_in): eval_dataloader_cfg_sol = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH_SOL, + "file_path": cfg.DATASET_PATH_SOL, "input_keys": ("t", "x"), "label_keys": ("u_sol",), "alias_dict": {"t": "t_star", "x": "x_star", "u_sol": "u_star"}, @@ -328,12 +321,12 @@ def transform_f_sol(_in): solver = ppsci.solver.Solver( model_list, constraint_sol, - OUTPUT_DIR, + cfg.output_dir, optimizer_sol, None, - EPOCHS, - ITERS_PER_EPOCH, - eval_during_train=False, + cfg.TRAIN.epochs, + cfg.TRAIN.iters_per_epoch, + eval_during_train=cfg.TRAIN.eval_during_train, validator=validator_sol, ) @@ -341,3 +334,21 @@ def transform_f_sol(_in): solver.train() # evaluate after finished training solver.eval() + + +def evaluate(cfg: DictConfig): + print("Not supported.") + + +@hydra.main(version_base=None, config_path="./conf", config_name="burgers.yaml") +def main(cfg: DictConfig): + if cfg.mode == "train": + train(cfg) + elif cfg.mode == "eval": + evaluate(cfg) + else: + raise ValueError(f"cfg.mode should in ['train', 'eval'], but got '{cfg.mode}'") + + +if __name__ == "__main__": + main() diff --git a/examples/deephpms/conf/burgers.yaml b/examples/deephpms/conf/burgers.yaml new file mode 100644 index 000000000..5df82a9fc --- /dev/null +++ b/examples/deephpms/conf/burgers.yaml @@ -0,0 +1,68 @@ +hydra: + run: + # dynamic output directory according to running time and override name + dir: outputs_burgers/${now:%Y-%m-%d}/${now:%H-%M-%S}/${hydra.job.override_dirname} + job: + name: ${mode} # name of logfile + chdir: false # keep current working direcotry unchaned + config: + override_dirname: + exclude_keys: + - TRAIN.checkpoint_path + - TRAIN.pretrained_model_path + - EVAL.pretrained_model_path + - mode + - output_dir + - log_freq + sweep: + # output directory for multirun + dir: ${hydra.run.dir} + subdir: ./ + +# general settings +mode: train # running mode: train/eval +seed: 42 +output_dir: ${hydra:run.dir} +DATASET_PATH: ./datasets/DeepHPMs/burgers_sine.mat +DATASET_PATH_SOL: ./datasets/DeepHPMs/burgers.mat + +# set working condition +T_LB: 0.0 +T_UB: 10.0 +X_LB: -8.0 +X_UB: 8.0 + +# model settings +MODEL: + idn_net: + input_keys: ["t", "x"] + output_keys: ["u_idn"] + num_layers: 4 + hidden_size: 50 + activation: "sin" + pde_net: + input_keys: ["u_x", "du_x", "du_xx"] + output_keys: ["f_pde"] + num_layers: 2 + hidden_size: 100 + activation: "sin" + sol_net: + input_keys: ["t", "x"] + output_keys: ["u_sol"] + num_layers: 4 + hidden_size: 50 + activation: "sin" + +# training settings +TRAIN: + epochs: 50000 + iters_per_epoch: 1 + max_iter: 50000 # for LBFGS + learning_rate: 1.0e-3 + eval_during_train: false + pretrained_model_path: null + checkpoint_path: null + +# evaluation settings +EVAL: + pretrained_model_path: null diff --git a/examples/deephpms/conf/korteweg_de_vries.yaml b/examples/deephpms/conf/korteweg_de_vries.yaml new file mode 100644 index 000000000..82119a5cd --- /dev/null +++ b/examples/deephpms/conf/korteweg_de_vries.yaml @@ -0,0 +1,68 @@ +hydra: + run: + # dynamic output directory according to running time and override name + dir: outputs_korteweg_de_vries/${now:%Y-%m-%d}/${now:%H-%M-%S}/${hydra.job.override_dirname} + job: + name: ${mode} # name of logfile + chdir: false # keep current working direcotry unchaned + config: + override_dirname: + exclude_keys: + - TRAIN.checkpoint_path + - TRAIN.pretrained_model_path + - EVAL.pretrained_model_path + - mode + - output_dir + - log_freq + sweep: + # output directory for multirun + dir: ${hydra.run.dir} + subdir: ./ + +# general settings +mode: train # running mode: train/eval +seed: 42 +output_dir: ${hydra:run.dir} +DATASET_PATH: ./datasets/DeepHPMs/KdV_sine.mat +DATASET_PATH_SOL: ./datasets/DeepHPMs/KdV_cos.mat + +# set working condition +T_LB: 0.0 +T_UB: 40.0 +X_LB: -20.0 +X_UB: 20.0 + +# model settings +MODEL: + idn_net: + input_keys: ["t", "x"] + output_keys: ["u_idn"] + num_layers: 4 + hidden_size: 50 + activation: "sin" + pde_net: + input_keys: ["u_x", "du_x", "du_xx", "du_xxx"] + output_keys: ["f_pde"] + num_layers: 2 + hidden_size: 100 + activation: "sin" + sol_net: + input_keys: ["t", "x"] + output_keys: ["u_sol"] + num_layers: 4 + hidden_size: 50 + activation: "sin" + +# training settings +TRAIN: + epochs: 50000 + iters_per_epoch: 1 + max_iter: 50000 # for LBFGS + learning_rate: 1.0e-3 + eval_during_train: false + pretrained_model_path: null + checkpoint_path: null + +# evaluation settings +EVAL: + pretrained_model_path: null diff --git a/examples/deephpms/conf/kuramoto_sivashinsky.yaml b/examples/deephpms/conf/kuramoto_sivashinsky.yaml new file mode 100644 index 000000000..a720d60c2 --- /dev/null +++ b/examples/deephpms/conf/kuramoto_sivashinsky.yaml @@ -0,0 +1,62 @@ +hydra: + run: + # dynamic output directory according to running time and override name + dir: outputs_kuramoto_sivashinsky/${now:%Y-%m-%d}/${now:%H-%M-%S}/${hydra.job.override_dirname} + job: + name: ${mode} # name of logfile + chdir: false # keep current working direcotry unchaned + config: + override_dirname: + exclude_keys: + - TRAIN.checkpoint_path + - TRAIN.pretrained_model_path + - EVAL.pretrained_model_path + - mode + - output_dir + - log_freq + sweep: + # output directory for multirun + dir: ${hydra.run.dir} + subdir: ./ + +# general settings +mode: train # running mode: train/eval +seed: 42 +output_dir: ${hydra:run.dir} +DATASET_PATH: ./datasets/DeepHPMs/KS.mat +DATASET_PATH_SOL: ./datasets/DeepHPMs/KS.mat + +# set working condition +T_LB: 0.0 +T_UB: 50.0 +X_LB: -10.0 +X_UB: 10.0 + +# model settings +MODEL: + idn_net: + input_keys: ["t", "x"] + output_keys: ["u_idn"] + num_layers: 4 + hidden_size: 50 + activation: "sin" + pde_net: + input_keys: ["u_x", "du_x", "du_xx", "du_xxx", "du_xxxx"] + output_keys: ["f_pde"] + num_layers: 2 + hidden_size: 100 + activation: "sin" + +# training settings +TRAIN: + epochs: 50000 + iters_per_epoch: 1 + max_iter: 50000 # for LBFGS + learning_rate: 1.0e-4 + eval_during_train: false + pretrained_model_path: null + checkpoint_path: null + +# evaluation settings +EVAL: + pretrained_model_path: null diff --git a/examples/deephpms/conf/navier_stokes.yaml b/examples/deephpms/conf/navier_stokes.yaml new file mode 100644 index 000000000..bcd67d62d --- /dev/null +++ b/examples/deephpms/conf/navier_stokes.yaml @@ -0,0 +1,62 @@ +hydra: + run: + # dynamic output directory according to running time and override name + dir: outputs_navier_stokes/${now:%Y-%m-%d}/${now:%H-%M-%S}/${hydra.job.override_dirname} + job: + name: ${mode} # name of logfile + chdir: false # keep current working direcotry unchaned + config: + override_dirname: + exclude_keys: + - TRAIN.checkpoint_path + - TRAIN.pretrained_model_path + - EVAL.pretrained_model_path + - mode + - output_dir + - log_freq + sweep: + # output directory for multirun + dir: ${hydra.run.dir} + subdir: ./ + +# general settings +mode: train # running mode: train/eval +seed: 42 +output_dir: ${hydra:run.dir} +DATASET_PATH: ./datasets/DeepHPMs/cylinder.mat +DATASET_PATH_SOL: ./datasets/DeepHPMs/cylinder.mat + +# set working condition +LB: [0.0, 1, -1.7] +UB: [30.0, 7.5, 1.7] + +# model settings +MODEL: + idn_net: + input_keys: ["t", "x", "y"] + output_keys: ["w_idn"] + num_layers: 4 + hidden_size: 200 + activation: "sin" + pde_net: + input_keys: ["u", "v", "w", "dw_x", "dw_y", "dw_xx", "dw_xy", "dw_yy"] + output_keys: ["f_pde"] + num_layers: 2 + hidden_size: 100 + activation: "sin" + +# training settings +TRAIN: + epochs: 50000 + iters_per_epoch: 1 + max_iter: 50000 # for LBFGS + learning_rate: 1.0e-4 + batch_size: + eval: 10000 + eval_during_train: false + pretrained_model_path: null + checkpoint_path: null + +# evaluation settings +EVAL: + pretrained_model_path: null diff --git a/examples/deephpms/conf/schrodinger.yaml b/examples/deephpms/conf/schrodinger.yaml new file mode 100644 index 000000000..aa5567600 --- /dev/null +++ b/examples/deephpms/conf/schrodinger.yaml @@ -0,0 +1,76 @@ +hydra: + run: + # dynamic output directory according to running time and override name + dir: outputs_schrodinger/${now:%Y-%m-%d}/${now:%H-%M-%S}/${hydra.job.override_dirname} + job: + name: ${mode} # name of logfile + chdir: false # keep current working direcotry unchaned + config: + override_dirname: + exclude_keys: + - TRAIN.checkpoint_path + - TRAIN.pretrained_model_path + - EVAL.pretrained_model_path + - mode + - output_dir + - log_freq + sweep: + # output directory for multirun + dir: ${hydra.run.dir} + subdir: ./ + +# general settings +mode: train # running mode: train/eval +seed: 42 +output_dir: ${hydra:run.dir} +DATASET_PATH: ./datasets/DeepHPMs/NLS.mat +DATASET_PATH_SOL: ./datasets/DeepHPMs/NLS.mat + +# set working condition +T_LB: 0.0 +T_UB: 2.0 +X_LB: -5.0 +X_UB: 5.0 + +# model settings +MODEL: + idn_u_net: + input_keys: ["t", "x"] + output_keys: ["u_idn"] + num_layers: 4 + hidden_size: 50 + activation: "sin" + idn_v_net: + input_keys: ["t", "x"] + output_keys: ["v_idn"] + num_layers: 4 + hidden_size: 50 + activation: "sin" + pde_f_net: + input_keys: ["u", "v", "du_x", "dv_x", "du_xx", "dv_xx"] + output_keys: ["f_pde"] + num_layers: 2 + hidden_size: 100 + activation: "sin" + pde_g_net: + input_keys: ["u", "v", "du_x", "dv_x", "du_xx", "dv_xx"] + output_keys: ["g_pde"] + num_layers: 2 + hidden_size: 100 + activation: "sin" + +# training settings +TRAIN: + epochs: 50000 + iters_per_epoch: 1 + max_iter: 50000 # for LBFGS + learning_rate: 1.0e-4 + batch_size: + eval: 10000 + eval_during_train: false + pretrained_model_path: null + checkpoint_path: null + +# evaluation settings +EVAL: + pretrained_model_path: null diff --git a/examples/deephpms/korteweg_de_vries.py b/examples/deephpms/korteweg_de_vries.py index 9c24b9281..a9f96a21a 100644 --- a/examples/deephpms/korteweg_de_vries.py +++ b/examples/deephpms/korteweg_de_vries.py @@ -12,13 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. +from os import path as osp + +import hydra import paddle import paddle.nn.functional as F +from omegaconf import DictConfig import ppsci from ppsci.autodiff import hessian from ppsci.autodiff import jacobian -from ppsci.utils import config from ppsci.utils import logger @@ -52,31 +55,24 @@ def boundary_loss_func(output_dict, *args): return losses -if __name__ == "__main__": +def train(cfg: DictConfig): # open FLAG for higher order differential operator when order >= 4 paddle.framework.core.set_prim_eager_enabled(True) - args = config.parse_args() ppsci.utils.misc.set_random_seed(42) - DATASET_PATH = "./datasets/DeepHPMs/KdV_sine.mat" - DATASET_PATH_SOL = "./datasets/DeepHPMs/KdV_cos.mat" - OUTPUT_DIR = "./output_kdv/" if args.output_dir is None else args.output_dir - # initialize logger - logger.init_logger("ppsci", f"{OUTPUT_DIR}/train.log", "info") + logger.init_logger("ppsci", osp.join(cfg.output_dir, f"{cfg.mode}.log"), "info") - # initialize burgers boundaries - t_lb = paddle.to_tensor([0.0]) - t_ub = paddle.to_tensor([40.0]) - x_lb = paddle.to_tensor([-20.0]) - x_ub = paddle.to_tensor([20.0]) + # initialize boundaries + t_lb = paddle.to_tensor(cfg.T_LB) + t_ub = paddle.to_tensor(cfg.T_UB) + x_lb = paddle.to_tensor(cfg.X_LB) + x_ub = paddle.to_tensor(cfg.T_UB) # initialize models - model_idn = ppsci.arch.MLP(("t", "x"), ("u_idn",), 4, 50, "sin") - model_pde = ppsci.arch.MLP( - ("u_x", "du_x", "du_xx", "du_xxx"), ("f_pde",), 2, 100, "sin" - ) - model_sol = ppsci.arch.MLP(("t", "x"), ("u_sol",), 4, 50, "sin") + model_idn = ppsci.arch.MLP(**cfg.MODEL.idn_net) + model_pde = ppsci.arch.MLP(**cfg.MODEL.pde_net) + model_sol = ppsci.arch.MLP(**cfg.MODEL.sol_net) # initialize transform def transform_u(_in): @@ -110,28 +106,23 @@ def transform_f_sol(_in): # initialize model list model_list = ppsci.arch.ModelList((model_idn, model_pde, model_sol)) - # set training hyper-parameters - ITERS_PER_EPOCH = 1 - EPOCHS = 50000 if args.epochs is None else args.epochs # set 1 for LBFGS - # MAX_ITER = 50000 # for LBFGS - # initialize optimizer # Adam - optimizer_idn = ppsci.optimizer.Adam(1e-3)(model_idn) - optimizer_pde = ppsci.optimizer.Adam(1e-3)(model_pde) - optimizer_sol = ppsci.optimizer.Adam(1e-3)(model_sol) + optimizer_idn = ppsci.optimizer.Adam(cfg.TRAIN.learning_rate)(model_idn) + optimizer_pde = ppsci.optimizer.Adam(cfg.TRAIN.learning_rate)(model_pde) + optimizer_sol = ppsci.optimizer.Adam(cfg.TRAIN.learning_rate)(model_sol) # LBFGS - # optimizer_idn = ppsci.optimizer.LBFGS(max_iter=MAX_ITER)((model_idn, )) - # optimizer_pde = ppsci.optimizer.LBFGS(max_iter=MAX_ITER)((model_pde, )) - # optimizer_sol = ppsci.optimizer.LBFGS(max_iter=MAX_ITER)((model_sol, )) + # optimizer_idn = ppsci.optimizer.LBFGS(max_iter=cfg.TRAIN.max_iter)((model_idn, )) + # optimizer_pde = ppsci.optimizer.LBFGS(max_iter=cfg.TRAIN.max_iter)((model_pde, )) + # optimizer_sol = ppsci.optimizer.LBFGS(max_iter=cfg.TRAIN.max_iter)((model_sol, )) # stage 1: training identification net # manually build constraint(s) train_dataloader_cfg_idn = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH, + "file_path": cfg.DATASET_PATH, "input_keys": ("t", "x"), "label_keys": ("u_idn",), "alias_dict": {"t": "t_train", "x": "x_train", "u_idn": "u_train"}, @@ -150,7 +141,7 @@ def transform_f_sol(_in): eval_dataloader_cfg_idn = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH, + "file_path": cfg.DATASET_PATH, "input_keys": ("t", "x"), "label_keys": ("u_idn",), "alias_dict": {"t": "t_star", "x": "x_star", "u_idn": "u_star"}, @@ -170,12 +161,12 @@ def transform_f_sol(_in): solver = ppsci.solver.Solver( model_list, constraint_idn, - OUTPUT_DIR, + cfg.output_dir, optimizer_idn, None, - EPOCHS, - ITERS_PER_EPOCH, - eval_during_train=False, + cfg.TRAIN.epochs, + cfg.TRAIN.iters_per_epoch, + eval_during_train=cfg.TRAIN.eval_during_train, validator=validator_idn, ) @@ -189,7 +180,7 @@ def transform_f_sol(_in): train_dataloader_cfg_pde = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH, + "file_path": cfg.DATASET_PATH, "input_keys": ("t", "x"), "label_keys": ("du_t",), "alias_dict": {"t": "t_train", "x": "x_train", "du_t": "t_train"}, @@ -211,7 +202,7 @@ def transform_f_sol(_in): eval_dataloader_cfg_pde = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH, + "file_path": cfg.DATASET_PATH, "input_keys": ("t", "x"), "label_keys": ("du_t",), "alias_dict": {"t": "t_star", "x": "x_star", "du_t": "t_star"}, @@ -234,12 +225,12 @@ def transform_f_sol(_in): solver = ppsci.solver.Solver( model_list, constraint_pde, - OUTPUT_DIR, + cfg.output_dir, optimizer_pde, None, - EPOCHS, - ITERS_PER_EPOCH, - eval_during_train=False, + cfg.TRAIN.epochs, + cfg.TRAIN.iters_per_epoch, + eval_during_train=cfg.TRAIN.eval_during_train, validator=validator_pde, ) @@ -256,7 +247,7 @@ def transform_f_sol(_in): train_dataloader_cfg_sol_f = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH_SOL, + "file_path": cfg.DATASET_PATH_SOL, "input_keys": ("t", "x"), "label_keys": ("du_t",), "alias_dict": {"t": "t_f_train", "x": "x_f_train", "du_t": "t_f_train"}, @@ -265,7 +256,7 @@ def transform_f_sol(_in): train_dataloader_cfg_sol_init = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH_SOL, + "file_path": cfg.DATASET_PATH_SOL, "input_keys": ("t", "x"), "label_keys": ("u_sol",), "alias_dict": {"t": "t0", "x": "x0", "u_sol": "u0"}, @@ -274,7 +265,7 @@ def transform_f_sol(_in): train_dataloader_cfg_sol_bc = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH_SOL, + "file_path": cfg.DATASET_PATH_SOL, "input_keys": ("t", "x"), "label_keys": ("x",), "alias_dict": {"t": "tb", "x": "xb"}, @@ -315,7 +306,7 @@ def transform_f_sol(_in): eval_dataloader_cfg_sol = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH_SOL, + "file_path": cfg.DATASET_PATH_SOL, "input_keys": ("t", "x"), "label_keys": ("u_sol",), "alias_dict": {"t": "t_star", "x": "x_star", "u_sol": "u_star"}, @@ -337,12 +328,12 @@ def transform_f_sol(_in): solver = ppsci.solver.Solver( model_list, constraint_sol, - OUTPUT_DIR, + cfg.output_dir, optimizer_sol, None, - EPOCHS, - ITERS_PER_EPOCH, - eval_during_train=False, + cfg.TRAIN.epochs, + cfg.TRAIN.iters_per_epoch, + eval_during_train=cfg.TRAIN.eval_during_train, validator=validator_sol, ) @@ -350,3 +341,23 @@ def transform_f_sol(_in): solver.train() # evaluate after finished training solver.eval() + + +def evaluate(cfg: DictConfig): + print("Not supported.") + + +@hydra.main( + version_base=None, config_path="./conf", config_name="korteweg_de_vries.yaml" +) +def main(cfg: DictConfig): + if cfg.mode == "train": + train(cfg) + elif cfg.mode == "eval": + evaluate(cfg) + else: + raise ValueError(f"cfg.mode should in ['train', 'eval'], but got '{cfg.mode}'") + + +if __name__ == "__main__": + main() diff --git a/examples/deephpms/kuramoto_sivashinsky.py b/examples/deephpms/kuramoto_sivashinsky.py index e21cc2235..9b6ca9f10 100644 --- a/examples/deephpms/kuramoto_sivashinsky.py +++ b/examples/deephpms/kuramoto_sivashinsky.py @@ -12,13 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. +from os import path as osp + +import hydra import paddle import paddle.nn.functional as F +from omegaconf import DictConfig import ppsci from ppsci.autodiff import hessian from ppsci.autodiff import jacobian -from ppsci.utils import config from ppsci.utils import logger @@ -55,24 +58,19 @@ def boundary_loss_func(output_dict, *args): return losses -if __name__ == "__main__": +def train(cfg: DictConfig): # open FLAG for higher order differential operator when order >= 4 paddle.framework.core.set_prim_eager_enabled(True) - args = config.parse_args() - ppsci.utils.misc.set_random_seed(42) - DATASET_PATH = "./datasets/DeepHPMs/KS.mat" - DATASET_PATH_SOL = "./datasets/DeepHPMs/KS.mat" - OUTPUT_DIR = "./output_ks/" if args.output_dir is None else args.output_dir - + ppsci.utils.misc.set_random_seed(cfg.seed) # initialize logger - logger.init_logger("ppsci", f"{OUTPUT_DIR}/train.log", "info") + logger.init_logger("ppsci", osp.join(cfg.output_dir, f"{cfg.mode}.log"), "info") - # initialize burgers boundaries - t_lb = paddle.to_tensor([0.0]) - t_ub = paddle.to_tensor([50.0]) - x_lb = paddle.to_tensor([-10.0]) - x_ub = paddle.to_tensor([10.0]) + # initialize boundaries + t_lb = paddle.to_tensor(cfg.T_LB) + t_ub = paddle.to_tensor(cfg.T_UB) + x_lb = paddle.to_tensor(cfg.X_LB) + x_ub = paddle.to_tensor(cfg.T_UB) # boundaries of KS_chaotic.mat # t_lb = paddle.to_tensor([0.0]) @@ -81,14 +79,8 @@ def boundary_loss_func(output_dict, *args): # x_ub = paddle.to_tensor([32.0 * np.pi]) # initialize models - model_idn = ppsci.arch.MLP(("t", "x"), ("u_idn",), 4, 50, "sin") - model_pde = ppsci.arch.MLP( - ("u_x", "du_x", "du_xx", "du_xxx", "du_xxxx"), - ("f_pde",), - 2, - 100, - "sin", - ) + model_idn = ppsci.arch.MLP(**cfg.MODEL.idn_net) + model_pde = ppsci.arch.MLP(**cfg.MODEL.pde_net) # initialize transform def transform_u(_in): @@ -125,26 +117,21 @@ def transform_f_idn(_in): # initialize model list model_list = ppsci.arch.ModelList((model_idn, model_pde)) - # set training hyper-parameters - ITERS_PER_EPOCH = 1 - EPOCHS = 50000 if args.epochs is None else args.epochs # set 1 for LBFGS - # MAX_ITER = 50000 # for LBFGS - # initialize optimizer # Adam - optimizer_idn = ppsci.optimizer.Adam(1e-4)(model_idn) - optimizer_pde = ppsci.optimizer.Adam(1e-4)(model_pde) + optimizer_idn = ppsci.optimizer.Adam(cfg.TRAIN.learning_rate)(model_idn) + optimizer_pde = ppsci.optimizer.Adam(cfg.TRAIN.learning_rate)(model_pde) # LBFGS - # optimizer_idn = ppsci.optimizer.LBFGS(max_iter=MAX_ITER)((model_idn, )) - # optimizer_pde = ppsci.optimizer.LBFGS(max_iter=MAX_ITER)((model_pde, )) + # optimizer_idn = ppsci.optimizer.LBFGS(max_iter=cfg.TRAIN.max_iter)((model_idn, )) + # optimizer_pde = ppsci.optimizer.LBFGS(max_iter=cfg.TRAIN.max_iter)((model_pde, )) # stage 1: training identification net # manually build constraint(s) train_dataloader_cfg_idn = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH, + "file_path": cfg.DATASET_PATH, "input_keys": ("t", "x"), "label_keys": ("u_idn",), "alias_dict": {"t": "t_train", "x": "x_train", "u_idn": "u_train"}, @@ -163,7 +150,7 @@ def transform_f_idn(_in): eval_dataloader_cfg_idn = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH, + "file_path": cfg.DATASET_PATH, "input_keys": ("t", "x"), "label_keys": ("u_idn",), "alias_dict": {"t": "t_star", "x": "x_star", "u_idn": "u_star"}, @@ -183,12 +170,12 @@ def transform_f_idn(_in): solver = ppsci.solver.Solver( model_list, constraint_idn, - OUTPUT_DIR, + cfg.output_dir, optimizer_idn, None, - EPOCHS, - ITERS_PER_EPOCH, - eval_during_train=False, + cfg.TRAIN.epochs, + cfg.TRAIN.iters_per_epoch, + eval_during_train=cfg.TRAIN.eval_during_train, validator=validator_idn, ) @@ -202,7 +189,7 @@ def transform_f_idn(_in): train_dataloader_cfg_pde = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH, + "file_path": cfg.DATASET_PATH, "input_keys": ("t", "x"), "label_keys": ("du_t",), "alias_dict": {"t": "t_train", "x": "x_train", "du_t": "t_train"}, @@ -224,7 +211,7 @@ def transform_f_idn(_in): eval_dataloader_cfg_pde = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH, + "file_path": cfg.DATASET_PATH, "input_keys": ("t", "x"), "label_keys": ("du_t",), "alias_dict": {"t": "t_star", "x": "x_star", "du_t": "t_star"}, @@ -247,12 +234,12 @@ def transform_f_idn(_in): solver = ppsci.solver.Solver( model_list, constraint_pde, - OUTPUT_DIR, + cfg.output_dir, optimizer_pde, None, - EPOCHS, - ITERS_PER_EPOCH, - eval_during_train=False, + cfg.TRAIN.epochs, + cfg.TRAIN.iters_per_epoch, + eval_during_train=cfg.TRAIN.eval_during_train, validator=validator_pde, ) @@ -266,7 +253,7 @@ def transform_f_idn(_in): train_dataloader_cfg_sol_f = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH_SOL, + "file_path": cfg.DATASET_PATH_SOL, "input_keys": ("t", "x"), "label_keys": ("du_t",), "alias_dict": {"t": "t_f_train", "x": "x_f_train", "du_t": "t_f_train"}, @@ -275,7 +262,7 @@ def transform_f_idn(_in): train_dataloader_cfg_sol_init = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH_SOL, + "file_path": cfg.DATASET_PATH_SOL, "input_keys": ("t", "x"), "label_keys": ("u0_sol",), "alias_dict": {"t": "t0", "x": "x0", "u0_sol": "u0"}, @@ -284,7 +271,7 @@ def transform_f_idn(_in): train_dataloader_cfg_sol_bc = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH_SOL, + "file_path": cfg.DATASET_PATH_SOL, "input_keys": ("t", "x"), "label_keys": ("x",), "alias_dict": {"t": "tb", "x": "xb"}, @@ -325,7 +312,7 @@ def transform_f_idn(_in): eval_dataloader_cfg_sol = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH_SOL, + "file_path": cfg.DATASET_PATH_SOL, "input_keys": ("t", "x"), "label_keys": ("u_sol",), "alias_dict": {"t": "t_star", "x": "x_star", "u_sol": "u_star"}, @@ -347,12 +334,12 @@ def transform_f_idn(_in): solver = ppsci.solver.Solver( model_list, constraint_sol, - OUTPUT_DIR, + cfg.output_dir, optimizer_idn, None, - EPOCHS, - ITERS_PER_EPOCH, - eval_during_train=False, + cfg.TRAIN.epochs, + cfg.TRAIN.iters_per_epoch, + eval_during_train=cfg.TRAIN.eval_during_train, validator=validator_sol, ) @@ -360,3 +347,23 @@ def transform_f_idn(_in): solver.train() # evaluate after finished training solver.eval() + + +def evaluate(cfg: DictConfig): + print("Not supported.") + + +@hydra.main( + version_base=None, config_path="./conf", config_name="kuramoto_sivashinsky.yaml" +) +def main(cfg: DictConfig): + if cfg.mode == "train": + train(cfg) + elif cfg.mode == "eval": + evaluate(cfg) + else: + raise ValueError(f"cfg.mode should in ['train', 'eval'], but got '{cfg.mode}'") + + +if __name__ == "__main__": + main() diff --git a/examples/deephpms/navier_stokes.py b/examples/deephpms/navier_stokes.py index e69cc2833..b9e7139c3 100644 --- a/examples/deephpms/navier_stokes.py +++ b/examples/deephpms/navier_stokes.py @@ -12,13 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. +from os import path as osp + +import hydra import paddle import paddle.nn.functional as F +from omegaconf import DictConfig import ppsci from ppsci.autodiff import hessian from ppsci.autodiff import jacobian -from ppsci.utils import config from ppsci.utils import logger @@ -35,30 +38,19 @@ def pde_l2_rel_func(output_dict, *args): return metric_dict -if __name__ == "__main__": - args = config.parse_args() - ppsci.utils.misc.set_random_seed(42) - DATASET_PATH = "./datasets/DeepHPMs/cylinder.mat" - DATASET_PATH_SOL = "./datasets/DeepHPMs/cylinder.mat" - OUTPUT_DIR = "./output_ns/" if args.output_dir is None else args.output_dir - +def train(cfg: DictConfig): + ppsci.utils.misc.set_random_seed(cfg.seed) # initialize logger - logger.init_logger("ppsci", f"{OUTPUT_DIR}/train.log", "info") + logger.init_logger("ppsci", osp.join(cfg.output_dir, f"{cfg.mode}.log"), "info") - # initialize burgers boundaries + # initialize boundaries # t, x, y - lb = paddle.to_tensor([0.0, 1, -1.7]) - ub = paddle.to_tensor([30.0, 7.5, 1.7]) + lb = paddle.to_tensor(list(cfg.LB)) + ub = paddle.to_tensor(list(cfg.UB)) # initialize models - model_idn = ppsci.arch.MLP(("t", "x", "y"), ("w_idn",), 4, 200, "sin") - model_pde = ppsci.arch.MLP( - ("u", "v", "w", "dw_x", "dw_y", "dw_xx", "dw_xy", "dw_yy"), - ("f_pde",), - 2, - 100, - "sin", - ) + model_idn = ppsci.arch.MLP(**cfg.MODEL.idn_net) + model_pde = ppsci.arch.MLP(**cfg.MODEL.pde_net) # initialize transform def transform_w(_in): @@ -99,27 +91,21 @@ def transform_f(_in): # initialize model list model_list = ppsci.arch.ModelList((model_idn, model_pde)) - # set training hyper-parameters - ITERS_PER_EPOCH = 1 - EPOCHS = 50000 if args.epochs is None else args.epochs # set 1 for LBFGS - # MAX_ITER = 50000 # for LBFGS - EVAL_BATCH_SIZE = 10000 - # initialize optimizer # Adam - optimizer_idn = ppsci.optimizer.Adam(1e-4)(model_idn) - optimizer_pde = ppsci.optimizer.Adam(1e-4)(model_pde) + optimizer_idn = ppsci.optimizer.Adam(cfg.TRAIN.learning_rate)(model_idn) + optimizer_pde = ppsci.optimizer.Adam(cfg.TRAIN.learning_rate)(model_pde) # LBFGS - # optimizer_idn = ppsci.optimizer.LBFGS(max_iter=MAX_ITER)((model_idn,)) - # optimizer_pde = ppsci.optimizer.LBFGS(max_iter=MAX_ITER)((model_pde,)) + # optimizer_idn = ppsci.optimizer.LBFGS(max_iter=cfg.TRAIN.max_iter)((model_idn, )) + # optimizer_pde = ppsci.optimizer.LBFGS(max_iter=cfg.TRAIN.max_iter)((model_pde, )) # stage 1: training identification net # manually build constraint(s) train_dataloader_cfg_idn = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH, + "file_path": cfg.DATASET_PATH, "input_keys": ("t", "x", "y", "u", "v"), "label_keys": ("w_idn",), "alias_dict": { @@ -145,7 +131,7 @@ def transform_f(_in): eval_dataloader_cfg_idn = { "dataset": { "name": "MatDataset", - "file_path": DATASET_PATH, + "file_path": cfg.DATASET_PATH, "input_keys": ("t", "x", "y", "u", "v"), "label_keys": ("w_idn",), "alias_dict": { @@ -157,7 +143,7 @@ def transform_f(_in): "w_idn": "w_star", }, }, - "batch_size": EVAL_BATCH_SIZE, + "batch_size": cfg.TRAIN.batch_size.eval, "sampler": { "name": "BatchSampler", "drop_last": False, @@ -178,12 +164,12 @@ def transform_f(_in): solver = ppsci.solver.Solver( model_list, constraint_idn, - OUTPUT_DIR, + cfg.output_dir, optimizer_idn, None, - EPOCHS, - ITERS_PER_EPOCH, - eval_during_train=False, + cfg.TRAIN.epochs, + cfg.TRAIN.iters_per_epoch, + eval_during_train=cfg.TRAIN.eval_during_train, validator=validator_idn, ) @@ -197,7 +183,7 @@ def transform_f(_in): train_dataloader_cfg_pde = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH, + "file_path": cfg.DATASET_PATH, "input_keys": ("t", "x", "y", "u", "v"), "label_keys": ("dw_t",), "alias_dict": { @@ -226,7 +212,7 @@ def transform_f(_in): eval_dataloader_cfg_pde = { "dataset": { "name": "MatDataset", - "file_path": DATASET_PATH, + "file_path": cfg.DATASET_PATH, "input_keys": ("t", "x", "y", "u", "v"), "label_keys": ("dw_t",), "alias_dict": { @@ -238,7 +224,7 @@ def transform_f(_in): "dw_t": "t_star", }, }, - "batch_size": EVAL_BATCH_SIZE, + "batch_size": cfg.TRAIN.batch_size.eval, "sampler": { "name": "BatchSampler", "drop_last": False, @@ -262,12 +248,12 @@ def transform_f(_in): solver = ppsci.solver.Solver( model_list, constraint_pde, - OUTPUT_DIR, + cfg.output_dir, optimizer_pde, None, - EPOCHS, - ITERS_PER_EPOCH, - eval_during_train=False, + cfg.TRAIN.epochs, + cfg.TRAIN.iters_per_epoch, + eval_during_train=cfg.TRAIN.eval_during_train, validator=validator_pde, ) @@ -281,7 +267,7 @@ def transform_f(_in): train_dataloader_cfg_sol_f = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH_SOL, + "file_path": cfg.DATASET_PATH_SOL, "input_keys": ("t", "x", "y", "u", "v"), "label_keys": ("dw_t",), "alias_dict": { @@ -297,7 +283,7 @@ def transform_f(_in): train_dataloader_cfg_sol_bc = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH_SOL, + "file_path": cfg.DATASET_PATH_SOL, "input_keys": ("t", "x", "y", "u", "v"), "label_keys": ("wb_sol",), "alias_dict": { @@ -335,7 +321,7 @@ def transform_f(_in): eval_dataloader_cfg_sol = { "dataset": { "name": "MatDataset", - "file_path": DATASET_PATH_SOL, + "file_path": cfg.DATASET_PATH_SOL, "input_keys": ("t", "x", "y", "u", "v"), "label_keys": ("w_sol",), "alias_dict": { @@ -347,7 +333,7 @@ def transform_f(_in): "v": "v_star", }, }, - "batch_size": EVAL_BATCH_SIZE, + "batch_size": cfg.TRAIN.batch_size.eval, "sampler": { "name": "BatchSampler", "drop_last": False, @@ -370,12 +356,12 @@ def transform_f(_in): solver = ppsci.solver.Solver( model_list, constraint_sol, - OUTPUT_DIR, + cfg.output_dir, optimizer_idn, None, - EPOCHS, - ITERS_PER_EPOCH, - eval_during_train=False, + cfg.TRAIN.epochs, + cfg.TRAIN.iters_per_epoch, + eval_during_train=cfg.TRAIN.eval_during_train, validator=validator_sol, ) @@ -383,3 +369,21 @@ def transform_f(_in): solver.train() # evaluate after finished training solver.eval() + + +def evaluate(cfg: DictConfig): + print("Not supported.") + + +@hydra.main(version_base=None, config_path="./conf", config_name="navier_stokes.yaml") +def main(cfg: DictConfig): + if cfg.mode == "train": + train(cfg) + elif cfg.mode == "eval": + evaluate(cfg) + else: + raise ValueError(f"cfg.mode should in ['train', 'eval'], but got '{cfg.mode}'") + + +if __name__ == "__main__": + main() diff --git a/examples/deephpms/schrodinger.py b/examples/deephpms/schrodinger.py index 4f1eb32e4..8a3944512 100644 --- a/examples/deephpms/schrodinger.py +++ b/examples/deephpms/schrodinger.py @@ -12,14 +12,17 @@ # See the License for the specific language governing permissions and # limitations under the License. +from os import path as osp + +import hydra import numpy as np import paddle import paddle.nn.functional as F +from omegaconf import DictConfig import ppsci from ppsci.autodiff import hessian from ppsci.autodiff import jacobian -from ppsci.utils import config from ppsci.utils import logger @@ -67,39 +70,22 @@ def sol_l2_rel_func(output_dict, label_dict): return metric_dict -if __name__ == "__main__": - args = config.parse_args() - ppsci.utils.misc.set_random_seed(42) - DATASET_PATH = "./datasets/DeepHPMs/NLS.mat" - DATASET_PATH_SOL = "./datasets/DeepHPMs/NLS.mat" - OUTPUT_DIR = "./output_schrodinger/" if args.output_dir is None else args.output_dir - +def train(cfg: DictConfig): + ppsci.utils.misc.set_random_seed(cfg.seed) # initialize logger - logger.init_logger("ppsci", f"{OUTPUT_DIR}/train.log", "info") + logger.init_logger("ppsci", osp.join(cfg.output_dir, f"{cfg.mode}.log"), "info") # initialize boundaries - t_lb = paddle.to_tensor([0.0]) - t_ub = paddle.to_tensor([np.pi / 2.0]) - x_lb = paddle.to_tensor([-5.0]) - x_ub = paddle.to_tensor([5.0]) + t_lb = paddle.to_tensor(cfg.T_LB) + t_ub = paddle.to_tensor(np.pi / cfg.T_UB) + x_lb = paddle.to_tensor(cfg.X_LB) + x_ub = paddle.to_tensor(cfg.X_UB) # initialize models - model_idn_u = ppsci.arch.MLP(("t", "x"), ("u_idn",), 4, 50, "sin") - model_idn_v = ppsci.arch.MLP(("t", "x"), ("v_idn",), 4, 50, "sin") - model_pde_f = ppsci.arch.MLP( - ("u", "v", "du_x", "dv_x", "du_xx", "dv_xx"), - ("f_pde",), - 2, - 100, - "sin", - ) - model_pde_g = ppsci.arch.MLP( - ("u", "v", "du_x", "dv_x", "du_xx", "dv_xx"), - ("g_pde",), - 2, - 100, - "sin", - ) + model_idn_u = ppsci.arch.MLP(**cfg.MODEL.idn_u_net) + model_idn_v = ppsci.arch.MLP(**cfg.MODEL.idn_v_net) + model_pde_f = ppsci.arch.MLP(**cfg.MODEL.pde_f_net) + model_pde_g = ppsci.arch.MLP(**cfg.MODEL.pde_g_net) # initialize transform def transform_uv(_in): @@ -142,27 +128,25 @@ def transform_fg(_in): (model_idn_u, model_idn_v, model_pde_f, model_pde_g) ) - # set training hyper-parameters - ITERS_PER_EPOCH = 1 - EPOCHS = 50000 if args.epochs is None else args.epochs # set 1 for LBFGS - # MAX_ITER = 50000 # for LBFGS - EVAL_BATCH_SIZE = 10000 - # initialize optimizer # Adam - optimizer_idn = ppsci.optimizer.Adam(1e-4)((model_idn_u, model_idn_v)) - optimizer_pde = ppsci.optimizer.Adam(1e-4)((model_pde_f, model_pde_g)) + optimizer_idn = ppsci.optimizer.Adam(cfg.TRAIN.learning_rate)( + (model_idn_u, model_idn_v) + ) + optimizer_pde = ppsci.optimizer.Adam(cfg.TRAIN.learning_rate)( + (model_pde_f, model_pde_g) + ) # LBFGS - # optimizer_idn = ppsci.optimizer.LBFGS(max_iter=MAX_ITER)((model_idn_u, model_idn_v)) - # optimizer_pde = ppsci.optimizer.LBFGS(max_iter=MAX_ITER)((model_pde_f, model_pde_g)) + # optimizer_idn = ppsci.optimizer.LBFGS(max_iter=cfg.TRAIN.max_iter)((model_idn_u, model_idn_v)) + # optimizer_pde = ppsci.optimizer.LBFGS(max_iter=cfg.TRAIN.max_iter)((model_pde_f, model_pde_g)) # stage 1: training identification net # manually build constraint(s) train_dataloader_cfg_idn = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH, + "file_path": cfg.DATASET_PATH, "input_keys": ("t", "x"), "label_keys": ("u_idn", "v_idn"), "alias_dict": { @@ -186,7 +170,7 @@ def transform_fg(_in): eval_dataloader_cfg_idn = { "dataset": { "name": "MatDataset", - "file_path": DATASET_PATH, + "file_path": cfg.DATASET_PATH, "input_keys": ("t", "x"), "label_keys": ("u_idn", "v_idn"), "alias_dict": { @@ -196,7 +180,7 @@ def transform_fg(_in): "v_idn": "v_star", }, }, - "batch_size": EVAL_BATCH_SIZE, + "batch_size": cfg.TRAIN.batch_size.eval, "sampler": { "name": "BatchSampler", "drop_last": False, @@ -217,12 +201,12 @@ def transform_fg(_in): solver = ppsci.solver.Solver( model_list, constraint_idn, - OUTPUT_DIR, + cfg.output_dir, optimizer_idn, None, - EPOCHS, - ITERS_PER_EPOCH, - eval_during_train=False, + cfg.TRAIN.epochs, + cfg.TRAIN.iters_per_epoch, + eval_during_train=cfg.TRAIN.eval_during_train, validator=validator_idn, ) @@ -236,7 +220,7 @@ def transform_fg(_in): train_dataloader_cfg_pde = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH, + "file_path": cfg.DATASET_PATH, "input_keys": ("t", "x"), "label_keys": ("du_t", "dv_t"), "alias_dict": { @@ -265,7 +249,7 @@ def transform_fg(_in): eval_dataloader_cfg_pde = { "dataset": { "name": "MatDataset", - "file_path": DATASET_PATH, + "file_path": cfg.DATASET_PATH, "input_keys": ("t", "x"), "label_keys": ("du_t", "dv_t"), "alias_dict": { @@ -275,7 +259,7 @@ def transform_fg(_in): "dv_t": "t_star", }, }, - "batch_size": EVAL_BATCH_SIZE, + "batch_size": cfg.TRAIN.batch_size.eval, "sampler": { "name": "BatchSampler", "drop_last": False, @@ -301,12 +285,12 @@ def transform_fg(_in): solver = ppsci.solver.Solver( model_list, constraint_pde, - OUTPUT_DIR, + cfg.output_dir, optimizer_pde, None, - EPOCHS, - ITERS_PER_EPOCH, - eval_during_train=False, + cfg.TRAIN.epochs, + cfg.TRAIN.iters_per_epoch, + eval_during_train=cfg.TRAIN.eval_during_train, validator=validator_pde, ) @@ -324,7 +308,7 @@ def transform_fg(_in): train_dataloader_cfg_sol_f = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH_SOL, + "file_path": cfg.DATASET_PATH_SOL, "input_keys": ("t", "x"), "label_keys": ("du_t", "dv_t"), "alias_dict": { @@ -338,7 +322,7 @@ def transform_fg(_in): train_dataloader_cfg_sol_init = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH_SOL, + "file_path": cfg.DATASET_PATH_SOL, "input_keys": ("t", "x"), "label_keys": ("u_idn", "v_idn"), "alias_dict": {"t": "t0", "x": "x0", "u_idn": "u0", "v_idn": "v0"}, @@ -347,7 +331,7 @@ def transform_fg(_in): train_dataloader_cfg_sol_bc = { "dataset": { "name": "IterableMatDataset", - "file_path": DATASET_PATH_SOL, + "file_path": cfg.DATASET_PATH_SOL, "input_keys": ("t", "x"), "label_keys": ("x",), "alias_dict": {"t": "tb", "x": "xb"}, @@ -391,7 +375,7 @@ def transform_fg(_in): eval_dataloader_cfg_sol = { "dataset": { "name": "MatDataset", - "file_path": DATASET_PATH_SOL, + "file_path": cfg.DATASET_PATH_SOL, "input_keys": ("t", "x"), "label_keys": ("u_idn", "v_idn"), "alias_dict": { @@ -401,7 +385,7 @@ def transform_fg(_in): "v_idn": "v_star", }, }, - "batch_size": EVAL_BATCH_SIZE, + "batch_size": cfg.TRAIN.batch_size.eval, "sampler": { "name": "BatchSampler", "drop_last": False, @@ -424,12 +408,12 @@ def transform_fg(_in): solver = ppsci.solver.Solver( model_list, constraint_sol, - OUTPUT_DIR, + cfg.output_dir, optimizer_idn, None, - EPOCHS, - ITERS_PER_EPOCH, - eval_during_train=False, + cfg.TRAIN.epochs, + cfg.TRAIN.iters_per_epoch, + eval_during_train=cfg.TRAIN.eval_during_train, validator=validator_sol, ) @@ -437,3 +421,21 @@ def transform_fg(_in): solver.train() # evaluate after finished training solver.eval() + + +def evaluate(cfg: DictConfig): + print("Not supported.") + + +@hydra.main(version_base=None, config_path="./conf", config_name="schrodinger.yaml") +def main(cfg: DictConfig): + if cfg.mode == "train": + train(cfg) + elif cfg.mode == "eval": + evaluate(cfg) + else: + raise ValueError(f"cfg.mode should in ['train', 'eval'], but got '{cfg.mode}'") + + +if __name__ == "__main__": + main()