本文档介绍如何向MindFlow合入代码,包括合入前需要准备的文件、数据,合入步骤以及需要注意的事项,帮助贡献者更高效地进行代码合入。
如果缺少调试代码的硬件环境,可以参考启智社区云脑使用指南, NPU使用录屏, GPU使用录屏。
API代码主要指合入MindFlow/mindflow
目录的代码,主要为案例提供高效、易用的公共API接口,因此API代码编写时需要注意以下几点:
1、考虑在多个案例上的可扩展性,避免'Hard Code',在维度、深度等参量上预留足够的入参,以供用户根据实际情况选择,注意非法入参的检查;
2、入参命名上,MindFlow追求尽量统一,因此新的API合入时,需要与原有API的入参尽量对齐,新的入参命名可与Commiter联系;
3、API的存放位置需根据MindFlow的套件架构决定,注意更新__init__.py
文件和cmake/package.cmake
文件;
4、API文档包含两部分,一个是代码注释部分,一个是mindscience/docs/api_python/mindflow
和mindscience/docs/api_python_en/mindflow
中的中英文文档;
5、API相关测试用例来进行维护,保证其随时可用,测试用例提交在mindscience/tests
中,可根据具体用例修改,但运行时间不宜过长,结果检查合理;
案例代码主要指合入MindFlow/applications
目录的代码,需要根据研究范式,归入physics_driven
、data_driven
、data_mechanism_fusion
、cfd
几个目录中。
【必须】Jupyter Notebook中英文:为用户提供逐行的代码实现方式,详细讲解案例的实现方式和运行结果。
【必须】images
:包含了README、notebook等文件里的所有图片。
【必须】src
:为了保证训练代码的整洁性,可以抽取的函数和类可以统一放在src目录中,__init__.py
一般为必须,dataset.py
中包含数据集相关函数和类,model.py
中包含模型相关函数和类,utils.py
中包含工具函数和类,外部文件的调用统一从src导入。
【必须】参数文件:案例中具体参数的配置,一般采用yaml文件,为了方便查看,按照优化器、模型等进行分类。
【必须】训练脚本:案例的训练和验证脚本,在训练时除特殊情况,必须有测试集进行验证;训练脚本中的代码应该尽量简洁,复杂的调用封装到后端函数里。
单一的案例代码如PINNs求解Burgers
为例,代码目录分成以下结构:
.
├──images
│ ├──background.png
│ └──result.png
├──src
│ ├──__init__.py
│ ├──dataset.py
│ ├──model.py
│ └──utils.py
├──configs
│ ├──fno1d.yaml
├──README.md
├──README_CN.md
├──problem.ipynb
├──problem_CN.ipynb
├──burgers_cfg.yaml
├──eval.py
└──train.py
有时,有多个案例会使用相同的模型和方法,使用不同的数据集,为了避免代码和文档的重复,src
目录下统一存放所有案例公共的代码和每个案例自定义的代码,images
目录统一存放图片文件,README.md
文件在总体上介绍模型方法和所有的案例,problem.ipynb
文件介绍具体的案例代码,所有案例具有相同的入口,在命令行里通过指定参数来确定运行的具体案例,文件格式如下:
.
├──images
│ ├──background.png
│ ├──result1.png
│ ├──result2.png
│ └──result3.png
├──src
│ ├──__init__.py
│ ├──dataset.py
│ ├──model.py
│ └──utils.py
├──configs
│ ├──fno1d.yaml
├──README.md
├──README_CN.md
├──problem.ipynb
├──problem_CN.ipynb
├──problem_cfg.yaml
├──eval.py
└──train.py
外层训练/测试文件调用的方式如下:
...
parser = argparse.ArgumentParser(description="Cae-Lstm")
parser.add_argument("--case", type=str, default='riemann', choices=['riemann', 'kh', 'sod'],
help="Which case to run")
...
args = parser.parse_args()
...
model = Model()
if args.case == 'riemann':
dataset = create_riemann_dataset()
elif args.case == 'kh':
dataset = create_kh_dataset()
else:
dataset = create_sod_dataset()
model.train(dataset)
...
训练文件train.py为模型训练的入口,格式如下:
import os
import time
import argparse
import numpy as np
from mindspore import context, nn, Tensor, set_seed, ops, data_sink, jit, save_checkpoint
from mindspore import dtype as mstype
from mindflow import FNO1D, load_yaml_config, get_warmup_cosine_annealing_lr
from mindflow.pde import FlowWithLoss
from src import create_training_dataset, visual, calculate_l2_error
# 相关依赖导入,按照python官方库、第三方库、mindflow、src的顺序导入,导入mindflow时,精确到二级目录
set_seed(123456)
np.random.seed(123456)
# 设置随机数
def parse_args():
'''Parse input args'''
parser = argparse.ArgumentParser(description='Problem description')
parser.add_argument("--config_file_path", type=str, default="./config.yaml")
parser.add_argument("--device_target", type=str, default="GPU", choices=["GPU", "Ascend"],
help="The target device to run, support 'Ascend', 'GPU'")
parser.add_argument("--device_id", type=int, default=3, help="ID of the target device")
parser.add_argument("--mode", type=str, default="GRAPH", choices=["GRAPH", "PYNATIVE"],
help="Context mode, support 'GRAPH', 'PYNATIVE'")
parser.add_argument("--save_graphs", type=bool, default=False, choices=[True, False],
help="Whether to save intermediate compilation graphs")
parser.add_argument("--save_graphs_path", type=str, default="./graphs")
input_args = parser.parse_args()
return input_args
def train(input_args):
use_ascend = context.get_context(attr_key='device_target') == "Ascend"
# 读取训练配置
config = load_yaml_config(input_args.config_file_path)
# 创建训练集和测试集
train_dataset, test_dataset = create_training_dataset(data_params, shuffle=True)
# 初始化模型
model = Model(config)
problem = FlowWithLoss(model)
# 前向函数
def forward_fn(data, label):
...
grad_fn = ops.value_and_grad(forward_fn, None, optimizer.parameters, has_aux=False)
# 训练的前向和反向过程
@jit
def train_step(data, label):
...
# 数据下沉
sink_process = data_sink(train_step, train_dataset, 1)
# 训练流程
for epoch in range(1, config["epochs"] + 1):
model.set_train()
train()
# 训练和验证函数,采用MindSpore函数式编程范式编写,注意打印内容尽量统一
print(f"epoch: {epoch} train loss: {step_train_loss} epoch time: {time.time() - time_beg:.2f}s")
# 验证
if epoch % config['eval_interval'] == 0:
model.set_train(False)
print("================================Start Evaluation================================")
eval()
print(f"epoch: {epoch} eval loss: {step_train_loss} epoch time: {time.time() - time_beg:.2f}s")
print("=================================End Evaluation=================================")
if epoch % config['save_ckpt_interval'] == 0:
save_checkpoint(model, 'my_model.ckpt')
if __name__ == '__main__':
print(f"pid: {os.getpid()}")
print(datetime.datetime.now())
# 读取脚本入参
args = parse_args()
context.set_context(mode=context.GRAPH_MODE if args.mode.upper().startswith("GRAPH") else context.PYNATIVE_MODE,
save_graphs=args.save_graphs,
save_graphs_path=args.save_graphs_path,
device_target=args.device_target,
device_id=args.device_id)
print(f"Running in {args.mode.upper()} mode, using device id: {args.device_id}.")
# context设置,由于Ascend和GPU使用的差异,需要使用use_ascend变量进行判断
start_time = time.time()
# 调用训练函数
train(args)
print("End-to-End total time: {}s".format(time.time() - start_time))
参数按照模型、数据、优化器等类别分类,放在"./configs"目录下,配置中的路径参数都是根目录的相对路径。参数命名规范统一格式,格式如下:
model:
in_channels: 3
out_channels: 3
height: 192
width: 384
encoder_depth: 6
decoder_depth: 6
decoder_num_heads: 16
data:
train_dataset_path: "./dataset/test.npy"
test_dataset_path: "./dataset/train.npy"
grid_path: "./dataset/grid.npy"
batch_size: 32
optimizer:
epochs: 1000
lr: 0.0005
wave_level: 1
其中,总目录中的README对整体背景、技术路线、结果进行讲解,在每个案例中,可以分别在案例的角度描述,注意整体和局部的详略关系,避免重复描述和重复代码。
【必须】README.md和README_CN.md,中英文README文件,一般包含以下部分:
# 标题
## 概述
简单介绍一下案例的背景、方法、数据集、效果等。
## 快速开始
为用户提供快速运行脚本的方法,一般提供脚本调用和Jupyter Notebook两种方式。其中,脚本调用需要展示启动命令的入参含义
### 训练方式一:在命令行中调用`train.py`脚本
python train.py --config_file_path ./configs/burgers.yaml --mode GRAPH --device_target Ascend --device_id 0
其中,
`--config_file_path`表示参数文件的路径,默认值'./burgers_cfg.yaml';
`--mode`表示运行的模式,'GRAPH'表示静态图模式, 'PYNATIVE'表示动态图模式,默认值'GRAPH';
`--device_target`表示使用的计算平台类型,可以选择'Ascend'或'GPU',默认值'Ascend';
`--device_id`表示使用的计算卡编号,可按照实际情况填写,默认值0;
### 训练方式二:运行Jupyter Notebook
您可以使用中英文版本的Jupyter Notebook(附链接)逐行运行训练和验证代码。
## 结果展示
用1-2张图的方式展示模型推理的效果,最好为gif。
## 性能
如果案例涉及到GPU和Ascend双后端,则需要用表格的形式展示训练的主要性能指标进行对比。
| 参数 | NPU | GPU |
|:----------------------:|:--------------------------:|:---------------:|
| 硬件资源 | Ascend, 显存32G | NVIDIA V100, 显存32G |
| MindSpore版本 | >=2.0.0 | >=2.0.0 |
| 数据集 | [Burgers数据集](https://download.mindspore.cn/mindscience/mindflow/dataset/applications/physics_driven/burgers_pinns/) | [Burgers数据集](https://download.mindspore.cn/mindscience/mindflow/dataset/applications/physics_driven/burgers_pinns/) |
| 参数量 | 6e4 | 6e4 |
| 训练参数 | batch_size=8192, steps_per_epoch=1, epochs=15000 | batch_size=8192, steps_per_epoch=1, epochs=15000 |
| 测试参数 | batch_size=8192, steps=4 | batch_size=8192, steps=4 |
| 优化器 | Adam | Adam |
| 训练损失(MSE) | 0.001 | 0.0001 |
| 验证损失(RMSE) | 0.010 | 0.008 |
| 训练速度(ms/step) | 10 | 130 |
## 贡献者
gitee id: [id](开发者gitee个人空间的链接)
email: myemail@163.com
Jupyter Notebook文件格式可参考2D_steady_CN.ipynb。
将主要代码模块从训练脚本中抽出,有序分块放入Jupyter Notebook文件。Jupyter Notebook一般包含概述
、问题背景
、技术路径
、依赖导入
、数据集制作
、模型搭建
、模型训练
、结果展示
等部分。在每个部分,应当对代码重要内容进行说明,保证按照说明执行代码块能正常运行。
请认真阅读MindScience贡献指南,提高代码合入效率。在确认代码完成度接近完成后,联系代码仓管理员进行代码review,根据review意见修改,代码仓门禁通过后,需要2位审核人通过审核,完成合入。
Dear OpenI User
Thank you for your continuous support to the Openl Qizhi Community AI Collaboration Platform. In order to protect your usage rights and ensure network security, we updated the Openl Qizhi Community AI Collaboration Platform Usage Agreement in January 2024. The updated agreement specifies that users are prohibited from using intranet penetration tools. After you click "Agree and continue", you can continue to use our services. Thank you for your cooperation and understanding.
For more agreement content, please refer to the《Openl Qizhi Community AI Collaboration Platform Usage Agreement》