Skip to content

Commit

Permalink
[Fix] Adapt preprocess transforms to multiple arguments (#572)
Browse files Browse the repository at this point in the history
* adapt preprocess transforms to multiple arguments

* update code

* update docs

* fix document

* refine code in IDE and FPDE
  • Loading branch information
HydrogenSulfate committed Oct 26, 2023
1 parent c20e44e commit c4bcd67
Show file tree
Hide file tree
Showing 9 changed files with 317 additions and 113 deletions.
58 changes: 37 additions & 21 deletions docs/zh/examples/volterra_ide.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,22 @@

<a href="https://aistudio.baidu.com/aistudio/projectdetail/6622866?sUid=438690&shared=1&ts=1691582831601" class="md-button md-button--primary" style>AI Studio快速体验</a>

=== "模型训练命令"

``` sh
python volterra_ide.py
```

=== "模型评估命令"

``` sh
python volterra_ide.py mode=eval EVAL.pretrained_model_path=https://paddle-org.bj.bcebos.com/paddlescience/models/volterra_ide/volterra_ide_pretrained.pdparams
```

| 预训练模型 | 指标 |
|:--| :--|
| [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 |

## 1. 背景简介

Volterra integral equation(沃尔泰拉积分方程)是一种积分方程,即方程中含有对待求解函数的积分运算,其有两种形式,如下所示
Expand Down Expand Up @@ -45,9 +61,9 @@ $$

在上述问题中,我们确定了输入为 $x$,输出为 $u(x)$,因此我们使用,用 PaddleScience 代码表示如下:

``` py linenums="37"
``` py linenums="39"
--8<--
examples/ide/volterra_ide.py:37:38
examples/ide/volterra_ide.py:39:40
--8<--
```

Expand All @@ -57,19 +73,19 @@ examples/ide/volterra_ide.py:37:38

Volterra_IDE 问题的积分域是 $a$ ~ $t$,其中 `a` 为固定常数 0,`t` 的范围为 0 ~ 5,因此可以使用PaddleScience 内置的一维几何 `TimeDomain` 作为计算域。

``` py linenums="40"
``` py linenums="42"
--8<--
examples/ide/volterra_ide.py:40:42
examples/ide/volterra_ide.py:42:43
--8<--
```

### 3.3 方程构建

由于 Volterra_IDE 使用的是积分方程,因此可以直接使用 PaddleScience 内置的 `ppsci.equation.Volterra`,并指定所需的参数:积分下限 `a``t` 的离散取值点数 `num_points`、一维高斯积分点的个数 `quad_deg`、$K(t,s)$ 核函数 `kernel_func`、$u(t) - f(t)$ 等式右侧表达式 `func`

``` py linenums="44"
``` py linenums="45"
--8<--
examples/ide/volterra_ide.py:44:64
examples/ide/volterra_ide.py:45:61
--8<--
```

Expand All @@ -81,9 +97,9 @@ examples/ide/volterra_ide.py:44:64

由于等式左侧涉及到积分计算(实际采用高斯积分近似计算),因此在 0 ~ 5 区间内采样出多个 `t_i` 点后,还需要计算其用于高斯积分的点集,即对每一个 `(0,t_i)` 区间,都计算出一一对应的高斯积分点集 `quad_i` 和点权 `weight_i`。PaddleScience 将这一步作为输入数据的预处理,加入到代码中,如下所示

``` py linenums="66"
``` py linenums="63"
--8<--
examples/ide/volterra_ide.py:66:108
examples/ide/volterra_ide.py:63:117
--8<--
```

Expand All @@ -97,47 +113,47 @@ $$

因此可以加入 `t=0` 时的初值条件,代码如下所示

``` py linenums="110"
``` py linenums="119"
--8<--
examples/ide/volterra_ide.py:110:128
examples/ide/volterra_ide.py:119:137
--8<--
```

在微分方程约束、初值约束构建完毕之后,以我们刚才的命名为关键字,封装到一个字典中,方便后续访问。

``` py linenums="129"
``` py linenums="138"
--8<--
examples/ide/volterra_ide.py:129:133
examples/ide/volterra_ide.py:138:142
--8<--
```

### 3.5 超参数设定

接下来我们需要指定训练轮数和学习率,此处我们按实验经验,让 `L-BFGS` 优化器进行一轮优化即可,但一轮优化内的 `max_iters` 数可以设置为一个较大的一个数 `15000`

``` py linenums="135"
``` yaml linenums="39"
--8<--
examples/ide/volterra_ide.py:135:136
examples/ide/conf/volterra_ide.yaml:39:57
--8<--
```

### 3.6 优化器构建

训练过程会调用优化器来更新模型参数,此处选择较为常用的 `LBFGS` 优化器。

``` py linenums="138"
``` py linenums="144"
--8<--
examples/ide/volterra_ide.py:138:146
examples/ide/volterra_ide.py:144:145
--8<--
```

### 3.7 评估器构建

在训练过程中通常会按一定轮数间隔,用验证集(测试集)评估当前模型的训练情况,因此使用 `ppsci.validate.GeometryValidator` 构建评估器。

``` py linenums="148"
``` py linenums="147"
--8<--
examples/ide/volterra_ide.py:148:163
examples/ide/volterra_ide.py:147:161
--8<--
```

Expand All @@ -149,9 +165,9 @@ examples/ide/volterra_ide.py:148:163

完成上述设置之后,只需要将上述实例化的对象按顺序传递给 `ppsci.solver.Solver`,然后启动训练。

``` py linenums="165"
``` py linenums="163"
--8<--
examples/ide/volterra_ide.py:165:181
examples/ide/volterra_ide.py:163:181
--8<--
```

Expand All @@ -161,7 +177,7 @@ examples/ide/volterra_ide.py:165:181

``` py linenums="183"
--8<--
examples/ide/volterra_ide.py:183:
examples/ide/volterra_ide.py:183:194
--8<--
```

Expand Down
34 changes: 24 additions & 10 deletions examples/fpde/fractional_poisson_2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import math
from typing import Dict
from typing import Tuple
from typing import Union

import numpy as np
Expand Down Expand Up @@ -68,22 +69,35 @@ def u_solution_func(
return paddle.abs(1 - (out["x"] ** 2 + out["y"] ** 2)) ** (1 + ALPHA / 2)
return np.abs(1 - (out["x"] ** 2 + out["y"] ** 2)) ** (1 + ALPHA / 2)

# set input transform
def fpde_transform(in_: Dict[str, np.ndarray]) -> Dict[str, np.ndarray]:
# set transform for input data
def input_data_fpde_transform(
input: Dict[str, np.ndarray],
weight: Dict[str, np.ndarray],
label: Dict[str, np.ndarray],
) -> Tuple[
Dict[str, paddle.Tensor], Dict[str, paddle.Tensor], Dict[str, paddle.Tensor]
]:
"""Get sampling points for integral.
Args:
in_ (Dict[str, np.ndarray]): Raw input dict.
input (Dict[str, paddle.Tensor]): Raw input dict.
weight (Dict[str, paddle.Tensor]): Raw weight dict.
label (Dict[str, paddle.Tensor]): Raw label dict.
Returns:
Dict[str, np.ndarray]: Input dict contained sampling points.
Tuple[ Dict[str, paddle.Tensor], Dict[str, paddle.Tensor], Dict[str, paddle.Tensor] ]:
Input dict contained sampling points, weight dict and label dict.
"""
points = np.concatenate((in_["x"].numpy(), in_["y"].numpy()), axis=1)
points = np.concatenate((input["x"].numpy(), input["y"].numpy()), axis=1)
x = equation["fpde"].get_x(points)
return {
**in_,
**{k: paddle.to_tensor(v) for k, v in x.items()},
}
return (
{
**input,
**{k: paddle.to_tensor(v) for k, v in x.items()},
},
weight,
label,
)

fpde_constraint = ppsci.constraint.InteriorConstraint(
equation["fpde"].equations,
Expand All @@ -95,7 +109,7 @@ def fpde_transform(in_: Dict[str, np.ndarray]) -> Dict[str, np.ndarray]:
"transforms": (
{
"FunctionalTransform": {
"transform_func": fpde_transform,
"transform_func": input_data_fpde_transform,
},
},
),
Expand Down
63 changes: 63 additions & 0 deletions examples/ide/conf/volterra_ide.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
hydra:
run:
# dynamic output directory according to running time and override name
dir: outputs_volterra_IDE/${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}
log_freq: 20

# set geometry
BOUNDS: [0, 5]

# model settings
MODEL:
input_keys: ["x"]
output_keys: ["u"]
num_layers: 3
hidden_size: 20
activation: "tanh"

# training settings
TRAIN:
epochs: 1
iters_per_epoch: 1
save_freq: 1
eval_during_train: true
eval_freq: 1
optimizer:
learning_rate: 1
max_iter: 15000
max_eval: 1250
tolerance_grad: 1.0e-8
tolerance_change: 0
history_size: 100
quad_deg: 20
npoint_interior: 12
npoint_ic: 1
pretrained_model_path: null
checkpoint_path: null

# evaluation settings
EVAL:
pretrained_model_path: null
eval_with_no_grad: true
npoint_eval: 100

0 comments on commit c4bcd67

Please sign in to comment.