Active Learning: Single-Molecule Comparison to M3GNet-UP-2022

Compare the retrained active-learning model against the M3GNet universal potential by plotting predicted-versus-reference forces for the same single-molecule workflow.

Load the Simple Active Learning job from disk.

retrained_params_job is the best ParAMS training job that was done during the Active Learning.

from scm.simple_active_learning import SimpleActiveLearningJob
from scm.params.plams.paramsjob import ParAMSJob
from scm.params import ResultsImporter, NoParameters
import scm.plams as plams
import os

# replace the path with your own path !
previous_sal_job_path = os.path.expandvars(
    "$AMSHOME/examples/SAL/Output/SingleMolecule/plams_workdir/sal"
)
sal_job = SimpleActiveLearningJob.load_external(previous_sal_job_path)
retrained_params_job = sal_job.results.get_params_job()

Get results for M3GNet-UP-2022 universal potential

Are the retrained results any better than those from the M3GNet-UP-2022 universal potential?

To find out, we need to evaluate the training and validation sets also with M3GNet-UP-2022. This can be done with the ParAMS “SinglePoint” task, which does not perform any parameter optimization but instead evaluates the training and validation sets with a given engine.

We initialize the new ParAMSJob using the same input file as for the retraining, modify the task, remove the MachineLearning block, and set the engine settings.

new_params_job = ParAMSJob.from_inputfile(retrained_params_job.results.get_inputfile())
# alternative (almost the same meaning): new_params_job = ParAMSJob.from_yaml(sal_job.results.get_reference_data_directory())
new_params_job.name = "m3gnet-up"
new_params_job.settings.input.Task = "SinglePoint"
del new_params_job.settings.input.MachineLearning
new_params_job.settings.input.MLPotential.Model = "M3GNet-UP-2022"
new_params_job.settings.input.ParallelLevels.Jobs = 1

plams.init(folder="plams_workdir_singlepoint_validation")
new_params_job.run();
PLAMS working folder: /path/to/plams_workdir_singlepoint_validation
[13.08|12:47:47] JOB m3gnet-up STARTED
[13.08|12:47:47] JOB m3gnet-up RUNNING
[13.08|12:48:00] JOB m3gnet-up FINISHED
[13.08|12:48:00] JOB m3gnet-up SUCCESSFUL

M3GNet-UP-2022 (predicted) forces vs. the reference (here UFF) forces

new_params_job.results.plot_simple_correlation(
    "forces", source="best", title="M3GNet-UP-2022"
);
image generated from notebook

Here we can see that M3GNet-UP-2022 gives quite different force prediction compared to our chosen reference method (UFF force field).

Note that M3GNet-UP-2022 was trained to PBE DFT data, and the plot above shows the agreement to the UFF force field. The plot does not show the agreement to the PBE level of theory to which M3GNet-UP-2022 was originally trained!

Retrained M3GNet (predicted) forces vs. the reference (here UFF) forces

retrained_params_job.results.plot_simple_correlation(
    "forces", source="best", title="Retrained M3GNet"
);
image generated from notebook

This is the same plot as shown in the previous tutorial. We can see that the active learning retraining has led to significant improvements in reproducing the reference data!

See also

Python Script

#!/usr/bin/env python
# coding: utf-8

# ## Load the Simple Active Learning job from disk.
# 
# ``retrained_params_job`` is the best ParAMS training job that was done during the Active Learning.

from scm.simple_active_learning import SimpleActiveLearningJob
from scm.params.plams.paramsjob import ParAMSJob
from scm.params import ResultsImporter, NoParameters
import scm.plams as plams
import os

# replace the path with your own path !
previous_sal_job_path = os.path.expandvars(
    "$AMSHOME/examples/SAL/Output/SingleMolecule/plams_workdir/sal"
)
sal_job = SimpleActiveLearningJob.load_external(previous_sal_job_path)
retrained_params_job = sal_job.results.get_params_job()


# ## Get results for M3GNet-UP-2022 universal potential
# 
# Are the retrained results any better than those from the M3GNet-UP-2022 universal potential?
# 
# To find out, we need to evaluate the training and validation sets also with M3GNet-UP-2022. This can be done with the ParAMS "SinglePoint" task, which does not perform any parameter optimization but instead evaluates the training and validation sets with a given engine.
# 
# We initialize the new ParAMSJob using the same input file as for the retraining, modify the task, remove the MachineLearning block, and set the engine settings.

new_params_job = ParAMSJob.from_inputfile(retrained_params_job.results.get_inputfile())
# alternative (almost the same meaning): new_params_job = ParAMSJob.from_yaml(sal_job.results.get_reference_data_directory())
new_params_job.name = "m3gnet-up"
new_params_job.settings.input.Task = "SinglePoint"
del new_params_job.settings.input.MachineLearning
new_params_job.settings.input.MLPotential.Model = "M3GNet-UP-2022"
new_params_job.settings.input.ParallelLevels.Jobs = 1

plams.init(folder="plams_workdir_singlepoint_validation")
new_params_job.run();


# ### M3GNet-UP-2022 (predicted) forces vs. the reference (here UFF) forces

new_params_job.results.plot_simple_correlation(
    "forces", source="best", title="M3GNet-UP-2022"
);


# Here we can see that M3GNet-UP-2022 gives quite different force prediction compared to our chosen reference method (UFF force field).
# 
# Note that M3GNet-UP-2022 was trained to PBE DFT data, and the plot above shows the agreement to the UFF force field. The plot does not show the agreement to the PBE level of theory to which M3GNet-UP-2022 was originally trained!

# ### Retrained M3GNet (predicted) forces vs. the reference (here UFF) forces

retrained_params_job.results.plot_simple_correlation(
    "forces", source="best", title="Retrained M3GNet"
);


# This is the same plot as shown in the previous tutorial. We can see that the active learning retraining has led to significant improvements in reproducing the reference data!