diff --git a/envs/environment-cpu.yml b/envs/environment-cpu.yml index 1bbbb18..2b447ad 100644 --- a/envs/environment-cpu.yml +++ b/envs/environment-cpu.yml @@ -4,7 +4,6 @@ name: jitterbug channels: - defaults - conda-forge - - pytorch - conda-forge/label/libint_dev dependencies: - python==3.9.* @@ -31,4 +30,5 @@ dependencies: - pip - pip: - git+https://gitlab.com/ase/ase.git # Needed for MOPAC + - gpytorch==1.11.* - -e ..[test] diff --git a/jitterbug/model/base.py b/jitterbug/model/base.py index 48cd9b7..db8a0df 100644 --- a/jitterbug/model/base.py +++ b/jitterbug/model/base.py @@ -1,6 +1,15 @@ """Base class defining the key methods""" +from tempfile import TemporaryDirectory +from typing import List, Optional +from random import choices +from pathlib import Path +import os + import numpy as np +from scipy import stats from ase import Atoms +from ase.vibrations import Vibrations +from ase.calculators.calculator import Calculator class EnergyModel: @@ -35,3 +44,89 @@ def sample_hessians(self, model: object, num_samples: int) -> list[np.ndarray]: A list of 2D hessians """ raise NotImplementedError() + + +class ASEEnergyModel(EnergyModel): + """Energy models which produce a series of ASE :class:`~ase.calculators.calculator.Calculator` objects""" + + def __init__(self, reference: Atoms, num_calculators: int, scratch_dir: Optional[Path] = None): + self.reference = reference + self.scratch_dir = scratch_dir + self.num_calculators = num_calculators + + def train_calculator(self, data: List[Atoms]) -> Calculator: + """Train one of the constituent calculators + + Args: + data: Training data + Returns: + Retrained calculator + """ + raise NotImplementedError() + + def train(self, data: list[Atoms]) -> List[Calculator]: + # Train each on a different bootstrap sample + output = [] + for _ in range(self.num_calculators): + sampled_data = choices(data, k=len(data)) + output.append(self.train_calculator(sampled_data)) + return output + + def compute_hessian(self, mol: Atoms, calc: Calculator) -> np.ndarray: + """Compute the Hessian using one of the calculators + + Args: + mol: Molecule to be evaluated + calc: Calculator to use + Returns: + 2D Hessian matrix + """ + # Clone the molecule to avoid any cross-talk + mol = mol.copy() + + with TemporaryDirectory(dir=self.scratch_dir) as td: + start_dir = Path.cwd() + try: + # Run the vibrations calculation in a temporary directory + os.chdir(td) + mol.calc = calc + vib = Vibrations(mol, name='mbtr-temp') + vib.run() + + # Return only the 2D Hessian + return vib.get_vibrations().get_hessian_2d() + finally: + os.chdir(start_dir) + + def mean_hessian(self, models: list[Calculator]) -> np.ndarray: + # Run all calculators + hessians = [self.compute_hessian(self.reference, calc) for calc in models] + + # Return the mean + return np.mean(hessians, axis=0) + + def sample_hessians(self, models: list[Calculator], num_samples: int) -> list[np.ndarray]: + # Run all calculators + hessians = [self.compute_hessian(self.reference, calc) for calc in models] + + # Compute the mean and covariance for each parameter + triu_ind = np.triu_indices(hessians[0].shape[0]) + hessians_flat = [h[triu_ind] for h in hessians] + hessian_mean = np.mean(hessians_flat, axis=0) + hessian_covar = np.cov(hessians_flat, rowvar=False) + + # Generate samples + hessian_mvn = stats.multivariate_normal(hessian_mean, hessian_covar, allow_singular=True) + diag_indices = np.diag_indices(hessians[0].shape[0]) + output = [] + for sample in hessian_mvn.rvs(size=num_samples): + # Fill in a 2D version + sample_hessian = np.zeros_like(hessians[0]) + sample_hessian[triu_ind] = sample + + # Make it symmetric + sample_hessian += sample_hessian.T + sample_hessian[diag_indices] /= 2 + + output.append(sample_hessian) + return output diff --git a/jitterbug/model/dscribe/__init__.py b/jitterbug/model/dscribe/__init__.py new file mode 100644 index 0000000..bfdf045 --- /dev/null +++ b/jitterbug/model/dscribe/__init__.py @@ -0,0 +1 @@ +"""Energy models using `DScribe `_""" diff --git a/jitterbug/model/dscribe/globald.py b/jitterbug/model/dscribe/globald.py new file mode 100644 index 0000000..ca1f811 --- /dev/null +++ b/jitterbug/model/dscribe/globald.py @@ -0,0 +1,87 @@ +"""Models which use a single vector to describe a molecule. + +Such approaches, such as MBTR, present a simple "molecule->energy" learning problem. +Other methods, such as SOAP, provided atomic-level features that must require an +extra step "molecule->atoms->energy/atom->energy". + +We train the models using sklearn for this example. +""" +from typing import List + +from dscribe.descriptors.descriptorglobal import DescriptorGlobal +from sklearn.linear_model import LinearRegression +from sklearn.base import BaseEstimator, clone +from dscribe.descriptors import MBTR +from ase.calculators.calculator import Calculator, all_changes +from ase import Atoms +import numpy as np + +from jitterbug.model.base import ASEEnergyModel + + +class DScribeGlobalCalculator(Calculator): + """A learnable forcefield based on global fingerprints computed using DScribe""" + + implemented_properties = ['energy', 'forces'] + default_parameters = { + 'descriptor': MBTR( + species=["H", "C", "N", "O"], + geometry={"function": "inverse_distance"}, + grid={"min": 0, "max": 1, "n": 100, "sigma": 0.1}, + weighting={"function": "exp", "scale": 0.5, "threshold": 1e-3}, + periodic=False, + normalization="l2", + ), + 'model': LinearRegression(), + 'offset': 0., # Normalizing parameters + 'scale': 1. + } + + def calculate(self, atoms=None, properties=('energy', 'forces'), system_changes=all_changes): + # Compute the energy using the learned model + desc = self.parameters['descriptor'].create_single(atoms) + energy_unscaled = self.parameters['model'].predict(desc[None, :]) + self.results['energy'] = energy_unscaled[0] * self.parameters['scale'] + self.parameters['offset'] + + # If desired, compute forces numerically + if 'forces' in properties: + # calculate_numerical_forces use that the calculation of the input atoms, + # even though it is a method of a calculator and not of the input atoms :shrug: + temp_atoms: Atoms = atoms.copy() + temp_atoms.calc = self + self.results['forces'] = self.calculate_numerical_forces(temp_atoms) + + +class DScribeGlobalEnergyModel(ASEEnergyModel): + """Compute energy using a scikit-learn model that computes energies from global descriptors + + Args: + reference: Reference structure at which we compute the Hessian + descriptors: Tool used to compute descriptors + model: Scikit-learn model to use to compute energies given descriptors + num_calculators: Number of models to use in ensemble + """ + + def __init__(self, reference: Atoms, descriptors: DescriptorGlobal, model: BaseEstimator, num_calculators: int): + super().__init__(reference, num_calculators) + self.desc = descriptors + self.model = model + + def train_calculator(self, data: List[Atoms]) -> Calculator: + # Make a copy of the model + model: BaseEstimator = clone(self.model) + + # Compute the descriptors then train + train_x = self.desc.create(data) + train_y = np.array([a.get_potential_energy() for a in data]) + scale_y, offset_y = np.std(train_y), np.mean(train_y) + train_y = (train_y - offset_y) / scale_y + model.fit(train_x, train_y) + + # Assemble into a Calculator + return DScribeGlobalCalculator( + descriptor=self.desc, + model=model, + offset=offset_y, + scale=scale_y, + ) diff --git a/jitterbug/model/dscribe/local.py b/jitterbug/model/dscribe/local.py new file mode 100644 index 0000000..70f4c79 --- /dev/null +++ b/jitterbug/model/dscribe/local.py @@ -0,0 +1,274 @@ +"""Create a PyTorch-based model which uses features for each atom""" +from typing import Union, Optional, Callable + +from ase.calculators.calculator import Calculator, all_changes +from dscribe.descriptors.descriptorlocal import DescriptorLocal +from torch.utils.data import TensorDataset, DataLoader +from ase import Atoms +from tqdm import tqdm +import pandas as pd +import numpy as np +import torch + +from jitterbug.model.base import ASEEnergyModel + + +class InducedKernelGPR(torch.nn.Module): + """Gaussian process regression model with an induced kernel + + Predicts the energy for each atom as a function of its descriptors + + Args: + inducing_x: Starting points for the reference points of the kernel + use_ard: Whether to employ a different length scale parameter for each descriptor, + a technique known as Automatic Relevance Detection (ARD) + """ + + def __init__(self, inducing_x: torch.Tensor, use_ard: bool): + super().__init__() + n_points, n_desc = inducing_x.shape + self.inducing_x = torch.nn.Parameter(inducing_x.clone()) + self.alpha = torch.nn.Parameter(torch.empty((n_points,), dtype=inducing_x.dtype)) + torch.nn.init.normal_(self.alpha) + self.lengthscales = torch.nn.Parameter(-torch.ones((n_desc,), dtype=inducing_x.dtype) if use_ard else -torch.ones((1,), dtype=inducing_x.dtype)) + + def forward(self, x) -> torch.Tensor: + # Compute an RBF kernel + lengthscales = torch.exp(self.lengthscales) + diff_sq = torch.pow(x[None, :, :] - self.inducing_x[:, None, :], 2) / lengthscales + diff = diff_sq.sum(axis=-1) # Sum along the descriptor axis + esd = torch.exp(-diff) + + # Return the sum + return torch.tensordot(self.alpha, esd, dims=([0], [0])) + + +def make_gpr_model(train_descriptors: np.ndarray, num_inducing_points: int, use_ard_kernel: bool = False) -> InducedKernelGPR: + """Make the GPR model for a certain atomic system + + Assumes that the descriptors have already been scaled + + Args: + train_descriptors: 3D array of all training points (num_configurations, num_atoms, num_descriptors) + num_inducing_points: Number of inducing points to use in the kernel. More points, more complex model + use_ard_kernel: Whether to use a different length scale parameter for each descriptor + Returns: + Model which can predict energy given descriptors for a single configuration + """ + + # Select a set of inducing points randomly + descriptors = np.reshape(train_descriptors, (-1, train_descriptors.shape[-1])) + num_inducing_points = min(num_inducing_points, descriptors.shape[0]) + inducing_inds = np.random.choice(descriptors.shape[0], size=(num_inducing_points,), replace=False) + inducing_points = descriptors[inducing_inds, :] + + # Make the model + return InducedKernelGPR( + inducing_x=torch.from_numpy(inducing_points), + use_ard=use_ard_kernel, + ) + + +def train_model(model: torch.nn.Module, + train_x: np.ndarray, + train_y: np.ndarray, + steps: int, + batch_size: int = 4, + learning_rate: float = 0.01, + device: Union[str, torch.device] = 'cpu', + verbose: bool = False) -> pd.DataFrame: + """Train the kernel model over many iterations + + Assumes that the descriptors have already been scaled + + Args: + model: Model to be trained + train_x: 3D array of all training points (num_configurations, num_atoms, num_descriptors) + train_y: Energies for each training point + steps: Number of interactions over all training points + batch_size: Number of conformers per batch + learning_rate: Learning rate used for the optimizer + device: Which device to use for training + verbose: Whether to display a progress bar + Returns: + Mean loss over each iteration + """ + + # Convert the data to Torches + n_conf, n_atoms = train_x.shape[:2] + train_x = torch.from_numpy(train_x) + train_y = torch.from_numpy(train_y) + + # Make the data loader + dataset = TensorDataset(train_x, train_y) + loader = DataLoader(dataset, batch_size=batch_size, shuffle=True, drop_last=True) + + # Convert the model to training mode on the device + model.train() + model.to(device) + + # Define the optimizer and loss function + opt = torch.optim.Adam([ + {'params': model.parameters()}, + ], lr=learning_rate) + loss = torch.nn.MSELoss() + + # Iterate over the data multiple times + losses = [] + for _ in tqdm(range(steps), disable=not verbose, leave=False): + epoch_loss = 0 + for batch_x, batch_y in loader: + # Prepare at the beginning of each batch + opt.zero_grad() + batch_x = batch_x.to(device) + batch_y = batch_y.to(device) + + # Predict on all configurations + batch_x = torch.reshape(batch_x, (-1, batch_x.shape[-1])) # Flatten from (n_confs, n_atoms, n_desc) -> (n_confs * n_atoms, n_desc) + pred_y_per_atoms_flat = model(batch_x) + + # Get the mean sum for each atom + pred_y_per_atoms = torch.reshape(pred_y_per_atoms_flat, (batch_size, n_atoms)) + pred_y = torch.sum(pred_y_per_atoms, dim=1) + + # Compute loss and propagate + batch_loss = loss(pred_y, batch_y) + if torch.isnan(batch_loss): + raise ValueError('NaN loss') + batch_loss.backward() + + opt.step() + epoch_loss += batch_loss.item() + + losses.append(epoch_loss) + + # Pull the model back off the GPU + model.to('cpu') + return pd.DataFrame({'loss': losses}) + + +class DScribeLocalCalculator(Calculator): + """Calculator which uses descriptors for each atom and PyTorch to compute energy + + Keyword Args: + model (torch.nn.Module): A machine learning model which takes descriptors as inputs + desc (DescriptorLocal): Tool used to compute the descriptors + desc_scaling (tuple[np.ndarray, np.ndarray]): A offset and factor with which to adjust the energy per atom predictions, + which are typically he mean and standard deviation of energy per atom across the training set. + energy_scaling (tuple[float, float]): A offset and factor with which to adjust the energy per atom predictions, + which are typically he mean and standard deviation of energy per atom across the training set. + device (str | torch.device): Device to use for inference + """ + + implemented_properties = ['energy', 'forces', 'energies'] + default_parameters = { + 'model': None, + 'desc': None, + 'desc_scaling': (0., 1.), + 'energy_scaling': (0., 1.), + 'device': 'cpu' + } + + def calculate(self, atoms=None, properties=('energy', 'forces', 'energies'), + system_changes=all_changes): + # Compute the descriptors for the atoms + d_desc_d_pos, desc = self.parameters['desc'].derivatives(atoms, attach=True) + + # Scale the descriptors + offset, scale = self.parameters['desc_scaling'] + desc = (desc - offset) / scale + d_desc_d_pos /= scale + + # Convert to pytorch + desc = torch.from_numpy(desc.astype(np.float32)) + desc.requires_grad = True + d_desc_d_pos = torch.from_numpy(d_desc_d_pos.astype(np.float32)) + + # Move the model to device if need be + model: torch.nn.Module = self.parameters['model'] + device = self.parameters['device'] + model.to(device) + + # Run inference + offset, scale = self.parameters['energy_scaling'] + model.eval() # Ensure we're in eval mode + desc = desc.to(device) + pred_energies_dist = model(desc) + pred_energies = pred_energies_dist * scale + offset + pred_energy = torch.sum(pred_energies) + self.results['energy'] = pred_energy.item() + self.results['energies'] = pred_energies.detach().cpu().numpy() + + if 'forces' in properties: + # Compute the forces + # See: https://singroup.github.io/dscribe/latest/tutorials/machine_learning/forces_and_energies.html + # Derivatives for the descriptors are for each center (which is the input to the model) with respect to each atomic coordinate changing. + # Energy is summed over the contributions from each center. + # The total force is therefore a sum over the effect of an atom moving on all centers + d_energy_d_desc = torch.autograd.grad( + outputs=pred_energy, + inputs=desc, + grad_outputs=torch.ones_like(pred_energy), + )[0] # Derivative of the energy with respect to the descriptors for each center + d_desc_d_pos = d_desc_d_pos.to(device) + d_energy_d_center_d_pos = torch.einsum('ijkl,il->ijk', d_desc_d_pos, d_energy_d_desc) # Derivative for each center with respect to each atom + pred_forces = -d_energy_d_center_d_pos.sum(dim=0) * scale # Total effect on each center from each atom + + # Store the results + self.results['forces'] = pred_forces.detach().cpu().numpy() + + # Move the model back to CPU memory + model.to('cpu') + + +class DScribeLocalEnergyModel(ASEEnergyModel): + """Energy model based on DScribe atom-level descriptors + + Trains an energy model using PyTorch + + Args: + reference: Reference structure at which we compute the Hessian + descriptors: Tool used to compute descriptors + model_fn: Function used to create the model given descriptors for the training set + num_calculators: Number of models to use in ensemble + device: Device used for training + train_options: Options passed to the training function + """ + + def __init__(self, + reference: Atoms, + descriptors: DescriptorLocal, + model_fn: Callable[[np.ndarray], torch.nn.Module], + num_calculators: int, + device: str = 'cpu', + train_options: Optional[dict] = None): + super().__init__(reference, num_calculators) + self.descriptors = descriptors + self.model_fn = model_fn + self.device = device + self.train_options = train_options or {'steps': 4} + + def train_calculator(self, data: list[Atoms]) -> Calculator: + # Train it using the user-provided options + train_x = self.descriptors.create(data) + offset_x = train_x.mean(axis=(0, 1)) + scale_x = np.clip(train_x.std(axis=(0, 1)), a_min=1e-6, a_max=None) + train_x -= offset_x + train_x /= scale_x + + train_y = np.array([a.get_potential_energy() for a in data]) + scale_y, offset_y = np.std(train_y), np.mean(train_y) + train_y = (train_y - offset_y) / scale_y + + # Make then train the model + model = self.model_fn(train_x) + train_model(model, train_x, train_y, device=self.device, **self.train_options) + + # Make the calculator + return DScribeLocalCalculator( + model=model, + desc=self.descriptors, + desc_scaling=(offset_x, scale_x), + energy_scaling=(offset_y, scale_y), + device=self.device + ) diff --git a/jitterbug/model/mbtr.py b/jitterbug/model/mbtr.py deleted file mode 100644 index f1e940c..0000000 --- a/jitterbug/model/mbtr.py +++ /dev/null @@ -1,96 +0,0 @@ -"""Learn a potential energy surface with the MBTR representation - -MBTR is an easy route for learning a forcefield because it represents -a molecule as a single vector, which means we can case the learning -problem as a simple "molecule->energy" learning problem. Other methods, -such as SOAP, provided atomic-level features that must require an -extra step "molecule->atoms->energy/atom->energy". -""" -from shutil import rmtree - -from ase.calculators.calculator import Calculator, all_changes -from ase.vibrations import Vibrations -from ase import Atoms -from sklearn.linear_model import LinearRegression -from dscribe.descriptors import MBTR -import numpy as np - -from jitterbug.model.base import EnergyModel - - -class MBTRCalculator(Calculator): - """A learnable forcefield based on GPR and fingerprints computed using DScribe""" - - implemented_properties = ['energy', 'forces'] - default_parameters = { - 'descriptor': MBTR( - species=["H", "C", "N", "O"], - geometry={"function": "inverse_distance"}, - grid={"min": 0, "max": 1, "n": 100, "sigma": 0.1}, - weighting={"function": "exp", "scale": 0.5, "threshold": 1e-3}, - periodic=False, - normalization="l2", - ), - 'model': LinearRegression(), - 'intercept': 0., # Normalizing parameters - 'scale': 0. - } - - def calculate(self, atoms=None, properties=('energy', 'forces'), system_changes=all_changes): - # Compute the energy using the learned model - desc = self.parameters['descriptor'].create_single(atoms) - energy_no_int = self.parameters['model'].predict(desc[None, :]) - self.results['energy'] = energy_no_int[0] * self.parameters['scale'] + self.parameters['intercept'] - - # If desired, compute forces numerically - if 'forces' in properties: - # calculate_numerical_forces use that the calculation of the input atoms, - # even though it is a method of a calculator and not of the input atoms :shrug: - temp_atoms: Atoms = atoms.copy() - temp_atoms.calc = self - self.results['forces'] = self.calculate_numerical_forces(temp_atoms) - - def train(self, train_set: list[Atoms]): - """Train the embedded forcefield object - - Args: - train_set: List of Atoms objects containing at least the energy - """ - - # Determine the mean energy and subtract it off - energies = np.array([atoms.get_potential_energy() for atoms in train_set]) - self.parameters['intercept'] = energies.mean() - energies -= self.parameters['intercept'] - self.parameters['scale'] = energies.std() - energies /= self.parameters['scale'] - - # Compute the descriptors and use them to fit the model - desc = self.parameters['descriptor'].create(train_set) - self.parameters['model'].fit(desc, energies) - - -class MBTREnergyModel(EnergyModel): - """Use the MBTR representation to model the potential energy surface - - Args: - calc: Calculator used to fit the potential energy surface - reference: Reference structure at which we compute the Hessian - """ - - def __init__(self, calc: MBTRCalculator, reference: Atoms): - super().__init__() - self.calc = calc - self.reference = reference - - def train(self, data: list[Atoms]) -> MBTRCalculator: - self.calc.train(data) - return self.calc - - def mean_hessian(self, model: MBTRCalculator) -> np.ndarray: - self.reference.calc = model - try: - vib = Vibrations(self.reference, name='mbtr-temp') - vib.run() - return vib.get_vibrations().get_hessian_2d() - finally: - rmtree('mbtr-temp', ignore_errors=True) diff --git a/notebooks/1_explore-sampling-methods/1_random-directions-variable-distance.ipynb b/notebooks/1_explore-sampling-methods/1_random-directions-variable-distance.ipynb index 6b59028..b87c281 100644 --- a/notebooks/1_explore-sampling-methods/1_random-directions-variable-distance.ipynb +++ b/notebooks/1_explore-sampling-methods/1_random-directions-variable-distance.ipynb @@ -47,7 +47,7 @@ }, "outputs": [], "source": [ - "starting_geometry = '../data/exact/water_b3lyp_def2-svpd.xyz'\n", + "starting_geometry = '../data/exact/caffeine_pm7_None.xyz'\n", "threads = min(os.cpu_count(), 12)\n", "step_size: float = 0.005 # Lambda parameter for an expontential distribution for the Perturbation amount" ] @@ -91,7 +91,7 @@ { "data": { "text/plain": [ - "Atoms(symbols='OH2', pbc=False, forces=..., calculator=SinglePointCalculator(...))" + "Atoms(symbols='O2N4C8H10', pbc=False, forces=..., calculator=SinglePointCalculator(...))" ] }, "execution_count": 4, @@ -183,15 +183,7 @@ "metadata": { "tags": [] }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " Threads set to 12 by Python driver.\n" - ] - } - ], + "outputs": [], "source": [ "calc = make_calculator(method, basis, num_threads=threads)" ] @@ -216,7 +208,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Need to run 55 calculations for full accuracy.\n" + "Need to run 2701 calculations for full accuracy.\n" ] } ], @@ -238,7 +230,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Already done 55. 0 left to do.\n" + "Already done 1. 2700 left to do.\n" ] } ], @@ -258,7 +250,7 @@ "name": "stderr", "output_type": "stream", "text": [ - " 0%| | 0/55 [00:00" ] @@ -329,9 +329,9 @@ { "data": { "text/plain": [ - "array([[-9.51409195e+08, -1.07310180e+09, -4.31182646e+08],\n", - " [-1.07310180e+09, 9.04030821e+08, -4.53419942e+07],\n", - " [-4.31182646e+08, -4.53419942e+07, 1.25376691e+08]])" + "array([[-1.22285341e+10, 1.08118660e+01, 1.90691352e-02],\n", + " [ 1.08118660e+01, -2.62969236e+07, 6.56681245e-02],\n", + " [ 1.90691352e-02, 6.56681245e-02, -4.34794305e+06]])" ] }, "execution_count": 15, @@ -353,7 +353,7 @@ "outputs": [ { "data": { - "image/png": "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", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXYAAADJCAYAAAA3tRlxAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAABAP0lEQVR4nO2de5RdRZ3vv+ecPueku9PdefIOiVmE8DLIQ+R5kQEdfIDei8JVLhCcmbXUKwsYdWaYweHhXcOapRFcV9coCmG84tW5g3ovOrPAUVA0BgwQYiQSeQQCJoSEpLvTnXT3OafuH7t++9SuU1W7ap/dne6T32etrM7Zu6p27b1r7/2r36sKQggBhmEYpmMoHugOMAzDMPnCL3aGYZgOg1/sDMMwHQa/2BmGYToMfrEzDMN0GPxiZxiG6TD4xc4wDNNh8IudYRimw+AXO8MwTIfBL3aGYaYFK1euxAc/+MED3Y2OgF/sAaxcuRKFQqHl38UXXzwlx7/11lvxtre9bUqOxcxc1qxZg1KpNGXjMi++/OUv47777pv04xwMH5CuA92BmcbFF1+M1atXJ7ZVq9UD1BuGaeXee+/Fddddh29+85t45ZVXcPTRR0/q8SYmJlAul9tuZ2BgIIfeMAAAwXhzzTXXiA984APGfY888ogol8viF7/4Rbzti1/8opg/f7744x//KIQQ4t///d/FOeecIwYGBsS8efPE+973PvH8888n2tm6dau44oorxNy5c0VPT4847bTTxNq1a8Xq1asFgMS/1atXT9apMjOUvXv3ir6+PvH73/9eXHHFFeK2226L9z3yyCMCgPjRj34kVqxYIarVqjjjjDPEhg0b4jKrV68WAwMD4gc/+IFYtmyZqFar4qKLLhKvvPJKXOaWW24RJ598srjnnnvEW97yFlEoFESj0RAvv/yyuPTSS0Vvb6/o6+sTH/7wh8X27duFEEJs2rRJdHd3i/vvvz9u54EHHhDVajU+vv58nX/++eJTn/qUuP7668WcOXPEIYccIr7+9a+LvXv3ipUrV4rZs2eLpUuXin/7t3+L69RqNfGxj31MLFmyRMyaNUsce+yx4q677kr0XX+OHnnkESGEEK+++qq4/PLLxZw5c8S8efPEpZdeKl566aVc7stUwy/2AFwvdiGE+OxnPysWL14s9uzZI9avXy+q1ar4/ve/H+//13/9V/HAAw+IzZs3i6efflpccskl4q1vfauo1+tCCCGGh4fF0qVLxXnnnScee+wx8Yc//EF873vfE2vWrBGjo6Pi05/+tDjxxBPFtm3bxLZt28To6OhknzIzw7jnnnvE6aefLoQQ4sEHHxRLliwRjUZDCNF8sR9//PHi4YcfFhs2bBDvf//7xZIlS8T4+LgQInqxl8tlcfrpp4s1a9aIdevWiTPOOEOcffbZ8TFuueUW0dvbK/70T/9UPPXUU+KZZ54RjUZDnHLKKeLcc88V69atE2vXrhWnnnqqOP/88+N6X/3qV8XAwIDYsmWLeO2118S8efPEnXfeGe83vdj7+vrE5z//ebF582bx+c9/XhSLRfGe97xH3H333WLz5s3iE5/4hJg/f74YGRkRQggxPj4u/v7v/1488cQT4sUXXxTf/va3RU9Pj/je974nhIiescsvv1xcfPHF8XM0NjYmRkZGxLJly8THPvYxsWHDBvHss8+Kj370o2L58uVibGxsMm7VpMIv9gCuueYaUSqVRG9vb+Lf7bffLoQQYmxsTJxyyini8ssvFyeeeKL48z//c2d7O3bsEADEb3/7WyGEEF//+tdFX1+f2LVrl7E8SUoMY+Pss8+OJdSJiQmxYMEC8ZOf/EQI0Xyxf/e7343L79q1S3R3d8cvPpoZrl27Ni6zadMmAUA8/vjjQohoHJbLZbFjx464zMMPPyxKpVJCsv/d734nAIgnnngi3va+971PnHfeeeLCCy8U73rXu+KPjhDmF/u5554b/67VaqK3t1dcddVV8bZt27YJAOLXv/619Zp88pOfFJdddpn1OEJEH8Tly5cn+jM2Nia6u7vFQw89ZG17usI69kAuuOAC/NM//VNi27x58wAAlUoF3/72t7FixQosXrwYd911V6LcCy+8gM997nNYu3Ytdu7ciUajAQB45ZVXcNJJJ2H9+vU45ZRT4vYYJoTnnnsOTzzxBL7//e8DALq6unDFFVfg3nvvxUUXXRSXO+uss+L/z5s3D8uXL8emTZvibV1dXTj99NPj38cddxzmzJmDTZs24YwzzgAALF68GAsXLozLbNq0CYsWLcKiRYvibSeccEJc7+1vfzuASP9/7LHHolgsYuPGjSgUCs5zWrFiRfz/UqmE+fPn461vfWu87dBDDwUA7NixI972ta99Dd/85jfx8ssvY9++fRgfH091OnjyySfx/PPPo6+vL7F9//79eOGFF5x1pyP8Yg+kt7cXxxxzjHX/mjVrAABvvvkm3nzzTfT29sb7LrnkEixatAjf+MY3cMQRR6DRaOCkk07C+Pg4AKC7u3tyO890NPfccw9qtRqOPPLIeJsQAuVyGbt373bW1V+wpheuuk0d13QcUx19+zPPPIORkREUi0Vs374dRxxxhLNfulG2UCgktlHbJCT9y7/8C2688UasWrUKZ511Fvr6+vCFL3wBjz/+uPM4jUYDp512Gu6///6WfeoHbKbA7o458sILL+DGG2/EN77xDZx55pm4+uqr4wG3a9cubNq0CTfffDMuvPBCHH/88S0P24oVK7B+/Xq8+eabxvYrlQrq9fqknwcz86jVavjWt76FVatWYf369fG/Z555BosXL068sNauXRv/f/fu3di8eTOOO+64RFvr1q2Lfz/33HPYs2dPoozOCSecgFdeeQVbt26Ntz377LMYHBzE8ccfDyASdlauXIm/+7u/w7XXXosrr7wS+/bty+X8icceewxnn302PvnJT+KUU07BMccc0yJxm56jU089FX/4wx9wyCGH4Jhjjkn8m4neOvxiD2RsbAzbt29P/Nu5cyfq9TquuuoqvPvd78a1116L1atXY+PGjVi1ahUAYO7cuZg/fz7uvvtuPP/88/jZz36Gv/zLv0y0/ZGPfASHHXYYPvjBD+JXv/oVXnzxRTzwwAP49a9/DQBYsmQJXnrpJaxfvx47d+7E2NjYlJ8/Mz350Y9+hN27d+PP/uzPcNJJJyX+fehDH8I999wTl7399tvx05/+FBs3bsTKlSuxYMGChF93uVzGddddh8cffxxPPfUUrr32Wpx55pmxGsbERRddhBUrVuDKK6/EU089hSeeeAJXX301zj///Fit8/GPfxyLFi3CzTffjC996UsQQuAzn/lMrtfhmGOOwbp16/DQQw9h8+bN+NznPoff/OY3iTJLlizBhg0b8Nxzz2Hnzp2YmJjAlVdeiQULFuADH/gAHnvsMbz00kv4+c9/juuvvx6vvvpqrn2cEg6sin9mcc0117S4SgEQy5cvF7fddps4/PDDxc6dO+PyP/zhD0WlUhFPP/20EEKIn/zkJ+L4448X1WpVrFixQjz66KMCgPjBD34Q19myZYu47LLLRH9/v+jp6RGnn356bLTav3+/uOyy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", "text/plain": [ "
" ] @@ -405,7 +405,7 @@ { "data": { "text/plain": [ - "11471.629752113282" + "3548.019924030835" ] }, "execution_count": 18, @@ -469,7 +469,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Plotting at 16 steps: 5, 252, 499, 746, 993, ...\n" + "Plotting at 16 steps: 5, 350, 695, 1041, 1386, ...\n" ] } ], @@ -490,7 +490,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 16/16 [00:20<00:00, 1.28s/it]\n" + "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 16/16 [00:25<00:00, 1.57s/it]\n" ] } ], @@ -524,7 +524,7 @@ "outputs": [ { "data": { - "image/png": "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", + "image/png": "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", "text/plain": [ "
" ] diff --git a/notebooks/2_testing-fitting-strategies/1_fit-forcefield-using-mbtr.ipynb b/notebooks/2_testing-fitting-strategies/1_fit-forcefield-using-mbtr.ipynb index ffa3e2b..6740d00 100644 --- a/notebooks/2_testing-fitting-strategies/1_fit-forcefield-using-mbtr.ipynb +++ b/notebooks/2_testing-fitting-strategies/1_fit-forcefield-using-mbtr.ipynb @@ -20,16 +20,20 @@ "source": [ "%matplotlib inline\n", "from matplotlib import pyplot as plt\n", - "from jitterbug.model.mbtr import MBTREnergyModel, MBTRCalculator\n", - "from sklearn.model_selection import GridSearchCV\n", + "from jitterbug.model.dscribe.globald import DScribeGlobalEnergyModel\n", + "from sklearn.model_selection import GridSearchCV, train_test_split\n", + "from sklearn.preprocessing import StandardScaler\n", + "from sklearn.metrics import mean_absolute_error\n", "from sklearn.kernel_ridge import KernelRidge\n", + "from sklearn.pipeline import Pipeline\n", "from dscribe.descriptors import MBTR\n", "from ase.vibrations import VibrationsData\n", "from ase.db import connect\n", "from pathlib import Path\n", "from tqdm import tqdm\n", "import numpy as np\n", - "import warnings" + "import warnings\n", + "import ase" ] }, { @@ -144,25 +148,37 @@ }, { "cell_type": "markdown", - "id": "04c60da8-4a1d-4ae3-b45d-b77e71fd598f", + "id": "03154497-b882-4531-bc66-0a3b51a4b9a9", "metadata": {}, "source": [ - "## Fit a Hessian with All Data\n", - "Fit a model which explains the energy data by fitting a Hessian matrix using compressed sensing (i.e., Lasso)." + "## Adjust Hyperparameters\n", + "We have a few different hyperparameters to fit, the type of descriptors we use and those of the underlying model." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "8711d448-0c8e-459b-9158-92dcfa4ddfd8", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "train_data, test_data = train_test_split(data, test_size=0.5)" ] }, { "cell_type": "markdown", - "id": "fe72ad76-2772-4094-a9b7-065be9a356d4", + "id": "d83a86b0-78ad-40be-9f29-77d91457835b", "metadata": {}, "source": [ - "Make the MBTR calculator using half the available data" + "Get a baseline score" ] }, { "cell_type": "code", - "execution_count": 7, - "id": "5a5b4a37-bd58-4855-bc3e-85d4258a25c8", + "execution_count": 8, + "id": "207fbca5-6020-4983-980a-9da5f6ff2e67", "metadata": { "tags": [] }, @@ -171,107 +187,284 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 3min 38s, sys: 9.7 s, total: 3min 48s\n", - "Wall time: 20.1 s\n" + "Baseline score: 5.48e-01 meV/atom\n" ] } ], "source": [ - "%%time\n", - "mbtr = MBTRCalculator(\n", - " model=GridSearchCV(\n", - " KernelRidge(kernel='rbf', alpha=1e-10), {\n", - " 'gamma': np.logspace(-5, 5, 32)\n", - " }),\n", - " descriptor=MBTR(\n", + "test_y = np.array([a.get_potential_energy() for a in test_data])\n", + "baseline_y = np.abs(test_y - test_y.mean()).mean()\n", + "print(f'Baseline score: {baseline_y*1000:.2e} meV/atom')`" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "287c812d-76c9-4907-b649-401a60a4ff1f", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "def test_model(train_data: list[ase.Atoms], test_data: list[ase.Atoms], descriptor: MBTR, model: GridSearchCV) -> float:\n", + " \"\"\"Get the MAE for a combination of descriptor and model\"\"\"\n", + " \n", + " # Compute descriptors and get energies\n", + " train_x = descriptor.create(train_data)\n", + " train_y = np.array([a.get_potential_energy() for a in train_data])\n", + " scale_y, offset_y = train_y.std(), train_y.mean()\n", + " train_y = (train_y - offset_y) / scale_y\n", + " \n", + " # Fit the model\n", + " model.fit(train_x, train_y)\n", + " \n", + " # Run on the test set\n", + " test_x = descriptor.create(test_data)\n", + " pred_y = (model.predict(test_x) * scale_y) + offset_y\n", + " \n", + " # Return the error\n", + " test_y = np.array([a.get_potential_energy() for a in test_data])\n", + " return mean_absolute_error(test_y, pred_y)" + ] + }, + { + "cell_type": "markdown", + "id": "b8b1440f-6e1f-4681-b402-b56ecc81462c", + "metadata": {}, + "source": [ + "We'll use KRR for all the tests" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "5726b0d1-ef03-4d93-ace7-f7636977ba07", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "model = Pipeline(\n", + " [('scale', StandardScaler()), \n", + " ('krr', GridSearchCV(KernelRidge(kernel='rbf', alpha=1e-10), {'gamma': np.logspace(-5, 5, 32)}))]\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "8e088dc8-f603-4e5e-ae50-4444f0d9fb97", + "metadata": {}, + "source": [ + "Start off with testing 2D descriptors. We'll want to evaluate the maximum distance of the grid and the number of points" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "574bb81a-ea70-45bc-b6bb-8556bf4ea753", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 17/17 [05:18<00:00, 18.73s/it]\n" + ] + } + ], + "source": [ + "max_dists = np.arange(2, 6.01, 0.25)\n", + "n_points = 32\n", + "sigma = 0.1\n", + "test_score = []\n", + "for max_dist in tqdm(max_dists):\n", + " desc = MBTR(\n", " species=[\"H\", \"C\", \"N\", \"O\"],\n", " geometry={\"function\": \"distance\"},\n", - " grid={\"min\": 0, \"max\": 6, \"n\": 64, \"sigma\": 0.05},\n", + " grid={\"min\": 0.5, \"max\": max_dist, \"n\": n_points, \"sigma\": sigma},\n", " weighting={\"function\": \"exp\", \"scale\": 0.1, \"threshold\": 1e-3},\n", " periodic=False,\n", " )\n", + " test_score.append(test_model(train_data, test_data, desc, model))" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "a59e6921-4baa-4a6c-bde0-bde54bbe59ee", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Selected a maximum distance of 5.25 A\n" + ] + } + ], + "source": [ + "max_dist = max_dists[np.argmin(test_score)]\n", + "print(f'Selected a maximum distance of {max_dist:.2f} A')" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "8921b7bc-6be6-44ae-a820-da15dce0c496", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 5/5 [01:42<00:00, 20.47s/it]\n" + ] + } + ], + "source": [ + "n_pointss = [8, 16, 32, 64, 128]\n", + "sigma = 0.1\n", + "test_score = []\n", + "for n_points in tqdm(n_pointss):\n", + " desc = MBTR(\n", + " species=[\"H\", \"C\", \"N\", \"O\"],\n", + " geometry={\"function\": \"distance\"},\n", + " grid={\"min\": 0.5, \"max\": max_dist, \"n\": n_points, \"sigma\": sigma},\n", + " weighting={\"function\": \"exp\", \"scale\": 0.1, \"threshold\": 1e-3},\n", + " periodic=False,\n", + " )\n", + " test_score.append(test_model(train_data, test_data, desc, model))" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "4c60271b-5d52-4606-a224-d1230c8c03ac", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Selected 16 grid points. Best 2D score: 1.71e-02 meV/atom\n" + ] + } + ], + "source": [ + "n_points = n_pointss[np.argmin(test_score)]\n", + "best_2d_score = min(test_score)\n", + "best_2d_desc = MBTR(\n", + " species=[\"H\", \"C\", \"N\", \"O\"],\n", + " geometry={\"function\": \"distance\"},\n", + " grid={\"min\": 0.5, \"max\": max_dist, \"n\": n_points, \"sigma\": sigma},\n", + " weighting={\"function\": \"exp\", \"scale\": 0.1, \"threshold\": 1e-3},\n", + " periodic=False,\n", ")\n", - "with warnings.catch_warnings():\n", - " warnings.simplefilter('ignore')\n", - " mbtr.train(data[:len(data) // 2])" + "print(f'Selected {n_points} grid points. Best 2D score: {best_2d_score*1000:.2e} meV/atom')" ] }, { "cell_type": "markdown", - "id": "503240dd-b52c-4111-a024-ec44766940e5", + "id": "7dd23c1d-bbed-4751-ba06-baa1532e745f", "metadata": {}, "source": [ - "Plot the model performance" + "Optimize for 3D. We have a cutoff distance, but it appears in the weighting now." ] }, { "cell_type": "code", - "execution_count": 8, - "id": "c0038a85-5a70-4a4e-b830-c3c54e5a8efc", + "execution_count": 15, + "id": "d61044e9-e93f-4a4d-898d-34bd7517c2d1", "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 6/6 [03:40<00:00, 36.83s/it]\n" + ] + } + ], "source": [ - "pred_energy= [mbtr.get_potential_energy(x) * 1000 for x in data[len(data) // 2:]]\n", - "true_energy = [x.get_potential_energy() * 1000 for x in data[len(data) // 2:]]" + "r_cutoffs = np.arange(2, 12.01, 2.)\n", + "n_points = 32\n", + "test_score = []\n", + "for r_cutoff in tqdm(r_cutoffs):\n", + " desc = MBTR(\n", + " species=[\"H\", \"C\", \"N\", \"O\"],\n", + " geometry={\"function\": \"angle\"},\n", + " grid={\"min\": 0., \"max\": 180, \"n\": n_points, \"sigma\": 180. / n_points / 2.},\n", + " weighting={\"function\": \"smooth_cutoff\", \"r_cut\": r_cutoff, \"threshold\": 1e-3},\n", + " periodic=False,\n", + " )\n", + " test_score.append(test_model(train_data, test_data, desc, model))" ] }, { "cell_type": "code", - "execution_count": 9, - "id": "fba09717-7b2b-40a7-a6d3-543c40080d02", + "execution_count": 16, + "id": "5ec34b9c-14a7-45f9-986e-8406106fdd37", "metadata": { "tags": [] }, "outputs": [ { - "data": { - "text/plain": [ - "Text(0, 0.5, '$E-E_0$, True (meV)')" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAUwAAAFQCAYAAADUeke/AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAAA6W0lEQVR4nO3dd3RU1drH8e+ZSe89EBKk1xAgBDQQKdKkSREQBAQpooYmokCkXECI16t4pYhIVynqpfmqgCgECIqUEGlKEZCSRkvPZJjy/hEZibSUSWaSPJ+1snTOHOY8k0x+2Wfvc/ZWjEajESGEEI+ksnQBQghRVkhgCiFEAUlgCiFEAUlgCiFEAUlgCiFEAUlgCiFEAUlgCiFEAUlgCiFEAdlYugBzMhgMJCQk4OrqiqIoli5HCFFGGI1GMjIyCAgIQKV6cDuyXAVmQkICQUFBli5DCFFGXb58mcDAwAc+X64C09XVFch7025ubhauRghhzT7//HMiIyMBGDJkCJ999pkpQx5EKU/3kqenp+Pu7k5aWpoEphDigVauXMnIkSMxGo1ERkYyd+5cPDw8HpkdMugjhKhQVqxYwYgRIzAajYwZM4aFCxcWeMxDAlMIUaHY2dmhKArjxo1jwYIFhRogLld9mEII8ShDhgyhbt26NG/evNBX00gLUwhR7q1du5bExETT4xYtWhTp0kMJTCFEufbRRx8xePBgnnrqKdLS0or1WhKYQohya/HixaZLh7p3717sq2ckMIUQ5dLChQsZM2YMAG+88Qbvvvtuse8AlMAUQpQrOr2BGfP+w7hx4wCYPHky//73v81yu7SMkgshyg2d3kDYC2/x67p3AJg8eQrR0fPMNreEBKYQoty4dDOb6+71sPGohFP91oyaGGXWiXgkMIUQ5UZVLydC69ckfuh/aVwzgMe8nc36+hKYQogy7/333ycoKIj+/fuz6dWWXLqZTVUvJ2zU5h2mkcAUQpRp7777LpMnT0atVtOwYUMaNmxIDV+XEjmWjJILIcqsd955h8mTJwMwffp0GjZsWKLHk8AUQpRJ8+bNY+rUqQDMnj2bmTNnlvgxJTCFEGXO22+/zVtvvQXAnDlzmD59eqkcV/owhRBlyvbt200BOXfuXKKiokrt2BKYQogypXPnzrz66qsEBQUxZcqUUj22BKYQokzQ6/Wo1WoURWHRokUWWRlW+jCFEFbNaDQyc+ZM+vbti1arBbDYMtrSwhRCWK07YTlnzhwAtm3bRs+ePS1WjwSmEMIqGY1Gpk+fzty5cwGYP3++RcMSJDCFEFbIaDTy1ltvER0dDcAHH3zAhAkTLFsUEphCCCtjNBqJiorinXfypmj78MMPTXNbWpoEphDCqly4cIEFCxYAsGDBAsaOHWvhiv4mgSmEsCo1atTgu+++49SpU7zyyiuWLicfxWg0Gi1dhLmkp6fj7u5OWlpasRc7EkKUHqPRSGJiIgEBARY5fkGzQ67DFEJYlNFo5PXXX6dx48acOHHC0uU8lASmEMJijEYjr732Gh988AHXr1/n0KFDli7poaQPUwhhEUajkQkTJpgGeJYuXcqLL75o4aoeTgJTCFHqjEYj48aNY9GiRQAsW7aMkSNHWriqR5PAFEKUKqPRyNixY1m8eDGKorB8+XKGDx9u6bIKRAJTCFGqNBoN8fHxKIrCihUrrP40/G4SmEKIUuXo6Mi2bduIiYmhR48eli6nUGSUXAhR4gwGA9u2bTM9dnV1LXNhCVYcmNHR0SiKYhU33Ashis5gMPDyyy/TtWtX0/3hZZVVnpIfOnSITz75hJCQEEuXIoQoBoPBwEsvvcSKFStQqVQEBgZauqRisboWZmZmJoMGDWLZsmV4enpauhwhRBEZDAZGjRplCstPP/2UwYMHW7qsYrG6wIyMjKRbt2506NDhkfvm5uaSnp6e70sIYXl6vZ4RI0awcuVKVCoVn3/+OYMGDbJ0WcVmVafkGzZsIC4ursC3R0VHRzNr1qwSrkoIURhGo5GRI0eyevVqVCoVa9euZcCAAZYuyyyspoV5+fJlxo8fz+eff46Dg0OB/s3UqVNJS0szfV2+fLmEqxRCPIqiKDRp0gS1Ws26devKTViCFU3vtmXLFnr37o1arTZt0+v1KIqCSqUiNzc333P3I9O7CWE9zp07R61atSxdRoGUuend2rdvz/Hjx4mPjzd9hYWFMWjQIOLj4x8ZlkIIy9HpdMyaNYvU1FTTtrISloVhNX2Yrq6uBAcH59vm7OyMt7f3PduFENZDp9PxwgsvsH79er7//nv27duHSmU1bTGzsprAFEKUPZpcLf0GDuKbzf/DxsaGN954o9yGJVh5YMbExFi6BCHEA2hytdRs2YWEuF0oahu++PJLevXqZemySlT5/VMghCgxOp2OZ58bSELcLlDZ4NNzKk0iOlq6rBJn1S1MIYT10ekNDB8dyXdbN6FS2+LdaypPtO1IVS8nS5dW4iQwhRAFptMb6PPRTxxRheLoVZm1Kz6mcaunqOrlhI26/J+wSmAKIQrs0s1sjl1Nw9Y7EN8XP6Jxq6eo4eti6bJKTfn/kyCEKDatVsvAgQP5/dA+Qqq4A9C4mk+FOA2/m7QwhRAPpdVq6devH19//TXbt2/n3B/nSdPbVpjT8LtJYAohHig3N5e+ffvyzTff4ODgwBdffIG3lyfeli7MQiQwhRD3lZuby7PPPsu3336LYmNHk+HzeKr9o6ddLM8qVntaCFEgGo2GPn36mMLS99kZJLrW4dLNbEuXZlHSwhRC3OOjjz7iu+++w9HRkcbD55HoUpuQQPcKN8jzTxKYQoh7jBs3jpMnTzJo0CBat2nLpZvZFXKQ55+sZj5Mc5D5MIUousysbBIzblPd17XCBWOZmw9TCGE5t9IyqBbahqYd+9J7USw6vcHSJVklCUwhKrj0jExqtWjHjTOHyT4dS9zxUxV+cOdBJDCFqMCys7Pp0q0HN88cQbF1wK/fvwhuWL/CD+48iASmEBVUekYmHZ7uyk/7YlDbO+LXfxaNw8LZGtmqwvVhFpSMkgtRAaWlZ1AzrC03zsahtnfk++3bqNawmYyEP4IEphAV0LaY/dz44xiKnSM+fWdTrWGzCjXrUFFJYApRAfXt1on5I97mco6a5o8/IX2WBSSBKUQFkZmZyY0bN3jsscewUav4ackbckF6Icl3SYgKICMjg6ef7kJ4qwjOnD0HgI1aRQ1fFwnLQpDvlBDl3K3UNNp26MT+/bEkXb/FyE9i5ML0IpLAFKIcu3krlZqhEcQdPIDK3hn/597mkrqyXJheREXuw7x9+zZJSUlkZ2fj6+uLl5eXOesSQhRTWloaHTp24taFE6jsnfEbMBf7SrVk1qFiKFRgZmZmsnbtWtavX8/BgwfJzc01PRcYGEinTp146aWXaN68udkLFUIUXPK1G7Tr2Inffo3D1skV735zCGsWyvz+Taju4yz9lkVU4MD84IMPmDt3LtWqVeOZZ55hypQpVKlSBUdHR27evMmJEyfYt28fHTt25IknnmDhwoXUrl27JGsXQtxHZo6WVtE/cCnxFipHV37Y+T2BtYNlNNwMCjy9W79+/ZgxYwaNGjV66H65ubmsWLECOzs7Ro4caZYiC0qmdxMVlU5v4ML1LHJv6xj9WRxX0zTos9PQZ96kbr2G7Hy9jYTlQxQ0Owo1H2Z8fDxNmjQxR30lQgJTVEQ6vYHei/fz6/kEci7G41wv4p59dr3eRu7keYgSmQ8zNDSUZs2asWTJEtLS0opdpBCi+C5czyL+fALJX0zj+tZ3yDy2EwBbtQIggzxmVKjA3L9/P6GhoUyZMoXKlSszePBgdu/eXVK1CSEeQac38OqKPaRseAtt0jlUjm7YVa7NY54OHJ3WgV2vt2HTKy3ldNxMCvVdDA8PZ9myZSQlJbFkyRKuXLlChw4dqFmzJnPnzuXKlSslVacQ4j4On77E3gUT0Cb/gcrJHf+B87DzrcbHQ8JwcbSTO3nMrEjfSUdHR4YOHUpMTAxnzpxh4MCBLF26lOrVq9O1a1dz1yiEuI8/ryTSoUPHv8LSA/8BeWEZHOBGbX9XS5dXLpllEbQ712dGRUWRmpqKXq83R22FJoM+oiLQ6Q0cu5hMy1YR5CafR+WcF5a169Rl6ZAwavlJq7KwCpodxZqtaM+ePaxcuZKNGzeiVqvp378/I0aMKM5LCiEe4s6I+LGraTjUbMHtzJtUGhBN9Vp12DGhNQ52MgFZSSr0d/fy5cusXr2a1atXc+HCBVq2bMnChQvp378/zs7OJVGjEOIvvyemczwhHUVRcI8YhGuzHji5ebB9fISEZSko1He4Y8eO7N69G19fX1544QWGDx9O3bp1S6o2IcRfdHoD+4+f45kXx+P+1EhUtg4oioLayZ2tkRG4ONpZusQKoVCB6ejoyMaNG+nevTtqtbqkahJC3EWnN9D1nW+I+WAst29cQqfNwbfHGwA0quJGLT+5IL20FCowv/7665KqQwhxHzq9ga0/nzKFpdrFG49Wz2Orgs2vtqJeZTcZ4ClFRf5O79u3j8GDBxMeHs7Vq1cB+Oyzz4iNjTVbcUJUZBqtjvZvb2Fgr66msPR/PpratWpxdHpHggM9JCxLWZG+2xs3bqRz5844Ojpy9OhR0zRvGRkZzJs3z6wFClER6fQGOs/byk8LxnP7xmXUrj74Px/NyrHd+eH1ttJnaSFFCsy3336bjz/+mGXLlmFra2va3rJlS+Li4sxWnBAVUWaOlsW7zvLL8unobl5B7eqL/8BobD0DsLNRSavSgop0HcLp06dp3br1Pdvd3NxITU0tbk1CVFjXM7IJm5s3P4Nnh9Hc2LYA395R2HpUwtFWTXgNbwtXWLEVKTArV67MuXPnqFatWr7tsbGx1KhRwxx1CVHhZOZoeXzuLiBvliH7SrWoPOy/BFfx4PWOdWhZ01uutbSwIrXtR48ezfjx4/nll19QFIWEhATWrl3LpEmTePXVV81doxDlnk5voMOcLVxZPYHcq7+Zts9+Jpitka14qr6/hKUVKNJP4M033yQtLY127dqh0Who3bo19vb2TJo0iTFjxpi7RiHKNZ3ewOZ9v3JkyQR0qYnc2LGYyi8uwEZR8VzzIOmztCLFmnwjOzubU6dOYTAYaNCgAS4ulr2AVibfEGWNRquj09ub+HnheHSpSajd/ak0MBobdz++jmxFSJCHpUusEEpkxvW7aTQaTpw4QVJSEklJSezatYuvv/66yBe3L1myhJCQENzc3HBzcyM8PJxt27YVtTwhrF5mjpYnZ3zJzwvGoUtNwsbdn2avzMfG3Y/gAFcaBMgffWtTpFPy7du3M2TIEG7cuHHPc4qiFGl6t8DAQN555x1q1aoFwJo1a+jZsydHjx6lYcOGRSlTCKul0epo9MY6rnw+BV1aMjYelag0MJod0/pwM1snKzxaqSL9RMaMGUP//v1JTEzEYDDk+yrqXJg9evSga9eu1KlThzp16jB37lxcXFw4cOBAkV5PCGv2428pXI/94q+wrIz/wGjUbr78eiVdZkm3YkVqYaakpDBx4kT8/f3NXQ8Aer2er776iqysLMLDwx+4X25urukuI8jrhxDCmun0BuL+vE7k+qN4dXgJFAX38OewcfPB0VbN49W9LF2ieIgiBWbfvn2JiYmhZs2aZi3m+PHjhIeHo9FocHFxYfPmzTRo0OCB+0dHRzNr1iyz1iBESdHpDXT597ecSVNQFAXFxg7vzpEARPcOpnfTKnLpkJUr0ih5dnY2/fr1w9fXl0aNGuW7PRJg3LhxRSpGq9Vy6dIlUlNT2bhxI8uXL2fPnj0PDM37tTCDgoJklFxYpR8PHqNzxw441W2FZ7sRKEreBeoNKjnz9djWchpuQQUdJS9SYC5fvpyXX34ZR0dHvL29TT94yBv0OX/+fNGq/oc7K1IuXbq0QPvLZUXCGmm0Otb/cJBXnu9Fbto1bLwCqTzkPVQOLvy3f2O6Nw6QsLSwEl3TZ9q0acyePZspU6agUpXcD9poNOZrQQpR1mTmaGk06XMufzYZfcZ1bLwC8R84D5WDC7V8nCQsy5giBaZWq+W5554za1hGRUXRpUsXgoKCyMjIYMOGDcTExLB9+3azHUOI0qTTG3hq5pdc/vRN9Jk3sPEKpNLAaNQuntTxc+HrMa0kLMuYIgXm0KFD+eKLL4iKijJbIcnJyQwZMoTExETc3d0JCQlh+/btdOzY0WzHEKK0ZOZomffFbuKWjEefeRNb76r4D5yLvYsnWyJlpvSyqkiBqdfreffdd9mxYwchISH3DPrMnz+/0K+5YsWKopQihNXJzNESPGsnWb/tRZ95yxSWgZX82TmxjUz+W4YVKTCPHz9O06ZNAThx4kS+5+4eABKiotHpDSzedQ4A5/qtUdQ22FdpQPUq/nw/sa1cNlTGFemnt3v3bnPXIUSZl5mjpe30dSRp1Ni45F2A7lSnJQDTewRLWJYD8hMUwgyuZ2TT5LVPSdoQhWLvjP/AeabQdLBReLK2j4UrFOZQ4F7nS5cuFeqF76wkKUR5l5mjJeS1NSRumIo+6xaKjS2KSg3AwgGNiZ/RSVqX5USBA7N58+aMGjWKgwcPPnCftLQ0li1bRnBwMJs2bTJLgUJYM53ewL8+3UHy+igMWanY+tXAf8BcOjatyYmZHenRJFDCshwp8E/yt99+Y968eTz99NPY2toSFhZGQEAADg4O3Lp1i1OnTnHy5EnCwsL4z3/+Q5cuXUqybiEsSqc38HtiGs9Hr+fk6igM2WnY+dfE77k5qB3dmNChroyGl0OFvjVSo9Hw3XffsW/fPi5evEhOTg4+Pj40bdqUzp07ExwcXFK1PpLcGilKg05voOfi/Rz99TjJG+4Oy7dRO7pSz8+Jb8a3kessy5ASuzXSwcGBPn360KdPn2IVKERZdTY5g5MJ6ajsnVHZOWHj5otf/zmoHV35eFAoHRr4S1iWU9K5IkQB6fQGLlzP4uVP8/rxbdx88B8YjWLngNrBhbp+ThKW5ZwEphAFoNMb6LkolqPxv3L7VgLO9SKAvNAE+M+zDekdWlXCspyTwBTiEXR6A9uOJ3I0Pp7kDW9hyM1GZeeIY41mADSo7CphWUFIYArxEHdalnFHj5LyxTQMmkzsKtfFvko9AD4b0YzwGn4SlhVEkX/K+/btY/DgwYSHh5suUv/ss8+IjY01W3FCWNqF61n5wzKgLv7PzUFl78y6EY/zZO1KEpYVSJF+0hs3bqRz5844Ojpy9OhR0yS/GRkZzJs3z6wFCmEpGq2OlZt2krLhLQyaTOwD6uHffw4qeydqeNnTooYsWFbRFCkw3377bT7++GOWLVuWb2q3li1bEhcXZ7bihLCU1CwN9SZ8yruvvYAhNwv7Kg3w6z8blb0TAIsHN5eWZQVUpD7M06dP07p163u2u7m5kZqaWtyahLCo1CwNTeb8iNHVD+eGbdGmXMCv779MYdmgkgu1/V0tXKWwhCIFZuXKlTl37hzVqlXLtz02NpYaNWqYoy4hLOJOWELe3K6eHV7GqNOisrUH4H+jw2lS1UNalxVUkX7qo0ePZvz48fzyyy8oikJCQgJr165l0qRJvPrqq+auUYhSkZqlof7Li7n+zfsY9beBvNBU2drjYa8QP709YdW9JCwrsCK1MN98803S0tJo164dGo2G1q1bY29vz6RJkxgzZoy5axSixCWlZdJ0zMckfzkDozYHG4/KeEQ8D4Cfk8LeKTJFmyjiuuR3ZGdnc+rUKQwGAw0aNMDFxcWctRWaTL4hCkunN/DLH9d5dvYaUr6aiVGbg33VRvg9OxOVnQMuNnB4RmcJy3KuRNclv8PJyYmwsLDivIQQFqPTG+j24R5+jTtEylf/wqjNweGxEHyfnYHK1gGAmMntJCyFSZE+CbNnz37o8zNmzChSMUKUFp3ewNdHr/DrkYN5YXlbg8NjjfF9djoqWwda1vDko0GheDg7WLpUYUWKFJibN2/O9/j27dtcuHABGxsbatasKYEprJpOb6D7h3s4dfUm17a+81dYNsH32WmmluUnQ8JkAmBxjyIF5tGjR+/Zlp6ezrBhw+jdu3exixKiJP3yx3V+T8lGZeuA7zOTST+8FZ8eb5guHTr8VjsJS3FfxRr0+acTJ07QvXt3Ll68aK6XLBQZ9BEPo9Hq2HjkKlGbjqKobe953s/Fll2vt5WwrIBKZdDnn1JTU0lLSzPnSwphFhqtjsazdpB2/hjXv/svfn1nYOdbzfS8l6OKvW8+JQM84qGK9OlYsGBBvsdGo5HExEQ+++wznn76abMUJoQ5ffNrIqnnf+Xa/2Zj1OWS/stGfLq/bnp+1yQZDRePVqRPyAcffJDvsUqlwtfXl6FDhzJ16lSzFCaEuVzPyCby/U+5tnE2Rp0WxxpheD89DoBREdUY3762nIaLAilSYF64cMHcdQhRIq7cyqDFyx9ybdOcvLCs2RzfXlEoNrZU87Rjcpf6cqujKLBCf1Ju375Nu3btOHPmTEnUI4TZnE5OpdnL/yXpTljWamEKy0rOKra/1k7CUhRKoVuYtra2nDhxAkVRSqIeIczi3LU0Os2PJf2XTX+F5eP49pqCorbFx1FNzOQO0mcpCq1If15feOEFVqxYYe5ahDCLizfS6fB+LIqi4Ns7Cvfw50xhCRAjo+GiiIr0qdFqtSxfvpydO3cSFhaGs7Nzvufnz59vluKEKKwrtzJoFfUltp6VAVDZO+HReggAlV3U7Hz9KRngEUVWpMA8ceIEoaGhAPf0ZcqpurCUpLRMQl96n2ub5+LR6nncw/ubnls8oDGdGwVIn6UolkIF5vDhw/nwww/ZvXt3SdUjRKFptDp2/ZbMsDmfcG3zPDDo0Cb/gdFoQFFUzO8XTLcmgZYuU5QDhfpzu2bNGnJyckqqFiEKTaPV0WjmDobNWWoKS6e6Efj0eANFyft4NwqU1R2FeRSqhWnG286FKLbULA3jNhwh7cwBrm15Jy8s6z2JT49JKCo1AMEBblT3cX7EKwlRMIXuw5Q+SmEN7ixWln3mZ65tfQcMepzqt8an++umsPxmTCvqVXaTfkthNoUOzDp16jwyNG/evFnkgoR4FI1Wx4QNeVMM6jKu/xWWbfDpPhFFpWZkeBCTujSQS4eE2RX6EzVr1izc3d1LohYhHkmj1VFvxg7TY7dmPbD1qIxD9aYoKjXVPe2Z0j1YWpWiRBQ6MAcMGICfn19J1CLEI63ee4Gc80ewC6iL2iFv0T3HmnnrSvk527LttbYSlqLEFOqTJf2XwlIyc7R8+N1vTF+0kpT/zSLli2kYcrPz7bNq+ONyGi5KlIySC6uXmaMleNZOsn7by/X/ew+MBmx9qqL8taQEQF1fR+pWcrVglaIiKFRgGgyGkqpDiHvo9AYuXM/ine2/knVqD9e/eR+MBpyD2+PdZZxpNHzdiMdpUcNLTsVFiZPzF2GVNFodzyyK5UxKFlmnYrj+zfy8sGzUAe+nx5rCMnZyawI9pWUpSocEprA6Or3h77D8PfausOyId5expjt4JCxFabOac5jo6GiaN2+Oq6srfn5+9OrVi9OnT1u6LGEB51IyOZOSBYCdX3XUzh64hHQyhaW7nUL89PYSlqLUWU1g7tmzh8jISA4cOMDOnTvR6XR06tSJrKwsS5cmSlFmjpbnFu8zPbb1qkKlF+bj9fQYFEVFgIuaX6Z1wsPZwYJViorKrOuSm9O1a9fw8/Njz549tG7dukD/RtYlL9s0Wh3BM3eQevxH1E4eONZolu95bycb9k9pL5cOCbMraHaYvYWpUql46qmnOHLkSLFe58765l5eD55pJjc3l/T09HxfomzSaHVEf3uS1F93cuPb/5Ky6W201/40Pa8C9rwhS+EKyzJ7YK5cuZI2bdowbty4Ir+G0Whk4sSJREREEBwc/MD9oqOjcXd3N30FBQUV+ZjCcq5nZFNvxg4WL1vJjW0LACOujTth61MVgKHNq3BqdmeZKV1YnFWekkdGRvLtt98SGxtLYOCDJ37Nzc0lNzfX9Dg9PZ2goCA5JS9D7lyUnvHrDm5uXwiAa2h3PDuMRlEU+jTyZf6gFhauUpR3BT0lt7rzm7Fjx/L111+zd+/eh4YlgL29Pfb29g/dR1gvnd7Af3b8Tkb8dm7uWASAa7MeeLZ/yXQb7vA2dSxZohD5FDswU1NT2bFjB1evXkVRFCpXrkznzp3x9PQs1OsYjUbGjh3L5s2biYmJoXr16sUtTVgxnd5Ap/kxnDzy811h+Qye7UeZwrJhZVfqVZYzBWE9itWHuWLFClq0aMGBAwcwGAzo9XoOHDjAE088UehleCMjI/n8889Zt24drq6uJCUlkZSUJEtilFPbTyZw/kYODlUb4VS/Da5hPfOF5bZxEWwdEyG3OwqrUqw+zLp163LkyBFcXFzybc/IyKBZs2b3rCj50EIeMBPSqlWrGDZsWIFeQy4rsn6ZOVo+++lP3vn+tOlnbjToQVGhKAqRraoytnN9GQ0XpapU+jAVRSEzM/OewMzMzCz0VHBWOPYkzMw0wBP3DblJ50z3hN+5L3xA88q80aORhasU4sGKFZjvvfcebdq0ITg4mCpVqgBw5coVTp48yfvvv2+WAkX5oNMbmL7lGOlH/o9bPywFwLFGGM71Ikz7DHmipqXKE6JAihWY3bt3p0uXLhw8eJCEhASMRiNVqlShRYsWqNVqc9UoyrjrGdlEzN1NyuGt3PpxGQBuj/fFqW4r0z71/Z1kPkth9QoVmEOGDGHp0qU4OTmZtqnVasLDw81emCgfUrM0hM3dTfqhrdza9VdYPtEPj9YvoCgKLz1ZjT6hQdTyc5EBHmH1CvUJXbduHZmZmabHo0eP5tatW/n2uX37tnkqE2VeZo6WyLVHSD+05e+wDH/OFJY1fBx48+n6shSuKDMK9Sn958DM+vXr8wVmcnIyrq5yWiXyTsODZ+0kJu53bu1ZDYB7+HN4PDkYRVFoW8eL719rJ0EpypRi9WHeb2Rbq9UW5yVFGafTGzidlEG3hbEA2HpUwrfXVLTJ53FvOcB09cR/n2sqYSnKHLNf7CYrS1ZcOr2Bngv3cTIpE0NuFip7ZwCcaj2OU63HAXAE9r3VTuazFGVSof/Er1u3jri4OFNfpQSkuONUQjonkzJJO/AVCSvGcDs1Kd/z3UJ8OT63Cz6uTg94BSGsW6FamBEREcycOZOMjAxsbW3R6XRERUURERFBaGgovr6+JVWnsHKZOVqeWbyftJ+/JHXvpwDknPsF27Cepn3+3buJnIaLMq1It0aePXuWI0eOEBcXx5EjRzh69Cipqamm1qZerzd7oQUht0aWvjt9lt0XxpL60xek7vsMAPcnB+PRcgAAzmrYH9VeTsOF1SrRWyNr165N7dq1GTBggGnbhQsXOHz4MEePHi3KS4oySKc30HNRLCcTM0jdv5602LUAeLR+Affw/gC0r+vB0hfCpWUpygWzDfpUr16d6tWr069fP3O9pLByZ5Mz8sIydh1p+9cB4NFmKO5P/P0ZWDzocQlLUW7IlDCiSDJztPRcEIvhdi7ZZ38GwKPNMNyf6AvAyJZBTHq6gcw6JMoV+TSLQtNodQTP2gmAytYe/+feJufcQVxCOgIQ4AxTugVLy1KUO8X+RMfFxcnF6hWITm9g1jfHyE04bdqmdnI3hWUlV3t2Te4sYSnKpWJ/qps3b87FixfNUIqwdqlZGprN2sZH771L0mevk3H0u3zPB7jZEvNGWzkNF+VWsT/ZMvFvxZCapaHx7B9I3fsp6Qe+AsCo+/vMYmR4EFO6y2m4KN+kKSAeSac3ED7nB1L3rCH9l/8B4Nl+FG53XZQ+qUsDCUtR7klgiofSaHVM2xxPQsxq0n/ZCIBn+5dwC3vGtM+BqW3kNFxUCPIpF/el0xs4lZBOr0Wx3IhZRfrBTQB4dhiNW7Mepv0Ov9VO7g0XFYYEpriHTm/gmYX7OJWUCYqCYmMPgFfHl3EN7W7aL3663O4oKhYJTHGPk1fT8sLyL+4Rz+NYMwz7gLoAOChwYJqEpah4pJde5JOUlskzi/eTcfQ7DFoNkDeF352wtFHB4RkdJSxFhVTswJw5cyY+Pj7mqEVYWGqWhsfnxXDrx2Xc/P4jrm2ajdFoMD3vqob46R1xcbSzYJVCWE6xT8lnzpxpjjqEhen0Bl759Gdu/fgJGUf+DwCn+m1QlL//pv48TcJSVGzShynQaHU0mb6dhB8+JiPuW0DBu8tYXEI6AeBuC/ujJCyFkMCs4O7cwXNz58dkHr0TluNM94Z7Oaj4KaqjXGcpBIXswxwyZAjZ2dklVYsoZalZGprM+ZHUPav/Dsuu401hqQB7J7eXsBTiL4UKzHXr1pGZ+fflJqNHj863LjlgWhxNWLc7YQngXL81Kkc3vLtOwKVRB9M+28Y/KafhQtylUIH5z4k21q9fny8wk5OTcXV1NU9lokRotDq2xF0xhSWAnX9Nqoxehkuj9qZtjaq4UcvPxRIlCmG1inWudb+ZimRuTOul0eoInrGD20YDt35chlO91jgE1gcwrSEOsHRwKO3r+8tkGkL8g9l/I2Sdcuuk0xtY+sNZbhsN3Ni2gIwj/8e1jbMwaDLz7dewsouEpRAPUOgW5rp162jdujWNGjUCJCDLAo1WR5cPYjh/I5sb2xaSdeIHUFR4dXwFlUPeabebDXwZ+SS1/FwkLIV4gEIFZkREBDNnziQjIwNbW1t0Oh1RUVFEREQQGhqKr69vSdUpikinN9Bj0f6/wnIBWSd+BEWFT49JONdvbdrvp7fkOkshHqVQgbl3714Azp49y5EjR4iLi+PIkSNMnz6d1NRUaW1aoWOXb3EmKY0b3/2XrJO7/wrLN3Cu/6Rpn/jp7SUshSiAIg361K5dm9q1azNgwADTtgsXLnD48GGOHj1qtuJE8VzPyKbPxwfIOPLN32H5zJs414sw7SNTtAlRcIqxHC3Kk56ejru7O2lpabi5uVm6HIvR6Q0cunCNgcsPA3lr71zb+m+cg5/CuW4r034HprahkrtcOiREQbNDbuEoZzRaHV0X7OOPlAxQVCiKgmJjh2+faaYuk5BKTnw6KlxalkIUkgyHliM6vYGuH8TwR0oG1795n1u7lpuulb27f3nd6FYSlkIUgbQwy5EjF2/xx41srv/fe2T/vg9UNriEdMTOt5ppnwNT28gAjxBFJIFZTqRmaej/cWxeWJ6OBZUNvr2mmsKyawMf3u3XVMJSiGKQwCwHdHoDreft4PrX75J95qe8sOw9Fadaj5v2mT+gmcw6JEQxSR9mGafR6piz9Sh//O+vsFTb4Ns7yhSWvRv78PvszhKWQpiB/BaVYdczsgmbuxvNn8fIPnsA1Db49X4Lx5rNAXAC/tO/udzqKISZSGCWUUlpmTwRvQcAh8dC8O72GmoHVxxrhpn2+WBQUwlLIcxIArOM0ekNxF9K5dmP9mLQZKF29gDApWG7fPs52qpoU9fPAhUKUX5ZVfNj79699OjRg4CAABRFYcuWLZYuyaro9Aa6fbCbZxfv5dqWaJLWTUGXefOe/ZYOasrR6bIOjxDmZlWBmZWVRePGjVm0aJGlS7FKx6+k8XtSBte2zCPn3EH06Snobl7Jt8/ht9rRuVGAhKUQJcCqfqu6dOlCly5dLF2GVcrM0dJrYQzXNs8j5/zhvNsdn52BQ9UQAMa1qcmr7WtJUApRgsr0b1dubi65ubmmx+np6RaspuRk5mhpOP1bUjbPRXP+CIqNPb7PTsexWhMAHvO0Z1ynOjLAI0QJK9O/YdHR0bi7u5u+goKCLF2S2ej0Bs5fy0Sj1dFm7rekbLorLPvOMIXlG0/V4MdJT0lYClEKynQLc+rUqUycONH0OD09vVyEpk5voNfi/ZxISMfP2ZaU1Cx0qQkotvb49Z1pOg33dVQY3b6uhKUQpaRMB6a9vT329vaWLsPszqVkciIhr3shJes2ahdP/AdEo0tPxiGwIQAKsPvNDhKWQpQi+W2zQpduZGO4nUvOxXjTNhs3H1NY+jgqHJ8pa/AIUdqsqoWZmZnJuXPnTI8vXLhAfHw8Xl5eVK1a1YKVlZ7ULA1jV+3n2sa30Vw6ds/6O9W8nNg+4UkZDRfCAqzqt+7w4cO0a/f3HSt3+ieHDh3K6tWrLVRV6UlKy6TF7B1c2zgbzZ/HUOwcUbt65dtn2dAwCUshLMSqfvPatm1LOVpiqMA0Wh07TyUR+ekvpGycTe6lvLD06zcLh8AGpv1CAt2p7uNswUqFqNisKjArIo1WR5M5O8nOyiZl4yxyLx3/Kyxn4xBY37TfqmFhPFnbVwZ5hLAgCUwL+/n8DXJyNKT871/kXj6BYueIf//Z2Ff5OyyDA9wkLIWwAhKYFpSapWH9L+dBbYud72Nok8//FZb1AJjepT6t6/lS3cdZwlIIKyCBWcp0egPnUjI5lZDKxK+OA3krOnp2eBnX5r2x9agEQE1PW4ZGVJOgFMKKSGCWorvv4DHkZpP+y0bcWw1AUduiKIopLDeMfJyw6l4SlkJYGQnMUnTpZrYpLFO+nEFuwu/oMq7j0+010z7x09vLmuFCWClpwpSiql5OeKs1JH85ndyE31E5uODarIfp+ff7hkhYCmHFpIVZCnR6A78nprPlp9OcWPUW2sTTqBxc8Hvubewr1QLATg3dQipbuFIhxMNIYJYwnd5AjwV7OflnMslfzkCbeAaVgyv+A97Gzr8mAO/2acQzTWSWdCGsnfyGliCd3sD2E0mcSsrk2pZ5d4XlXOz8a5j2C6vuJWEpRBkgv6UlRKc30HXBXs4kZ6EoCu6tnuf2rST8np2Gnd/fYVnX35WqXk4WrFQIUVASmCXk5/MpnEnOMj12CAqmyktLUdS2pm11/V3YGtlSLh8SooyQwDSzvAGeNJ5fFMP1r9/Fs91w7PyqA5jCMnZya7Q6hapeThKWQpQhEphmpNMb6Ll4P8f+uELyhmncTjnP9a//Q+URi1CUvGCs7W1PJTe51VGIskh+a83obHJGvrBUOXng03OyKSwBzt7I5dLNbAtWKYQoKglMM9DpDZy4cosZ62NJ3vBWXlg6e+A/cB52vo8BUM0zb+2hkEB3GeQRooySU/Ji0ukNdF+wl5MXEvLC8tpFVM4eVBoQja1P3gqWtbzs+GZCWxLSNNJvKUQZJoFZDDq9gW9+vcLvyVmk7v2U29cuonb2xH/gPGy988Jy1QvNeLKuHzZqFTV8XSxcsRCiOCQwi0ij1dFj0X7OpmQC4NluBIacDDxaDzGF5drhzWlVx8+SZQohzEgCswh0egM9FsVy+uoNVLZ5k2Wo7J3w7R1l2qeahx2P1/SxVIlCiBIgnWmFoNMbOH8tk5NXU/n9whWS1kwk7ecv79mvqoc92ye2k75KIcoZaWEWkE5voM9HP3Hsahr6zFskb4ji9o3LZMR9i0vTrqgd8vonFz3fmKcbBkhYClEOSWAW0IXrWRy7moYu8ybJ66PQ3byC2tUH/4HzTGEZ88aTVPN2s3ClQoiSIoH5CDq9gQvXs4j8/NA/wtI3bzTcM28Oy69eelzCUohyTgLzIXR6A70X7+d4Qjq6jBskb4hCd/Mqajdf/AdG/71gmZcdTR/zsnC1QoiSJoH5EBeuZ3E8IR0AzcX4+4bl3ddZCiHKNwnMh9DpDab/d2nUHqNBj8NjIaaw3PFaK+r6e1ioOiFEaZPAfACNVseXPxxFn5OB2tEVANfGnfLtY6uSb58QFYn8xt9HZo6WBq+vI3F9FCp7J/wGzDWNhN8hk2gIUfFIYP7lzmh47m0dgz/4PxLXT0WXmoSNuz9GbQ78FZhbIp/AzcFeJtEQogKSwOQfo+FpKSSvn4ouLRkbj0r4D4zGxs0XgB9ej6CWr7uFqxVCWIoEJnDpZvZfYZlM0voo9GnJ2HhU/issfVABcdPb4+HsYOlShRAWVOEDU6c3kHtbjzEtmaR1U9Gnp2DjWRn/AXlhWdndgZ0TnsTF0c7SpQohLKxCB+bd94fr9Dow6LDxDMB/4DxsXPNmGprTs6GEpRACqOCBeef+cABbryr4D4xGsXXAxtU7b5sCEbVkijYhRJ4KG5g6vYERC74m58IFHKs3BfJCE8DdwYY5PYPp1NAfB7sK+y0SQvxDhU2DH3/5lZ8WTkCfnYZ/v1k4PBZiem7dqCdoWEVGw4UQ+VXICwnPnTvH4D7d0Gdcx8bd37SkBEDDyq7UreRqweqEENaqwrUwz549S9u2bbmenIidTxB+A+Zh7+LJulEt8HR2oLqPs1yQLoS4rwoVmGfOnKFt27YkJibSoEEDvtv+PRezbXm8upf0VQohHqnCpMTly5dNYdmwYUN27dqFn58fj1m6MCFEmVFhzj0DAgJo164djRo1Yvfu3fj5yfK3QojCqTAtTLVazZo1a8jIyMDT09PS5QghyqBy3cI8deoUEydORK/XA2BjYyNhKYQosnLbwjx58iTt2rXj2rVreHp6Mn36dEuXJIQo48plC/PUqVOmsGzatCmvvvqqpUsSQpQD5bKF2a1bN27evEloaCg7d+7Ey0tWdBRCFF+5bGHevHmTZs2aSVgKIcyqXLUwjUYjACEhIWzcuBEbGxvS09MtXJUQwtrdyYk7GfIgivFRe5QhV65cISgo6NE7CiHEfVy+fJnAwMAHPl+uAtNgMJCQkICrqyuKoli6HLNLT08nKCiIy5cv4+bmZulySkRFeI9QMd5nWXqPRqORjIwMAgICUKke3FNZrk7JVSrVQ/86lBdubm5W/wEsrorwHqFivM+y8h7d3R89pWO5HPQRQoiSIIEphBAFJIFZhtjb2zNz5kzs7e0tXUqJqQjvESrG+yyP77FcDfoIIURJkhamEEIUkASmEEIUkASmEEIUkASmEEIUkARmGbB371569OhBQEAAiqKwZcsWS5dkdtHR0TRv3hxXV1f8/Pzo1asXp0+ftnRZZrVkyRJCQkJMF3KHh4ezbds2S5dVoqKjo1EUhQkTJli6FLOQwCwDsrKyaNy4MYsWLbJ0KSVmz549REZGcuDAAXbu3IlOp6NTp05kZWVZujSzCQwM5J133uHw4cMcPnyYp556ip49e3Ly5ElLl1YiDh06xCeffEJISIilSzEfoyhTAOPmzZstXUaJS0lJMQLGPXv2WLqUEuXp6Wlcvny5pcswu4yMDGPt2rWNO3fuNLZp08Y4fvx4S5dkFtLCFFYpLS0NoNzOZ6rX69mwYQNZWVmEh4dbuhyzi4yMpFu3bnTo0MHSpZhVuZp8Q5QPRqORiRMnEhERQXBwsKXLMavjx48THh6ORqPBxcWFzZs306BBA0uXZVYbNmwgLi6OQ4cOWboUs5PAFFZnzJgxHDt2jNjYWEuXYnZ169YlPj6e1NRUNm7cyNChQ9mzZ0+5Cc3Lly8zfvx4vv/+exwcHCxdjtnJrZFljKIobN68mV69elm6lBIxduxYtmzZwt69e6levbqlyylxHTp0oGbNmixdutTSpZjFli1b6N27N2q12rRNr9ejKAoqlYrc3Nx8z5U10sIUVsFoNDJ27Fg2b95MTExMhQhLyHvfubm5li7DbNq3b8/x48fzbXvxxRepV68ekydPLtNhCRKYZUJmZibnzp0zPb5w4QLx8fF4eXlRtWpVC1ZmPpGRkaxbt46tW7fi6upKUlISkDepq6Ojo4WrM4+oqCi6dOlCUFAQGRkZbNiwgZiYGLZv327p0szG1dX1nn5nZ2dnvL29y0V/tARmGXD48GHatWtnejxx4kQAhg4dyurVqy1UlXktWbIEgLZt2+bbvmrVKoYNG1b6BZWA5ORkhgwZQmJiIu7u7oSEhLB9+3Y6duxo6dJEAUkfphBCFJBchymEEAUkgSmEEAUkgSmEEAUkgSmEEAUkgSmEEAUkgSmEEAUkgSmEEAUkgSmEEAUkgSmEEAUkgSlEEdy4cQM/Pz8uXrxo6VIA6Nu3L/Pnz7d0GeWeBKbIp3Xr1iiKcs/XoEGDyswxhg0bhqIovPzyy/c89+qrr6Ioiun+9GHDhhVpqrzo6Gh69OhBtWrVilfsQ/To0eOBM5b//PPPKIpCXFwcADNmzGDu3Lmkp6eXWD1CAlPcxWg0Eh8fz3vvvUdiYmK+L3PN11gaxwAICgpiw4YN5OTkmLZpNBrWr19f7BmecnJyWLFiBSNHjixumQ81YsQIdu3axZ9//nnPcytXrqRJkyaEhoYCEBISQrVq1Vi7dm2J1lTRSWAKk7Nnz5KRkUHr1q2pVKlSvi8XF5cycwyA0NBQqlatyqZNm0zbNm3aRFBQEE2bNi3Wa2/btg0bG5t8a/G0bduWsWPHMmHCBDw9PfH39+eTTz4hKyuLF198EVdXV2rWrHnPsrpGo5F3332XGjVq4OjoSOPGjfnf//4HQPfu3fHz87tnRqrs7Gy++OILRowYkW/7M888w/r164v13sTDSWAKkyNHjmBjY1Oiy6KWxjHuePHFF1m1apXp8cqVKxk+fHixX3fv3r2EhYXds33NmjX4+Phw8OBBxo4dyyuvvEK/fv1o2bIlcXFxdO7cmSFDhpCdnW36N9OmTWPVqlUsWbKEkydP8tprrzF48GD27NmDjY0NL7zwAqtXr+buScW++uortFrtPV0YLVq04ODBg+VqQmJrI4EpTOLi4tDr9Xh7e+Pi4mL6GjVqVKke45tvvqFu3brUrl2b5cuXF/lYQ4YMITY2losXL/Lnn3+yf/9+Bg8eXOz3cPHiRQICAu7Z3rhxY6ZNm0bt2rWZOnUqjo6O+Pj4MGrUKGrXrs2MGTO4ceMGx44dA/LWm58/fz4rV66kc+fO1KhRg2HDhjF48GBT98Tw4cO5ePEiMTExpuOsXLmSPn364Onpme/4VapUITc31zT5sjA/mUBYmBw5coR+/foxd+7cfNv/+YsJ8K9//YtZs2Y99PUOHTp0T0vsUcfQ6XRMnDiR3bt34+bmRmhoKH369CnScrs+Pj5069aNNWvWYDQa6datGz4+PoV+nX/Kycm57wJfd7ea1Wo13t7eNGrUyLTN398fgJSUFABOnTqFRqO5ZwJhrVZr6jaoV68eLVu2ZOXKlbRr144//viDffv28f33399z/Dsz09/dghXmJYEpTI4ePcrs2bOpVavWI/cdM2YMAwYMeOg+9xtBftQxDh48SMOGDalSpQoAXbt2ZceOHQwcOPDRb+A+hg8fzpgxYwBYvHhxkV7jn3x8fLh169Y9221tbfM9VhQl3zZFUQAwGAz5/vvtt9+a3u8d9vb2pv8fMWIEY8aMYfHixaxatYrHHnuM9u3b33P8mzdvAuDr61uUtyUKQAJTAHD+/HlSU1MLPCDi4+NT6NZaQY6RkJCQLzwCAwO5evVqoY5zt6effhqtVgtA586di/w6d2vatCmff/55sV+nQYMG2Nvbc+nSJdq0afPA/fr378/48eNZt24da9asYdSoUabwvduJEycIDAw0Syta3J8EpgDyTpUh77Txn31gfn5+qFTF7+4uyDHut2LK/cKhoNRqNb/99pvp/+8nLS2N+Pj4fNsetsBc586dmTp1Krdu3bpvd0VBubq6MmnSJF577TUMBgMRERGkp6fz008/4eLiwtChQwFwcXHhueeeIyoqirS0tAeucbRv3z46depU5HrEo0lgCgDTBdB16tTJt93W1paMjIx8p4gleYwqVarka1FeuXKFxx9/3PR49erVvPjii/cN1gdxc3N76PMxMTH3tHoftsBco0aNCAsL48svv2T06NEFruN+5syZg5+fH9HR0Zw/fx4PDw9CQ0OJiorKt9+IESNYsWIFnTp1um+QazQaNm/ezI4dO4pVj3g4WQRNWBWdTkf9+vWJiYkxDfocOHAAb29vIG+wKSYmJt+osSV89913TJo0iRMnTpil9V1cixcvZuvWrfcdDBLmIy1MYVVsbGx4//33adeuHQaDgTfffNMUlgA7duzgww8/tGCFebp27crZs2e5evUqQUFBli4HW1tbFi5caOkyyj1pYQohRAFZ/lxCCCHKCAlMIYQoIAlMIYQoIAlMIYQoIAlMIYQoIAlMIYQoIAlMIYQoIAlMIYQoIAlMIYQoIAlMIYQoIAlMIYQoIAlMIYQooP8HDqiRiwMUbpEAAAAASUVORK5CYII=", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" + "name": "stdout", + "output_type": "stream", + "text": [ + "Selected a maximum distance of 6.00 A. Score: 1.02e-02 meV/atom\n" + ] } ], "source": [ - "fig, ax = plt.subplots(figsize=(3.5, 3.5))\n", - "\n", - "base_energy = data[0].get_potential_energy() * 1000 # in meV\n", - "ax.scatter(np.subtract(pred_energy, base_energy), np.subtract(true_energy, base_energy), s=2)\n", - "\n", - "ax.set_xlim(ax.get_ylim())\n", - "ax.set_ylim(ax.get_ylim())\n", - "ax.plot(ax.get_xlim(), ax.get_xlim(), 'k--')\n", - "\n", - "ax.set_xlabel('$E-E_0$, ML (meV)')\n", - "ax.set_ylabel('$E-E_0$, True (meV)')" + "r_cutoff = r_cutoffs[np.argmin(test_score)]\n", + "print(f'Selected a maximum distance of {r_cutoff:.2f} A. Score: {min(test_score)*1000:.2e} meV/atom')" ] }, { - "cell_type": "markdown", - "id": "71e8e883-2c4b-4929-a000-297233dabe96", - "metadata": {}, + "cell_type": "code", + "execution_count": 17, + "id": "471ac3f2-4d9f-4ee9-9859-802b9a40f5bf", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 4/4 [02:30<00:00, 37.74s/it]\n" + ] + } + ], "source": [ - "Build the ASE-compatible calculator" + "n_pointss = [8, 16, 32, 64]\n", + "test_score = []\n", + "for n_points in tqdm(n_pointss):\n", + " desc = MBTR(\n", + " species=[\"H\", \"C\", \"N\", \"O\"],\n", + " geometry={\"function\": \"angle\"},\n", + " grid={\"min\": 0., \"max\": 180, \"n\": n_points, \"sigma\": 180. / n_points / 2.},\n", + " weighting={\"function\": \"smooth_cutoff\", \"r_cut\": r_cutoff, \"threshold\": 1e-3},\n", + " periodic=False,\n", + " )\n", + " test_score.append(test_model(train_data, test_data, desc, model))" ] }, { "cell_type": "code", - "execution_count": 10, - "id": "d6a7d756-37d3-44e0-b5e2-348d07c9d296", + "execution_count": 18, + "id": "c6387acd-37ec-40b7-9b3c-fe0a642a44e8", "metadata": { "tags": [] }, @@ -280,38 +473,91 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 14min 25s, sys: 43.9 s, total: 15min 9s\n", - "Wall time: 1min 23s\n" + "Selected 16 points. Score: 8.66e-03 meV/atom\n" ] } ], "source": [ - "%%time\n", - "model = MBTREnergyModel(reference=data[0], calc=mbtr)\n", - "with warnings.catch_warnings():\n", - " warnings.simplefilter(\"ignore\")\n", - " hess_model = model.train(data)" + "n_points = n_pointss[np.argmin(test_score)]\n", + "best_3d_score = min(test_score)\n", + "best_3d_desc = MBTR(\n", + " species=[\"H\", \"C\", \"N\", \"O\"],\n", + " geometry={\"function\": \"angle\"},\n", + " grid={\"min\": 0., \"max\": 180, \"n\": n_points, \"sigma\": 180. / n_points / 2.},\n", + " weighting={\"function\": \"smooth_cutoff\", \"r_cut\": r_cutoff, \"threshold\": 1e-3},\n", + " periodic=False,\n", + ")\n", + "print(f'Selected {n_points:} points. Score: {min(test_score)*1000:.2e} meV/atom')" + ] + }, + { + "cell_type": "markdown", + "id": "29162290-044f-4386-a542-a95a3c979613", + "metadata": {}, + "source": [ + "Pick either the 2D or 3D, as applicable" ] }, { "cell_type": "code", - "execution_count": 11, - "id": "372a4089-88cb-47ae-a917-190bc26287ff", + "execution_count": 19, + "id": "95041363-dc5a-4d94-9c17-04d1b6f4f040", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "desc = best_2d_desc if best_2d_score < best_3d_score else best_3d_desc" + ] + }, + { + "cell_type": "markdown", + "id": "04c60da8-4a1d-4ae3-b45d-b77e71fd598f", "metadata": {}, + "source": [ + "## Fit a Hessian with All Data\n", + "Use the provided energy model" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "788d95d1-7e13-45b0-a337-5d53b0c059a6", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "model = DScribeGlobalEnergyModel(\n", + " reference=data[0],\n", + " model=model,\n", + " descriptors=desc,\n", + " num_calculators=2\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "d6a7d756-37d3-44e0-b5e2-348d07c9d296", + "metadata": { + "tags": [] + }, "outputs": [ { - "data": { - "text/plain": [ - "{'gamma': 9.284145445194744e-05}" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 1h 38min 50s, sys: 2min 31s, total: 1h 41min 22s\n", + "Wall time: 9min 7s\n" + ] } ], "source": [ - "hess_model.parameters['model'].best_params_" + "%%time\n", + "with warnings.catch_warnings():\n", + " warnings.simplefilter(\"ignore\")\n", + " hess_models = model.train(data)" ] }, { @@ -324,7 +570,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 25, "id": "70d80f87-9983-4bd5-a6ae-b9c966b0d838", "metadata": { "tags": [] @@ -336,19 +582,19 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 26, "id": "f548b145-0aa8-47f7-802b-6b7232a74bd3", "metadata": { "tags": [] }, "outputs": [], "source": [ - "pred_forces = hess_model.get_forces(data[0])" + "pred_forces = hess_models[0].get_forces(data[0])" ] }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 27, "id": "d7cd7762-6e12-4dcd-b564-67a33b18d9e0", "metadata": { "tags": [] @@ -358,7 +604,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Maximum force: 1.51e-02 eV/Angstrom\n" + "Maximum force: 3.14e-02 eV/Angstrom\n" ] } ], @@ -368,7 +614,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 29, "id": "425b77a9-7fd7-40da-af6f-eaed197c9ab6", "metadata": { "tags": [] @@ -376,7 +622,7 @@ "outputs": [ { "data": { - "image/png": "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", + "image/png": "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", "text/plain": [ "
" ] @@ -409,7 +655,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 31, "id": "00a10907-667a-413c-851d-d47f0eff092b", "metadata": {}, "outputs": [ @@ -417,14 +663,14 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 4min 8s, sys: 3.23 s, total: 4min 12s\n", - "Wall time: 1min 24s\n" + "CPU times: user 12min 20s, sys: 26.6 s, total: 12min 46s\n", + "Wall time: 4min 15s\n" ] } ], "source": [ "%%time\n", - "approx_hessian = model.mean_hessian(hess_model)" + "approx_hessian = model.mean_hessian(hess_models)" ] }, { @@ -437,7 +683,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 32, "id": "d48893fd-df0d-4fa8-bfbe-0d04b71fbf1a", "metadata": { "tags": [] @@ -451,7 +697,7 @@ " [-2.39586674e-04, -3.46912831e-05, 2.52655314e+00]])" ] }, - "execution_count": 17, + "execution_count": 32, "metadata": {}, "output_type": "execute_result" } @@ -462,7 +708,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 33, "id": "9b311dea-5744-4211-81cb-40aa1183301e", "metadata": { "tags": [] @@ -471,12 +717,12 @@ { "data": { "text/plain": [ - "array([[ 1.50773132e+01, 2.24398727e+01, 4.01418338e-03],\n", - " [ 2.24398727e+01, 8.10175928e+01, -5.86781535e-03],\n", - " [ 4.01418338e-03, -5.86781535e-03, 2.09022244e+00]])" + "array([[1.73301126e+01, 2.66199439e+01, 1.17359295e-02],\n", + " [2.66199439e+01, 9.95655784e+01, 4.70084143e-02],\n", + " [1.17359295e-02, 4.70084143e-02, 2.30755503e+00]])" ] }, - "execution_count": 18, + "execution_count": 33, "metadata": {}, "output_type": "execute_result" } @@ -487,7 +733,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 34, "id": "addd7bef-854a-4b9f-96e9-2aa01b652495", "metadata": { "tags": [] @@ -495,7 +741,7 @@ "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXYAAADJCAYAAAA3tRlxAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAABAj0lEQVR4nO2de5xdRZXvf+fVJ92dTifpBEJCTMwNBBIIBgICwiAjOvgAncsIowwQdOZz1ZGLjnpH7sjwcD7DZ+4I4p3xqiiP8YJXnUG9g44X0AFhjAEDJjEQCa+QEBJCXt2dpNPd55y6f+xa+9SuU1W7ap/TSffJ+n4+/enuvavWrr332nuvWrVqVU4IIcAwDMO0DfnD3QCGYRimtfCLnWEYps3gFzvDMEybwS92hmGYNoNf7AzDMG0Gv9gZhmHaDH6xMwzDtBn8YmcYhmkz+MXOMAzTZvCLnWGYccGKFSvwgQ984HA3oy3gF3sAK1asQC6Xa/i58MILD8nxb7zxRrzlLW85JMdiJi4rV65EoVA4ZHrZKr7yla/gnnvuGfPjHAkfkOLhbsBE48ILL8Tdd9+d2FYulw9TaximkbvuugvXXHMNvvWtb2Hz5s1405veNKbHGx0dRalUalpOb29vC1rDAAAE481VV10l3v/+9xv3PfLII6JUKonHHnss3valL31J9PX1iddee00IIcRPf/pT8ba3vU309vaK6dOni/e+973ihRdeSMjZsmWLuOyyy8S0adNEV1eXOO2008SqVavE3XffLQAkfu6+++6xOlVmgrJv3z7R09Mjfve734nLLrtM3HTTTfG+Rx55RAAQP/7xj8XSpUtFuVwWZ5xxhli3bl1c5u677xa9vb3ihz/8oTjuuONEuVwWF1xwgdi8eXNc5oYbbhCnnHKKuPPOO8Wb3/xmkcvlRK1WE6+88oq4+OKLRXd3t+jp6REf/OAHxfbt24UQQmzYsEF0dnaK++67L5Zz//33i3K5HB9ff77OO+888clPflJce+21YurUqeKoo44S3/jGN8S+ffvEihUrxOTJk8WCBQvEv/3bv8V1KpWK+MhHPiLmz58vJk2aJI4//nhx++23J9quP0ePPPKIEEKIV199VVx66aVi6tSpYvr06eLiiy8WL7/8ckvuy6GGX+wBuF7sQgjxuc99TsybN0/s3btXrFmzRpTLZfGDH/wg3v8v//Iv4v777xcbN24Uv/nNb8RFF10kTj75ZFGtVoUQQgwODooFCxaIc889Vzz++OPi+eefF9/73vfEypUrxYEDB8RnPvMZsWTJErFt2zaxbds2ceDAgbE+ZWaCceedd4rly5cLIYR44IEHxPz580WtVhNC1F/sJ554onjooYfEunXrxPve9z4xf/58MTIyIoSIXuylUkksX75crFy5UqxevVqcccYZ4uyzz46PccMNN4ju7m7xB3/wB+Lpp58Wa9euFbVaTSxbtkycc845YvXq1WLVqlXi1FNPFeedd15c76tf/aro7e0VmzZtElu3bhXTp08XX/7yl+P9phd7T0+P+OIXvyg2btwovvjFL4p8Pi/e/e53izvuuENs3LhRfPzjHxd9fX1i//79QgghRkZGxF//9V+LJ598Urz00kvi3nvvFV1dXeJ73/ueECJ6xi699FJx4YUXxs/R8PCw2L9/vzjuuOPERz7yEbFu3Trx7LPPig9/+MNi0aJFYnh4eCxu1ZjCL/YArrrqKlEoFER3d3fi5+abbxZCCDE8PCyWLVsmLr30UrFkyRLxp3/6p055O3bsEADEb3/7WyGEEN/4xjdET0+P2LVrl7E8WUoMY+Pss8+OLdTR0VExY8YM8fDDDwsh6i/27373u3H5Xbt2ic7OzvjFRz3DVatWxWU2bNggAIgnnnhCCBHpYalUEjt27IjLPPTQQ6JQKCQs+2eeeUYAEE8++WS87b3vfa8499xzxTve8Q7xzne+M/7oCGF+sZ9zzjnx/5VKRXR3d4srrrgi3rZt2zYBQPzqV7+yXpNPfOIT4pJLLrEeR4jog7ho0aJEe4aHh0VnZ6d48MEHrbLHK+xjD+T888/H1772tcS26dOnAwA6Ojpw7733YunSpZg3bx5uv/32RLkXX3wR119/PVatWoWdO3eiVqsBADZv3oyTTjoJa9aswbJly2J5DBPCc889hyeffBI/+MEPAADFYhGXXXYZ7rrrLlxwwQVxubPOOiv+e/r06Vi0aBE2bNgQbysWi1i+fHn8/wknnICpU6diw4YNOOOMMwAA8+bNw8yZM+MyGzZswNy5czF37tx42+LFi+N6p59+OoDI/3/88ccjn89j/fr1yOVyznNaunRp/HehUEBfXx9OPvnkeNvRRx8NANixY0e87etf/zq+9a1v4ZVXXsHQ0BBGRkZSgw6eeuopvPDCC+jp6UlsP3jwIF588UVn3fEIv9gD6e7uxsKFC637V65cCQDYvXs3du/eje7u7njfRRddhLlz5+Kb3/wmZs+ejVqthpNOOgkjIyMAgM7OzrFtPNPW3HnnnahUKpgzZ068TQiBUqmEPXv2OOvqL1jTC1fdpuo1HcdUR9++du1a7N+/H/l8Htu3b8fs2bOd7dIHZXO5XGIbySYj6fvf/z4+/elP49Zbb8VZZ52Fnp4e/P3f/z2eeOIJ53FqtRpOO+003HfffQ371A/YRIHDHVvIiy++iE9/+tP45je/iTPPPBNXXnllrHC7du3Chg0b8IUvfAHveMc7cOKJJzY8bEuXLsWaNWuwe/duo/yOjg5Uq9UxPw9m4lGpVPDtb38bt956K9asWRP/rF27FvPmzUu8sFatWhX/vWfPHmzcuBEnnHBCQtbq1avj/5977jns3bs3UUZn8eLF2Lx5M7Zs2RJve/bZZ9Hf348TTzwRQGTsrFixAn/1V3+Fq6++GpdffjmGhoZacv7E448/jrPPPhuf+MQnsGzZMixcuLDB4jY9R6eeeiqef/55HHXUUVi4cGHiZyJG6/CLPZDh4WFs37498bNz505Uq1VcccUVeNe73oWrr74ad999N9avX49bb70VADBt2jT09fXhjjvuwAsvvIB///d/x1/8xV8kZH/oQx/CrFmz8IEPfAC//OUv8dJLL+H+++/Hr371KwDA/Pnz8fLLL2PNmjXYuXMnhoeHD/n5M+OTH//4x9izZw8++tGP4qSTTkr8/NEf/RHuvPPOuOzNN9+Mn//851i/fj1WrFiBGTNmJOK6S6USrrnmGjzxxBN4+umncfXVV+PMM8+M3TAmLrjgAixduhSXX345nn76aTz55JO48sorcd5558VunY997GOYO3cuvvCFL+C2226DEAKf/exnW3odFi5ciNWrV+PBBx/Exo0bcf311+PXv/51osz8+fOxbt06PPfcc9i5cydGR0dx+eWXY8aMGXj/+9+Pxx9/HC+//DJ+8Ytf4Nprr8Wrr77a0jYeEg6vi39icdVVVzWESgEQixYtEjfddJM45phjxM6dO+PyP/rRj0RHR4f4zW9+I4QQ4uGHHxYnnniiKJfLYunSpeLRRx8VAMQPf/jDuM6mTZvEJZdcIqZMmSK6urrE8uXL40GrgwcPiksuuURMnTqVwx2ZBO973/vEe97zHuO+p556SgAQt956qwAgHnjgAbFkyRLR0dEhTj/9dLFmzZq4LIU73n///WLBggWio6ND/P7v/77YtGlTXMY2iO8Kd/ynf/on0d3dLTZu3BiXX716tejo6BA/+clPhBDmwdNrr702cYx58+YlImmEEIln6ODBg2LFihWit7dXTJ06VXz84x8Xn//85xPt3bFjh3jnO98pJk+enAh33LZtm7jyyivFjBkzRLlcFgsWLBB/9md/Jvr7+43XdTyTE4IXs2aYI4FHH30U559/Pvbs2YOpU6cay9xzzz341Kc+hb179x7StjGthV0xDMMwbQa/2BmGYdqMpl7sw8PDuPHGG1s+iDeR5E6ktrLc1jLRzvmss87CDTfc4AyrXbFiRbAbZqJdhyPhPdCUj31gYAC9vb3o7+/HlClTsoqZ0HInUltZbmuZaOfMcsdO7nhrK7tiGIZh2gx+sTMMw7QZmVMK1Go1bN26FUDUXWglJG8iyJ1IbZ3ocoUQGBwcxOzZs5HPH16bhPWf5Y61TJNc32fA28c+PDyccOBv3boVixcvbqbNDJOJLVu24Nhjjz2kx2T9Z8YTac+At8V+yy234KabbmrY/q+r1uHaO9YCAFb97TszNDGavgkAOe1/ojBU/wqKQpQAqNaRHNnX0w9VFCEdQ1HulVrXdKN8tW7xjRcAAGuuvQ4AcNJ3/jlRp6ZULuT82m9qHxEycm2Sr8v1kWer49P+Zs7VdUwfBgYHcdxxxzVk4DsUuPT/z/8xmrK++kvvtdYPOV+9bF7V/3wh+l3uTpSFVqeq7ChJ/a9K/ScdzhsaU9L0f4nU/5D7nVUn9Pqt0DnX8xDy7NjaYqo/VmUBYNDzGfB+sV933XWJ3CYDAwOYO3cuuif3IN/RBQCZR4NTX+yl+pb6i70rUcb5Yi+ORnW6pxjlJ17sBycDACYXo0tD58Qv9vCyLrK82OM6Kalex4Jm9b+pF7uq//GLfXKiLLQ6iRe71P+q1H/ni92i//xiN7fFVH8sX+xxe1KegczhjhSG8/r27fHNH6nV95c094/rBGwn5WoYKWchQGMqWh2fF2XuYGQt1SZNadhva5/PjUyTYWufTb4Nn5e0a3vaA5P1Pqadg6nO4MAAjp41a1yEPpL+b9++Hb2yLaox4dIxGyH3lV7c+svZdQ9tdVz188P7AAA1+SFx3W+XnqbpcBYDx9WGkGfQVs517Fbpf+izPeD5DHBUDMMwTJvBL3aGYZg2o6UrKKnul0UfiwZd/uO2/wwAmNkV+QYL+94AAOzvnBGX7dT8KXqXhtwhKrlJyW6IT1dOd9u4ulMx8jhrL3o3AOC0++6Kd1WnHGM8jqstzfhafc6x4do52qXLNcnP4qdrxnXkqjMe05Cq7VT1i/T/sdv+EAAwqyt61PL7dwEA9k+qL39I+m+7bqr+58hz2tmbqOO6xrFbxVLIpSPkyyf9P/U798T7aj1HG+W49KkVuuB0nXrIS3OZ+MgIcVu65IW6VX2fAbbYGYZh2owxW/OULPWC9ukYkpb6JMOop89AiChNMtYhfCw9lwVgG5QlS6VWSl+X1PU1DxlwtZF1cDNtgCmk3c1GKIT0QtLkjhfU9pGlnkfSGj/Y2QcAmKQ8FyE9HD3MV5cR0lMzytf0n+pST7XWUV/rNIsepdV1lXURMohqK5PF2s86kGuTq7dRl+P7DLDFzjAM02a01GJXvybkUydGZShk2eBPTA3dmtQY1lO1WNbNfCVNbaAyuj8RqPs+qX0hVpNPW5oJd/SxqNMsLlcZr/EJh9xmyow3TOdNPnXaR/rakW+sY4srj8so+h/rY0roYog+qZA8vQyNJ6nbKRSS/PCuY9v2ZdEjEyFWcivGjZolpOee5Zlgi51hGKbNaNpiF5a/KfqFfOpkqS/9bw8CAH59y7visrQPtQoAoJqTEQRy84gyjY5mXJHlQ1bzcEdk1egTowAgr00yEj+LVmzPn/PBxHYAyI8cAABUSl2JNhR3bQIA7J3yprjsZK0nkRNRt0Tk8olrAACiWI5+63Vof2Ozg6wEqwVQHWloX63oHqcIke9TtpVRAeMNAfM9pOgX8qmTvi677iEAwKq/qaff0PW/IvWfNg9XG8+8Q+7MW/Q/Mbai6T889H9U6n/Bof/dhklLKgn9p7Epy4xZEy3RDXlNASAv/07Tfx+/ueu4Pr52275WRRKxxc4wDNNmtDSlgMqQtDL06Beyvs//u8fibSv/+3kA/L5ehaF+AEBVxvGS754OE0/llv4/ABAyl0eDJS0t2KriPyfjqKj5GncfrAIAjtm1Pi47POeURNv0dueVNhS2RvUqC85M1GnWJxjXk+eSGz0Y/UvRQ0LJ8yDPn65DTqtT0aw0VxtCLIws52iymsZjSgFV/9VzOJii/xd9/cl420N//tZEfVdUiN771I150tuctLyBuv7HMhRLGgBqk2fGf1c0/SdI/4/e/Uz9XGYvTbRXv4eq/he3bQAAjM4/3Vg265hYXJ90WfZQRaFDVmrU//i3VqdSiJ4ZV8oFvb1Z9T/tXWcryykFGIZhjlD4xc4wDNNmtMQV02PoEujdEVt4ItDotmlm8kqmUCllgEXkiwl5OolJF1QvX2zYZ5WhdxVN7bEc02sQJaVNxiZZut+hx05z1/i4YlyTW3y7oYeCNFeMfh6ubKSk/2mpNUzyyG1AZXwyOOrkFbeNng5bJzEAWIlcePpgpPNYljqm5mYaYPXQf/3aNaP/WQf0QyZhqbo0MDCAWeyKYRiGOfJoSbijjyUWWxDyi0qWMVC31E+VoWAPXv8OAMBRcpKTIdqrbvko1nZ0IGlxP/rteNPwuVcAqIeV0cBSbnQokt/dV6+eEj6pWvd0rPzg6wCA/V1HAWi0vADlyy8t9dKOjVHz5SCwOoBr/XrLwZ7hWl1+w4SvfPot1a1JvbnqwBsKUp5sd3weWmhnoj4NWNEgrXY8U1uyTMMeD5isdH074Nb/Ti0U+Gc3XgDArf+xpU7hrKSLdM0V/R+S+t+p638lWuqv2jWtLlcOeA6XorDEhvBhRf/J6i5I/R+S+l82dUu0Oi79Jxp0QurViKg3qiG8U9N/U0v0Xo6ePiEfoP/w0H/CFBoeov85y3YTbLEzDMO0GU1b7Dn4hfMQNPmogEbIUn/bp6KUp8/f8cdRWcdnKn9gT3QcmtxBU5/ffmVcplMLkYy/juV6QiPiYClaS7Bs+eSplhbJeb0YTcKaufI7UZlzL0/sTxxT/q5JK6nY/1rUNoPFotetyu9wGfVJRwIdxrIhEx0a/H1KojWhWd10nel3tVAvWxDJfTSOYLTqtXa6fI7j2Xq36T8s22jykenBI0v9vM//FADw7P98HwC3v5z0nyA9UvW/i1JfFJI+2ZrUf1X8gWK0rdOQ+gCoP79A/RneXoj0/yip/5D677qHpP+FgW2Jdrsg/e8Qdv338VWnPQet1v9YvvIcjPVkO+8Xu75K+8BAY450hmlXWP+ZiYR3VMyNN95oXKV9u2WCUsiUWb0OsXc48lVNNZjPWQL8yXdGI/96JAHQ6H+zHdd1bNvIvwuqo9bLcg11XNEGIdE3ejQG/Z+IJCDfIv12RCakHXu8RcXY9N82QU8ny7T1foP++45BmK5fTtN/wrRAuw+2duvPmQ9jpf8uQiJTbJE06vWK/zSMo5iOZzq2S/+BMZigdN1116G/vz/+2bJli29VhpnwsP4zEwlvV0y5XEa5XG7Ynh/ej8JQ9H0hHzaAOPFQ/AWSU6BpSnWHwTTQv4JkqZz9t7+Iyzx23XlRw7WRbF2a6nvcX54KAJhEljpFEkgfmOrDLP7u0agtx50dyZdliuQLVCJoaF+D/1yzOFztpO1Cse5LO18CAOyaMh8AMEVmkMoSD+6zT7dUXBa2q0cT+yNzyfY6kfdiNBddyzg1RK3uRx3JGaaHH2Js+p8b3o+81P+aQf9jpP4PG/TfFoNO+v/2W/8jLvvQp88BYE52p8qi1BsAsF9GeHnp/8bHAQCV//TWRBnyhdeUCBpInW2wNh2Wuk131d5tSSYc29UTJRzT9d8kz6ZrrkglfbtLlj7Oob9/EnI8ItNi5L2o5pPvElX/K3JfETXvZ4CjYhiGYdoMfrEzDMO0Gc2HO9aqEIWSdb++RinlU1e7iqoLxwS5XwDggtuibukjnznHWWe0s95lpNbFvSktu5s6kaBywtuj9sl82uR6ETLzYfHFJ+pljz/X2QbXQKvLnUIumL7+yCVTmbmwQZ5+jGYm+oQMItmO75JLGQNLo41T12uym9mhNYK6puq+IUPY5OEmV6tC5BuDd3MyJoHWKG0YYFdcNTXDCmFqHXK/AMDF34iyQv6/j5+RKKPf99FJ9WeqQf8dg3qjUqcL0pVZ65Ihq5T5c9PT9bILz26or7bBdAwfvdw5OXLBzND0H4ZJcWlulGYHWrPI1dtk0n9yV8VuFu2CVBT9r7t98sbQYRPj70lhGIZhmqLpJGBquKMrbEofGM0SAqdu2ycTsfeU0gfqmhlgoTAsYQhd1JMg+UwOyhKqmHO0gXCF04XiMzkoZFKaSS4RJ2CC1ntSpq7TpJj9g+M7CVjVQ/9Nk41s65e6Qt9I/7tL5rQNpntgewZ99N8Uumt7NkIG8L2se22w1yRPr2vaH6LLNvk6Ic+ZKqshbNhD/ws5zsfOMAxzxNK0j13FtfJOvLKR9C2OdNS/NnHolvxKUagirexi+mqSpf7Bb68BAHz3irckjjOiRAUNVaJ/emXYVMfWtQCAbX0nAQD6JtV9pPEpWNYHzSnhRnESpKceiDYsilZHqsp2m77mIZMu9FBImvhhmvJsq2vCZ1KXLifEV2+Ta7IM6zqjJUzKN05db9XElFYioEzMySW3q9A+8q2Pluv6Hz8b0jKN9d8wzZ7kkqV+qdT/71/5lkQ5k/5T2GDptXUAgK1TlwCoJxsD7Pqvb1f3xfp/QuRzV0OCbbj0v2EfhWWS/hcVy10bL7CNOaUd0/S/Xj+tbNo+VVbju1LzPBj0PwS22BmGYdqMlljsIb4pSodrnIpL/9OUXA/5ZKlf+X8iK+S+D0frMKoTOCaNRhZQtSOyJF6YshgAsOC1XwMARrV1SAEkEvaobTBZyIVjj4v2SUurqqwhqbfXB+skDookUYTprcniW/fx/7ssIV95Ln+nq/cQ0ms41NjaZLsGpP95Q9mQlMsEWep/8p1I/++V+t/h0P+Xe04EAMzfHum/vg5vdKCk717fru7Lz10U/UE9DYokc7TbRcP7QP6O1y4OkOvTc3WV9el92uRm6RG45Kq9wzTYYmcYhmkzWrI0nml0Ns2f5TPV11TWJp/oH0n609Wy+hJYsW/UI6bYFaFgi1FWZaX56nwSMflEMaR98U1lQiIVXNja0mxcM5UZHOdL4/lgOl9bxEyWKI39MlpmcqlR//Xl+WL9NyyN14ooLlMkjY/cLPMqsvjCbTKy9ixttOq5BXhpPIZhmCOWliyNV9EsYRMNviS5BBcAiHK0DBct50WLBMQ+PCWhF80oJeuGRv/JQCFL/cybH4nr/PqaaOZabtpcAEBhT5SZjxKTqTNfi/1bAQDbSrMAKBEDMhpg1LAsF1noA4XoPHqkXOcXWkZA0FJ5IelSE3Is201WQpo/2FUuzdp3yTftt/USfC2X8UJVuGPUbeenLj+YJytZ0/84ckiZpU0zSvXoL+qgkqV+/m2/jOs89tH5AIBK75yortRx0RHpq0n/Xy1GETnHdMtXhNT/imILUht0/Z9csifBI/TYdFdUDP02XecQS923bEgEmEmOtVeiRBTpifJ8es0hsMXOMAzTZvCLnWEYps1o2hVTFUDHgShhVs0wMcE2sEjuF5VhWk1dW6OU8qkDjQmNaPJFHNIl20DuFwBYdNNvAQDP3h65YuIJDht/Ff0+5cK47BvlyAVz7K71UZu6TpEHlOuNVusrvYh81OU8INdJ7R2Jzq1a6k20UUXfZlqJxWeCQ1pZ3/1p8m3yQiaAZO3ahrTrcCEAlAz6r3exCZqgJwyD9ENS/7u0MvvVyXx6HYv+k/sFABbdsBYA8Mztc2QjpD0n9T+n6P/uzmjN4HlvRM/MSHek/xTmW1JWOqKJc7H+D+8FANRK0xrOzYZrYFHf55oASeh6GRLCO+ZhtR7Jy1zXIxfQNrbYGYZh2oyWhjtWFElZBgP1r5dp7UTb19UW0qiy40AVADCzKzlJ15RCOB64lftodZxmQ6GylMlCq62OkF6ErW5IKKbpOh/ONU91VP3vMSTBS0vo5TMBy7RGqWsgUW2DaSD3DYv+q+G+ek9C72H4hPuGEDJY3kwIpkmuT1hlmjUfEooZIt/2nvF9BrxdMbxKO3Mkw/rPTCS8X+y33HKLcZV2QAnLcoR7xWV/dmdU9syL421x0ixpoVCdmr5GI1D3U8np15TQi9IEvKkn8kJSSCNQ96nPlEmVjn7PzQCAl/7vFwAAk5Vwr4PSFOqUJ0OWOlnu/cWeuCyFlhV3vxKdx/R50fHiE7O322UJZLG2s/gHW+ETzxpWFhKmOR7CHF3677KSG66T1P+8Q/9juSb9z1MK12RCL0oTcCzpvwxbjAREZWdOkf7zD30NAPDst/8LAKBbsdKHZLe7S3Z5aZJdwaD/lIivKJ+1igwnji+DknqWEB76D22bq5fbTKhiK/TdR0+z9ARscnyfBW8fO6/SzhzJsP4zEwlvi922SrvNCtO/LLHf/JwPRn+MDjXIysltotydlKcm2NdW6abUu3FCr54ooVHCV6hFv5Cl/odymbGHP1lPglSSZldei8wZkRNDysqJUfsO9EZLeY1oi3+oKX5FSnrRkIk+LjkhNDO5w3VcH398WhnT/sNpudv0HzBb6jZi/a8MN+zLyW01qf8xjgUmKPUuJfSK9b9DiTqL9T+y2MlS/8DXomUeH/6vZ8VFOwpu/e80tOHAlGOjMrr+KxY7pd5tGEdoOLNGWh0x1creraktWcYAfHoCHBXDMAxzBNOSpfF6pzQ3Yh6n6dWsWh/fJRH3CAwJuIiCFuFCbNtftyxoCrWX786wGLapbkKOtiBvq6JisozWt5o0qz6rlUNl+j0TIB0KTEtDqoRETOnRL67IlzSLzRVJk7M8G9sd+p/l3oVESplI0wmfiKJmLGqXfJ92u9qQVjdtjImTgDEMwxyh8IudYRimzWg6pUBh/04UD24HAFSOOj7eTt0H3Z1Ck45GS/WuYkG6YMiNclBOUaaBnOLvHo3LVk54e0K+3v2hbmZRCfeiNAHTpAuGQhppoDTOYAfgyu9GU6m/ekk0KEUDQeR2ye97o34sfU1KWUZffUltr+62adiP+urvlYJc61SepGug1WcyR5auqA2XDJ/BqVSXQqC8w0Vh3w6UmtV/6TbJy4ynB4rR4CmF3BY3Ph6XHT3+3MTxG/RfylL1n9IE9Mpng0Ia6flS9f/q70epNP7hD6Pw4claIIBJ/+M2ONyMQW4Jqf9VD/3XCdmXJeQypA2tdA9RWR48ZRiGOUJpevB099pH8fznookbS3/0k3i/7atlSnpF6Lml65XqEzTyBwejTTLZUU4bwKTj0vRpADh2T2SFjMw5JSFWD+kCgH0yZGvOeddE57nyq5F4aUUIZVUY/Rz1cwuxrFUqmhyfgZUsVnaWEMaQwTSfQcAQueMxpYCq/ycr+k/o52VKeUH7Rn30f3h/tKlrWiTfMoCvBgTM2/sMAD/9pxWYZjeh/7qFbcKla7r+6/jop749bV+afNvxTPXGMjTS9xlgi51hGKbNaGkSsJwjmVBIeJPPlzXvWFdRl0H19XBHn4k4mwdHAQBze/SEqXZryddfZqPhOmi+yxCyWDdZJxKF+PvT5Jna4BvqdSgwhTvmDauCtWKylnGfpv9e/mJLuKPrOE79txwzRI9c2Nrl89yOdRuyyHS1hcMdGYZhGCdNR8UA9S+KaqWvvejdAIBTv3MPgPoIenHXJgDA691z47J9k5JpRBsaObCtfiwZTaBPMmr4sqqpB6Slqyf0omnSiRS/FNki/ZpzeyKLaNrvfQoAsOXnt8VF1ZXgfQnxtdd9lskogxCLxeVjTJPhU8dXThr6Ofmc43ggJ2pxu2rK4jGk/6fddxcAoCoTcJH+71D0f1qK/hcM+q+nl25ATWdBPT0todeItn4qnQ/QqP+9Z/85AGDrL/4hLttTMvdUs4zDmOTYUhP79HZN/6f1ALL4vVWase599Z+jYhiGYY5Qmvaxv7at7mNUv/xkZdQ6ophcsuYp6mT6jt/GZYflaL0ttYCatrT4YpS4qELxvBb/86hisJdrSX8ktaFciOqoUQj5wdejsrKHQReH6lx139q47A9WLEuU0dMFqAsvFKvmMQGXlUAxz0KZHq6TJTbXNzrGRBb5tuO45JgsrfGYUmDrtu2Y1ivHmJT9pEdC6j9Z8xR1Mu2N9XHZ0dlLoz+k/ldzlJo32pxTlqMrbHo6qrPw7GifJSqsqlzAUtWs/53FfOI4AFBI0f+P/XO93fd+OGo36bkexaK2oVCLnmGhJTRz6YS+0E5Ij1WX5Sqjlw2Jismq/yFjVyrsY2cYhjlC4Rc7wzBMmzHm2R3j/11rJ1Le5rx5LNckVw/30vf7TEzQwwmjjckurSsb46syFGyODAXzCuvzyO7YgKW77aqfdQDIFw53bFzzVEU/HwqFVAdYCT101+dapNUxtUUnZEKavh0AXtsXPbdzJjefEdJEiHslS8hlFr30baNKlrZwuCPDMAyToOlwxxz8vr76hKUElARMDty8XpwBAJjRWYiPoUOWSuGpB6Lfxx4HABg5+oRIljJZ6oBMKhYnVZJrlNLKRzSIqhIf0zH5iCz1ZX/5EABg3Y1vjdrmmADVMMnIMskp2Ri5vuW2aOBqz4zF8S495NI1MJploFWv29ATM5TV5bqskBB54xGBlIlEVE5a6k5dlvq/vRDp/1FdhfgYDfI0/c/PXQQAGJWJyEz6P4n0X65RSisfdSijnjntt64zakAAWerLr/8ZAOCpvzojKuN61jVMk/xsemPS/+6Su+ebpUfpo28+vZxmeiW2Mr7PgveLnVdpZ45kWP+ZiYS3j/3GG280rtKuphTw8ms7vtCUTrdz5Xei7edebm+4/E1pRPMH9gCoWyz7lHjH3opMHKZN6hjU1miMDhptqyIZCtbQfuUcaMLTh34Y9QTuk2FgXv5Ow/iC7YbQOU2p1qeuk3XkM/EpzW+axV+YNfTMVtbVlsOZBKxZ/dcxXYsRqf9lTf9dsvL7d0W/pf5XZi4EUNdtAOgdjfSTEocRpE9qry+Xpv+Gc6DewYp/3QwAuOvSkxraaT0HQ4izzYKmc5pSO1BvgzZmkUU/08J/XWS951kmQ+UwBknAeJV25kiG9Z+ZSLQkKiZOAqbs9xlVb2iMViYt0ZeJvBZ94zpmSASNC70OpUyd1Z1uhbh6Aj7X0HaNWu2XznIdQnyO7RYVQzTjb80ZJqil6bIpWizLWEpa21x1KGX2zC53qgSb/JB3R96QTjitTkj0VjP3L6Qn4DvhiaNiGIZhjlBakgTMhf4lKkifuCh11stofjIqq8foqvL0soTuczaVoYUL4phyw9fe9oVWowIoOZFeliz1r6x6Nd52zVuPNdYxRd/Yjm20ZmXbqacy3BGdf1V2xHq3r4vLDs0+JdEGvU65kp7CwMf6ayaG3qcXNZ6wtVOP7CBM+q/Htsd1Pe5DQx3DM9OA9GvHKTwM1r0OyTfpvw5Z6v/4ZH15vk+eMSe9XZZjutpWC9B/Sl2ijw3o+g+PHpKrTVni5dNkhMIWO8MwTJvBL3aGYZg2oyUTlHxCi+pdxTIAoLC1niWusuDMRBnXIERaV9ErzIkGJw0pDNLkUJZGIH31JnK/AMCXfhmFgv3lOW9KyDWdc5ZByBHZnZw03J/crqxzWdQG1oa1Ov3FaCKL6hiwXW+Xy8Rn0CtkoCkkHPNQ46v/BLlgits2xNtG5p9urBMSStrwnFnKJdqiZVpU69naQFkaTfX1OuR+AYD/8R9m/dfr6n+bypqIdfngHikkesZV/dcDDfQ6/aUoHLox6UO2NrnKWl1phv1Z3DJssTMMw7QZTVvsoYNHFIZIVjqA+mCmtAB8rDfTPhsN1oee790RaqjLSISRWRJ6xYMzSuPIUvnO+mjw7EMnzTS3LRCqT4NFIhdtKezbGW1XV5qigSZpuZRrUfsHpKU+rX8TAGB0xoK4Spq17HNvsoSMTcTBUxWrhScHSkcVKz3L+r02fELqqKcacl3j+6JY6Wn11f02/dfbljhWyv8qsf7no4Fbk/7HgQYyjLQstw9IS92k/yG6GxJWHSIrS3222BmGYdqMlvjYQ7abICugtGMjAKAmpz5XJ89sKOvrS1RXXYqRx2mQ4UjA5fpa2uqZ6tDfZKnc8tgrAIDPnjMPQHIVp4bj2HfF+yjBWa0Q9YhciZj08M5u+bsiLZWObfXxD0q4RNPOadJMRa69WRCVuGy+MpLYR22LVwLyPKeG9maoc6hwhtXC0GM1lZH3I0T/0+T76L+zTRnK+PQWSP//5tFNAIC//L35AADX8sE+bSH9F1L/Kwb9j3vd2opM5FMfDdD/UanjRYP+0z5CX1nKB9sYk68ottgZhmHajJb42EMsKZcFTOlui/2vAahbLC751ggSxRdIay8W9DIe7U07XiSwlvht8mHqxyRL/csrk9ECalmfNrhG09Nk2XyY/TOXxGV6ZAK1WklaQtIa6TgQJZ/aU5oWl+3W9tF4BVmgLr95lrGTiUCIf5T0n9YLNlnsROr9VvQ/xFcNbZ+rbLxP03/bgjkqZKn/w6oo585nzp7bkrbodVzybHVbrf+UfC1kPLBZ2GJnGIZpM8Y8pYDNJ26yOqtyZXT67UrwY/O7mlZM131cLgvAZhU4ozXI107RMYbUxHp98qnr0QIA8OGTzJZayMi8LaZcxXaOXcX6nloxslToXuSkNUaWSt/AprjsgekymoDSGctUsnq6WFd7s5YZD4T0LE3Y9N+VBM92TFfvqOXXkSLJHMs96vpPPnWy1L/7TF3//3iJOWLGx1J34RvBZNR/6VvPFaOekEn/D/Zp+i/Tedcc+q+3Ie1cfc+XLXaGYZg2g1/sDMMwbcaYhTtmkdHgVqEwsJ0vxdt2TZkPAJiixQeSDFNoUcjEGer+jhYmWeXZiLtRhklONjFURnW/3C6zQn7qzGMNNZKkyQ2p4yqruwN65dicOpmjRGVl15N+Fw4kp3kD9YkjlO2w1t0HANgro/Smj+6Ky9K+/IHdAS0/dPhc6yyDw7H+79oUb9s5OXLdTS375+wPmWSWs+h/lkF40zFsbVDdL/9rdRQ88Ynlsx1HNctvpqyr3ZRpk8pMkfpfUfSfgjPI9VjNoP8Do9H+aSMG/R/qR2Fo0NL6JGyxMwzDtBktXczaZ3p5ltBIstIBoK8/st5pbcdWT1qpaJYKtYFCJoujynqLlnzZzbaJLPVbVyZDwbJcw2ZJs8Zc91z/Pz/4evw3WSw1GdJHlmJPR3T9a+W6BRevCtQ51b/hLcal/yH3xRk2aKmzq6ceCjtD6v+o1H8fKzwkJLaaQf9t8n0mNZkgS/3vLInDTJPCfAdGTXiFdGaQq2PUf2mN04SyySWp/6W++rHkvlpnL2qjfkf2tthvueUW9Pb2xj9z59rjThmm3WD9ZyYS3muemiyWuXPnJtY8TQjW/m/VJKbYV6eFgvmEy4W0LS5jSfSl7ktbo9R2DFebVP73b3cAAP7k5KOs9cZqgk+IxZ4mQ4XGMvbWImclTdku74osUjVEjCbuHNi0Hn1Lzjwsa57a9N+25mnI9crybFDiPGFJkxEyiSfLGIHtGK7jmeQ5w4glFApsCwM2HbPV7wOdkPBcY09Dhk/uRfT+8tH/4q5NGBjc5/UMeLtiyuUyyuVyekGGaUNY/5mJREsmKJm+upmsEGkBV6WHyDQiH/+tpeCsBazT6dOWuKxj0gXtK8mkQbtlwqCekn9UDOGybshSX/v6EADg1J76Yh9p05Vb1YYQy9PHKqNJZ73aPoqyMfmIK33zDUc9/GQZ+zBeaw/9j3uJ0lIn/dfHe6pKJVMSNhtZfNa6/scJswxlbeMwrrJkqa9x6L+NkEl9hGvcKESuC3pfkc1Nx6QoG9NzOzpjAUY7Gsc2TXBUDMMwTJvREos9y6iy6Ys3XItKlWH2HxqPTaPIhlQCWbBZmabzoG2U2nNKdV/UFpkwyOfLH+ILJEtld6E33jY1QH4zfv4sPQKXjzHEz3k4ooF8Uad5h1xrEyMisrM6RFL/E8fTF3UpmhenyRtumE+ER0ivi4j1vyZ7z8bF5dxyXWUJ0v838nXfch/MhPj3XTTzOnEdZ6x1mi12hmGYNoNf7AzDMG1GS1IKZOnCm7aXaRUUNHZBiYauIWVSs+xXt9lkmdrlU4fK0mARuWBcWSltLh5TGR0aKJqqbKvQxBHTQJtFflqbfMqaSKsfMpDVrFvjcBAyUK1CZSnjoa7/rslG0HL/+1w/H/eKD1S/Ow4WiFwwPlkpdXyeA9J/1f1C+m9zwYboUZZQ0RA5PueY5r7x1Su22BmGYdqMMc/HrhN/kShsC2iY4OOiFYMOIYO9IdYNlSFLJX+wHpo00hFZ87SaerxGY4b2qnXIUt83Gl3PyfloDcacXH9RDYOjMDqqb8tTH9IWEyFWiF7GRasmXbWaTJNVDPpvu24hA8lZrlFI0INroDXebtD/4QD9DxnkJB3e76H/NZgnErrCQbMM8vt4KVw99izbddhiZxiGaTPGLNwxNbRutD7JgEK2bP5CH99lFp9mFny+6gRZKQAwabg/KpuLJNQKyZDIrD0QqkeWyhsjUfLQQq4TADBNSRVKf6X5/kLCEn33hTJRwh1t10q33hquo0wJACBeI5f033WeWfzjIRZwmn9Y3Z5WJqH/B/dEZfKRfoqCf0oIn3Nspf5nJSSMMgvsY2cYhjmCadpiT/P1WS2AkjJinkt+X3wsyJDoFZMcW1mfMmmQjKohv1ph304AQG1S0mLJaiXHZaRPkSyVvcNVAMC0SYV6Ga1Ow70hK9IwMSYEW/td92Q8W+Uu0nTHqv/qNc5lt6+a0WlT2Wb2NUSxqPovz5H0vzKpcRKfDa/oEov+95br+m9bNCSWX4usfuo5mY7Z7JiYTpbxKB/YYmcYhmkzWro0no+PMfYtKlaKsFgsrqm4WduVhv7F9IkPtrWpd/u6+O+ROacAqCfY95WRVja2JOToP/kUyVJfvW1/XPbUWd0AlCgAPSWxwVJvVZSFjbTrPd7JIT32OAFZhQrGlNAWGbrl6HO9sliBNvmusQ+9DT767yIkDlzXf7LU17xeXxjk1FldSbm6/hveQ2nX2fWecdUd6wgvttgZhmHaDH6xMwzDtBljNnhqneBA3R/DAEVcxuMYaYNGWbs6NtdLyOQaKjs0+5R4W1FOs0bANOu0tqnQ5CM9pIvcLwAwVJGTOOQUcL1OiLspS9c/q3tsPCMsf9vIS1eMKXMjkebiMJWx7ffBJzjBZ2BYb8vwnLr+62k2mgk5NLW3pukyuRvJ/QIAB2WS+klyp17H5RLzcU252pkm12d7yD1li51hGKbN8LbYbau0pwXN6186V2KgLKE/Pl/FEGwDID7ox1ZzYsdpBhwJwmxyfLBdKzVtAFnqw9JyKeeikDCRM08MM8nX25g1VE6X46ozHqx7l/4TPpavaY1eWkuA9CWrta0ex0SWyU0++PTqapYVz3wGnH2eSZ+eBlnqMvsAOiB7T7n012AzPRifcN9WD7R6W+y8SjtzJMP6z0wkckIYZtEYcK3STqtlu74yDRafkgQpJNxRx2cyTzNf0rTjucrmDEmQypXkGpXNhKIZj6mVUa9zvJamiCyVfdXof5qOfUCUAABdxcbWZJl0pNf1sWhNMmjf4MAAjp41K3WF9rHApv/bt29Hr6MtVh+4Qf9b0VMLudYu69DnuUprkykJmK7/eh3TsXzaQmu86pOQmtX/tGNntazTxkZs+wcGBjDL4xnwdsXwKu3MkQzrPzORaGkSMNe2BmtBSQJWKUVfb1v6TJ+voo8PLE2GD67JInoZUxKwgWIPAKBbK9uK9qhtia+HIQkS+RQny7U1KXHS0VWZ7mDyTKu8kLb40GwU0+Emrd3W+6MkAasUIv+zLY1yFl+465kJifDSt4f0ukxJwAZK0QSlyVqdLFE3Kg2WOtXJoP9VRf9DaIUut2rcg6NiGIZh2oyWWOw+X1sdstKB+mIRNhk+x3YdL0vMbIiP0baP/IkA0C8t9Wn9mwAAlRkLEscJGU/wiTOnhF5qmgC9LPkUyVJ5oRpZU29WxIT4XLNYGyFW6XiIjjERdF8kZKUDjcsahvQ+9V5js/cl7X6H9M4T+i8tddL/Uan/Jpp9JgDEqRtyjtQlPvpPZInYyzJO0aqIJbbYGYZh2oyWzDwNiZ0lTIvP5mSMK6X0zRmWzEv7koX42LPM7gr5kqoj/+RTJEulY9t6AED/zCUAzJEoWYilOBJ60TnQMcmnTpbK09vrltbyaXKmcHlyQoYehaBC+/LavqxzAiaKHz5kLEi/NkA9xjtOae1YMjItakvdn2YFunq5rh5Bavx6i/Q/pDceY5jZrpelY1Y1/X/itXrivLP6oqPXSP8pysYUyaclFWvYbdgW2hPwfQbYYmcYhmkz+MXOMAzTZrRk8JQICYVSifcV5JqPHhM2WjXIkEar3AB6e/fMWAwA6KkMAgBqxSnWsvp2Fz4TfWx1qCy5XwBgIB91p3vk/7aJIEB9arzunglx1ZlCSMezCyZU/5yDj5r+m0ibZJRlkD9raKRv6LFpXxb9zzJAnOX9QO4XwKD/NMnJIL+m7XO1xXbfTOeubvM9H7bYGYZh2owxC3ckgiwyOeCXxQoJ6SHY6qoEDZIGHJvKUEKuWimyVCg5GGBOFGU6TihpA2Lx9vLkuA5ZKnrisKpUHdU6j8/bNcAU2FZTe8cTOYT1Sl0Wma7/pkHoZq6Bj5WfJdSQ8LHUaV+D/o/UB+yFliDMq7dv2R7iRaDtNYP+j1DisFz0R1XIlL/G7oO2MlOGdptQdS0NttgZhmHajJamFGjWFxrLkZMLanLqr+mrmOYL9PEtu/Dxc/taAEb50kKhiVo5x8roLkJ6N76oMshqJEt9SEQexE5pElSURtat92SYXogll9ae8Ybq9/SxzLyseqn/ecdiNDoh19Gr9zDGNOh/sXEiXZA87X+XZyA1pNCQOIws9aFaVKszH/1fEXXbOJbn0VPNEs7IPnaGYZgjmKYt9jQfY4g1S1/KXLx8WNFaNsg61uqE+Natky8M+0IiO8hS6TiwCwCwpzQt3terzS1qJuIhRI7u2wXqVjj51MlS33EgsuBnyenYAFDrOdp4nCx6ETIp53Bi0389ysFLlqb/FdljVefu+EaKZPGRm7a59L+ZY4069H9KR2uPrddPjQ5SLG6KcCGfOlnqO4ai0rOqr8dl0/Tf5UXwOdcQ2GJnGIZpM8bcx27bZ/R9yS9lVSZIMs0y9vUlu6ynkCiWVvnY9bKU7J8slb6BTXFZmnZts/qa/Zqn1TdFutA28qmTpf5ibXpc9s26IEMiMl1uiFU2HqNibL2ykPOrC0jqv2mugOlYPtuztimkZxxStujQ/4ojQZjvsU1tSBvvcL2/8rH+R/eILHUf/Tel9wghi/6zxc4wDNNm8IudYRimzfB2xdhWaVe7B1kmEpj2kZsiDpszhA+ldStDJl00O+HHZ7vencpXom5atxxEOjC93v0saWWbGYRx4eOSojQBukuGBorU7ueQHHXtjJfCSt43n7C6EHfeocSm/0Dr3Uex/svB0ywyQiZLZXHfhJbRy+r6f7Cvrv/6lHwfubbr7Rogtt4jJdyxptm+VMek/wekn7KrICVqE5Ra5VLzwdti51XamSMZ1n9mIpETQngZBLZV2l/fvt24WnYmi5rCveSgg6AJGo6JGj5WrW9ddZtOlq+ua3IEWcIlGe6lWre1rnroVxpZrrPeJn1/TSkYD6RqaQJc14FCIQvylKZPsqVFCsN3hfaxIFT/bTSr/63Qd52s+h8SwKBDIbUdBv2vpuh/s4PUWQIvvPRfJEMhdf0PCdu2vTt8nwFvVwyv0s4cybD+MxOJlqyg1Czxl4y+hhQeZPg6plnHWXy0Lvk+5xcSPtlQRp5j/sCeuAxZ7M1YZ17HtmBMbKTdi7gIhXQpZQpSwMBwZMG4LPbxHMroi4/uwVGmvjOp/6axJV/9D7meh1L/GyD9H+qPN+kWu0+odINYR9lMYZ85s6/dpf/7ZOawPqn/PmMxaWOEvs8+R8UwDMO0GS1JKUBk/ZI27HMk0aEJMjR5qRUTXExtda3pmSbXp9cQR5dI60S1UgqK9a7uc51HluiYEGtMlxufj2HyxfRJ9DuyVPYcJJ97vVW9HZoF5Ep1Sr5nj/YeDlzWYRYL2IWu/zpBvUUHrSjj8oXHqSqkbtc89N8kN61trgi1EKz3UdF/KkP6T5b6boP+T0nRf9O+kDTYbLEzDMO0GWPuY7d9OX38kSZKo1G6z1pKMn7Xl9rHJ0gfV5fcLL5FrzrkdxyMpi1XLT532zabXJ97YG1TE/vIUnl1oO6P7J0hzRqbNaLEEjezYMdYE2qBu/Q+vpeOBRrS9L8higNwRnLY2qK3N0s8e+aepab/riixLONnae8ktU5IL992/qT/L++pR1W95ehOWWhs9H/8PjEMwzBMJvjFzjAM02a0ZPB0rAcqVKgLSmRxRfgM4Lrk6PiUsck1Dtx29iZ+03qoQq6FmnUATq/XzECeTzgZQQOlsfsF9TVUi/l8opJxsFrtlo4z0vSfcLkpfELeYjlS/2uW66W7c/RjmeSGBBxknfgT8h5o0P8Rs/vJp10+98RFiPvWBg2Uxu4X1NdQLeSS+p+2hqrvcdliZxiGaTNaMnga8lX0+aq7JsHU8h2JMlaLxXEc23FNcny2tyKkTa1T2PcGAKA2eSYAYG8tOufeAHlZeiUhE2x8rnPDPsXyJkt911AUCnZUVxQaVhjYBgAY6TkmLmu0YsYRLitcJ1PvVtH/St6c29tm9Zvk+rQhRIdDdMKHWP+7+wAAexH19GgCvU8vMWRwU8cWwp1G6nVQ9J8sdZv+V6YcA52cSaYFttgZhmHajJZOUAohxAc+mqtbKR3xTvr6mae6+3zVfdqil/E53yw9ALUOWSo56VufXJpkLWuTb5sg4zp2q3sjsXxTSJfcSZZKnPJXpkMd71Y6IRAWAprlWlcVK71o0X+X/JBeVzPttcmwbbPJivVf9lRI/1ulElmscN/tpuP46D/53Duk/jcLW+wMwzBtRkvWPPUhxLeubzdGSqQE7Tc7QakVk42yRgntlS7Vno7IUinveglAfS1UUxvS2uZTxyVHJ8ivbLhXdE/Jp0iW+ksD0SITb+41+JLVhEvjBF+/p4/vOqjXZUvKZvg/ZBKPb5tc9bJEraj7B0aj32Spk/6b1kIN6YXb2hfS289yr036n9f0nyz1lwcin/v8XsP7rTri/Qywxc4wDNNmtDSlgI/1Ztpv+2LGkS+1+leK/I20fBgtRhDk8zK0V29XWptMx3T5o0Os+umj0eIDtXIUFVNzJAFL84FniTv2sfYy+SkN8egU/UIWDFnqb8jFOoC6H3LnSGsW7DiUtOIaq/pPUTFFWj7PsghNVt2ztSkk2sanDa5nZ9qI1P9S5GvX01ib6oVExYT0crOMy/lExRB69AtZ6ib9f2OkgEHPZ4AtdoZhmDaDX+wMwzBthrcrxrZKeyvCHdNcGiOGcMeqbDp1THxcDj7dtpAB0bQudIhc9X893LEmp1aHhKe58O2SqvJCBukaBZrCvaJttrBG6n4C9VDIaS1aOzULNv1Xwx19JsWEDDrT9ooh3FHXf/14rja4ytrquvb5yPWdHAQ0hjuS/rcq3NGnDXrZkP0Nz4xD/22o+k+hkNMnFVBstSuGV2lnjmRY/5mJRE4I4TUOZlulfbuySntWazYV5eumr7ATYjU0U8bnK9/MRB91f36/HDySg0bFXZsA1MO9QgaRXITcG5+JK1kG6RqQVtobimVCKzE9s3Un3nr8m1JXaB8LWqX/JlLLOvRfl2EiS3ifT9m0Oi5cdWgFJbLUSf9N4b5ZwhFNx7S1LeT5d8mxHbuhjEP/Nw+MYt/gAM44fm7qM+DtitFXaafvweDgYLyNX+zZj514sR+IrmmtEt3Q4uA+AEClo979Dzm2jfH8YldH/6n7uW9fdF08bZGW0ir9N8Evdu3FPiT1fzQqRfo/KvXfJKfdXuxG/R8c9X4GMoc7kkIfd9xxWUUwTCYGBwfR29t72NsAsP4zh4e0Z8DbFaNTq9Xw3HPPYfHixdiyZUtLu8bUzZ0IcidSWye63J6eHgwODmL27NnI5w9vQBfrP8sda5kmuUIIr2cgs8Wez+cxZ84cAMCUKVPGxOc5keROpLZOZLmH21InWP9Z7qGSqcv1eQY4jp1hGKbN4Bc7wzBMm9HUi71cLuOGG25IRAu0gokkdyK1leW2lol2zix37OSOt7ZmHjxlGIZhxifsimEYhmkz+MXOMAzTZvCLnWEYps3gFzvDMEybwS92hmGYNoNf7AzDMG0Gv9gZhmHaDH6xMwzDtBn/Hxvoe3BLdPC3AAAAAElFTkSuQmCC", + "image/png": "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", "text/plain": [ "
" ] @@ -528,7 +774,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 35, "id": "abbbbfd6-7d17-4b93-880a-3352903b56c4", "metadata": { "tags": [] @@ -540,17 +786,17 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 36, "id": "fdd80af3-8c18-40d8-b971-4a473bc91498", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "4.684709110728037" + "4.804039278125661" ] }, - "execution_count": 21, + "execution_count": 36, "metadata": {}, "output_type": "execute_result" } @@ -561,7 +807,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 37, "id": "6b1af348-4bc9-4ced-9a12-44b3e49abe9c", "metadata": { "tags": [] @@ -573,7 +819,7 @@ "4.746888516975277" ] }, - "execution_count": 22, + "execution_count": 37, "metadata": {}, "output_type": "execute_result" } @@ -600,7 +846,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 38, "id": "40fd3d44-df72-4b9d-b7b0-f09fabe74c0d", "metadata": { "tags": [] @@ -624,7 +870,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 39, "id": "bce41a81-6c88-4b0c-9d8d-0891d1832fd6", "metadata": { "tags": [] @@ -645,7 +891,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 40, "id": "fe39ce86-1806-4367-8c86-e3ef58f81f84", "metadata": { "tags": [] @@ -655,7 +901,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 16/16 [18:07<00:00, 67.94s/it]\n" + "100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 16/16 [1:30:46<00:00, 340.43s/it]\n" ] } ], @@ -681,7 +927,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 41, "id": "1c6706a9-a27f-448f-81d4-957939bb2ca8", "metadata": { "tags": [] @@ -689,7 +935,7 @@ "outputs": [ { "data": { - "image/png": "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hgbU1dXh3nvvxbvvvouUlBRMnToVmZmZuPPOO6HR8L/VtYj/6tTlDAYD+vXr1+rzWq3W67EkSXC5XAAAl8uFO++8E2+88Uaz1yUkJHh9RlOihQukiass5etyufDKK69g+vTpzZ4LDw9HUlISiouLkZubiy1btuCpp57CW2+9hW3btjVrA4U+FlMKKiNGjMDatWtxww03tKsHOHDgQHz11Vde23766aerflZxcXGbhV+v1+Ouu+7CXXfdhblz52LgwIEoLCzEiBEjfM6NQgOLKXU5q9Xa7KqSGo0GsbGxV33t3LlzsXLlSsycORPPP/88YmNj8b///Q9r1qzBypUroVarW3zdE088gWXLlmHRokWYM2cOCgoKsGrVKgAtX+oXAF566SVMmzYNSUlJuPfee6FSqXDgwAEUFhbitddew6pVq+B0OjFmzBhERETg448/hl6vR9++fdv3hVBI4NF86nKbNm1CQkKC1238+PE+vTYxMRE7d+6E0+nElClTkJqaigULFsBkMkGlav3XOTk5GZ999hnWrVuHtLQ0LF++XD6a39oc1ylTpuCLL75Abm4uRo8ejbFjx2LZsmVysezRowdWrlyJX/ziF0hLS8O3336Lzz//HDExMe38RigU8BpQdM16/fXX8eGHH6KsrCzQqVAI4DCfrhkffPABRo8ejZiYGOzcuRNvvfUW5s2bF+i0KESwmNI149ixY3jttddw6dIlXH/99Xj22WexePHiQKdFIYLDfCIiBfAAFBGRAlhMiYgUwGJKRKQAFlMiIgWwmBIRKYDFlIhIASymREQKYDElIlLA/wfnmwzhEO/9jwAAAABJRU5ErkJggg==", + "image/png": "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", "text/plain": [ "
" ] @@ -712,17 +958,6 @@ "fig.tight_layout()" ] }, - { - "cell_type": "markdown", - "id": "e8788f74-c208-4939-aa9b-3bbdfd8310ee", - "metadata": {}, - "source": [ - "We consistently underestimate the ZPE. Is it because we have too few oscillators?\n", - "\n", - "TODO: \n", - "- Save this data so we can compare it in a later notebook" - ] - }, { "cell_type": "code", "execution_count": null, @@ -748,7 +983,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.17" + "version": "3.9.18" } }, "nbformat": 4, diff --git a/notebooks/2_testing-fitting-strategies/2_fit-forcefield-using-soap.ipynb b/notebooks/2_testing-fitting-strategies/2_fit-forcefield-using-soap.ipynb new file mode 100644 index 0000000..9c511f2 --- /dev/null +++ b/notebooks/2_testing-fitting-strategies/2_fit-forcefield-using-soap.ipynb @@ -0,0 +1,1152 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "201346ec-3f5a-4235-b8ef-4a0051373865", + "metadata": {}, + "source": [ + "# Generate Approximate Hessians\n", + "Like the previous notebook, fit an approximate model and use that to compute the Hessian. Instead of treating the Hessian parameters as separate, we try here to fit a forcefield using the data." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "ebbbc7f5-3007-420f-861a-9f65f84436be", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "%matplotlib inline\n", + "from matplotlib import pyplot as plt\n", + "from jitterbug.model.dscribe.local import make_gpr_model, train_model, DScribeLocalCalculator, DScribeLocalEnergyModel\n", + "from sklearn.preprocessing import StandardScaler\n", + "from sklearn.model_selection import train_test_split\n", + "from dscribe.descriptors.soap import SOAP\n", + "from ase.vibrations import VibrationsData\n", + "from ase.db import connect\n", + "from pathlib import Path\n", + "from tqdm import tqdm\n", + "from io import StringIO\n", + "import pandas as pd\n", + "import numpy as np\n", + "import warnings\n", + "import torch\n", + "import json\n", + "import ase" + ] + }, + { + "cell_type": "markdown", + "id": "85a147c1-2758-465b-bc54-dc373d73a0f3", + "metadata": {}, + "source": [ + "Configuration" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "99bd4c92-9a7b-4e88-ac45-dbf30fbfc9e0", + "metadata": { + "tags": [ + "parameters" + ] + }, + "outputs": [], + "source": [ + "db_path = '../1_explore-sampling-methods/data/along-axes/caffeine_pm7_None_d=5.00e-03-N=2.db'\n", + "device = 'cuda'" + ] + }, + { + "cell_type": "markdown", + "id": "8505d400-8427-45b9-b626-3f9ca557d0c8", + "metadata": {}, + "source": [ + "Derived" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "a8be3c37-bf1f-4ba4-ba8f-afff6d6bed7d", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "run_name, sampling_options = Path(db_path).name[:-3].rsplit(\"_\", 1)\n", + "exact_path = Path('../data/exact/') / f'{run_name}-ase.json'\n", + "sampling_name = Path(db_path).parent.name\n", + "out_name = '_'.join([run_name, sampling_name, sampling_options])" + ] + }, + { + "cell_type": "markdown", + "id": "de1f6aac-b93e-45a7-98e6-ffd5205916a6", + "metadata": {}, + "source": [ + "## Read in the Data\n", + "Get all computations for the desired calculation and the exact solution" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "797b96d8-050c-4bdf-9815-586cfb5bc311", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loaded 5185 structures\n" + ] + } + ], + "source": [ + "with connect(db_path) as db:\n", + " data = [a.toatoms() for a in db.select('')]\n", + "print(f'Loaded {len(data)} structures')" + ] + }, + { + "cell_type": "markdown", + "id": "3fa7d5d6-f9ee-431f-b16b-dcc556cdeb49", + "metadata": {}, + "source": [ + "Read in the exact Hessian" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "7389208d-9323-492c-8fc5-d05a372206c6", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "with open(exact_path) as fp:\n", + " exact_vibs = VibrationsData.read(fp)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "a9965595-532c-4067-ba24-7620bd977007", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "exact_hess = exact_vibs.get_hessian_2d()\n", + "exact_zpe = exact_vibs.get_zero_point_energy()" + ] + }, + { + "cell_type": "markdown", + "id": "52d04ec1-6ecc-458a-a580-79de2c327c09", + "metadata": {}, + "source": [ + "## Start by Adjusting Hyperparameters\n", + "There are many layers of things we can adjust with SOAP, including\n", + "- The descriptors which are used. SOAP has at least 3 main adjustable parameters\n", + "- The complexity of the GPR model, which is mainly varied by the number of inducing points (more points -> more complexity)\n", + "- How the model is trained: E.g., batch size, learning rate\n", + "\n", + "Here, we adjust them for our particular problem and start with the descriptors. \n", + "\n", + "We'll start from a reasonable guess for all then tweak each" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "b3abeb98-ad43-4411-9b70-b86d28dcf0f4", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "train_data, test_data = train_test_split(data, test_size=0.1)" + ] + }, + { + "cell_type": "markdown", + "id": "bbe4599a-3928-4420-9156-a4ee66adfc5b", + "metadata": {}, + "source": [ + "Get a baseline score" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "26c0f2c0-58fe-4ad8-8f99-22e29e2ef9a2", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Baseline score: 5.61e-01 meV\n" + ] + } + ], + "source": [ + "test_y = np.array([a.get_potential_energy() for a in test_data])\n", + "baseline_y = np.abs(test_y - test_y.mean()).mean()\n", + "print(f'Baseline score: {baseline_y*1000:.2e} meV')" + ] + }, + { + "cell_type": "markdown", + "id": "a4989393-60cc-4cd1-b97d-1291a4cd6083", + "metadata": {}, + "source": [ + "Make a model testing function" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "da82d49d-62ad-4219-bbbc-e37ec9c0fba4", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "def test_soap_model(train_data: list[ase.Atoms],\n", + " test_data: list[ase.Atoms],\n", + " soap: SOAP,\n", + " num_inducing_points: int,\n", + " train_steps: int,\n", + " batch_size: int,\n", + " learning_rate: float,\n", + " fit_inducing_points: bool = False,\n", + " device: str = 'cpu',\n", + " verbose: bool = False):\n", + " \"\"\"Train a model then evaluate on a test set\n", + " \n", + " Args:\n", + " train_data: Training data\n", + " test_data: Test data\n", + " soap: SOAP descriptor computer\n", + " train_steps: Number of training steps\n", + " batch_size: Batch size to use for training\n", + " learning_rate: Learning rate to use for training\n", + " fit_inducing_points: Whether to fit inducing points during training\n", + " device: Device used for training\n", + " verbose: Whether to display progress bar\n", + " Returns:\n", + " - Training curve\n", + " - Predictions on each entry in the test set\n", + " - MAE on the test set\n", + " \"\"\"\n", + " \n", + " # Prepare the training set, scaling the input\n", + " train_x = soap.create(train_data).astype(np.float32)\n", + " offset_x = train_x.mean(axis=(0, 1))\n", + " train_x -= offset_x\n", + " scale_x = np.clip(train_x.std(axis=(0, 1)), a_min=1e-6, a_max=None)\n", + " train_x /= scale_x\n", + " \n", + " train_y_per_atom = np.array([a.get_potential_energy() / len(a) for a in train_data])\n", + " scale, offset = train_y_per_atom.std(), train_y_per_atom.mean()\n", + " train_y = np.array([(a.get_potential_energy() - len(a) * offset) / scale for a in train_data]).astype(np.float32)\n", + " \n", + " # Make the model and train it\n", + " model = make_gpr_model(train_x, num_inducing_points=num_inducing_points, use_ard_kernel=True)\n", + " model.inducing_x.requires_grad = fit_inducing_points\n", + " log = train_model(model, train_x, train_y, steps=train_steps, batch_size=batch_size, verbose=verbose, learning_rate=learning_rate, device=device)\n", + " \n", + " # Run it on the test set\n", + " calc = DScribeLocalCalculator(model=model, desc=soap, desc_scaling=(offset_x, scale_x), energy_scaling=(offset, scale), device=device)\n", + " test_preds = {'true': [], 'pred': []}\n", + " for atoms in test_data:\n", + " test_preds['true'].append(atoms.get_potential_energy())\n", + " atoms = atoms.copy()\n", + " test_preds['pred'].append(calc.get_potential_energy(atoms))\n", + " \n", + " # Get the MAE\n", + " preds = pd.DataFrame(test_preds)\n", + " mae = (preds['true'] - preds['pred']).abs().mean()\n", + " return log, preds, mae" + ] + }, + { + "cell_type": "markdown", + "id": "a72ba9ca-5776-478f-87a0-797cb3289cf6", + "metadata": {}, + "source": [ + "Determine a good cutoff" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "61ac83ed-585c-409c-8ca9-a8368dd81fa9", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 4/4 [01:33<00:00, 23.31s/it]\n" + ] + } + ], + "source": [ + "species = ['C', 'O', 'N', 'H']\n", + "n_max = 4\n", + "l_max = 4\n", + "cutoffs = np.arange(3., 6.01, 1)\n", + "inducing_points = 64\n", + "train_steps = 8\n", + "test_scores = []\n", + "for cutoff in tqdm(cutoffs):\n", + " soap = SOAP(\n", + " species=species,\n", + " n_max=n_max,\n", + " l_max=l_max,\n", + " periodic=False,\n", + " r_cut=cutoff\n", + " )\n", + " log, preds, mae = test_soap_model(train_data, test_data, soap, inducing_points, train_steps=train_steps, batch_size=2, learning_rate=0.01, device=device)\n", + " test_scores.append(mae)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "61393e22-7343-4064-bb3e-d92988fdfd31", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Selected a maximum distance of 6.00 A. Best score: 1.97e-01 meV\n" + ] + } + ], + "source": [ + "cutoff = cutoffs[np.argmin(test_scores)]\n", + "print(f'Selected a maximum distance of {cutoff:.2f} A. Best score: {min(test_scores)*1000:.2e} meV')" + ] + }, + { + "cell_type": "markdown", + "id": "9633efde-b487-4976-a3a2-5a33a10127ce", + "metadata": {}, + "source": [ + "Determine a good descriptor complexity. We are going to optimize $n$ and $l$ together for simplicty, but they do describe very different types of orbitals" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "f8f3b5aa-012c-4a90-ae4f-1e84edfa17c2", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 6/6 [02:52<00:00, 28.77s/it]\n" + ] + } + ], + "source": [ + "nl_maxes = range(1, 7)\n", + "test_scores = []\n", + "for nl_max in tqdm(nl_maxes):\n", + " soap = SOAP(\n", + " species=species,\n", + " n_max=nl_max,\n", + " l_max=nl_max,\n", + " periodic=False,\n", + " r_cut=cutoff\n", + " )\n", + " log, preds, mae = test_soap_model(train_data, test_data, soap, inducing_points, train_steps=train_steps, batch_size=2, learning_rate=0.01, device=device)\n", + " test_scores.append(mae)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "80ff45c3-3dfb-4f9d-ba10-03a9b1593a71", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Selected a complexity of 6. Best score: 1.79e-01 meV\n" + ] + } + ], + "source": [ + "nl_max = nl_maxes[np.argmin(test_scores)]\n", + "print(f'Selected a complexity of {nl_max}. Best score: {min(test_scores)*1000:.2e} meV')" + ] + }, + { + "cell_type": "markdown", + "id": "5101fa9c-08f8-4ac5-a488-d9e47a3e14f4", + "metadata": {}, + "source": [ + "Determine a good model complexity, increaseing the number of steps to allow more complex models to train effectively" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "ff6fb4e5-e77b-419d-993a-0b18aa5d2fe3", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 5/5 [12:13<00:00, 146.69s/it]\n" + ] + } + ], + "source": [ + "inducing_pointss = [32, 64, 128, 256, 512]\n", + "train_steps *= 2\n", + "test_scores = []\n", + "for inducing_points in tqdm(inducing_pointss):\n", + " soap = SOAP(\n", + " species=species,\n", + " n_max=nl_max,\n", + " l_max=nl_max,\n", + " periodic=False,\n", + " r_cut=cutoff\n", + " )\n", + " log, preds, mae = test_soap_model(train_data, test_data, soap, inducing_points, train_steps=train_steps, batch_size=2, learning_rate=0.01, device=device)\n", + " test_scores.append(mae)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "244c59e1-799f-4d91-ba4f-5a4fa69b94dc", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, axs = plt.subplots(1, 2, figsize=(4.5, 2.))\n", + "\n", + "ax = axs[0]\n", + "ax.semilogx(inducing_pointss, np.multiply(test_scores, 1000), '--o')\n", + "ax.set_xlabel('Inducing Points')\n", + "ax.set_ylabel('MAE (meV)')\n", + "\n", + "ax = axs[1]\n", + "ax.semilogy(log['loss'])\n", + "ax.set_xlabel('Epoch')\n", + "ax.set_ylabel('Loss')\n", + "\n", + "fig.tight_layout()" + ] + }, + { + "cell_type": "markdown", + "id": "401d908c-386c-4237-b150-79c90c4bcd01", + "metadata": {}, + "source": [ + "At least 512 is fine, let's just increase the number of training steps" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "8049f3e3-c51d-4b00-9d1d-0c61c6264bf0", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "inducing_points = 512\n", + "train_steps = 128" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "533109bb-d210-49f5-a97d-8598b4ea7cbc", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " \r" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 5h 52min 46s, sys: 17min 29s, total: 6h 10min 16s\n", + "Wall time: 31min 33s\n" + ] + } + ], + "source": [ + "%%time\n", + "log, preds, mae = test_soap_model(train_data, test_data, soap, inducing_points, train_steps=train_steps, batch_size=2, learning_rate=0.01, device=device, verbose=True)" + ] + }, + { + "cell_type": "markdown", + "id": "2a4ea177-b258-412e-8405-08f3e372f345", + "metadata": {}, + "source": [ + "Plot the learning curve of the final model" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "3043cc87-30ef-4ebb-98d0-5d2deedf0a25", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Final MAE: 1.61e-01 meV\n" + ] + } + ], + "source": [ + "print(f'Final MAE: {mae*1000:.2e} meV')" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "2edfad92-6cc6-48a7-8232-d8741a987363", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, axs = plt.subplots(1, 2, figsize=(4.5, 2.))\n", + "\n", + "ax = axs[0]\n", + "ax.semilogy(log['loss'])\n", + "ax.set_xlabel('Epoch')\n", + "ax.set_ylabel('Loss')\n", + "\n", + "\n", + "ax = axs[1]\n", + "ax.scatter((preds['pred'] - preds['true'].min()) * 1000,\n", + " (preds['true'] - preds['true'].min()) * 1000, s=5)\n", + "ax.set_xlabel('Pred (eV)')\n", + "ax.set_ylabel('True (eV)')\n", + "ax.set_xlim(ax.get_ylim())\n", + "ax.set_ylim(ax.get_ylim())\n", + "\n", + "ax.plot(ax.get_xlim(), ax.get_xlim(), 'k--', lw=1)\n", + "\n", + "fig.tight_layout()" + ] + }, + { + "cell_type": "markdown", + "id": "04c60da8-4a1d-4ae3-b45d-b77e71fd598f", + "metadata": {}, + "source": [ + "## Fit a Hessian with All Data\n", + "Fit a model with the parameters tuned above" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "a29c67ad-dc76-4bfb-94f0-d567a3544a9f", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "model = DScribeLocalEnergyModel(\n", + " reference=data[0],\n", + " model_fn=lambda x: make_gpr_model(x, num_inducing_points=512, use_ard_kernel=True),\n", + " descriptors=soap,\n", + " num_calculators=1,\n", + " device=device,\n", + " train_options=dict(steps=128, batch_size=2, learning_rate=0.01, verbose=True),\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "503240dd-b52c-4111-a024-ec44766940e5", + "metadata": {}, + "source": [ + "Plot the model performance" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "5749c977-51bf-46e1-a4fc-d22159daf2e5", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " " + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 1d 4h 36min 50s, sys: 1h 24min 52s, total: 1d 6h 1min 43s\n", + "Wall time: 2h 30min 15s\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\r" + ] + } + ], + "source": [ + "%%time\n", + "with warnings.catch_warnings():\n", + " warnings.simplefilter(\"ignore\")\n", + " hess_models = model.train(data)" + ] + }, + { + "cell_type": "markdown", + "id": "aa509659-701d-4001-8cc7-980c9d999976", + "metadata": {}, + "source": [ + "Compare the forces estimated at a zero displacement to the true value" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "70d80f87-9983-4bd5-a6ae-b9c966b0d838", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "actual_forces = data[0].get_forces()" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "b8a3d38e-09f9-498b-9066-a5c2a87c427b", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "pred_forces = hess_models[0].get_forces(data[0])" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "d7cd7762-6e12-4dcd-b564-67a33b18d9e0", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Maximum force: 2.79e-17 eV/Angstrom\n" + ] + } + ], + "source": [ + "print(f'Maximum force: {np.abs(pred_forces).max():.2e} eV/Angstrom')" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "425b77a9-7fd7-40da-af6f-eaed197c9ab6", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "image/png": "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mzdvtgfJKisr9dlnn2nSpElyHEfl5eUaPny4zpw5o8WLF2vChAnasmWLNm/erHA4bNffq1cvrV27VoMGDZLrunr66aeZ+oeMiMViqq+vT1pWUFCgTZs2KZFIaPDgwSopKdHatWtVXFysHj16SGq9L2dCz549FY/H9eqrr2rMmDHas2ePXn/99aTnVFZW6vz589q+fbv69++vkpIS9enTR5MnT9aUKVO0ZMkSDRw4UGfPntWOHTvUt29f1dTUaM6cORo6dKgWL16s+++/X5988omvdx1J4kBzOkaPHm1qampafWzfvn1Gktm3b5/54IMPzIABA0xRUZEpLy8348ePt8/78ssvTb9+/YzjOObv/x3Lly830WjUlJaWmilTpphFixYlHWjev3+/GTRokHEcx/Tu3du89957lxzoEweacZWmTp1qJF1yq6qqMhs2bDCDBw824XDYlJaWmjvuuMNs27bNvra1vtzageZ/TqKYOnWque+++5KWDRs2zDzxxBP2/tKlS83NN99siouLzb333mvWrFljJJlz587Z58ycOdN07tzZSDLz5883xhjT1NRk5s2bZyorK01hYaGpqKgw48aNMwcPHrSvW7FihenWrZspLi42Y8aMMS+//LKvDzQHjGGnGgDgL/xOAQBgEQoAAKtdhUIsFtOCBQsUi8VyXUrW+KGNkn/amUl++Zv5oZ353MZ2dUzBdV1FIhE1NDQkzcTxEj+0UfJPOzPJL38zP7Qzn9vYrkYKAIDsIhQAAFabf7zW3NyskydPqqyszP7qNttc103614v80Ebp2rfTGKPGxkZ16dIl6Rw7bUX/zx4/tDMXbUx1G2jzMYXjx48rGo22uUAgF44dO6Zu3bqlvR76P9qrK20DbR4ptJzl8L9+PJR0xkMvijfnuoLsizje3pPY2NioXr17Z6yvtqzn8OHDnu//8IbGxkb1TmEbSDkUYrFY0vSplou5lJWVqSzPjp5nmh9CIezxUGjR1l09/6n/59vsEeA/udI2kPInQW1trSKRiL0xdIaf0P/hFykfU/jnNyXXdRWNRvXfx04yUvCA6zw+UnBdVzdVVLR5Xvjl+n99fT0jBbQLruuqIoVtIOXdR47jyHGcjBQHtDf0f/hF2tdTKA3G1TEYz0QteSsWTP2qUu1Vu/lZext5vX1Apnh7nwEA4KoQCgAAi1AAAFiEAgDAIhQAAFbas48CplkB4+2J/AWha3PCMwDINUYKAACLUAAAWIQCAMAiFAAAFqEAALDSnn3kB6HmplyXkHUmVJTrEgDkAUYKAACLUAAAWIQCAMAiFAAAFqEAALDSnn1kggUyQW9PYooHvN0+SQrlugAAeYGRAgDAIhQAABahAACwCAUAgEUoAACstKfVxExIMePtuSuO4rkuIeuMD2ZYAbgyRgoAAItQAABYKe8ziMViisVi9r7rulkpCMhH9H/4RcojhdraWkUiEXuLRqPZrAvIK/R/+EXAGGNSeWJr35Si0aiOnjilcDictQLzgRNI5LqErPP6qUpc11VFRYUaGhra1F8v1//r6+s93//hDaluAyl/EjiOI8dxLl2ui3J0sW1VthscevG7y/V/wGv4tAMAWIQCAMAiFAAAFqEAALAIBQCARSgAAKy0J6e7iQKZhLfnuHcs9H52er+FAFLBZwEAwCIUAAAWoQAAsAgFAIBFKAAArLSnDV2XcBWOp3Si1faryfuX40x0vCHXJQDIA4wUAAAWoQAAsAgFAIBFKAAALEIBAGClPfvof0JhJQq8fY3aDqFArkvIuqJcFwAgLzBSAABYhAIAwCIUAAAWoQAAsAgFAICV9uyjcCiucMjj5wYKeX9ujsfPXgUgRYwUAABWyiOFWCymWCxm77uum5WCgHxE/4dfpDxSqK2tVSQSsbdoNJrNuoC8Qv+HXwSMMSntTm7tm1I0GtVvJ44qHPb2L5o5ptD+ua6riooKNTQ0tKm/Xq7/19fXe7//wxNS3QZS3n3kOI4cx8lIcUB7Q/+HX6Q9+8iEimQ8/k3a+2c+8n4bvd4+IFOYfQQAsAgFAIBFKAAALEIBAGARCgAAK+3ZRwF5f2ZHU3OuK8i+Ir4eABAjBQDA3xAKAACLUAAAWIQCAMAiFAAAVvrnPpL3z7BZSHQC8Ak+7gAAFqEAALAIBQCARSgAACxCAQBgpT37qNn8dfOywn+fy3UJWddccn2uSwCQBxgpAAAsQgEAYBEKAACLUAAAWIQCAMDi3EcpaCr2/sycgMf/ExMebx+QKYwUAABWyiOFWCymWCxm77uum5WCgHxE/4dfpDxSqK2tVSQSsbdoNJrNuoC8Qv+HXwSMMSntbW3tm1I0GtWJU/UKh8NZKxDXRiDXBWSZ67rqcnOFGhoa2tRfL9f/6+vp/2gfXNdVRcWVt4GUdx85jiPHcTJSHNDe0P/hF2nPPvKDAhPPdQlZZ4Le7gpBrw+FgAxh9hEAwCIUAAAWoQAAsAgFAIBFKAAALK68loJ4wNszcySpoNnbM6wCHm8fkCmMFAAAFqEAALAIBQCARSgAACxCAQBgpT2tJhjw/nllQh5vnyQZj8+w8vq5nYBMYaQAALAIBQCARSgAACxCAQBgEQoAAItQAABYac/TK7z4bxVe9PZ0v+aiklyXkHXB+J+5LiGrvN4+IFMYKQAALEIBAGARCgAAi1AAAFiEAgDASn/akGn+6+ZhXr/cqCRdDHbIdQlZFQs25boEoF1gpAAAsFIeKcRiMcViMXvfdd2sFATkI/o//CLlkUJtba0ikYi9RaPRbNYF5BX6P/wiYIxJaY95a9+UotGoTh/5VeFwWdYKzAfxoo65LiHrEh4/buK6rqJdKtTQ0KBwOHzVr79c/6+vr2/T+oBrzXVdVVRceRtIefeR4zhyHCcjxQHtDf0ffpH27KN4Uannv0k3+WD6UQePX3O0kCkVQErYVAAAFqEAALAIBQCARSgAACxCAQBgpT37KGTiCpl4JmrJWyUeb58kxY23z33kgwlkQEYwUgAAWIQCAMAiFAAAFqEAALAIBQCAlf6V1wLBv25o17w+g8zr7QMyhU9zAIBFKAAALEIBAGARCgAAq80Hmluu4tnY2JixYvJVINGU6xKyzgTTn3OQz1r6aYpXn70iP/V/eEOq20CbPwla3qBXn6q2rgK45hobGxWJRDKyHknq3bt32usCrqUrbQMB08avTs3NzTp58qTKysoUCFybSzm2XCz92LFjnr1Yuh/aKF37dhpj1NjYqC5duigYTH+vKf0/e/zQzly0MdVtoM0jhWAwqG7durX15WkJh8Oe7Swt/NBG6dq2MxMjhBb0/+zzQzuvdRtT2QY40AwAsAgFAIDVrkLBcRzNnz9fjuPkupSs8UMbJf+0M5P88jfzQzvzuY1tPtAMAPCedjVSAABkF6EAALAIBQCARSgAACxCAQBgEQoAAItQAABYhAIAwPpfYNoXxEbeL1YAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, axs = plt.subplots(1, 2, figsize=(4, 2))\n", + "\n", + "for ax, l, h in zip(axs, ['Actual', 'Estimated'], [actual_forces, pred_forces]):\n", + " ax.matshow(h, vmin=-0.05, vmax=0.05, aspect='auto', cmap='RdBu')\n", + "\n", + " ax.set_xticklabels([])\n", + " ax.set_yticklabels([])\n", + " \n", + " ax.set_title(l, fontsize=10)\n", + "\n", + "fig.tight_layout()" + ] + }, + { + "cell_type": "markdown", + "id": "46a0f2f8-f863-4de3-bd97-97ebd92676d4", + "metadata": {}, + "source": [ + "Get the mean Hessian" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "00a10907-667a-413c-851d-d47f0eff092b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 13.5 s, sys: 214 ms, total: 13.7 s\n", + "Wall time: 13.6 s\n" + ] + } + ], + "source": [ + "%%time\n", + "approx_hessian = model.mean_hessian(hess_models)" + ] + }, + { + "cell_type": "markdown", + "id": "f4de2e78-00c2-427f-b9bd-eb3ca881564b", + "metadata": {}, + "source": [ + "Compare to exact answer" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "d48893fd-df0d-4fa8-bfbe-0d04b71fbf1a", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 1.42193910e+01, 2.19101005e+01, -2.39586674e-04],\n", + " [ 2.19101005e+01, 7.86328494e+01, -3.46912831e-05],\n", + " [-2.39586674e-04, -3.46912831e-05, 2.52655314e+00]])" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "exact_hess[:3, :3]" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "9b311dea-5744-4211-81cb-40aa1183301e", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[-5.55912223e-14, -3.93125436e-15, -3.51610438e-17],\n", + " [-3.93125436e-15, -2.08549314e-16, -2.18213076e-17],\n", + " [-3.51610438e-17, -2.18213076e-17, 3.54173454e-20]])" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "approx_hessian[:3, :3]" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "addd7bef-854a-4b9f-96e9-2aa01b652495", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXYAAADJCAYAAAA3tRlxAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAAAv/UlEQVR4nO2de5AV1fXvv+fNvGF4io4QCkQeYlA0SOQaoyYmPu816o1eEU1SFa1Yah73F2/0h5qqn3UrwZg/UokPxOSqN+YGzb2apNRfotFfEBEVkEhEUQQRRF4zAwMzc85Z94/u1ad7n919uvv0mTmnZ32qpmame+/du/v02f3ttddaO0FEBEEQBCE2JIe7A4IgCEK0yMAuCIIQM2RgFwRBiBkysAuCIMQMGdgFQRBihgzsgiAIMUMGdkEQhJghA7sgCELMkIFdEAQhZsjALghCXbB06VJceumlw92NWCADewCWLl2KRCJR9nP++ecPyfHvvPNOfPaznx2SYwmNy+rVq5FKpYbsvoyKn//853jkkUdqfpyR8ABJD3cHGo3zzz8fK1eudGzL5XLD1BtBKOfhhx/GTTfdhIceegjbt2/H8ccfX9PjDQ4OIpPJVN1OR0dHBL0RAAAk+Obaa6+lSy65RLvvhRdeoEwmQy+99JK17ac//SmNHTuWPv74YyIi+vOf/0yf//znqaOjgzo7O+mCCy6g9957z9HOjh076Morr6QxY8ZQc3MznXrqqbRmzRpauXIlAXD8rFy5slanKjQohw4dora2NvrnP/9JV155Jd11113WvhdeeIEA0DPPPEPz5s2jXC5Hp59+Om3cuNEqs3LlSuro6KCnnnqKZsyYQblcjs4991zavn27VWbZsmV08skn04oVK+gzn/kMJRIJKhaL9OGHH9LFF19MLS0t1NbWRpdffjnt3r2biIg2b95MTU1N9Nhjj1ntrFq1inK5nHV89ft11lln0Xe+8x26+eabafTo0TRhwgS6//776dChQ7R06VJqbW2ladOm0Z/+9CerTj6fp+uvv56mTp1Ko0aNohNOOIHuu+8+R9/V79ELL7xAREQfffQRXXHFFTR69Gjq7Oykiy++mD744INIPpehRgb2AHgN7EREP/jBD2jKlCl08OBBWr9+PeVyOXryySet/b///e9p1apVtGXLFnrzzTfpoosuopNOOokKhQIREfX29tK0adNo8eLF9PLLL9O7775LTzzxBK1evZr6+vroe9/7Hs2ZM4d27dpFu3btor6+vlqfstBgrFixghYsWEBERE8//TRNnTqVisUiEZUG9lmzZtFzzz1HGzdupAsvvJCmTp1KAwMDRGQM7JlMhhYsWECrV6+mdevW0emnn06LFi2yjrFs2TJqaWmhL3/5y/TGG2/Qhg0bqFgs0vz58+nMM8+kdevW0Zo1a+iUU06hs846y6r3i1/8gjo6Omjbtm20c+dO6uzspJ/97GfWft3A3tbWRj/+8Y9py5Yt9OMf/5iSySR95StfoQceeIC2bNlCN9xwA40dO5YOHz5MREQDAwP0r//6r7R27Vp6//336dFHH6Xm5mZ64okniMj4jl1xxRV0/vnnW9+j/v5+Onz4MM2YMYOuv/562rhxI7399tt01VVX0cyZM6m/v78WH1VNkYE9ANdeey2lUilqaWlx/Nx9991ERNTf30/z58+nK664gubMmUPf/OY3Pdvbs2cPAaC33nqLiIjuv/9+amtro3379mnLs1ISBDcWLVpkKdTBwUEaN24cPf/880RUGth/+9vfWuX37dtHTU1N1sDHb4Zr1qyxymzevJkA0KuvvkpExn2YyWRoz549VpnnnnuOUqmUQ9n/4x//IAC0du1aa9sFF1xAixcvpnPOOYfOO+8866FDpB/YzzzzTOv/fD5PLS0tdM0111jbdu3aRQDolVdecb0mN954I1122WWuxyEyHogzZ8509Ke/v5+ampro2WefdW27XhEbe0DOPvts/PKXv3Rs6+zsBABks1k8+uijmDdvHqZMmYL77rvPUW7r1q244447sGbNGuzduxfFYhEAsH37dsydOxfr16/H/PnzrfYEIQjvvPMO1q5diyeffBIAkE6nceWVV+Lhhx/Gueeea5U744wzrL87Ozsxc+ZMbN682dqWTqexYMEC6/8TTzwRo0ePxubNm3H66acDAKZMmYLx48dbZTZv3oyuri50dXVZ22bPnm3VO+200wAY9v8TTjgByWQSmzZtQiKR8DynefPmWX+nUimMHTsWJ510krVt4sSJAIA9e/ZY2371q1/hoYcewocffogjR45gYGCgotPB66+/jvfeew9tbW2O7UePHsXWrVs969YjMrAHpKWlBdOnT3fdv3r1agDA/v37sX//frS0tFj7LrroInR1deHB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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, axs = plt.subplots(1, 2, figsize=(4, 2))\n", + "\n", + "for ax, l, h in zip(axs, ['Exact', 'Approximate'], [exact_hess, approx_hessian]):\n", + " ax.matshow(h, vmin=-100, vmax=100, cmap='RdBu')\n", + "\n", + " ax.set_xticklabels([])\n", + " ax.set_yticklabels([])\n", + " \n", + " ax.set_title(l, fontsize=10)\n", + "\n", + "fig.tight_layout()" + ] + }, + { + "cell_type": "markdown", + "id": "b516bb4e-d27d-4ad6-ad4b-b873c81670ff", + "metadata": {}, + "source": [ + "Get the zero point energy" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "abbbbfd6-7d17-4b93-880a-3352903b56c4", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "approx_vibs = VibrationsData.from_2d(data[0], approx_hessian)" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "fdd80af3-8c18-40d8-b971-4a473bc91498", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "6.83574459431342e-08" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "approx_vibs.get_zero_point_energy()" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "6b1af348-4bc9-4ced-9a12-44b3e49abe9c", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "4.746888516975277" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "exact_zpe" + ] + }, + { + "cell_type": "markdown", + "id": "ab6a6645-bf0e-4ed7-874e-6a345063e0b5", + "metadata": {}, + "source": [ + "The two differ, but I'm not sure how important the difference is." + ] + }, + { + "cell_type": "markdown", + "id": "29a44b3d-cd3e-44af-9bc2-3e0164b22a38", + "metadata": {}, + "source": [ + "Save it to disk" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "40fd3d44-df72-4b9d-b7b0-f09fabe74c0d", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "out_dir = Path('data/soap')\n", + "out_dir.mkdir(exist_ok=True, parents=True)\n", + "with open(f'data/soap/{out_name}.json', 'w') as fp:\n", + " approx_vibs.write(fp)" + ] + }, + { + "cell_type": "markdown", + "id": "6489882c-acaf-4a07-bbe9-d643f7c5c882", + "metadata": {}, + "source": [ + "## Plot as a Function of Data\n", + "See what happens as we add more data to the training" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "3842d670-67b7-42e8-a6af-04b65f6eb77a", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "model.train_options['verbose'] = False" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "bce41a81-6c88-4b0c-9d8d-0891d1832fd6", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Plotting at 16 steps: 5, 350, 695, 1041, 1386, ...\n" + ] + } + ], + "source": [ + "steps = np.linspace(5, len(data), 16, dtype=int)\n", + "print(f'Plotting at {len(steps)} steps: {\", \".join(map(str, steps[:5]))}, ...')" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "id": "fe39ce86-1806-4367-8c86-e3ef58f81f84", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + " 25%|████████████████████████████████████████████████████████████ | 4/16 [1:14:57<3:44:53, 1124.42s/it]\n" + ] + }, + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[43], line 6\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m warnings\u001b[38;5;241m.\u001b[39mcatch_warnings():\n\u001b[1;32m 5\u001b[0m warnings\u001b[38;5;241m.\u001b[39msimplefilter(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mignore\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m----> 6\u001b[0m hess_model \u001b[38;5;241m=\u001b[39m \u001b[43mmodel\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtrain\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdata\u001b[49m\u001b[43m[\u001b[49m\u001b[43m:\u001b[49m\u001b[43mcount\u001b[49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 8\u001b[0m \u001b[38;5;66;03m# Compute the approximate Hessian\u001b[39;00m\n\u001b[1;32m 9\u001b[0m approx_hessian \u001b[38;5;241m=\u001b[39m model\u001b[38;5;241m.\u001b[39mmean_hessian(hess_model)\n", + "File \u001b[0;32m~/Work/ExaLearn/faster-molecular-hessians/jitterbug/model/base.py:72\u001b[0m, in \u001b[0;36mASEEnergyModel.train\u001b[0;34m(self, data)\u001b[0m\n\u001b[1;32m 70\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m _ \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mnum_calculators):\n\u001b[1;32m 71\u001b[0m sampled_data \u001b[38;5;241m=\u001b[39m choices(data, k\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mlen\u001b[39m(data))\n\u001b[0;32m---> 72\u001b[0m output\u001b[38;5;241m.\u001b[39mappend(\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtrain_calculator\u001b[49m\u001b[43m(\u001b[49m\u001b[43msampled_data\u001b[49m\u001b[43m)\u001b[49m)\n\u001b[1;32m 73\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m output\n", + "File \u001b[0;32m~/Work/ExaLearn/faster-molecular-hessians/jitterbug/model/dscribe/local.py:265\u001b[0m, in \u001b[0;36mDScribeLocalEnergyModel.train_calculator\u001b[0;34m(self, data)\u001b[0m\n\u001b[1;32m 263\u001b[0m \u001b[38;5;66;03m# Make then train the model\u001b[39;00m\n\u001b[1;32m 264\u001b[0m model \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mmodel_fn(train_x)\n\u001b[0;32m--> 265\u001b[0m \u001b[43mtrain_model\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmodel\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtrain_x\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtrain_y\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdevice\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdevice\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtrain_options\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 267\u001b[0m \u001b[38;5;66;03m# Make the calculator\u001b[39;00m\n\u001b[1;32m 268\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m DScribeLocalCalculator(\n\u001b[1;32m 269\u001b[0m model\u001b[38;5;241m=\u001b[39mmodel,\n\u001b[1;32m 270\u001b[0m desc\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdescriptors,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 273\u001b[0m device\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdevice\n\u001b[1;32m 274\u001b[0m )\n", + "File \u001b[0;32m~/Work/ExaLearn/faster-molecular-hessians/jitterbug/model/dscribe/local.py:141\u001b[0m, in \u001b[0;36mtrain_model\u001b[0;34m(model, train_x, train_y, steps, batch_size, learning_rate, device, verbose)\u001b[0m\n\u001b[1;32m 138\u001b[0m batch_loss\u001b[38;5;241m.\u001b[39mbackward()\n\u001b[1;32m 140\u001b[0m opt\u001b[38;5;241m.\u001b[39mstep()\n\u001b[0;32m--> 141\u001b[0m epoch_loss \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[43mbatch_loss\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mitem\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 143\u001b[0m losses\u001b[38;5;241m.\u001b[39mappend(epoch_loss)\n\u001b[1;32m 145\u001b[0m \u001b[38;5;66;03m# Pull the model back off the GPU\u001b[39;00m\n", + "\u001b[0;31mKeyboardInterrupt\u001b[0m: " + ] + } + ], + "source": [ + "zpes = []\n", + "vib_data = []\n", + "for count in tqdm(steps):\n", + " with warnings.catch_warnings():\n", + " warnings.simplefilter(\"ignore\")\n", + " hess_model = model.train(data[:count])\n", + " \n", + " # Compute the approximate Hessian\n", + " approx_hessian = model.mean_hessian(hess_model)\n", + " approx_vibs = VibrationsData.from_2d(data[0], approx_hessian)\n", + " \n", + " # Save a ZPE and the JSON as a summary\n", + " \n", + " zpes.append(approx_vibs.get_zero_point_energy())\n", + " fp = StringIO()\n", + " approx_vibs.write(fp)\n", + " vib_data.append({'count': int(count), 'vib_data': fp.getvalue()})" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "id": "4b4563c7-f35c-458b-bb4f-36c466d59cd5", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "with (out_dir / f'{out_name}-incremental.json').open('w') as fp:\n", + " json.dump(vib_data, fp)" + ] + }, + { + "cell_type": "markdown", + "id": "c179c3ae-695f-44ad-b548-10002c4ff30b", + "metadata": {}, + "source": [ + "Plot it" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "id": "1c6706a9-a27f-448f-81d4-957939bb2ca8", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, ax = plt.subplots(figsize=(3.5, 2))\n", + "\n", + "ax.plot(steps[:len(zpes)], zpes)\n", + "\n", + "ax.set_xlim([0, steps.max()])\n", + "ax.plot(ax.get_xlim(), [exact_zpe]*2, 'k--')\n", + "\n", + "ax.set_xlabel('Energies')\n", + "ax.set_ylabel('ZPE (eV)')\n", + "\n", + "fig.tight_layout()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "384af4b3-5eb3-4eac-b176-160f19944853", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.18" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/proof-of-concept/README.md b/notebooks/proof-of-concept/README.md deleted file mode 100644 index 3ca3018..0000000 --- a/notebooks/proof-of-concept/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Proof of Concept - -The goal behind these notebooks are to illustrate a proof-of-concept for the larger application. diff --git a/tests/models/test_mbtr.py b/tests/models/test_mbtr.py index c500156..60757b3 100644 --- a/tests/models/test_mbtr.py +++ b/tests/models/test_mbtr.py @@ -1,15 +1,35 @@ """Test for a MBTR-based energy model""" import numpy as np - -from jitterbug.model.mbtr import MBTRCalculator, MBTREnergyModel - - -def test_model(train_set): +from pytest import fixture +from dscribe.descriptors import MBTR +from sklearn.linear_model import LinearRegression + +from jitterbug.model.dscribe.globald import DScribeGlobalEnergyModel + + +@fixture() +def model(train_set): + return DScribeGlobalEnergyModel( + reference=train_set[0], + descriptors=MBTR( + species=["H", "C", "N", "O"], + geometry={"function": "inverse_distance"}, + grid={"min": 0, "max": 1, "n": 100, "sigma": 0.1}, + weighting={"function": "exp", "scale": 0.5, "threshold": 1e-3}, + periodic=False, + normalization="l2", + ), + model=LinearRegression(), + num_calculators=8 + ) + + +def test_calculator(train_set, model): # Create then fit the model - calc = MBTRCalculator() - calc.train(train_set) + calcs = model.train(train_set) # Predict the energy (we should be close!) + calc = calcs[0] test_atoms = train_set[0].copy() test_atoms.calc = calc energy = test_atoms.get_potential_energy() @@ -18,14 +38,22 @@ def test_model(train_set): # See if force calculation works forces = test_atoms.get_forces() assert forces.shape == (3, 3) # At least make sure we get the right shape, values are iffy + assert not np.isclose(forces, 0).all() -def test_hessian(train_set): +def test_hessian(train_set, model): """See if we can compute the Hessian""" - calc = MBTRCalculator() - model = MBTREnergyModel(calc, train_set[0]) # Run the fitting - hess_model = model.train(train_set) - hess = model.mean_hessian(hess_model) - assert hess.shape == (9, 9) + calcs = model.train(train_set) + + # Test the mean hessian function + mean_hess = model.mean_hessian(calcs) + assert mean_hess.shape == (9, 9), 'Wrong shape' + assert np.isclose(mean_hess, mean_hess.T).all(), 'Not symmetric' + + # Test the sampling + sampled_hess = model.sample_hessians(calcs, 128) + assert all(np.isclose(hess, hess.T).all() for hess in sampled_hess) + mean_sampled_hess = np.mean(sampled_hess, 0) + assert np.isclose(np.diag(mean_sampled_hess), np.diag(mean_hess), atol=5).mean() > 0.5 # Make sure most agree diff --git a/tests/models/test_soap.py b/tests/models/test_soap.py new file mode 100644 index 0000000..d920137 --- /dev/null +++ b/tests/models/test_soap.py @@ -0,0 +1,112 @@ +import numpy as np +import torch +from dscribe.descriptors.soap import SOAP +from pytest import mark, fixture + +from jitterbug.model.dscribe.local import make_gpr_model, train_model, DScribeLocalCalculator, DScribeLocalEnergyModel + + +@fixture +def soap(train_set): + species = sorted(set(sum([a.get_chemical_symbols() for a in train_set], []))) + return SOAP( + species=species, + r_cut=4., + n_max=4, + l_max=4, + ) + + +@fixture +def descriptors(train_set, soap): + return soap.create(train_set) + + +@mark.parametrize('use_adr', [True, False]) +def test_make_model(use_adr, descriptors, train_set): + model = make_gpr_model(descriptors, 4, use_ard_kernel=use_adr) + + # Evaluate on a single point + model.eval() + pred_y = model(torch.from_numpy(descriptors[0, :, :])) + assert pred_y.shape == (3,) # 3 Atoms + + +@mark.parametrize('use_adr', [True, False]) +def test_train(descriptors, train_set, use_adr): + # Make the model and the training set + train_y = np.array([a.get_potential_energy() for a in train_set]) + train_y -= train_y.min() + model = make_gpr_model(descriptors, 4, use_ard_kernel=use_adr) + model.inducing_x.requires_grad = False + + # Evaluate the untrained model + model.eval() + pred_y = model(torch.from_numpy(descriptors.reshape((-1, descriptors.shape[-1])))) + assert pred_y.dtype == torch.float64 + error_y = pred_y.sum(axis=-1).detach().numpy() - train_y + mae_untrained = np.abs(error_y).mean() + + # Train + losses = train_model(model, descriptors, train_y, 64) + assert len(losses) == 64 + + # Run the evaluation + model.eval() + pred_y = model(torch.from_numpy(descriptors.reshape((-1, descriptors.shape[-1])))) + error_y = pred_y.sum(axis=-1).detach().numpy() - train_y + mae_trained = np.abs(error_y).mean() + assert mae_trained < mae_untrained + + +def test_calculator(descriptors, soap, train_set): + # Scale the input and outputs + train_y = np.array([a.get_potential_energy() for a in train_set]) + train_y -= train_y.mean() + + offset_x = descriptors.mean(axis=(0, 1)) + scale_x = np.clip(descriptors.std(axis=(0, 1)), a_min=1e-6, a_max=None) + descriptors = (descriptors - offset_x) / scale_x + + # Assemble and train for a few instances so that we get nonzero forces + model = make_gpr_model(descriptors, 32) + train_model(model, descriptors, train_y, 32) + + # Make the model + calc = DScribeLocalCalculator( + model=model, + desc=soap, + desc_scaling=(offset_x, scale_x), + ) + energies = [] + for atoms in train_set: + atoms.calc = calc + forces = atoms.get_forces() + energies.append(atoms.get_potential_energy()) + numerical_forces = calc.calculate_numerical_forces(atoms, d=1e-4) + assert np.isclose(forces[:, :2], numerical_forces[:, :2], rtol=5e-1).all() # Make them agree w/i 50% (PES is not smooth) + assert np.std(energies) > 1e-6 + + +def test_model(soap, train_set): + # Assemble the model + model = DScribeLocalEnergyModel( + reference=train_set[0], + descriptors=soap, + model_fn=lambda x: make_gpr_model(x, num_inducing_points=32), + num_calculators=4, + ) + + # Run the fitting + calcs = model.train(train_set) + + # Test the mean hessian function + mean_hess = model.mean_hessian(calcs) + assert mean_hess.shape == (9, 9), 'Wrong shape' + assert np.isclose(mean_hess, mean_hess.T).all(), 'Not symmetric' + + # Test the sampling + sampled_hess = model.sample_hessians(calcs, 128) + assert all(np.isclose(hess, hess.T).all() for hess in sampled_hess) + mean_sampled_hess = np.mean(sampled_hess, 0) + assert np.isclose(np.diag(mean_sampled_hess), np.diag(mean_hess), atol=5).mean() > 0.5 # Make sure most agree