机器学习势

本教程包含:

For examples how to train, test, and use ML potentials (MLPs) you can see tutorials below. In addition, you can check the command-line and Python API manuals. For these examples, the materials are available as zip archive. It contains Jupyter notebook tutorial_mlp.ipynb. After uploading the content of the zipped directory to the XACS cloud, you can run it on XACS Jupyter lab. For a fast training speed, here we use a 451-point dataset for H2 with H–H bond length ranging from 0.5 to 5.0 Å. The dataset is randomly splitted into a training set of 361 points (H2.xyz, H2_HF.en, H2_HF.grad, which store the geometries, potential energies, and energy gradients, respectively) and a test set of 90 points (names begin with “test_”).

支持的机器学习势

MLatom支持的MLP(以粗体显示)及其他代表(改编自我们的 MLP基准论文 )的概述:

_images/mlp.png

备注

在本教程中,用在小数据上训练的最快势是使用核模型,例如KREG模型或sGDML。较慢的势可能更准确,且需要更多的数据。例如,ANI具有出色的成本/性能比,但如果您有足够的资源,可以使用非常慢的MACE,该模型已被证明在性能上超过了大多数其他MLP模型。总的来说,您需要根据您的数据和应用程序对它们进行基准测试。

Prerequisites

You can run the examples on the XACS cloud. Otherwise, you might need to install the required packages for MLPs.

For the KREG model through the KREG_API program, the following commands for installing packages might be required (depending on your OS/environment):

sudo apt install libomp-dev
sudo apt install libmkl-intel-lp64
sudo apt install libmkl-intel-thread
sudo apt install libmkl-core

训练

您可以在 Python 中或通过 命令行 (输入文件)训练机器学习势。

Python API

首先导入MLatom:

import mlatom as ml

在开始训练前需要先加载数据:

molDB = ml.data.molecular_database.from_xyz_file(filename = 'H2.xyz')
molDB.add_scalar_properties_from_file('H2_HF.en', 'energy')
molDB.add_xyz_vectorial_properties_from_file('H2_HF.grad', 'energy_gradients')

然后定义一个您想用的机器学习势:

# Here we define the KREG model for demonstration purposes as it is the fastest
model = ml.models.kreg(model_file='kreg.npz')

# Alternatives:
# model = ml.models.mace(model_file='mace.pt')
# model = ml.models.ani(model_file='ani.pt')
# model = ml.models.dpmd(model_file='dpmd.pt')
# model = ml.models.gap(model_file='gap.pt') # for GAP-SOAP
# model = ml.models.physnet(model_file='physnet.pt')
# model = ml.models.sgdml(model_file='sgdml.pt')

然而,默认选项并不总是能得到预期结果。特别是像KREG这样的核方法需要进行 超参数优化 。对于本教程,您可以通过以下方式定义KREG的超参数:

model = ml.models.kreg(model_file='kreg.npz', prior='mean')
model.hyperparameters.sigma = 1.0
model.hyperparameters['lambda'].value = 1e-6   # 'lambda' is reserverd by Python but the value can still be set like this

另一方面,像MACE这样的模型非常慢,因此您可能希望首先尝试请求少量的epochs,以确定训练是否有效:

model = ml.models.mace(model_file='mace.pt', hyperparameters={'max_num_epochs': 100})

现在您可以训练选中的机器学习势:

model.train(molecular_database=molDB, property_to_learn='energy', xyz_derivative_property_to_learn='energy_gradients')

备注

仅基于能量进行训练会更快,但也会更不准确: model.train(molecular_database=molDB, property_to_learn='energy')

在训练诸如MACE、ANI或PhysNet等神经网络时,默认的子训练集划分(用于反向传播,通常在文献中称为“训练集”)和验证集(用于监测拟合质量和提前停止)比例为80:20。您可以使用MLatom生成另一个划分,并将其用于训练,如下所示:

