Skip to content

Commit f3a9ad9

Browse files
[Fix&Doc] Fix vdl (#671)
* fix wrong argument order for vdl and add note when vdl is enabled * update user_guide for VDL tool and refine some code * add accurate condition for saving *.eqn file, refine code in init_logger
1 parent 0860a51 commit f3a9ad9

File tree

7 files changed

+101
-27
lines changed

7 files changed

+101
-27
lines changed

docs/requirements.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ mkdocs-git-revision-date-localized-plugin
66
mkdocs-glightbox
77
mkdocs-include-markdown-plugin
88
mkdocs-material
9-
mkdocs-material
109
mkdocs-material-extensions
1110
mkdocs-video
1211
mkdocstrings

docs/zh/user_guide.md

Lines changed: 68 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ PaddleScience/examples/bracket/outputs_bracket/
169169

170170
1. 加载 `*.pdparams` 文件内的参数到模型中
171171

172-
``` py
172+
``` py hl_lines="9 10"
173173
import ppsci
174174
import numpy as np
175175
@@ -186,7 +186,7 @@ PaddleScience/examples/bracket/outputs_bracket/
186186
187187
2. 准备好用于预测的输入数据,并以字典 `dict` 的方式传递给 `solver.predict`。
188188
189-
``` py
189+
``` py hl_lines="12 13 14 15 16"
190190
N = 100 # 假设要预测100个样本的结果
191191
x = np.random.randn(N, 1) # 准备 字段
192192
y = np.random.randn(N, 1)
@@ -224,7 +224,7 @@ PaddleScience/examples/bracket/outputs_bracket/
224224
225225
因此我们只需要在 `Solver` 时指定 `checkpoint_path` 参数为 `latest.*` 的所在路径,即可自动载入上述的几个文件,并从 `latest` 中记录的 epoch 开始继续训练。
226226
227-
``` py hl_lines="9"
227+
``` py hl_lines="7"
228228
import ppsci
229229
230230
...
@@ -241,19 +241,35 @@ solver = ppsci.solver.Solver(
241241
242242
### 1.4 迁移学习
243243
244-
迁移学习是一种广泛使用、低成本提高模型精度的训练方式。在 PaddleScience 中,只需在 `model` 实例化完毕之后,手动为其载入预训练模型权重,即可进行迁移学习
244+
迁移学习是一种广泛使用、低成本提高模型精度的训练方式。在 PaddleScience 中,可以通过在 `model` 实例化完毕之后,手动为其载入预训练模型权重;也可以在 `Solver` 实例化时指定 `pretrained_model_path` 自动载入预训练模型权重,两种方式都可以进行迁移学习
245245
246-
``` py hl_lines="9"
247-
import ppsci
248-
import ppsci.utils
249-
from ppsci.utils import save_load
246+
=== "手动载入预训练模型"
250247
251-
...
252-
...
248+
``` py hl_lines="8"
249+
import ppsci
250+
from ppsci.utils import save_load
253251
254-
model = ...
255-
save_load.load_pretrain(model, "/path/to/pretrain")
256-
```
252+
...
253+
...
254+
255+
model = ...
256+
save_load.load_pretrain(model, "/path/to/pretrain")
257+
```
258+
259+
=== "指定 `pretrained_model_path` 自动载入预训练模型"
260+
261+
``` py hl_lines="9"
262+
import ppsci
263+
264+
...
265+
...
266+
267+
model = ...
268+
solver = ppsci.solver.Solver(
269+
...,
270+
pretrained_model_path="/path/to/pretrain",
271+
)
272+
```
257273
258274
!!! info "迁移学习建议"
259275
@@ -278,7 +294,42 @@ solver = ppsci.solver.Solver(
278294
solver.eval()
279295
```
280296
281-
### 1.6 使用 WandB 记录实验
297+
### 1.6 使用 VisualDL 记录实验
298+
299+
[VisualDL](https://www.paddlepaddle.org.cn/paddle/visualdl) 是飞桨推出的可视化分析工具,以丰富的图表呈现训练参数变化趋势、数据样本、模型结构、PR曲线、ROC曲线、高维数据分布等。帮助用户清晰直观地理解深度学习模型训练过程及模型结构,进而实现高效的模型调优。
300+
301+
PaddleScience 支持使用 VisualDL 记录训练过程中的基础实验数据,包括 train/eval loss,eval metric,learning rate 等基本信息,可按如下步骤使用该功能。
302+
303+
1. 安装 VisualDL
304+
305+
``` sh
306+
pip install -U visualdl
307+
```
308+
309+
2. 在案例代码的 `Solver` 实例化时指定 `use_visualdl=True`,然后再启动案例训练
310+
311+
``` py hl_lines="3"
312+
solver = ppsci.solver.Solver(
313+
...,
314+
use_visualdl=True,
315+
)
316+
```
317+
318+
3. 可视化记录数据
319+
320+
根据上述步骤,在训练时 VisualDL 会自动记录数据并保存到 `${solver.output_dir}/vdl` 的目录中。`vdl` 所在路径在实例化 `Solver` 时,会自动打印在终端中,如下所示。
321+
322+
``` log hl_lines="3"
323+
Please NOTE: device: 0, GPU Compute Capability: 7.0, Driver API Version: 11.8, Runtime API Version: 11.6
324+
device: 0, cuDNN Version: 8.4.
325+
ppsci INFO: VisualDL tool enabled for logging, you can view it by running: 'visualdl --logdir outputs_darcy2d/2023-10-08/10-00-00/TRAIN.epochs=400/vdl --port 8080'.
326+
```
327+
328+
在终端里输入上述可视化命令,并用浏览器进入 VisualDL 给出的可视化地址,即可在浏览器内查看记录的数据,如下图所示。
329+
330+
![visualdl_record](https://paddle-org.bj.bcebos.com/paddlescience/docs/user_guide/VisualDL_preview.png)
331+
332+
### 1.7 使用 WandB 记录实验
282333
283334
[WandB](https://wandb.ai/) 是一个第三方实验记录工具,能在记录实验数据的同时将数据上传到其用户的私人账户上,防止实验记录丢失。
284335
@@ -331,7 +382,7 @@ PaddleScience 支持使用 WandB 记录基本的实验数据,包括 train/eval
331382
332383
接下来以 `examples/pipe/poiseuille_flow.py` 为例,介绍如何正确使用 PaddleScience 的数据并行功能。分布式训练细节可以参考:[Paddle-使用指南-分布式训练-快速开始-数据并行](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/guides/06_distributed_training/cluster_quick_start_collective_cn.html)。
333384
334-
1. 在 constraint 实例化完毕后,将 `ITERS_PER_EPOCH` 重新赋值为经过自动多卡数据切分后的 `dataloader` 的长度(一般情况下其长度等于单卡 dataloader 的长度除以卡数,向上取整),如代码中黄色高亮行所示
385+
1. 在 constraint 实例化完毕后,将 `ITERS_PER_EPOCH` 重新赋值为经过自动多卡数据切分后的 `dataloader` 的长度(一般情况下其长度等于单卡 dataloader 的长度除以卡数,向上取整),如代码中高亮行所示
335386
336387
``` py linenums="146" title="examples/pipe/poiseuille_flow.py" hl_lines="22"
337388
ITERS_PER_EPOCH = int((N_x * N_y * N_p) / BATCH_SIZE)
@@ -379,7 +430,7 @@ TODO -->
379430
380431
接下来介绍如何正确使用 PaddleScience 的自动混合精度功能。自动混合精度的原理可以参考:[Paddle-使用指南-性能调优-自动混合精度训练(AMP)](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/guides/performance_improving/amp_cn.html#amp)。
381432
382-
实例化 `Solver` 时加上 2 个参数: `use_amp=True`, `amp_level="O1"`(或`amp_level="O2"`)。如代码中黄色高亮行所示,通过指定 `use_amp=True`,开启自动混合精度功能,接着再设置 `amp_level="O1"`,指定混合精度所用的模式,`O1` 为自动混合精度,`O2` 为更激进的纯 fp16 训练模式,一般推荐使用 `O1`。
433+
实例化 `Solver` 时加上 2 个参数: `use_amp=True`, `amp_level="O1"`(或`amp_level="O2"`)。如代码中高亮行所示,通过指定 `use_amp=True`,开启自动混合精度功能,接着再设置 `amp_level="O1"`,指定混合精度所用的模式,`O1` 为自动混合精度,`O2` 为更激进的纯 fp16 训练模式,一般推荐使用 `O1`。
383434
384435
``` py hl_lines="5 6"
385436
# initialize solver
@@ -395,7 +446,7 @@ solver = ppsci.solver.Solver(
395446
396447
接下来介绍如何正确使用 PaddleScience 的梯度累加功能。梯度累加的原理可以参考:[Paddle-使用指南-性能调优-自动混合精度训练(AMP)-动态图下使用梯度累加](https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/guides/performance_improving/amp_cn.html#dongtaituxiashiyongtiduleijia)。
397448
398-
实例化 `Solver` 时指定 `update_freq` 参数为大于 1 的正整数即可。如代码中黄色高亮行所示,`update_freq` 可以设置为 2 或者更大的整数,推荐使用 248,此时对于训练任务来说,全局 `batch size` 等价于 `update_freq * batch size`。梯度累加方法在大多数场景中能够让间接地扩大每个 batch 内的样本数量,从而让每个 batch 分布更接近真实数据分布,提升训练任务的性能。
449+
实例化 `Solver` 时指定 `update_freq` 参数为大于 1 的正整数即可。如代码中高亮行所示,`update_freq` 可以设置为 2 或者更大的整数,推荐使用 248,此时对于训练任务来说,全局 `batch size` 等价于 `update_freq * batch size`。梯度累加方法在大多数场景中能够让间接地扩大每个 batch 内的样本数量,从而让每个 batch 分布更接近真实数据分布,提升训练任务的性能。
399450
400451
``` py hl_lines="5"
401452
# initialize solver

examples/amgnet/amgnet_airfoil.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ def train(cfg: DictConfig):
136136
solver.train()
137137

138138
# visualize prediction
139+
logger.message("Now visualizing prediction, please wait...")
139140
with solver.no_grad_context_manager(True):
140141
for index, (input_, label, _) in enumerate(rmse_validator.data_loader):
141142
truefield = label["label"].y

examples/amgnet/amgnet_cylinder.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ def train(cfg: DictConfig):
136136
solver.train()
137137

138138
# visualize prediction
139+
logger.message("Now visualizing prediction, please wait...")
139140
with solver.no_grad_context_manager(True):
140141
for index, (input_, label, _) in enumerate(rmse_validator.data_loader):
141142
truefield = label["label"].y

ppsci/solver/solver.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,10 @@ def __init__(
300300
with misc.RankZeroOnly(self.rank) as is_master:
301301
if is_master:
302302
self.vdl_writer = vdl.LogWriter(osp.join(output_dir, "vdl"))
303+
logger.info(
304+
"VisualDL tool is enabled for logging, you can view it by "
305+
f"running: 'visualdl --logdir {self.vdl_writer._logdir} --port 8080'."
306+
)
303307

304308
# set WandB tool
305309
self.wandb_writer = None
@@ -413,7 +417,10 @@ def train(self):
413417
)
414418
for metric_dict in metric_dict_group.values():
415419
logger.scaler(
416-
metric_dict, epoch_id, self.vdl_writer, self.wandb_writer
420+
{f"eval/{k}": v for k, v in metric_dict.items()},
421+
epoch_id,
422+
self.vdl_writer,
423+
self.wandb_writer,
417424
)
418425

419426
# visualize after evaluation

ppsci/utils/logger.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,9 @@ def init_logger(
100100
stream_handler._name = "stream_handler"
101101
_logger.addHandler(stream_handler)
102102

103-
# add file_handler, output to log_file(if specified)
103+
# add file_handler, output to log_file(if specified), only for rank 0 device
104104
if log_file is not None and dist.get_rank() == 0:
105-
log_file_folder = os.path.split(log_file)[0]
105+
log_file_folder = os.path.dirname(log_file)
106106
os.makedirs(log_file_folder, exist_ok=True)
107107
file_formatter = logging.Formatter(
108108
"[%(asctime)s] %(name)s %(levelname)s: %(message)s",
@@ -122,7 +122,18 @@ def init_logger(
122122

123123

124124
def set_log_level(log_level: int):
125-
"""Set logger level, only msg of level >= `log_level` will be printed.
125+
"""Set logger level, only message of level >= `log_level` will be printed.
126+
127+
Built-in log level are below:
128+
129+
CRITICAL = 50,
130+
FATAL = 50,
131+
ERROR = 40,
132+
WARNING = 30,
133+
WARN = 30,
134+
INFO = 20,
135+
DEBUG = 10,
136+
NOTSET = 0.
126137
127138
Args:
128139
log_level (int): Log level.
@@ -135,7 +146,7 @@ def set_log_level(log_level: int):
135146

136147
def ensure_logger(log_func: Callable) -> Callable:
137148
"""
138-
Automatically initialize `logger` by default arguments
149+
A decorator which automatically initialize `logger` by default arguments
139150
when init_logger() is not called manually.
140151
"""
141152

@@ -201,7 +212,7 @@ def scaler(
201212
"""
202213
if vdl_writer is not None:
203214
for name, value in metric_dict.items():
204-
vdl_writer.add_scalar(name, step, value)
215+
vdl_writer.add_scalar(name, value, step)
205216

206217
if wandb_writer is not None:
207218
with misc.RankZeroOnly() as is_master:

ppsci/utils/save_load.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,13 @@ def save_checkpoint(
186186
if grad_scaler is not None:
187187
paddle.save(grad_scaler.state_dict(), f"{ckpt_path}.pdscaler")
188188
if equation is not None:
189-
paddle.save(
190-
{key: eq.state_dict() for key, eq in equation.items()},
191-
f"{ckpt_path}.pdeqn",
189+
num_learnable_params = sum(
190+
[len(eq.learnable_parameters) for eq in equation.values()]
192191
)
192+
if num_learnable_params > 0:
193+
paddle.save(
194+
{key: eq.state_dict() for key, eq in equation.items()},
195+
f"{ckpt_path}.pdeqn",
196+
)
193197

194198
logger.message(f"Finish saving checkpoint to {ckpt_path}")

0 commit comments

Comments
 (0)