Example #1
0
def init():
    model = KIMModel(model_name="SW_StillingerWeber_1985_Si__MO_405512056662_006")

    # Cannot set them all by calling this function only once, because the assertion
    # depends on order
    model.set_opt_params(A=[[5.0]])
    model.set_opt_params(B=[["default"]])
    model.set_opt_params(sigma=[[2.0951, "fix"]])
    model.set_opt_params(gamma=[[1.5]])

    path = Path(__file__).parent.joinpath("configs_extxyz/Si_4")
    tset = Dataset(path)
    configs = tset.get_configs()

    calc = Calculator(model)
    calc.create(configs, use_energy=True, use_forces=True)

    loss = Loss(calc, residual_fn=residual_fn, nprocs=1)

    return loss
Example #2
0
    nn.Tanh(),
    # second hidden layer
    nn.Linear(N1, N2),
    nn.Tanh(),
    # output layer
    nn.Linear(N2, 1),
)
model_c.set_save_metadata(prefix="./kliff_saved_model_c", start=5, frequency=2)

# training set
dataset_path = download_dataset(dataset_name="SiC_training_set")
tset = Dataset(dataset_path)
configs = tset.get_configs()

# calculator
calc = CalculatorTorchSeparateSpecies({"Si": model_si, "C": model_c})
_ = calc.create(configs, reuse=False)

# loss
loss = Loss(calc, residual_data={"forces_weight": 0.3})
result = loss.minimize(method="Adam", num_epochs=10, batch_size=4, lr=0.001)

##########################################################################################
# We can save the trained model to disk, and later can load it back if we want. We can
# also write the trained model to a KIM model such that it can be used in other simulation
# codes such as LAMMPS via the KIM API.

model_si.save("final_model_si.pkl")
model_c.save("final_model_c.pkl")
loss.save_optimizer_state("optimizer_stat.pkl")
Example #3
0
from kliff.models import LennardJones
from kliff.utils import download_dataset

# training set
dataset_path = download_dataset(dataset_name="Si_training_set_4_configs")
tset = Dataset(dataset_path)
configs = tset.get_configs()

# calculator
model = LennardJones()
model.echo_model_params()

# fitting parameters
model.set_opt_params(sigma=[["default"]], epsilon=[["default"]])
model.echo_opt_params()

calc = Calculator(model)
calc.create(configs)

# loss
loss = Loss(calc, nprocs=1)
result = loss.minimize(method="L-BFGS-B",
                       options={
                           "disp": True,
                           "maxiter": 10
                       })

# print optimized parameters
model.echo_opt_params()
model.save("kliff_model.yaml")
Example #4
0
# -------------
#
# KLIFF uses a loss function to quantify the difference between the training set data and
# potential predictions and uses minimization algorithms to reduce the loss as much as
# possible. KLIFF provides a large number of minimization algorithms by interacting with
# SciPy_. For physics-motivated potentials, any algorithm listed on
# `scipy.optimize.minimize`_ and `scipy.optimize.least_squares`_ can be used. In the
# following code snippet, we create a loss of energy and forces, where the residual
# function uses an ``energy_weight`` of ``1.0`` and a ``forces_weight`` of ``0.1``, and
# ``2`` processors will be used to calculate the loss. The ``L-BFGS-B`` minimization
# algorithm is applied to minimize the loss, and the minimization is allowed to run for
# a max number of 100 iterations.

steps = 100
residual_data = {"energy_weight": 1.0, "forces_weight": 0.1}
loss = Loss(calc, residual_data=residual_data, nprocs=2)
loss.minimize(method="L-BFGS-B", options={"disp": True, "maxiter": steps})


##########################################################################################
# The minimization stops after running for 27 steps.  After the minimization, we'd better
# save the model, which can be loaded later for the purpose to do a retraining or
# evaluations. If satisfied with the fitted model, you can also write it as a KIM model
# that can be used with LAMMPS_, GULP_, ASE_, etc. via the kim-api_.

model.echo_opt_params()
model.save("kliff_model.yaml")
model.write_kim_model()
# model.load("kliff_model.yaml")