subtrainDB, valDB = molDB.split(fraction_of_points_in_splits=[0.9, 0.1])
model.train(molecular_database=subtrainDB, validation_molecular_database=valDB, property_to_learn='energy', xyz_derivative_property_to_learn='energy_gradients')

在训练结束结束时,您应该可以得到模型文件。

参见 手册 以获取更多选项信息。

命令行(输入文件)

您可以对以下输入文件 train.inp 进行修改,以选用合适的机器学习势,并提供辅助文件 H2.xyzH2_HF.enH2_HF.grad 来进行训练。

createMLmodel            # task to create MLmodel
XYZfile=H2.xyz           # file with geometies
Yfile=H2_HF.en           # file with energies
YgradXYZfile=H2_HF.grad  # file with energy gradients
MLmodelType=[model type] # specify the model type to be KREG, MACE, ANI, etc.
MLmodelOut=MyModel       # give your trained model a name

然后再终端中运行MLatom

mlatom train.inp

或者,您也可以在命令行中运行所有选项(将 [model type] 替换为实际的模型):

mlatom createMLmodel XYZfile=H2.xyz Yfile=H2_HF.en YgradXYZfile=H2_HF.grad MLmodelType=[model type] MLmodelOut=MyModel

几个重要说明:默认选项并不总是能得到好的结果。特别是像KREG这样的核方法需要进行 超参数优化 。对于本教程,您可以通过以下方式定义KREG的超参数(下载输入文件 train_KREG.inp):

createMLmodel            # task to create MLmodel
XYZfile=H2.xyz           # file with geometries
Yfile=H2_HF.en           # file with energies
YgradXYZfile=H2_HF.grad  # file with energy gradients
MLmodelType=KREG         # specify the model type to be KREG
MLmodelOut=KREG.unf      # give your trained model a name
sigma=1.0                # hyperparameter sigma defining the width of Gaussian
lambda=0.000001          # regularization parameter

然后运行MLatom

rm -f kreg.unf # KREG will not train if it finds the file with the model
mlatom train.inp

备注

目前KREG模型有两种实现:一种是 KREG_API (Python API的默认值,模型以 npz 格式输出),另一种是 MLatomF (命令行的默认值)。

另一方面,像MACE这样的模型非常慢,因此您可能希望首先尝试请求少量的epochs,以确定训练是否有效:

createMLmodel            # task to create MLmodel
XYZfile=H2.xyz           # file with geometies
Yfile=H2_HF.en           # file with energies
YgradXYZfile=H2_HF.grad  # file with energy gradients
MLmodelType=MACE         # specify the model type to be MACE
MLmodelOut=mace.pt       # give your trained model a name
mace.max_num_epochs=100  # only train for 100 epochs (optional)

请参见 手册 来获取更多选项。

超参数优化

超参数优化的一般步骤是将训练数据集分割成子训练集和验证集,然后在子训练集上训练超参数的同时,将验证集上的误差最小化。不同的模型有不同的超参数,神经网络对超参数的变化不像核方法那样敏感。因此,必须优化核方法的超参数。

Python API

对于KREG模型,我们可以使用简单的网格搜索优化超参数。

model = ml.models.kreg(model_file=f'kreg.npz')

sub, val = molDB.split(number_of_splits=2, fraction_of_points_in_splits=[0.9, 0.1])

model.hyperparameters['sigma'].minval = 2**-5 # As an example, modifying the default lower bound of the hyperparameter sigma
model.optimize_hyperparameters(subtraining_molecular_database=sub, validation_molecular_database=val,
                                optimization_algorithm='grid',
                                hyperparameters=['lambda', 'sigma'],
                                training_kwargs={'property_to_learn': 'energy', 'prior': 'mean'},
                                prediction_kwargs={'property_to_predict': 'estimated_y'})
