Skip to content

Commit f116bbf

Browse files
authored
隐空间神经算子LatentNO(or LNO) (#1209)
* launch example LatentNO * fix LatentNO.py & update config files * reconstruct files * style(LatentNO): fix code formatting * docs: add latent_no.md document * feat: add latent_no.py model implementation * feat: add latent_no_datset.py dataset implementation * feat(arch): register LatentNO model in __init__.py * style(utils): fix code formatting * delete logger setting in yaml files * update LatentNO-Ns2d.yaml * update all files in /examples/LatentNO * update /ppsci/arch/latent_no.py * update /ppsci/arch/latent_no.py * docs(README): update hyperlink for LNO example * docs(arch,md): update LNO example * docs(index.md): update LNO example * update /ppsci/arch/latent_no.py * update LatentNO-time.py/LatentNO-steady.py & config files * update utils.py * update /ppsci/arch/latent_no.py * update latent_no_dataset.py * update LatentNO-time.py & LatentNO-steady.py * update config files * fix(latent_no): update model initialization * style(LatentNO-time): fix code formatting * update LatentNO-steady.py * update latent_no.md * docs(latent_no):add figs * update LantentNO-NS2d.yaml * update config files * update config files * fix(LatentNO):reformat code * fix(latent_no_dataset):reformat code * update doc
1 parent 16c8ba2 commit f116bbf

File tree

16 files changed

+1822
-2
lines changed

16 files changed

+1822
-2
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ PaddleScience 是一个基于深度学习框架 PaddlePaddle 开发的科学计
6969
| 域分解 | [XPINN](https://paddlescience-docs.readthedocs.io/zh-cn/latest/zh/examples/xpinns) | 机理驱动 | MLP | 无监督学习 | - | [Paper](https://doi.org/10.4208/cicp.OA-2020-0164)|
7070
| 布鲁塞尔扩散系统 | [3D-Brusselator](https://paddlescience-docs.readthedocs.io/zh-cn/latest/zh/examples/brusselator3d) | 数据驱动 | LNO | 监督学习 | - | [Paper](https://arxiv.org/abs/2303.10528)|
7171
| 符号回归 | [Transformer4SR](https://paddlescience-docs.readthedocs.io/zh-cn/latest/zh/examples/transformer4sr.md) | 数据驱动 | Transformer | 监督学习 | - | [Paper](https://arxiv.org/abs/2312.04070)|
72-
| 算子学习 | [隐空间神经算子LNO](https://github.com/L-I-M-I-T/LatentNeuralOperator) | 数据驱动 | Transformer | 监督学习 | - | [Paper](https://arxiv.org/abs/2406.03923)|
72+
| 算子学习 | [隐空间神经算子LNO](https://paddlescience-docs.readthedocs.io/zh-cn/latest/zh/examples/latent_no.md) | 数据驱动 | Transformer | 监督学习 | - | [Paper](https://arxiv.org/abs/2406.03923)|
7373
</details>
7474

7575
<details>

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@
9494
| 域分解 | [XPINN](./zh/examples/xpinns.md) | 机理驱动 | MLP | 无监督学习 | - | [Paper](https://doi.org/10.4208/cicp.OA-2020-0164)|
9595
| 布鲁塞尔扩散系统 | [3D-Brusselator](./zh/examples/brusselator3d.md) | 数据驱动 | LNO | 监督学习 | - | [Paper](https://arxiv.org/abs/2303.10528)|
9696
| 符号回归 | [Transformer4SR](./zh/examples/transformer4sr.md) | 数据驱动 | Transformer | 监督学习 | - | [Paper](https://arxiv.org/abs/2312.04070)|
97-
| 算子学习 | [隐空间神经算子LNO](https://github.com/L-I-M-I-T/LatentNeuralOperator) | 数据驱动 | Transformer | 监督学习 | - | [Paper](https://arxiv.org/abs/2406.03923)|
97+
| 算子学习 | [隐空间神经算子LNO](./zh/examples/latent_no.md) | 数据驱动 | Transformer | 监督学习 | - | [Paper](https://arxiv.org/abs/2406.03923)|
9898

9999
=== "技术科学"
100100

docs/zh/api/arch.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
- Generator
2323
- HEDeepONets
2424
- KAN
25+
- LatentNO
2526
- LorenzEmbedding
2627
- MLP
2728
- ModelList

docs/zh/examples/latent_no.md

Lines changed: 292 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
import hydra
2+
import paddle
3+
from omegaconf import DictConfig
4+
from utils import RelLpLoss
5+
6+
import ppsci
7+
8+
9+
def train(cfg: DictConfig):
10+
model = ppsci.arch.LatentNO(**cfg.MODEL)
11+
12+
train_dataloader_cfg = {
13+
"dataset": {
14+
"name": "LatentNODataset",
15+
"data_name": cfg.data_name,
16+
"data_mode": "train",
17+
"data_normalize": cfg.data_normalize,
18+
"data_concat": cfg.data_concat,
19+
"input_keys": ("x", "y1"),
20+
"label_keys": ("y2",),
21+
},
22+
"sampler": {"name": "BatchSampler", "drop_last": True, "shuffle": True},
23+
"batch_size": cfg.batch_size,
24+
"num_workers": cfg.get("num_workers", 0),
25+
}
26+
27+
eval_dataloader_cfg = {
28+
"dataset": {
29+
"name": "LatentNODataset",
30+
"data_name": cfg.data_name,
31+
"data_mode": "val",
32+
"data_normalize": cfg.data_normalize,
33+
"data_concat": cfg.data_concat,
34+
"input_keys": ("x", "y1"),
35+
"label_keys": ("y2",),
36+
},
37+
"sampler": {"name": "BatchSampler", "drop_last": True, "shuffle": False},
38+
"batch_size": cfg.batch_size,
39+
"num_workers": cfg.get("num_workers", 0),
40+
}
41+
42+
train_loss_fn = RelLpLoss(p=2, key="y2", normalizer=None)
43+
44+
sup_constraint = ppsci.constraint.SupervisedConstraint(
45+
train_dataloader_cfg,
46+
train_loss_fn,
47+
output_expr={"y2": lambda out: out["y2"]},
48+
name="SupTrain",
49+
)
50+
if cfg.data_normalize:
51+
normalizer = sup_constraint.data_loader.dataset.normalizer
52+
else:
53+
normalizer = None
54+
constraint = {sup_constraint.name: sup_constraint}
55+
56+
cfg.TRAIN.iters_per_epoch = len(sup_constraint.data_loader)
57+
lr_scheduler = ppsci.optimizer.lr_scheduler.OneCycleLR(
58+
epochs=cfg.TRAIN.epochs,
59+
iters_per_epoch=cfg.TRAIN.iters_per_epoch,
60+
max_learning_rate=cfg.TRAIN.lr,
61+
divide_factor=cfg.TRAIN.div_factor,
62+
end_learning_rate=cfg.TRAIN.lr
63+
/ cfg.TRAIN.div_factor
64+
/ cfg.TRAIN.final_div_factor,
65+
phase_pct=cfg.TRAIN.pct_start,
66+
)()
67+
68+
optimizer = ppsci.optimizer.AdamW(
69+
lr_scheduler,
70+
weight_decay=cfg.TRAIN.weight_decay,
71+
grad_clip=paddle.nn.ClipGradByNorm(clip_norm=cfg.TRAIN.clip_norm),
72+
beta1=cfg.TRAIN.beta0,
73+
beta2=cfg.TRAIN.beta1,
74+
)(model)
75+
76+
metric_dict = {"L2Rel": RelLpLoss(p=2, key="y2", normalizer=normalizer)}
77+
78+
val_loss_fn = RelLpLoss(p=2, key="y2", normalizer=normalizer)
79+
80+
sup_validator = ppsci.validate.SupervisedValidator(
81+
eval_dataloader_cfg,
82+
val_loss_fn,
83+
output_expr={"y2": lambda out: out["y2"]},
84+
metric=metric_dict,
85+
name="SupVal",
86+
)
87+
validator = {sup_validator.name: sup_validator}
88+
89+
solver = ppsci.solver.Solver(
90+
model=model,
91+
optimizer=optimizer,
92+
constraint=constraint,
93+
validator=validator,
94+
cfg=cfg,
95+
)
96+
97+
solver.train()
98+
solver.eval()
99+
100+
101+
def evaluate(cfg: DictConfig):
102+
train_ds = ppsci.data.dataset.LatentNODataset(
103+
cfg.data_name,
104+
"train",
105+
cfg.data_normalize,
106+
cfg.data_concat,
107+
input_keys=("x", "y1"),
108+
label_keys=("y2",),
109+
)
110+
if cfg.data_normalize:
111+
normalizer = train_ds.normalizer
112+
else:
113+
normalizer = None
114+
115+
eval_loss_fn = RelLpLoss(p=2, key="y2", normalizer=normalizer)
116+
117+
model = ppsci.arch.LatentNO(**cfg.MODEL)
118+
119+
eval_dataloader_cfg = {
120+
"dataset": {
121+
"name": "LatentNODataset",
122+
"data_name": cfg.data_name,
123+
"data_mode": "val",
124+
"data_normalize": cfg.data_normalize,
125+
"data_concat": cfg.data_concat,
126+
"input_keys": ("x", "y1"),
127+
"label_keys": ("y2",),
128+
},
129+
"sampler": {"name": "BatchSampler", "drop_last": True, "shuffle": False},
130+
"batch_size": cfg.batch_size,
131+
"num_workers": cfg.get("num_workers", 0),
132+
}
133+
134+
metric_dict = {"L2Rel": RelLpLoss(p=2, key="y2", normalizer=normalizer)}
135+
136+
validator = ppsci.validate.SupervisedValidator(
137+
eval_dataloader_cfg,
138+
eval_loss_fn,
139+
output_expr={"y2": lambda out: out["y2"]},
140+
metric=metric_dict,
141+
name="Evaluation",
142+
)
143+
144+
solver = ppsci.solver.Solver(
145+
model=model,
146+
validator={"eval": validator},
147+
pretrained_model_path=cfg.EVAL.pretrained_model_path,
148+
)
149+
150+
solver.eval()
151+
152+
153+
@hydra.main(
154+
version_base=None, config_path="./config", config_name="LatentNO-Darcy.yaml"
155+
)
156+
def main(cfg: DictConfig):
157+
158+
if cfg.mode == "train":
159+
train(cfg)
160+
elif cfg.mode == "eval":
161+
evaluate(cfg)
162+
else:
163+
raise ValueError(f"cfg.mode should in ['train', 'eval'], but got '{cfg.mode}'")
164+
165+
166+
if __name__ == "__main__":
167+
main()

examples/LatentNO/LatentNO-time.py

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
import hydra
2+
import paddle
3+
from omegaconf import DictConfig
4+
from utils import RelLpLoss_time
5+
6+
import ppsci
7+
8+
9+
def train(cfg: DictConfig):
10+
model = ppsci.arch.LatentNO_time(**cfg.MODEL)
11+
12+
train_dataloader_cfg = {
13+
"dataset": {
14+
"name": "LatentNODataset_time",
15+
"data_name": cfg.data_name,
16+
"data_mode": "train",
17+
"data_normalize": cfg.data_normalize,
18+
"data_concat": cfg.data_concat,
19+
"input_keys": ("x", "y1", "y2"),
20+
"label_keys": ("y2",),
21+
},
22+
"sampler": {"name": "BatchSampler", "drop_last": True, "shuffle": True},
23+
"batch_size": cfg.batch_size,
24+
"num_workers": cfg.get("num_workers", 0),
25+
}
26+
27+
eval_dataloader_cfg = {
28+
"dataset": {
29+
"name": "LatentNODataset_time",
30+
"data_name": cfg.data_name,
31+
"data_mode": "val",
32+
"data_normalize": cfg.data_normalize,
33+
"data_concat": cfg.data_concat,
34+
"input_keys": ("x", "y1", "y2"),
35+
"label_keys": ("y2",),
36+
},
37+
"sampler": {"name": "BatchSampler", "drop_last": True, "shuffle": False},
38+
"batch_size": cfg.batch_size,
39+
"num_workers": cfg.get("num_workers", 0),
40+
}
41+
42+
train_loss_fn = RelLpLoss_time(
43+
p=2, key="y2", normalizer=None, use_full_sequence=False
44+
)
45+
46+
sup_constraint = ppsci.constraint.SupervisedConstraint(
47+
train_dataloader_cfg,
48+
train_loss_fn,
49+
output_expr={"y2": lambda out: out["y2"]},
50+
name="SupTrain",
51+
)
52+
53+
if cfg.data_normalize:
54+
normalizer = sup_constraint.dataloader.dataset.normalizer
55+
else:
56+
normalizer = None
57+
constraint = {sup_constraint.name: sup_constraint}
58+
59+
cfg.TRAIN.iters_per_epoch = len(sup_constraint.data_loader)
60+
lr_scheduler = ppsci.optimizer.lr_scheduler.OneCycleLR(
61+
epochs=cfg.TRAIN.epochs,
62+
iters_per_epoch=cfg.TRAIN.iters_per_epoch,
63+
max_learning_rate=cfg.TRAIN.lr,
64+
divide_factor=cfg.TRAIN.div_factor,
65+
end_learning_rate=cfg.TRAIN.lr
66+
/ cfg.TRAIN.div_factor
67+
/ cfg.TRAIN.final_div_factor,
68+
phase_pct=cfg.TRAIN.pct_start,
69+
)()
70+
71+
optimizer = ppsci.optimizer.AdamW(
72+
lr_scheduler,
73+
weight_decay=cfg.TRAIN.weight_decay,
74+
grad_clip=paddle.nn.ClipGradByNorm(clip_norm=cfg.TRAIN.clip_norm),
75+
beta1=cfg.TRAIN.beta0,
76+
beta2=cfg.TRAIN.beta1,
77+
)(model)
78+
79+
metric_dict = {
80+
"L2Rel": RelLpLoss_time(
81+
p=2, key="y2", normalizer=normalizer, use_full_sequence=True
82+
)
83+
}
84+
85+
val_loss_fn = RelLpLoss_time(
86+
p=2, key="y2", normalizer=normalizer, use_full_sequence=True
87+
)
88+
89+
sup_validator = ppsci.validate.SupervisedValidator(
90+
eval_dataloader_cfg,
91+
val_loss_fn,
92+
output_expr={"y2": lambda out: out["y2"]},
93+
metric=metric_dict,
94+
name="SupVal",
95+
)
96+
validator = {sup_validator.name: sup_validator}
97+
98+
solver = ppsci.solver.Solver(
99+
model=model,
100+
optimizer=optimizer,
101+
constraint=constraint,
102+
validator=validator,
103+
cfg=cfg,
104+
)
105+
106+
solver.train()
107+
solver.eval()
108+
109+
110+
def evaluate(cfg: DictConfig):
111+
train_ds = ppsci.data.dataset.LatentNODataset_time(
112+
cfg.data_name,
113+
"train",
114+
cfg.data_normalize,
115+
cfg.data_concat,
116+
input_keys=("x", "y1", "y2"),
117+
label_keys=("y2",),
118+
)
119+
if cfg.data_normalize:
120+
normalizer = train_ds.normalizer
121+
else:
122+
normalizer = None
123+
124+
eval_loss_fn = RelLpLoss_time(
125+
p=2, key="y2", normalizer=normalizer, use_full_sequence=True
126+
)
127+
128+
model = ppsci.arch.LatentNO_time(**cfg.MODEL)
129+
130+
eval_dataloader_cfg = {
131+
"dataset": {
132+
"name": "LatentNODataset_time",
133+
"data_name": cfg.data_name,
134+
"data_mode": "val",
135+
"data_normalize": cfg.data_normalize,
136+
"data_concat": cfg.data_concat,
137+
"input_keys": ("x", "y1", "y2"),
138+
"label_keys": ("y2",),
139+
},
140+
"sampler": {"name": "BatchSampler", "drop_last": True, "shuffle": False},
141+
"batch_size": cfg.batch_size,
142+
"num_workers": cfg.get("num_workers", 0),
143+
}
144+
145+
metric_dict = {
146+
"L2Rel": RelLpLoss_time(
147+
p=2, key="y2", normalizer=normalizer, use_full_sequence=True
148+
)
149+
}
150+
151+
validator = ppsci.validate.SupervisedValidator(
152+
eval_dataloader_cfg,
153+
eval_loss_fn,
154+
output_expr={"y2": lambda out: out["y2"]},
155+
metric=metric_dict,
156+
name="Evaluation",
157+
)
158+
159+
solver = ppsci.solver.Solver(
160+
model=model,
161+
validator={"eval": validator},
162+
pretrained_model_path=cfg.EVAL.pretrained_model_path,
163+
)
164+
165+
solver.eval()
166+
167+
168+
@hydra.main(version_base=None, config_path="./config", config_name="LatentNO-NS2d.yaml")
169+
def main(cfg: DictConfig):
170+
171+
if cfg.mode == "train":
172+
train(cfg)
173+
elif cfg.mode == "eval":
174+
evaluate(cfg)
175+
else:
176+
raise ValueError(f"cfg.mode should in ['train', 'eval'], but got '{cfg.mode}'")
177+
178+
179+
if __name__ == "__main__":
180+
main()

0 commit comments

Comments
 (0)