Example #5
0
def train_fn(rank, world_size):

    descriptor = SymmetryFunction(cut_name="cos",
                                  cut_dists={"Si-Si": 5.0},
                                  hyperparams="set30",
                                  normalize=True)

    ##########################################################################################
    # The ``cut_name`` and ``cut_dists`` tells the descriptor what type of cutoff function to
    # use and what the cutoff distances are. ``hyperparams`` specifies the the set of
    # hyperparameters used in the symmetry function descriptor. If you prefer, you can provide
    # a dictionary of your own hyperparameters. And finally, ``normalize`` informs that the
    # generated fingerprints should be normalized by first subtracting the mean and then
    # dividing the standard deviation. This normalization typically makes it easier to
    # optimize NN model.
    #
    # We can then build the NN model on top of the descriptor.

    N1 = 10
    N2 = 10
    model = NeuralNetwork(descriptor)
    model.add_layers(
        # first hidden layer
        nn.Linear(descriptor.get_size(), N1),
        nn.Tanh(),
        # second hidden layer
        nn.Linear(N1, N2),
        nn.Tanh(),
        # output layer
        nn.Linear(N2, 1),
    )
    model.set_save_metadata(prefix="./my_kliff_model", start=5, frequency=2)

    ##########################################################################################
    # In the above code, we build a NN model with an input layer, two hidden layer, and an
    # output layer. The ``descriptor`` carries the information of the input layer, so it is
    # not needed to be specified explicitly. For each hidden layer, we first do a linear
    # transformation using ``nn.Linear(size_in, size_out)`` (essentially carrying out :math:`y
    # = xW+b`, where :math:`W` is the weight matrix of size ``size_in`` by ``size_out``, and
    # :math:`b` is a vector of size ``size_out``. Then we apply the hyperbolic tangent
    # activation function ``nn.Tanh()`` to the output of the Linear layer (i.e. :math:`y`) so
    # as to add the nonlinearity. We use a Linear layer for the output layer as well, but
    # unlike the hidden layer, no activation function is applied here. The input size
    # ``size_in`` of the first hidden layer must be the size of the descriptor, which is
    # obtained using ``descriptor.get_size()``. For all other layers (hidden or output), the
    # input size must be equal to the output size of the previous layer. The ``out_size`` of
    # the output layer much be 1 such that the output of the NN model is gives the energy of
    # atom.
    #
    # The ``set_save_metadata`` function call informs where to save intermediate models during
    # the optimization (discussed below), and what the starting epoch and how often to save
    # the model.
    #
    #
    # Training set and calculator
    # ---------------------------
    #
    # The training set and the calculator are the same as explained in :ref:`tut_kim_sw`. The
    # only difference is that we need use the
    # :mod:`~kliff.calculators.CalculatorTorch()`, which is targeted for the NN model.
    # Also, its ``create()`` method takes an argument ``reuse`` to inform whether to reuse the
    # fingerprints generated from the descriptor if it is present.

    # training set
    dataset_name = "Si_training_set/varying_alat"
    tset = Dataset()
    tset.read(dataset_name)
    configs = tset.get_configs()
    print("Number of configurations:", len(configs))

    # calculator
    calc = CalculatorTorchDDPCPU(model, rank, world_size)
    calc.create(configs, reuse=True)

    ##########################################################################################
    # Loss function
    # -------------
    #
    # KLIFF uses a loss function to quantify the difference between the training data and
    # potential predictions and uses minimization algorithms to reduce the loss as much as
    # possible. In the following code snippet, we create a loss function that uses the
    # ``Adam`` optimizer to minimize it. The Adam optimizer supports minimization using
    # `mini-batches` of data, and here we use ``100`` configurations in each minimization step
    # (the training set has a total of 400 configurations as can be seen above), and run
    # through the training set for ``10`` epochs. The learning rate ``lr`` used here is
    # ``0.01``, and typically, one may need to play with this to find an acceptable one that
    # drives the loss down in a reasonable time.

    loss = Loss(calc, residual_data={"forces_weight": 0.3})
    result = loss.minimize(method="Adam",
                           num_epochs=10,
                           batch_size=100,
                           lr=0.01)
Example #6
0
# If we are load a model to continue the training (the case here), ``mode`` needs to be
# set to ``train``; if we load the model for evaluation, it should be ``eval``. For
# fully-connected layer, this actually does not matter. But for dropout and batchNorm
# layers, the two modes are different.
model.load(path="final_model.pkl", mode="train")

# training set
dataset_name = "Si_training_set/varying_alat"
tset = Dataset()
tset.read(dataset_name)
configs = tset.get_configs()

# calculator
calc = CalculatorTorch(model)
calc.create(configs, reuse=True)

# loss
loss = Loss(calc, residual_data={"forces_weight": 0.3})

##########################################################################################
# load the state dictionary of the optimizer.
# We also set ``start_epoch`` to ``10`` such that the epoch number continues from the last
# training.

loss.load_optimizer_stat("optimizer_stat.pkl")
result = loss.minimize(method="Adam",
                       num_epochs=10,
                       start_epoch=10,
                       batch_size=100,
                       lr=0.001)
Example #7
0
from kliff.dataset import DataSet
from kliff.calculators import KIM
from kliff.calculators import WrapperCalculator
from kliff.loss import Loss

kliff.logger.set_level("debug")

# training set
tset = DataSet()
tset.read("../tests/calculators/Si_T300_4/")
configs = tset.get_configs()

# calculators
calc1 = KIM(model_name="Three_Body_Stillinger_Weber_Si__MO_405512056662_004")
calc1.create(configs)
calc1.set_fitting_params(A=[[16.0, 1.0, 20]], B=[["DEFAULT"]])
calc2 = KIM(model_name="Three_Body_Stillinger_Weber_Si__MO_405512056662_004")
calc2.create(configs)
calc2.set_fitting_params(sigma=[[2.0951, "fix"]], gamma=[[1.1]])

# wrapper
calc = WrapperCalculator(calc1, calc2)

# loss
with Loss(calc, nprocs=2) as loss:
    result = loss.minimize(method="L-BFGS-B",
                           options={
                               "disp": True,
                               "maxiter": 10
                           })