lmbd = model.hyperparameters['lambda'].value ; sigma=model.hyperparameters['sigma'].value
valloss = model.validation_loss
print('Optimized sigma:', sigma)
print('Optimized lambda:', lmbd)
print('Optimized validation loss:', valloss)
# Train the model with the optimized hyperparameters to dump it to disk.
model.train(molecular_database=molDB, property_to_learn='energy')
# Train the model with the optimized hyperparameters to dump it to disk.
model.train(molecular_database=molDB, property_to_learn='energy', xyz_derivative_property_to_learn='energy_gradients')

输出如下所示(它可能随子训练集和验证集的随机子抽样而变化):

Optimized sigma: 0.10511205190671434
Optimized lambda: 2.910383045673381e-11
Optimized validation loss: 3.1550365181164988e-06

其他参数也是可用的,例如SciPy(Nelder-Mead, BFGS, L-BFGS-B, Powell, CG, Newton-CG, TNC, COBYLA, SLSQP, trust-constr, dogleg, trust-krylov, trust-exact)和hyperopt库(TPE)。

关于不同模型中超参数的描述,请参见 手册

自定义验证损失函数

MLatom还具有通过自定义验证损失函数优化超参数的功能。

我们通过修改上述示例来展示它,使其在能量和梯度上进行训练,但仅在能量上优化超参数。此示例还展示了如何设置新的超参数(需要模型支持它):

model = ml.models.kreg(model_file=f'kreg.npz')

sub, val = molDB.split(number_of_splits=2, fraction_of_points_in_splits=[0.9, 0.1])

model.hyperparameters['sigma'].minval = 2**-5
# Defining a new hyperparameter for regularizing the energy gradients
model.hyperparameters['lambdaGradXYZ'] = ml.models.hyperparameter(value=2**-35,
                                                        minval=2**-35,
                                                        maxval=1.0,
                                                        optimization_space='log',
                                                        name='lambdaGradXYZ')

# Custom validation loss function
def vlf(validation_db):
    estimated_y = validation_db.get_properties('estimated_energy')
    y = validation_db.get_properties('energy')
    return ml.stats.rmse(estimated_y,y)

model.optimize_hyperparameters(subtraining_molecular_database=sub, validation_molecular_database=val,
                                optimization_algorithm='grid', optimization_algorithm_kwargs={'grid_size': 4},
                                hyperparameters=['lambda', 'sigma', 'lambdaGradXYZ'],
                                training_kwargs={'property_to_learn': 'energy', 'xyz_derivative_property_to_learn': 'energy_gradients', 'prior': 'mean'},
                                prediction_kwargs=None,
                                validation_loss_function=vlf, validation_loss_function_kwargs={'validation_db': val},
                                maximum_evaluations=1000)
lmbd = model.hyperparameters['lambda'].value ; sigma=model.hyperparameters['sigma'].value
valloss = model.validation_loss
print('Optimized sigma:', sigma)
print('Optimized lambda:', lmbd)
print('Optimized validation loss:', valloss)

输出如下所示(它可能随子训练集和验证集的随机子抽样而变化):

Optimized sigma: 0.7937005259840996
Optimized lambda: 2.910383045673381e-11
Optimized validation loss: 0.00036147922242234806

命令行(输入文件)

通过命令行优化超参数可能更简单,但灵活性较差。上面的例子可以在 train_KREG_opt.inp 中修改为KREG模型:

createMLmodel            # task to create MLmodel
XYZfile=H2.xyz           # file with geometies
Yfile=H2_HF.en           # file with energies
YgradXYZfile=H2_HF.grad  # file with energy gradients
MLmodelType=KREG         # specify the model type to be KREG
MLmodelOut=kreg.unf      # give your trained model a name
sigma=opt                # hyperparameter sigma defining the width of Gaussian
lambda=opt               # regularization parameter

在MLatom中运行:

!rm -f kreg.unf
!mlatom train_KREG_opt.inp

输出文件中优化的超参数类似于(它可能会随子训练集和验证集的随机子采样而变化):

