{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Tutorial on transfer learning from universal models\n",
    "\n",
    "In this tutorial, we will improve the universal machine learning potential ANI-1ccx-gelu specifically on CH3NO2 molecule, which will be reflected in improved harmonic frequencies compared with experiment"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import mlatom as ml \n",
    "import numpy as np \n",
    "import pandas as pd \n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Overview of the dataset\n",
    "\n",
    "We take the datasets from https://doi.org/10.1021/acs.jctc.1c00249. There are 9001 training points with energies and forces at MP2/aug-cc-pVTZ level. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Number of training points:  9001\n"
     ]
    }
   ],
   "source": [
    "# prepare the dataset\n",
    "training_data = ml.data.molecular_database.load('CH3NO2_MP2_avtz.json',format='json')\n",
    "print('Number of training points: ', len(training_data))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0, 0.5, 'Number of entries')"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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X331lZFkPvzwQ7d+Y8eONXfddVeu/SWZuLg4t7b777/fTJo0ya1t/vz5pnLlysYYY7744gsTGhpqzp0759anZs2aZubMmW5t5cqVM3PmzPnV+gG4454jANfVtm1bzZgxw62tfPnybt8bNWpk/XNwcLBCQkKsS02JiYn66quvdNttt+U69t69e1W7dm1JyrWas3v3bt1zzz1ubffee2+u7/Xr19e8efP03HPPaf78+apatapatWr1q+PJyspSmTJl8ty2dOlS1a1b163tySefdPu+bds2jRs3TklJSTpx4oQuXbokSfrll19Ur149q58nq1NX901MTNSWLVuslSJJunjxos6dO6ezZ88qMTFRp0+fVoUKFXKNbe/evW5tQUFBOnv2bL5rAW51hCMA1xUcHKw777zzmn2uvoHY4XBYoeHSpUt6+OGHNWXKlFz7Va5c2e08dsYYORyOXG1X+9Of/qTp06frueee0+zZs/XMM8/k2s+uYsWKysjIyHNbVFRUrrEGBQVZ/3zmzBl17NhRHTt21IIFC1SpUiX98ssv6tSpk3Jyctz2u3o813J130uXLmn8+PHq0aNHrr5lypTRpUuXVLlyZa1ZsybX9ttvv93t+4kTJ1SpUqV81wLc6ghHAApdkyZN9P7776t69eoKCMj//+z89re/zfVE2datW3P1e+qppzRy5Ei9/vrr2rFjh3r37n3N4959991asGBBvuuw27Vrl44dO6bJkycrKirqV2vKS+nSpfP91FqTJk20e/fuXw2lTZo0UXp6ugICAqzXEeRl7969OnfunO6+++58nRcAN2QDyIfs7Gylp6e7fexPml3PwIEDdeLECT3xxBPavHmzfvrpJ61atUp9+vS5Zljo37+/du3apVGjRum///2v/vOf/7g94XVFuXLl1KNHD/3P//yPOnbsqCpVqlyznk6dOmnHjh2/unp0LVWrVlXp0qX1xhtv6KefftLHH3+sF198MV/7Vq9eXampqUpKStKxY8eUnZ39q32ff/55zZs3T+PGjdOOHTuUkpKipUuX6m9/+5skqX379oqOjlb37t21cuVK7du3T+vXr9ff/vY3t7D2zTff6I477lDNmjU9HitwqyIcAbiuhIQEVa5c2e3jyXtzIiMj9e233+rixYvq1KmTGjRooCFDhsjpdMrP79f/Z6hGjRp677339MEHH6hRo0aaMWOG9bTa1e9Z6tu3r3JyctSnT5/r1tOwYUM1a9ZM//nPf/I9hisqVaqkOXPm6N1331W9evU0efJkvfzyy/na99FHH1Xnzp3Vtm1bVapUSYsXL/7Vvp06ddKnn36q1atX65577lGLFi00bdo0VatWTdLlcLhixQq1atVKffr0Ue3atfX4449r3759Cg8Pt46zePFixcbGejxO4FbmMHldwAeAYmrixIl66623tH//frf2hQsXasiQITp06FC+Xh65YsUKjRgxQsnJydcMaCVZcnKy2rVrp//+979yOp2+LgcoMbjnCECx9uabb+qee+5RhQoV9O233+qll17SoEGDrO1nz55Vamqq4uPj1b9//3y/Vfuhhx7Sjz/+qIMHD1r3Dt1sDh06pHnz5hGMAA+xcgSgWBs6dKiWLl2qEydOqGrVqoqJidHo0aOtG7vHjRuniRMnqlWrVvroo4/yfF0AAHiCcAQAAGBzc15oBwAAKCDCEQAAgA3hCAAAwIZwBAAAYEM4AgAAsCEcAQAA2BCOAAAAbAhHAAAANv8L7wLbFZ9Cjb8AAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# plot the energy distribution\n",
    "energies = training_data.get_properties('energy')\n",
    "plt.hist(energies)\n",
    "plt.xlabel('Energy (Hartree)')\n",
    "plt.ylabel('Number of entries')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Load universal model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "ani1ccx_gelu = ml.models.methods(method='ANI-1ccx-gelu')\n",
    "# ani = ml.models.methods(method='ANI-1ccx')\n",
    "# ani = ml.models.methods(method='ANI-2x')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Fine tune\n",
    "\n",
    "There are several parameters we need to care about when transfer learning (though we have default settings in MLatom, you might want to customize the procedure yourself)\n",
    "\n",
    "### Arguments to pass to `train()`\n",
    "\n",
    "The arguments available can be found in manual for API about torchani interface. Here several key arguments are listed:\n",
    "\n",
    "- `reset_energy_shifter [list, bool]`: Control how the self atomic energies will be extracted. By default we will use those extracted from the training data. If set to False, we will use those from pretrained models. If list, values inside will be used as the self atomic energies for scaling. \n",
    "- `file_to_save_model [str]`: The file name to save the retrained models. Defaul \"{universal model name}_retrained.pt.cv{model index}\"\n",
    "- `verbose [bool or int]`: Control the information printed out when training. 1 will print out training procedure and 2 will print out metrics from training and validation. \n",
    "- `hyperparameters [dict]`: Control the training procedure, will explain in detail later.\n",
    "\n",
    "\n",
    "### Parameters in `hyperparameters`\n",
    "\n",
    "- `batch_size`: default 8\n",
    "- `max_epochs`: default 100 for transfer learning\n",
    "- `fixed_layers`: default 1 and 3 layer are fixed. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Start retraining on model 0...\n",
      "\n",
      "Start retraining on model 1...\n",
      "\n",
      "Start retraining on model 2...\n",
      "\n",
      "Start retraining on model 3...\n",
      "\n",
      "Start retraining on model 4...\n",
      "\n",
      "Start retraining on model 5...\n",
      "\n",
      "Start retraining on model 6...\n",
      "\n",
      "Start retraining on model 7...\n"
     ]
    }
   ],
   "source": [
    "ani1ccx_gelu_tl = ani1ccx_gelu.train(\n",
    "    molecular_database=training_data,\n",
    "    property_to_learn='energy',\n",
    "    xyz_derivative_property_to_learn = 'energy_gradients',\n",
    "    # verbose=2,\n",
    "    hyperparameters={\n",
    "        'max_epochs':1000,\n",
    "        'batch_size':512,\n",
    "        # 'fixed_layers':[[0,4],[0,4],[0,4],[0,4]]\n",
    "        }\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "After transfer learning, the models will be saved in the current directory either named in the combination of the universal model name plus 'retrained' or the user defined name for the model. You can still load them with torchani interface to do the simulations:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# for loading one model\n",
    "ani_tl_cv0 = ml.models.ani(model_file='ani1ccxgelu_retrained.pt.cv0')\n",
    "\n",
    "# for loading multiple models as an ensemble\n",
    "children = [\n",
    "    ml.models.model_tree_node(\n",
    "        name=f'nn{ii}', \n",
    "        model=ml.models.ani(model_file=f'ani1ccxgelu_retrained.pt.cv{ii}'), \n",
    "        operator='predict') \n",
    "    for ii in range(8)]\n",
    "ani_tl_ensemble = ml.models.model_tree_node(\n",
    "        name='nn', \n",
    "        children=children, \n",
    "        operator='average')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Compare harmonic frequencies"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "def calculate_harmonic_frequency(\n",
    "    calculator=None,\n",
    "    initmol=None,\n",
    "    opt_program='geometric', # do not use gaussian which currently cannot recognize the retrained method\n",
    "    freq_program='pyscf',\n",
    "     \n",
    "):\n",
    "    geomopt = ml.simulations.optimize_geometry( \n",
    "        model=calculator, \n",
    "        initial_molecule=initmol, \n",
    "        program=opt_program)\n",
    "    optmol = geomopt.optimized_molecule\n",
    "    ml.simulations.freq(\n",
    "        model=calculator, \n",
    "        molecule=optmol,\n",
    "        program=freq_program,)\n",
    "    return optmol"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "# load initial molecule\n",
    "initmol = ml.data.molecule.from_xyz_file('CH3NO2_init.xyz')\n",
    "\n",
    "# load universal model\n",
    "ani1ccx_gelu = ml.models.methods(method='ANI-1ccx-gelu')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "# calculate harmonic frequency\n",
    "freqmol_anigelu = calculate_harmonic_frequency(ani1ccx_gelu, initmol)\n",
    "freqmol_anigelu_tl = calculate_harmonic_frequency(ani1ccx_gelu_tl, initmol)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "MAE (cm-1) of harmonic frequencies compared to MP2:\n",
      "ANI-1ccx-gelu: 23.052539825439453\n",
      "ANI-1ccx-gelu-tl: 2.7490692138671875\n"
     ]
    }
   ],
   "source": [
    "# load performance table and check MAE\n",
    "reference_table = pd.read_csv('CH3NO2_harmonic.csv')\n",
    "reference_table['ANI-1ccx-gelu'] = freqmol_anigelu.frequencies\n",
    "reference_table['ANI-1ccx-gelu-TL'] = freqmol_anigelu_tl.frequencies\n",
    "\n",
    "print('MAE (cm-1) of harmonic frequencies compared to MP2:')\n",
    "mae = abs(reference_table['ANI-1ccx-gelu'].astype(np.float32)-reference_table['MP2/avtz'].astype(np.float32)).mean()\n",
    "print(f'ANI-1ccx-gelu: {mae}')\n",
    "mae = abs(reference_table['ANI-1ccx-gelu-TL'].astype(np.float32)-reference_table['MP2/avtz'].astype(np.float32)).mean()\n",
    "print(f'ANI-1ccx-gelu-tl: {mae}')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Model</th>\n",
       "      <th>MP2/avtz</th>\n",
       "      <th>exp</th>\n",
       "      <th>ANI-1ccx-gelu</th>\n",
       "      <th>ANI-1ccx-gelu-TL</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>28.91</td>\n",
       "      <td>-</td>\n",
       "      <td>39.162458</td>\n",
       "      <td>27.883071</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2</td>\n",
       "      <td>478.65</td>\n",
       "      <td>479</td>\n",
       "      <td>513.907740</td>\n",
       "      <td>481.061675</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>3</td>\n",
       "      <td>610.43</td>\n",
       "      <td>599</td>\n",
       "      <td>621.854552</td>\n",
       "      <td>612.820447</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>4</td>\n",
       "      <td>669.67</td>\n",
       "      <td>647</td>\n",
       "      <td>672.364872</td>\n",
       "      <td>674.836687</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5</td>\n",
       "      <td>940.48</td>\n",
       "      <td>921</td>\n",
       "      <td>965.614276</td>\n",
       "      <td>941.793370</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>6</td>\n",
       "      <td>1127.28</td>\n",
       "      <td>1097</td>\n",
       "      <td>1118.814348</td>\n",
       "      <td>1125.883438</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>7</td>\n",
       "      <td>1148.99</td>\n",
       "      <td>1153</td>\n",
       "      <td>1119.440409</td>\n",
       "      <td>1148.615487</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>8</td>\n",
       "      <td>1412.12</td>\n",
       "      <td>1384</td>\n",
       "      <td>1417.415336</td>\n",
       "      <td>1410.780877</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>9</td>\n",
       "      <td>1430.54</td>\n",
       "      <td>1413</td>\n",
       "      <td>1462.593407</td>\n",
       "      <td>1431.172850</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>10</td>\n",
       "      <td>1491.90</td>\n",
       "      <td>1449</td>\n",
       "      <td>1476.140398</td>\n",
       "      <td>1490.940371</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>11</td>\n",
       "      <td>1502.67</td>\n",
       "      <td>1488</td>\n",
       "      <td>1477.055380</td>\n",
       "      <td>1496.736090</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>12</td>\n",
       "      <td>1745.72</td>\n",
       "      <td>1582</td>\n",
       "      <td>1649.087029</td>\n",
       "      <td>1757.541987</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>13</td>\n",
       "      <td>3115.24</td>\n",
       "      <td>2965</td>\n",
       "      <td>3096.572449</td>\n",
       "      <td>3114.823545</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>14</td>\n",
       "      <td>3221.29</td>\n",
       "      <td>3048</td>\n",
       "      <td>3215.946024</td>\n",
       "      <td>3215.934658</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>15</td>\n",
       "      <td>3247.61</td>\n",
       "      <td>3048</td>\n",
       "      <td>3223.968484</td>\n",
       "      <td>3246.913792</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    Model  MP2/avtz   exp  ANI-1ccx-gelu  ANI-1ccx-gelu-TL\n",
       "0       1     28.91     -      39.162458         27.883071\n",
       "1       2    478.65   479     513.907740        481.061675\n",
       "2       3    610.43   599     621.854552        612.820447\n",
       "3       4    669.67   647     672.364872        674.836687\n",
       "4       5    940.48   921     965.614276        941.793370\n",
       "5       6   1127.28  1097    1118.814348       1125.883438\n",
       "6       7   1148.99  1153    1119.440409       1148.615487\n",
       "7       8   1412.12  1384    1417.415336       1410.780877\n",
       "8       9   1430.54  1413    1462.593407       1431.172850\n",
       "9      10   1491.90  1449    1476.140398       1490.940371\n",
       "10     11   1502.67  1488    1477.055380       1496.736090\n",
       "11     12   1745.72  1582    1649.087029       1757.541987\n",
       "12     13   3115.24  2965    3096.572449       3114.823545\n",
       "13     14   3221.29  3048    3215.946024       3215.934658\n",
       "14     15   3247.61  3048    3223.968484       3246.913792"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "reference_table"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "mlatom",
   "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.17"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
