
DeePMD-kit 使用入门
运行DeePMD-Kit
准备工作
使用PBS脚本进行提交,规则参考集群使用说明及样例文件
/public/example/PBS
通过命令
CUDA_VISIBLE_DEVICES=0;CUDA_VISIBLE_DEVICES=1;CUDA_VISIBLE_DEVICES=0,1
指定调用的gpu,0代表节点上的第一块,1代表第二块,0,1代表同时调用,目前集群007,008是带有gpu的节点。集群已经安装了DeePMD-kit v2.0.3 于目录
/public/software/anaconda3/envs/deepmd
更新环境变量以使用该软件
vi ~/.bashrc
export PATH=/public/software/anaconda3/envs/deepmd/bin:$PATH
source ~/.bashrc
如需安装,查看官网教程。
下载样例文件
在官网下载样例文件,保存至个人目录文件夹下,可命名如 example
deepmd-kit/examples at master · deepmodeling/deepmd-kit (github.com)
以水模型的例子为参考,首先进入该目录
cd ~/examlpe/examples/water/se_e2_a/
可以看到 input.json 文件,即DeePMD-kit使用的输入文件。现在复制PBS提交脚本至该目录并修改
cp /public/example/PBS/lammps-gpu.pbs ./
vi lammps-gpu.pbs
修改来指定节点和gpu,如提交至008节点,并调用第一块gpu,绿色为修改项目,分别是:任务名称;提交节点和调用核数;指定gpu队列(注:为限制显存,保证任务正常进行,gpu任务尽量提交至gpu队列);指定训练任务dp train;指定输入文件 input.json ;指定输出文件 LOG.dptrain。除前五行外,#号开始的行被视为注释,通过修改注释行可方便的修改调用的gpu。
#!/bin/bash
#PBS -N GPU-dptrain
#PBS -l nodes=node008:ppn=2
#PBS -q gpu
#PBS -j oecd "$PBS_O_WORKDIR"
NPROCS=`wc -l < $PBS_NODEFILE`########使用第1块gpu计算
OMP_NUM_THREADS=1 CUDA_VISIBLE_DEVICES=0 mpirun -machinefile $PBS_NODEFILE -np $NPROCS dp train input.json >|LOG.dptrain 2>&1########使用第2块gpu计算
#OMP_NUM_THREADS=1 CUDA_VISIBLE_DEVICES=1 mpirun -machinefile $PBS_NODEFILE -np $NPROCS lmp_gpu -sf gpu -in in.file >|LOG.lammps 2>&1########使用两块gpu计算
#OMP_NUM_THREADS=1 mpirun -machinefile $PBS_NODEFILE -np $NPROCS lmp_gpu -sf gpu -pk gpu 2 -in in.file >|LOG.lammps 2>&1/public/bin/info_job.sh
使用该脚本
qsub lammps-gpu.pbs
来提交训练任务。当任务执行中,当前目录会生成以下文件:
train.log
: 训练的记录文件lcurve.out
: 机器学习的学习曲线model.ckpt.data-00000-of-00001
,model.ckpt.index
,checkpoint
,model.ckpt.meta
: 以上三个为训练存档点
恭喜!已经成功开始第一次机器学习训练了!
浏览输出文件
使用 cat 命令来浏览输出文件
cat LOG.dptrain
你可看到
DEEPMD INFO initialize model from scratch
DEEPMD INFO broadcast global variables to other tasks
DEEPMD INFO start training at lr 1.00e-03 (== 1.00e-03), decay_step 5000, decay_rate 0.950006, final lr will be 3.51e-08
2022-01-19 09:03:33.004718: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcublas.so.11
2022-01-19 09:03:35.748227: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcublas.so.11
2022-01-19 09:03:37.685970: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcublasLt.so.11
2022-01-19 09:03:38.244605: I tensorflow/stream_executor/platform/default/dso_loader.cc:53] Successfully opened dynamic library libcublasLt.so.11
DEEPMD INFO batch 100 training time 17.41 s, testing time 0.38 s
DEEPMD INFO batch 200 training time 13.58 s, testing time 0.37 s
DEEPMD INFO batch 300 training time 13.60 s, testing time 0.37 s
DEEPMD INFO batch 400 training time 13.42 s, testing time 0.36 s
DEEPMD INFO batch 500 training time 13.41 s, testing time 0.38 s
DEEPMD INFO batch 600 training time 13.68 s, testing time 0.32 s
DEEPMD INFO batch 700 training time 13.60 s, testing time 0.38 s
DEEPMD INFO batch 800 training time 13.52 s, testing time 0.36 s
DEEPMD INFO batch 900 training time 13.55 s, testing time 0.37 s
DEEPMD INFO batch 1000 training time 13.44 s, testing time 0.37 s
DEEPMD INFO saved checkpoint model.ckpt
DEEPMD INFO batch 1100 training time 13.59 s, testing time 0.38 s
DEEPMD INFO batch 1200 training time 13.64 s, testing time 0.35 s
DEEPMD INFO batch 1300 training time 13.40 s, testing time 0.35 s在
batch
后面的数字表明程序已经放入了多少数据进行训练。这个数字的显示间隔,即100,是在输入文件的"disp_freq": 100
设置的。现在来看看你的学习曲线lcurve.out
cat
lcurve.out
你将会看到:
# step rmse_val rmse_trn rmse_e_val rmse_e_trn rmse_f_val rmse_f_trn lr
0 3.79e+01 2.59e+01 1.62e-01 1.03e-01 1.20e+00 8.20e-01 1.0e-03
100 1.34e+01 7.90e+00 5.16e-01 5.25e-01 4.23e-01 2.50e-01 1.0e-03
200 8.28e+00 6.65e+00 6.85e-01 6.86e-01 2.61e-01 2.09e-01 1.0e-03
300 4.85e+00 2.79e+00 1.91e-01 1.94e-01 1.53e-01 8.80e-02 1.0e-03
400 4.98e+00 1.71e+00 2.03e-02 7.61e-01 1.57e-01 5.06e-02 1.0e-03
500 4.31e+00 2.48e+00 1.75e-01 1.73e-01 1.36e-01 7.83e-02 1.0e-03
600 7.06e+00 2.08e+00 9.60e-01 7.75e-01 2.22e-01 6.29e-02 1.0e-03
700 4.95e+00 3.22e+00 4.69e-03 4.21e-03 1.57e-01 1.02e-01 1.0e-03
800 5.90e+00 1.88e+00 6.27e-01 1.05e+00 1.86e-01 5.31e-02 1.0e-03
900 3.97e+00 3.74e+00 6.12e-03 4.06e-03 1.26e-01 1.18e-01 1.0e-03
1000 4.08e+00 2.52e+00 2.51e-01 2.51e-01 1.29e-01 7.94e-02 1.0e-03
1100 3.54e+00 3.27e+00 1.32e-01 1.32e-01 1.12e-01 1.03e-01 1.0e-03
1200 5.61e+00 6.73e+00 1.95e-01 1.98e-01 1.77e-01 2.13e-01 1.0e-03
1300 7.39e+00 3.69e+00 1.49e+00 1.68e+00 2.31e-01 1.09e-01 1.0e-03
1400 4.43e+00 2.98e+01 4.65e-02 1.31e+00 1.40e-01 9.42e-01 1.0e-03
1500 5.60e+00 5.44e+00 3.17e-01 3.21e-01 1.77e-01 1.72e-01 1.0e-03
1600 5.30e+00 2.62e+00 1.59e-01 1.56e-01 1.67e-01 8.26e-02 1.0e-03
1700 3.51e+00 3.44e+00 2.05e-01 2.39e+00 1.11e-01 9.05e-02 1.0e-03
1800 3.38e+00 2.65e+00 1.68e-01 1.69e-01 1.07e-01 8.38e-02 1.0e-03
1900 3.72e+00 2.18e+00 1.07e-01 1.08e-01 1.18e-01 6.90e-02 1.0e-03这些数字展示了当前机器学习模型对于数据预测的误差有多大。
rmse_e_trn
意味着在测试集上使用机器学习模型预测的能量误差会有多大。rmse_e_val
意味着在训练集上使用机器学习模型预测的能量误差会有多大。rmse_f_tst
和rmse_f_trn
表示相同意义,不过是对于力的预测. 你可以使用Matplotlib、
Python、Origin进行作图。进阶使用
准备训练数据
前半部分仅仅是让你运行DeePMD-kit进行训练。为了训练一个针对你的体系的模型,你需要自己来准备数据。这些数据都是第一性原理计算得到的数据。这些数据可以是单点能计算得到的数据,或者是分子动力学模拟得到的数据。作为数据集需要的数据有:
- 体系的结构文件:
coord.npy
- 体系的结构文件对应的元素标记:
type.raw
- 体系的结构文件对应的能量:
energy.npy
- 体系的结构文件对应的力:
force.npy
- 体系的结构文件对应的晶胞大小,如果是非周期性体系,请在训练文件里准备一个超大周期边界条件:
box.npy
代码块里的文件名为DeePMD-kit使用的命名。
npy
后缀为Python的numpy代码包生成的文件,请在此之前学习numpy。现在我们来看看DeePMD-kit的训练数据格式。之前我们训练的水模型的数据集储存在 ~/example/examples/water/data/data_0
. 让我们来看看数据集的目录结构:# directory structre for training data .
├── data_0
│ ├── set.000
│ │ ├── box.npy
│ │ ├── coord.npy
│ │ ├── energy.npy
│ │ └── force.npy
│ ├── type.raw
│ └── type_map.raw
├── data_1
│ ├── set.000
│ │ ├── box.npy
│ │ ├── coord.npy
│ │ ├── energy.npy
│ │ └── force.npy
│ ├── set.001
│ │ ├── box.npy
│ │ ├── coord.npy
│ │ ├── energy.npy
│ │ └── force.npy
│ ├── type.raw
│ └── type_map.raw
├── data_2
│ ├── set.000
│ │ ├── box.npy
│ │ ├── coord.npy
│ │ ├── energy.npy
│ │ └── force.npy
│ ├── type.raw
│ └── type_map.raw
└── data_3
├── set.000
│ ├── box.npy
│ ├── coord.npy
│ ├── energy.npy
│ └── force.npy
├── type.raw
└── type_map.raw
显然,我们会看到
type.raw
文件和一堆以set
开头的目录。type.raw
文件记录了体系的元素信息。如果你打开你会发现它仅仅记录了一堆数字。这些数字对应着你在water_se_a.json
中"type_map":["O","H"]
的信息。此时0
代表O
,1
代表H
。对应着["O","H"]
中的位置,其中第一位为0。0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
box.npy
,coord.npy
,energy.npy
和force.npy
储存的信息在上文已经说过。唯一需要注意的是这些文件都储存着一个超大的矩阵。如果我们有Y个结构,每个结构有X个原子。box.npy
,coord.npy
,energy.npy
和force.npy
对应的矩阵形状分别是 (Y, 9), (Y, X*3), (Y, 1), (Y, X*3)。设置输入文件
输入文件是
json
文件。你可以使用之前我们的json
文件进行细微改动就投入到自己体系的训练中。先来看一个适用于DeePMD-kit 2.0的例子{
"_comment": " model parameters",
"model": {
"type_map": [ "O", "H" ],
"descriptor": {
"type": "se_e2_a",
"sel": [ 46, 92 ],
"rcut_smth": 0.50,
"rcut": 6.00,
"neuron": [ 25, 50, 100 ],
"resnet_dt": false,
"axis_neuron": 16,
"seed": 1,
"_comment": " that's all"
},
"fitting_net": {
"neuron": [ 240, 240, 240 ],
"resnet_dt": true,
"seed": 1,
"_comment": " that's all"
},
"_comment": " that's all"
},
"learning_rate": {
"type": "exp",
"decay_steps": 5000,
"start_lr": 0.001,
"stop_lr": 3.51e-8,
"_comment": "that's all"
},
"loss": {
"type": "ener",
"start_pref_e": 0.02,
"limit_pref_e": 1,
"start_pref_f": 1000,
"limit_pref_f": 1,
"start_pref_v": 0,
"limit_pref_v": 0,
"_comment": " that's all" },
"training": {
"training_data": {
"systems": [ "../data/data_0/", "../data/data_1/", "../data/data_2/" ],
"batch_size": "auto",
"_comment": "that's all"
},
"validation_data": {
"systems": [ "../data/data_3" ],
"batch_size": 1,
"numb_btch": 3,
"_comment": "that's all"
},
"numb_steps": 1000000,
"seed": 10,
"disp_file": "lcurve.out",
"disp_freq": 100,
"save_freq": 1000,
"_comment": "that's all"
},
"_comment": "that's all"
}
这些需要修改的关键词如下:
"type": "se_a"
: 设置描述符(descriptor)类型。"sel": [46, 92]
: 设置每个原子的截断半径内所拥有的最大原子数。注意这里的两个数字46,92分别对应的是O
原子和H
原子。与你在type_map
里设置的元素类型是相对应的。
"descriptor" :{"type": "se_a","sel": [46, 92],"rcut_smth": 0.50,"rcut": 6.00,"neuron": [25, 50, 100],"resnet_dt": false,"axis_neuron": 16,"seed": 1,"_comment": " that's all"},在”training”的”training_data”下"systems": ["../data/data_0/", "../data/data_1/", "../data/data_2/"]
: 设置包含训练数据的目录。"batch_size": auto
, 这个会根据体系原子数进行分配,不过我们自己通常设置为1,因为体系原子数有400-800个左右。
"training_data": {"systems": ["../data/data_0/", "../data/data_1/", "../data/data_2/"],"batch_size": "auto","_comment": "that's all"}在”training”的”validation_data”下
"systems": ["../data/data_3"]
: 设置包含测试数据的目录。"batch_size": 1
, 这个会根据体系原子数进行分配,不过我们自己通常设置为1,因为体系原子数有400-800个左右。"numb_btch": 3
, 每次迭代中,测试的结构数量为batch_size
乘以numb_btch
。- 更多参数说明,请参考官方文档: deepmd-kit/train-input-auto.rst at master · deepmodeling/deepmd-kit (github.com)
默认情况下,每一训练步骤中,DeePMD-kit随机从数据集中挑选结构加入本轮训练,这一步骤加入数据的多少取决于
batch_size
的大小,此时,各 system 中数据被使用的概率是均等的。 若希望控制各 system 数据的权重,可使用auto_prob
来控制,其参数选项如下所示prob_uniform
: 各 system 数据权重均等。prob_sys_size
: 各 system 数据的权重取决于其各自的大小。prob_sys_size
: 写法示例如下:sidx_0:eidx_0:w_0; sidx_1:eidx_1:w_1;...
。 该参数中,sidx_i
和eidx_i
表示第i
组数据的起止点,规则同 Python 语法中的切片,w_i
则表示该组数据的权重。在同一组中,各 system 数据的权重取决于各自的大小。batch_size
的值可手动设定,根据经验一般根据“乘以原子数≤32”的规则设定。新版则支持自动设定,若设定为"auto"
则表示按照此规则自动设置,若设定为"auto:N"
则根据“乘以原子数≤N”的规则设定。- 由于参数较多,更多详细说明,请参见官方文档。
开始训练
使用以下命令开始:
dp train input.json
使用以下命令,可以重启训练或从一个中途停止的训练继续训练
dp train input.json --restart model.ckpt
!在集群上训练,需使用PBS脚本提交到作业系统上!
利用生成的势函数进行分子动力学(MD)模拟
当我们完成训练之后,我们需要根据节点文件(
model.ckpt*
)冻结(Freeze)出一个模型来。利用如下命令,可以冻结模型:dp freeze
你将会得到一个
*.pb
文件。利用此文件可以使用LAMMPS
,ASE
等软件进行分子动力学模拟。通过在LAMMPS的in文件中指定pair_style deepmd graph.003.pb
pair_coeff * *即使用了深度势进行分子动力学模拟。
模型压缩
机器学习势能*.pb
文件进行MD模拟虽然已经非常迅速了。但是还有提升的空间。建议将原训练文件夹备份后复制,我们利用如下命令进行压缩(文件夹下应该含有对应的input.json
文件和checkpoint文件):module load deepmd/2.0
dp compress -i normal-model.pb -o compressed-model.pb -l compress.log