Optimal value of lambda is          0.00000000000944
Optimal value of sigma is          1.20080342748521

其他参数也是可用的,例如hyperopt库(TPE)。

关于如何优化超参数的描述,请参见 手册此手册 列出了不同模型支持的超参数。

测试

以下是简短的说明。在相应的教程中给出了更多关于测试MLPs的细节,包括在命令行中 生成学习曲线

Python API

使用模型进行预测: test_H2.xyz, test_H2_HF.en, test_H2_HF.grad

test_molDB = ml.data.molecular_database.from_xyz_file(filename = 'test_H2.xyz')
test_molDB.add_scalar_properties_from_file('test_H2_HF.en', 'energy')
test_molDB.add_xyz_vectorial_properties_from_file('test_H2_HF.grad', 'energy_gradients')

model.predict(molecular_database=test_molDB, property_to_predict='mlp_energy', xyz_derivative_property_to_predict='mlp_gradients')

然后您可以进行任何分析,例如计算RMSE:

ml.stats.rmse(test_molDB.get_properties('energy'), test_molDB.get_properties('mlp_energy'))*ml.constants.Hartree2kcalpermol

ml.stats.rmse(test_molDB.get_xyz_vectorial_properties('energy_gradients').flatten(), test_molDB.get_xyz_vectorial_properties('mlp_gradients').flatten())*ml.constants.Hartree2kcalpermol

命令行(输入文件)

然后您可以使用测试文件测试训练后的模型: use.inp, test_H2.xyz

useMLmodel
XYZfile=test_H2.xyz
YgradXYZestFile=test_gradest.dat
Yestfile=test_enest.dat
MLmodelType=KREG
MLmodelIn=kreg.unf
MLprog=MLatomF
#MLmodelIn=kreg.npz
#MLprog=KREG_API # required for the model saved in npz format

analyze.inp, test_H2_HF.en, test_H2_HF.grad

analyze
Yfile=test_H2_HF.en
YgradXYZfile=test_H2_HF.grad
Yestfile=test_enest.dat
YgradXYZestFile=test_gradest.dat

结果的拟合度很好,R^2 = 0.9998。注意原始单位是Hartree和Hartree/Angstrom。

备注

更简单的方法是在MLatom中使用内置选项进行训练、测试(以及超参数优化——一次完成所有任务)。为此,您可以在命令行或输入文件中使用 estAccMLmodel 选项。有关更多详细信息,请参阅 手册 。将任务分割为独立的训练、预测和分析步骤的优点在于可以检查每个阶段,并且可以比较测试数据集的参考值与估计值。

使用

模型训练完成后,可以在MLatom中进行使用,例如,请参阅有关 单点计算几何优化分子动力学 的专门教程。以下是几何优化的输入文件的简要示例: geomopt.inp, H2_init.xyz

geomopt                      # Request geometry optimization
MLmodelType=KREG             # use ML model of the KREG type
MLmodelIn=kreg.unf           # load the model file
#MLmodelIn=kreg.npz           # load the model file
#MLprog=KREG_API              # required for the model saved in npz format
XYZfile=H2_init.xyz          # The file with the initial guess
optXYZ=eq_KREG.xyz           # optimized geometry output

输出类似于:

==============================================================================
Optimization of molecule 1
==============================================================================

Iteration         Energy (Hartree)
            1             -1.0663613863289
            2             -1.1040852870792
            3             -1.1171046681702
            4             -1.1176623851061
            5             -1.1176625713706

Final energy of molecule      1:          -1.1176625713706 Hartree

优化后的模型储存在 eq_KREG.xyz 中:

2

H             0.0000000000000           0.0000000000000           0.3556619967058
H             0.0000000000000           0.0000000000000          -0.3556619967058

在Python中,几何优化也很简单:

import mlatom as ml

# load initial geometry
mol = ml.data.molecule.from_xyz_file('H2_init.xyz')
print(mol.get_xyz_string())

# load the model
model = ml.models.kreg(model_file='kreg.npz')

# run geometry optimization
ml.optimize_geometry(model=model, molecule=mol, program='ASE')
print(mol.get_xyz_string())

取决于您如何获取您的KREG模型,输出类似于:

MACE势:

等变势能是相对较新的领域,具有在已发表的基准测试中表现出高准确性的潜力。其中之一是 MACE ,我们现在将其添加到MLatom支持的机器学习势中。请参阅上面的图表,其中显示了MLatom支持的MLP(以粗体显示)和其他代表(改编自我们的 MLP基准论文 )。以下我们将展示如何使用MACE。

安装

pip install mlatom
git clone https://github.com/ACEsuit/mace.git
pip install ./mace

数据准备

在这里,我们提供了一个来自 MD17数据集 的1000个点的数据集,作为乙醇分子的训练数据(xyz.dat, en.dat, grad.dat,分别存储几何结构、势能和能量梯度),以及另外1000个点的测试数据(名称以 “test_” 开头)。我们还提供了名为 mace_tutorial.zip 的压缩文件。下文中我们也单独提供了每个文件。

注意能量的单位是Hartree,距离的单位是埃。

通过输入文件、命令行和Python API可以进行MACE的训练、测试和使用。下面我们将展示如何操作。

在命令行或输入文件中训练和测试

createMLmodel            # task to create MLmodel
XYZfile=xyz.dat          # file with geometies
Yfile=en.dat             # file with energies
YgradXYZfile=grad.dat    # file with energy gradients
MLmodelType=MACE         # specify the model type to be MACE
mace.max_num_epochs=100  # only train for 100 epochs (optional)
MLmodelOut=mace.pt       # give your trained model a name

您可以下载上述输入文件 train_MACE.inp 和辅助文件 xyz.dat, en.dat, grad.dat ,然后在终端中使用MLatom运行它:

mlatom train_MACE.inp

或者,您也可以在命令行中运行:

mlatom createMLmodel XYZfile=xyz.dat Yfile=en.dat YgradXYZfile=grad.dat MLmodelType=MACE mace.max_num_epochs=100 MLmodelOut=mace.pt

您还可以在 XACS云平台 上或者它的 终端 中提交任务。平台可免费使用,但只使用CPU训练会很慢。 为了加快测试速度,您可以注释或者删除 YgradXYZfile=grad.dat 命令, 这样只会训练能量但是会很快。

在100次epoch的训练完成后(如果不使用GPU,可能需要花一段时间),您将看到MACE和MLatom生成的训练性能分析。我们的结果如下:

2024-01-05 17:17:31.318 INFO:
+-------------+--------------+------------------+-------------------+
| config_type | RMSE E / meV | RMSE F / meV / A | relative F RMSE % |
+-------------+--------------+------------------+-------------------+
|    train    |     14.3     |       24.0       |        2.45       |
|    valid    |     14.1     |       26.0       |        2.65       |
+-------------+--------------+------------------+-------------------+

验证RMSE为14.1 meV(或0.33 kcal/mol),这对于仅1000个训练点来说是相当令人印象深刻的。

然后您可以使用测试文件测试训练后的模型:use_MACE.inp, test_xyz.dat

useMLmodel
XYZfile=test_xyz.dat
YgradXYZestFile=test_gradest.dat
Yestfile=test_enest.dat
MLmodelType=MACE
MLmodelIn=mace.pt

analyze.inp, test_en.dat, test_grad.dat

analyze
Yfile=test_en.dat
YgradXYZfile=test_grad.dat
Yestfile=test_enest.dat
YgradXYZestFile=test_gradest.dat

分析结果如下所示(注意原始单位是Hartree和Hartree/Angstrom):

Analysis for values
Statistical analysis for 1000 entries in the set
MAE =           0.0006553622464
MSE =          -0.0006529191680
RMSE =           0.0007100342323
mean(Y) =        -154.8910225874238
mean(Yest) =        -154.8916755065918
correlation coefficient =           0.9992099019391
linear regression of {y, y_est} by f(a,b) = a + b * y
    R^2 =           0.9984203065680
...
Analysis for gradients in XYZ coordinates
Statistical analysis for 1000 entries in the set
MAE =           0.0008618973153
MSE =          -0.0000057122824
RMSE =           0.0012088419764
mean(Y) =           0.0000057123026
mean(Yest) =           0.0000000000202
correlation coefficient =           0.9996190787940
linear regression of {y, y_est} by f(a,b) = a + b * y
    R^2 =           0.9992383026890
...

能量约0.45 kcal/mol,梯度约0.76 kcal/mol/A。

在Python中训练和使用模型

MLatom也能在Python脚本中使用。下面是它在Google colab中的使用:

以下是如果您无法访问Google Colab时的命令详细说明。首先,让我们导入MLatom:

import mlatom as ml

这提供了很大的灵活性,您可以从 此处 查看文档。

在Python中进行训练也很简单。

首先,将数据加载到分子数据库中: xyz.dat, en.dat, grad.dat

molDB = ml.data.molecular_database.from_xyz_file(filename = 'xyz.dat')
molDB.add_scalar_properties_from_file('en.dat', 'energy')
molDB.add_xyz_vectorial_properties_from_file('grad.dat', 'energy_gradients')

然后定义一个MACE模型,用数据集进行训练:

model = ml.models.mace(model_file='mace.pt', hyperparameters={'max_num_epochs': 100})
model.train(molDB, property_to_learn='energy', xyz_derivative_property_to_learn='energy_gradients')

利用模型进行预测: test_xyz.dat, test_en.dat, test_grad.dat

test_molDB = ml.data.molecular_database.from_xyz_file(filename = 'test_xyz.dat')
test_molDB.add_scalar_properties_from_file('test_en.dat', 'energy')
test_molDB.add_xyz_vectorial_properties_from_file('test_grad.dat', 'energy_gradients')

model.predict(molecular_database=test_molDB, property_to_predict='mace_energy', xyz_derivative_property_to_predict='mace_gradients')

然后您可以进行任何分析,例如计算RMSE:

ml.stats.rmse(test_molDB.get_properties('energy'), test_molDB.get_properties('mace_energy'))*ml.constants.Hartree2kcalpermol

ml.stats.rmse(test_molDB.get_xyz_vectorial_properties('energy_gradients').flatten(), test_molDB.get_xyz_vectorial_properties('mace_gradients').flatten())*ml.constants.Hartree2kcalpermol

使用模型

模型训练好后,可以在MLatom中应用,例如,几何优化或分子动力学,请参阅MLatom的手册以获取更多细节。这里提供了一个简短的例子来展示几何优化的输入文件: geomopt_MACE.inp, ethanol_init.xyz

geomopt                      # Request geometry optimization
MLmodelType=MACE             # use ML model of the MACE type
MLmodelIn=mace.pt            # the model to be used
XYZfile=ethanol_init.xyz     # The file with the initial guess
optXYZ=eq_MACE.xyz           # optimized geometry output

在Python中,几何优化很简单:ethanol_init.xyz

import mlatom as ml

# load initial geometry
mol = ml.data.molecule.from_xyz_file('ethanol_init.xyz')
print(mol.get_xyz_string())

# load the model
model = ml.models.mace(model_file='mace.pt')

# run geometry optimization
ml.optimize_geometry(model=model, molecule=mol, program='ASE')
print(mol.get_xyz_string())

(p)KREG势

在命令行中的使用请参阅 http://mlatom.com/kreg/

基准测试

在命令行中的使用请参阅 http://mlatom.com/tutorial-on-benchmarking-machine-learning-potentials