{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## General Information" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This notebook is used to train a simple neural network model to predict the chemistry in the barite benchmark (50x50 grid). The training data is stored in the repository using **git large file storage** and can be downloaded after the installation of git lfs using the `git lfs pull` command.\n", "\n", "It is then recommended to create a Python environment using miniconda. The necessary dependencies are contained in `environment.yml` and can be installed using `conda env create -f environment.yml`.\n", "\n", "The data set is divided into a design and result part and consists of the iterations of a reference simulation. The design part of the data set contains the chemical concentrations at time $t$ and the result part at time $t+1$, which are to be learned by the model." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Setup Libraries" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Running Keras in version 3.8.0\n" ] } ], "source": [ "import keras\n", "import h5py\n", "import numpy as np\n", "import pandas as pd\n", "import time\n", "import sklearn.model_selection as sk\n", "import matplotlib.pyplot as plt\n", "from sklearn.cluster import KMeans\n", "from sklearn.pipeline import Pipeline, make_pipeline\n", "from sklearn.preprocessing import StandardScaler, MinMaxScaler\n", "from imblearn.over_sampling import SMOTE\n", "from imblearn.under_sampling import RandomUnderSampler\n", "from imblearn.over_sampling import RandomOverSampler\n", "from collections import Counter\n", "import os\n", "from preprocessing import *\n", "from sklearn import set_config\n", "from importlib import reload\n", "set_config(transform_output = \"pandas\")" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "%load_ext autoreload\n", "%autoreload 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Define parameters" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "dtype = \"float32\"\n", "activation = \"relu\"\n", "\n", "lr = 0.001\n", "batch_size = 512\n", "epochs = 50 # default 400 epochs\n", "\n", "lr_schedule = keras.optimizers.schedules.ExponentialDecay(\n", " initial_learning_rate=lr,\n", " decay_steps=2000,\n", " decay_rate=0.9,\n", " staircase=True\n", ")\n", "\n", "optimizer_simple = keras.optimizers.Adam(learning_rate=lr_schedule)\n", "optimizer_large = keras.optimizers.Adam(learning_rate=lr_schedule)\n", "\n", "loss = keras.losses.MeanSquaredError()\n", "\n", "sample_fraction = 0.8" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Setup the model" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
Model: \"sequential\"\n",
"\n"
],
"text/plain": [
"\u001b[1mModel: \"sequential\"\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
"┃ Layer (type) ┃ Output Shape ┃ Param # ┃\n",
"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
"│ dense (Dense) │ (None, 128) │ 1,664 │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_1 (Dense) │ (None, 128) │ 16,512 │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_2 (Dense) │ (None, 12) │ 1,548 │\n",
"└─────────────────────────────────┴────────────────────────┴───────────────┘\n",
"\n"
],
"text/plain": [
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
"┃\u001b[1m \u001b[0m\u001b[1mLayer (type) \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mOutput Shape \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1m Param #\u001b[0m\u001b[1m \u001b[0m┃\n",
"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
"│ dense (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m128\u001b[0m) │ \u001b[38;5;34m1,664\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_1 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m128\u001b[0m) │ \u001b[38;5;34m16,512\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_2 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m12\u001b[0m) │ \u001b[38;5;34m1,548\u001b[0m │\n",
"└─────────────────────────────────┴────────────────────────┴───────────────┘\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"Total params: 19,724 (77.05 KB)\n", "\n" ], "text/plain": [ "\u001b[1m Total params: \u001b[0m\u001b[38;5;34m19,724\u001b[0m (77.05 KB)\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
Trainable params: 19,724 (77.05 KB)\n", "\n" ], "text/plain": [ "\u001b[1m Trainable params: \u001b[0m\u001b[38;5;34m19,724\u001b[0m (77.05 KB)\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
Non-trainable params: 0 (0.00 B)\n", "\n" ], "text/plain": [ "\u001b[1m Non-trainable params: \u001b[0m\u001b[38;5;34m0\u001b[0m (0.00 B)\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# small model\n", "model_simple = keras.Sequential(\n", " [\n", " keras.Input(shape = (12,), dtype = \"float32\"),\n", " keras.layers.Dense(units = 128, activation = \"relu\", dtype = \"float32\"),\n", " keras.layers.Dense(units = 128, activation = \"relu\", dtype = \"float32\"),\n", " keras.layers.Dense(units = 12, dtype = \"float32\")\n", " ]\n", ")\n", "\n", "model_simple.compile(optimizer=optimizer_simple, loss = loss)\n", "model_simple.summary()" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
Model: \"sequential_1\"\n",
"\n"
],
"text/plain": [
"\u001b[1mModel: \"sequential_1\"\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
"┃ Layer (type) ┃ Output Shape ┃ Param # ┃\n",
"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
"│ dense_3 (Dense) │ (None, 512) │ 6,656 │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_4 (Dense) │ (None, 1024) │ 525,312 │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_5 (Dense) │ (None, 512) │ 524,800 │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_6 (Dense) │ (None, 12) │ 6,156 │\n",
"└─────────────────────────────────┴────────────────────────┴───────────────┘\n",
"\n"
],
"text/plain": [
"┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
"┃\u001b[1m \u001b[0m\u001b[1mLayer (type) \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mOutput Shape \u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1m Param #\u001b[0m\u001b[1m \u001b[0m┃\n",
"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
"│ dense_3 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m512\u001b[0m) │ \u001b[38;5;34m6,656\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_4 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m1024\u001b[0m) │ \u001b[38;5;34m525,312\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_5 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m512\u001b[0m) │ \u001b[38;5;34m524,800\u001b[0m │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_6 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m12\u001b[0m) │ \u001b[38;5;34m6,156\u001b[0m │\n",
"└─────────────────────────────────┴────────────────────────┴───────────────┘\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"Total params: 1,062,924 (4.05 MB)\n", "\n" ], "text/plain": [ "\u001b[1m Total params: \u001b[0m\u001b[38;5;34m1,062,924\u001b[0m (4.05 MB)\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
Trainable params: 1,062,924 (4.05 MB)\n", "\n" ], "text/plain": [ "\u001b[1m Trainable params: \u001b[0m\u001b[38;5;34m1,062,924\u001b[0m (4.05 MB)\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
Non-trainable params: 0 (0.00 B)\n", "\n" ], "text/plain": [ "\u001b[1m Non-trainable params: \u001b[0m\u001b[38;5;34m0\u001b[0m (0.00 B)\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# large model\n", "model_large = keras.Sequential(\n", " [keras.layers.Input(shape=(12,), dtype=dtype),\n", " keras.layers.Dense(512, activation='relu', dtype=dtype),\n", " keras.layers.Dense(1024, activation='relu', dtype=dtype),\n", " keras.layers.Dense(512, activation='relu', dtype=dtype),\n", " keras.layers.Dense(12, dtype=dtype)\n", " ])\n", "\n", "model_large.compile(optimizer=optimizer_large, loss = loss)\n", "model_large.summary()\n" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "# model from paper" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Define transformer functions" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "def Safelog(val):\n", " # get range of vector\n", " if val > 0:\n", " return np.log10(val)\n", " elif val < 0:\n", " return -np.log10(-val)\n", " else:\n", " return 0\n", "\n", "def Safeexp(val):\n", " if val > 0:\n", " return -10 ** -val\n", " elif val < 0:\n", " return 10 ** val\n", " else:\n", " return 0" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "# ? Why does the charge is using another logarithm than the other species\n", "\n", "func_dict_in = {\n", " \"H\" : np.log1p,\n", " \"O\" : np.log1p,\n", " \"Charge\" : Safelog,\n", " \"H_0_\" : np.log1p,\n", " \"O_0_\" : np.log1p,\n", " \"Ba\" : np.log1p,\n", " \"Cl\" : np.log1p,\n", " \"S_2_\" : np.log1p,\n", " \"S_6_\" : np.log1p,\n", " \"Sr\" : np.log1p,\n", " \"Barite\" : np.log1p,\n", " \"Celestite\" : np.log1p,\n", "}\n", "\n", "func_dict_out = {\n", " \"H\" : np.expm1,\n", " \"O\" : np.expm1,\n", " \"Charge\" : Safeexp,\n", " \"H_0_\" : np.expm1,\n", " \"O_0_\" : np.expm1,\n", " \"Ba\" : np.expm1,\n", " \"Cl\" : np.expm1,\n", " \"S_2_\" : np.expm1,\n", " \"S_6_\" : np.expm1,\n", " \"Sr\" : np.expm1,\n", " \"Barite\" : np.expm1,\n", " \"Celestite\" : np.expm1,\n", "}\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Read data from `.h5` file and convert it to a `pandas.DataFrame`" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "# os.chdir('/mnt/beegfs/home/signer/projects/model-training')\n", "data_file = h5py.File(\"Barite_50_Data_training.h5\")\n", "\n", "design = data_file[\"design\"]\n", "results = data_file[\"result\"]\n", "\n", "df_design = pd.DataFrame(np.array(design[\"data\"]).transpose(), columns = np.array(design[\"names\"].asstr()))\n", "df_results = pd.DataFrame(np.array(results[\"data\"]).transpose(), columns = np.array(results[\"names\"].asstr()))\n", "\n", "data_file.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Preprocess Data\n", "\n", "The data are preprocessed in the following way:\n", "\n", "1. Label data points in the `design` dataset with `reactive` and `non-reactive` labels using kmeans clustering\n", "2. Transform `design` and `results` data set into log-scaled data.\n", "3. Split data into training and test sets.\n", "4. Learn scaler on training data for `design` and `results` together (option `global`) or individual (option `individual`).\n", "5. Transform training and test data.\n", "6. Split training data into training and validation dataset." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/Users/hannessigner/miniforge3/envs/ai/lib/python3.12/site-packages/sklearn/base.py:1474: ConvergenceWarning: Number of distinct clusters (1) found smaller than n_clusters (2). Possibly due to duplicate points in X.\n", " return fit_method(estimator, *args, **kwargs)\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Amount class 0 before: 0.9879169719169719\n", "Amount class 1 before: 0.012083028083028084\n", "Using Oversampling\n", "Amount class 0 after: 0.5\n", "Amount class 1 after: 0.5\n" ] } ], "source": [ "X_train, X_val, X_test, y_train, y_val, y_test, scaler_X, scaler_y = preprocessing_training(df_design, df_results, func_dict_in, func_dict_out, \"over\", 'global', 0.1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Custom Loss function" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "def custom_loss_H20(df_design_log, df_result_log, data_min_log, data_max_log, func_dict_out, postprocess):\n", " df_result = postprocess(df_result_log, func_dict_out, data_min_log, data_max_log) \n", " return keras.losses.Huber + np.sum(((df_result['H'] / df_result['O']) - 2)**2)\n", "\n", "def loss_wrapper(data_min_log, data_max_log, func_dict_out, postprocess):\n", " def loss(df_design_log, df_result_log):\n", " return custom_loss_H20(df_design_log, df_result_log, data_min_log, data_max_log, func_dict_out, postprocess)\n", " return loss" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Train the model" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Epoch 1/20\n", "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m14s\u001b[0m 2ms/step - loss: 0.0021 - val_loss: 3.4232e-05\n", "Epoch 2/20\n", "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m15s\u001b[0m 2ms/step - loss: 3.5182e-05 - val_loss: 3.3009e-05\n", "Epoch 3/20\n", "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m15s\u001b[0m 2ms/step - loss: 3.3553e-05 - val_loss: 3.1858e-05\n", "Epoch 4/20\n", "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m15s\u001b[0m 2ms/step - loss: 3.2530e-05 - val_loss: 3.1686e-05\n", "Epoch 5/20\n", "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m15s\u001b[0m 2ms/step - loss: 3.1540e-05 - val_loss: 3.1268e-05\n", "Epoch 6/20\n", "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m15s\u001b[0m 2ms/step - loss: 3.1264e-05 - val_loss: 3.1947e-05\n", "Epoch 7/20\n", "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m15s\u001b[0m 2ms/step - loss: 3.1342e-05 - val_loss: 3.1175e-05\n", "Epoch 8/20\n", "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m14s\u001b[0m 2ms/step - loss: 3.1101e-05 - val_loss: 3.1003e-05\n", "Epoch 9/20\n", "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m14s\u001b[0m 2ms/step - loss: 3.1035e-05 - val_loss: 3.0818e-05\n", "Epoch 10/20\n", "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m14s\u001b[0m 2ms/step - loss: 3.0654e-05 - val_loss: 3.0667e-05\n", "Epoch 11/20\n", "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m15s\u001b[0m 2ms/step - loss: 3.0462e-05 - val_loss: 3.0639e-05\n", "Epoch 12/20\n", "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m14s\u001b[0m 2ms/step - loss: 3.0563e-05 - val_loss: 3.0643e-05\n", "Epoch 13/20\n", "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m14s\u001b[0m 2ms/step - loss: 3.1567e-05 - val_loss: 3.0610e-05\n", "Epoch 14/20\n", "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m15s\u001b[0m 2ms/step - loss: 3.0625e-05 - val_loss: 3.0598e-05\n", "Epoch 15/20\n", "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m15s\u001b[0m 2ms/step - loss: 3.0962e-05 - val_loss: 3.0589e-05\n", "Epoch 16/20\n", "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m15s\u001b[0m 2ms/step - loss: 3.1131e-05 - val_loss: 3.0598e-05\n", "Epoch 17/20\n", "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m15s\u001b[0m 2ms/step - loss: 3.0939e-05 - val_loss: 3.0580e-05\n", "Epoch 18/20\n", "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m15s\u001b[0m 2ms/step - loss: 3.1100e-05 - val_loss: 3.0580e-05\n", "Epoch 19/20\n", "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m15s\u001b[0m 2ms/step - loss: 3.0586e-05 - val_loss: 3.0579e-05\n", "Epoch 20/20\n", "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m15s\u001b[0m 2ms/step - loss: 3.0749e-05 - val_loss: 3.0576e-05\n", "Training took 295.5790858268738 seconds\n" ] } ], "source": [ "# measure time\n", "start = time.time()\n", "callback = keras.callbacks.EarlyStopping(monitor='loss', patience=3)\n", "history = model_simple.fit(X_train.iloc[:, X_train.columns != \"Class\"], \n", " y_train.iloc[:, y_train.columns != \"Class\"], \n", " batch_size = batch_size, \n", " epochs = 20, \n", " validation_data = (X_val.iloc[:, X_val.columns != \"Class\"], y_val.iloc[:, y_val.columns != \"Class\"]),\n", " callbacks = [callback])\n", "\n", "end = time.time()\n", "\n", "print(\"Training took {} seconds\".format(end - start))" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\u001b[1m32/32\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 595us/step\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjcAAAHFCAYAAAAOmtghAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAUPRJREFUeJzt3Xl4FFWiNvC3eu90ks5GVkISVCASUEiUTQYRDbIp44bLAFEYwR35mEGGqyyOxm24qENYRhBBR6IDcpVhHKNgZFMggIoBFAHD0iFk687a6/n+iGlospBIdQqS9+dTj+nTp6pOnyz1cupUlSSEECAiIiJqJ1RKN4CIiIhITgw3RERE1K4w3BAREVG7wnBDRERE7QrDDREREbUrDDdERETUrjDcEBERUbvCcENERETtCsMNERERtSsMN9RurFy5EpIkYffu3Y2+P3r0aCQmJrZ4e5988gnGjBmDqKgo6HQ6hIWFYdiwYXjvvffgdDplavWlY+PGjZg7d67ftp+VlYWVK1c2KD927BgkSWr0PapT30evvfaatyw/Px9z587FsWPHlGvYBdqRkZHRqt85Irkw3BCdRwiBBx98ELfddhs8Hg8WLFiAzz//HO+88w6uueYaPProo8jKylK6mbLbuHEj5s2b57ftNxVuYmJisGPHDowaNcpv+26P8vPzMW/evEsi3DTVjmeffRYfffRR2zeKOjyN0g0gutS8+uqrWLlyJebNm4fnnnvO570xY8bgz3/+Mw4fPqxQ6y4NQgjU1tbCaDRe9Lb0ej369+8vQ6subzU1NTAYDJAkSdF2VFdXIyAgQJZtXXHFFbJsh6i1OHJDdA6n04mXX34ZPXr0wLPPPttonejoaNxwww3e16WlpXj00UcRFxcHnU6Hrl27Yvbs2bDb7T7rSZKExx9/HKtXr0ZycjICAgJwzTXXYMOGDQ32cfDgQdx3332IioqCXq9Hly5dMGHCBJ9tFhYWYsqUKejcuTN0Oh2SkpIwb948uFwub51zT2csWLAASUlJCAwMxIABA/D1119762VkZGDRokXedtYv9f8ar2/7kiVLkJycDL1ej3feeQcAMG/ePPTr1w9hYWEIDg5G3759sXz5cpz7TN7ExET88MMPyM3N9W67/nRFU6eltm7dimHDhiEoKAgBAQEYOHAg/v3vf/vUqT8VuXnzZjzyyCOIiIhAeHg47rjjDpw6darR79/5Pv74YwwYMAABAQEICgrCLbfcgh07dnjfX79+PSRJwhdffNFg3cWLF0OSJHz33Xfest27d+O2225DWFgYDAYD+vTpgw8++KDRdn/22Wd46KGH0KlTJwQEBDT4mWnKypUrcffddwMAhg4d6u3Tc/vw888/x7BhwxAcHIyAgAAMGjSowWeYO3cuJEnCnj17cNdddyE0NNQbSHbv3o17770XiYmJMBqNSExMxH333Ydffvmlxe1o7LRUbW0tZs2ahaSkJOh0OsTFxeGxxx5DeXm5T73ExESMHj0an376Kfr27Quj0YgePXpgxYoVPvWqq6sxY8YMJCUlwWAwICwsDGlpaXj//fdb1JfUTgmiduLtt98WAMTXX38tnE5ng2XkyJEiISGh2W1s375dABAzZ85s0T5rampE7969hclkEq+99pr47LPPxLPPPis0Go0YOXKkT10AIjExUVx//fXigw8+EBs3bhQ33nij0Gg04ueff/bW27dvnwgMDBSJiYliyZIl4osvvhDvvvuuuOeee4TNZhNCCGGxWER8fLxISEgQS5cuFZ9//rl4/vnnhV6vFxkZGd5tHT161LvfW2+9Vaxfv16sX79e9OrVS4SGhory8nIhhBCHDx8Wd911lwAgduzY4V1qa2u9bY+LixO9e/cW//znP8WmTZvE/v37hRBCZGRkiOXLl4ucnByRk5Mjnn/+eWE0GsW8efO87dizZ4/o2rWr6NOnj3fbe/bs8Wnj22+/7a3/5ZdfCq1WK1JTU0V2drZYv369SE9PF5IkiTVr1jT4nnft2lU88cQT4r///a946623RGhoqBg6dOgFv3/vvfeeACDS09PF+vXrRXZ2tkhNTRU6nU5s2bJFCCGE0+kUkZGR4oEHHmiw/vXXXy/69u3rfb1p0yah0+nE4MGDRXZ2tvj0009FRkZGg89X3+64uDjx8MMPi//85z/iX//6l3C5XI22s76PXn31VSGEEEVFReLFF18UAMSiRYu8fVpUVCSEEGL16tVCkiQxduxYsW7dOvHJJ5+I0aNHC7VaLT7//HPvdufMmSMAiISEBDFz5kyRk5Mj1q9fL4QQ4sMPPxTPPfec+Oijj0Rubq5Ys2aNGDJkiOjUqZM4c+ZMi9oxceJEn985j8cjhg8fLjQajXj22WfFZ599Jl577TVhMplEnz59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R0fD4XCgrKysyTodXV5eHoqKipCamgqNRgONRoPc3Fy88cYb0Gg03n5iP1+cmJgYXH311T5lycnJKCgoAMCfZzn96U9/wjPPPIN7770XvXr1wvjx4/H0008jMzMTAPvaH+Tq0+joaJw+fbrB9s+cOXPR/c5wc5F0Oh1SU1ORk5PjU56Tk4OBAwcq1KrLjxACjz/+ONatW4dNmzYhKSnJ5/2kpCRER0f79LPD4UBubq63n1NTU6HVan3qWCwW7N+/n9+LXw0bNgzff/899u3b513S0tLwwAMPYN++fejatSv7WQaDBg1qcCuDH3/8EQkJCQD48yyn6upqqFS+hzK1Wu29FJx9LT+5+nTAgAGwWq3YuXOnt84333wDq9V68f1+UdORSQhx9lLw5cuXi/z8fDFt2jRhMpnEsWPHlG7aZeORRx4RZrNZfPnll8JisXiX6upqb52XXnpJmM1msW7dOvH999+L++67r9FLDzt37iw+//xzsWfPHnHTTTd16Ms5W+Lcq6WEYD/LYefOnUKj0YgXXnhB/PTTT+K9994TAQEB4t133/XWYT/LY+LEiSIuLs57Kfi6detERESE+POf/+ytw75uvYqKCrF3716xd+9eAUAsWLBA7N2713uLE7n69NZbbxW9e/cWO3bsEDt27BC9evXipeCXkkWLFomEhASh0+lE3759vZcwU8sAaHR5++23vXU8Ho+YM2eOiI6OFnq9Xvzud78T33//vc92ampqxOOPPy7CwsKE0WgUo0ePFgUFBW38aS4v54cb9rM8PvnkE5GSkiL0er3o0aOHWLZsmc/77Gd52Gw28dRTT4kuXboIg8EgunbtKmbPni3sdru3Dvu69TZv3tzo3+SJEycKIeTr05KSEvHAAw+IoKAgERQUJB544AFRVlZ20e2XhBDi4sZ+iIiIiC4dnHNDRERE7QrDDREREbUrDDdERETUrjDcEBERUbvCcENERETtCsMNERERtSsMN0RERNSuMNwQUYeTmJiIhQsXKt0MIvIThhsi8quMjAyMHTsWAHDjjTdi2rRpbbbvlStXIiQkpEH5rl278PDDD7dZO4iobWmUbgARUWs5HA7odLrfvH6nTp1kbA0RXWo4ckNEbSIjIwO5ubl4/fXXIUkSJEnCsWPHAAD5+fkYOXIkAgMDERUVhfHjx6O4uNi77o033ojHH38c06dPR0REBG655RYAwIIFC9CrVy+YTCbEx8fj0UcfRWVlJQDgyy+/xIMPPgir1erd39y5cwE0PC1VUFCA22+/HYGBgQgODsY999yD06dPe9+fO3curr32WqxevRqJiYkwm8249957UVFR4d9OI6LfhOGGiNrE66+/jgEDBuCPf/wjLBYLLBYL4uPjYbFYMGTIEFx77bXYvXs3Pv30U5w+fRr33HOPz/rvvPMONBoNtm3bhqVLlwIAVCoV3njjDezfvx/vvPMONm3ahD//+c8AgIEDB2LhwoUIDg727m/GjBkN2iWEwNixY1FaWorc3Fzk5OTg559/xrhx43zq/fzzz1i/fj02bNiADRs2IDc3Fy+99JKfeouILgZPSxFRmzCbzdDpdAgICEB0dLS3fPHixejbty9efPFFb9mKFSsQHx+PH3/8Ed26dQMAXHnllXjllVd8tnnu/J2kpCQ8//zzeOSRR5CVlQWdTgez2QxJknz2d77PP/8c3333HY4ePYr4+HgAwOrVq9GzZ0/s2rUL1113HQDA4/Fg5cqVCAoKAgCMHz8eX3zxBV544YWL6xgikh1HbohIUXl5edi8eTMCAwO9S48ePQDUjZbUS0tLa7Du5s2bccsttyAuLg5BQUGYMGECSkpKUFVV1eL9HzhwAPHx8d5gAwBXX301QkJCcODAAW9ZYmKiN9gAQExMDIqKilr1WYmobXDkhogU5fF4MGbMGLz88ssN3ouJifF+bTKZfN775ZdfMHLkSEydOhXPP/88wsLCsHXrVkyaNAlOp7PF+xdCQJKkC5ZrtVqf9yVJgsfjafF+iKjtMNwQUZvR6XRwu90+ZX379sXatWuRmJgIjablf5J2794Nl8uFv/3tb1Cp6gahP/jggwvu73xXX301CgoKcPz4ce/oTX5+PqxWK5KTk1vcHiK6dPC0FBG1mcTERHzzzTc4duwYiouL4fF48Nhjj6G0tBT33Xcfdu7ciSNHjuCzzz7DQw891GwwueKKK+ByufDmm2/iyJEjWL16NZYsWdJgf5WVlfjiiy9QXFyM6urqBtu5+eab0bt3bzzwwAPYs2cPdu7ciQkTJmDIkCGNngojoksfww0RtZkZM2ZArVbj6quvRqdOnVBQUIDY2Fhs27YNbrcbw4cPR0pKCp566imYzWbviExjrr32WixYsAAvv/wyUlJS8N577yEzM9OnzsCBAzF16lSMGzcOnTp1ajAhGag7vbR+/XqEhobid7/7HW6++WZ07doV2dnZsn9+ImobkhBCKN0IIiIiIrlw5IaIiIjaFYYbIiIialcYboiIiKhdYbghIiKidoXhhoiIiNoVhhsiIiJqVxhuiIiIqF1huCEiIqJ2heGGiIiI2hWGGyIiImpXGG6IiIioXWG4ISIionbl/wOIQ9raEHCnFQAAAABJRU5ErkJggg==", "text/plain": [ "
| \n", " | H | \n", "O | \n", "Charge | \n", "H_0_ | \n", "O_0_ | \n", "Ba | \n", "Cl | \n", "S_2_ | \n", "S_6_ | \n", "Sr | \n", "Barite | \n", "Celestite | \n", "
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | \n", "111.012434 | \n", "55.508700 | \n", "-1.216415e-09 | \n", "0.0 | \n", "2.217711e-13 | \n", "4.495355e-07 | \n", "1.532249e-12 | \n", "0.0 | \n", "0.000621 | \n", "0.000620 | \n", "0.001000 | \n", "1.000000 | \n", "
| 1 | \n", "111.012434 | \n", "55.508700 | \n", "-1.222504e-09 | \n", "0.0 | \n", "1.312902e-12 | \n", "4.500359e-07 | \n", "1.044603e-08 | \n", "0.0 | \n", "0.000621 | \n", "0.000620 | \n", "0.001000 | \n", "1.000000 | \n", "
| 2 | \n", "111.012434 | \n", "55.508699 | \n", "-1.220407e-09 | \n", "0.0 | \n", "1.614098e-12 | \n", "4.500563e-07 | \n", "4.907802e-07 | \n", "0.0 | \n", "0.000621 | \n", "0.000620 | \n", "0.001000 | \n", "1.000000 | \n", "
| 3 | \n", "111.012434 | \n", "55.508695 | \n", "-1.216831e-09 | \n", "0.0 | \n", "2.293739e-12 | \n", "4.504482e-07 | \n", "4.772370e-06 | \n", "0.0 | \n", "0.000620 | \n", "0.000622 | \n", "0.001000 | \n", "1.000000 | \n", "
| 4 | \n", "111.012434 | \n", "55.508679 | \n", "-1.216842e-09 | \n", "0.0 | \n", "2.641545e-12 | \n", "4.534070e-07 | \n", "2.200220e-05 | \n", "0.0 | \n", "0.000616 | \n", "0.000626 | \n", "0.001000 | \n", "1.000000 | \n", "
| ... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "
| 995 | \n", "111.012434 | \n", "55.506410 | \n", "2.170844e-08 | \n", "0.0 | \n", "4.777415e-11 | \n", "1.550089e-04 | \n", "9.784038e-02 | \n", "0.0 | \n", "0.000048 | \n", "0.048814 | \n", "0.149476 | \n", "0.846327 | \n", "
| 996 | \n", "111.012434 | \n", "55.506410 | \n", "2.166504e-08 | \n", "0.0 | \n", "4.808612e-11 | \n", "1.559012e-04 | \n", "9.785750e-02 | \n", "0.0 | \n", "0.000048 | \n", "0.048821 | \n", "0.151708 | \n", "0.844093 | \n", "
| 997 | \n", "111.012434 | \n", "55.506409 | \n", "2.162167e-08 | \n", "0.0 | \n", "4.811205e-11 | \n", "1.567226e-04 | \n", "9.787459e-02 | \n", "0.0 | \n", "0.000048 | \n", "0.048829 | \n", "0.153945 | \n", "0.841856 | \n", "
| 998 | \n", "111.012434 | \n", "55.506409 | \n", "2.157995e-08 | \n", "0.0 | \n", "4.815004e-11 | \n", "1.574812e-04 | \n", "9.789167e-02 | \n", "0.0 | \n", "0.000048 | \n", "0.048836 | \n", "0.156185 | \n", "0.839614 | \n", "
| 999 | \n", "111.012434 | \n", "55.506409 | \n", "2.153938e-08 | \n", "0.0 | \n", "4.815067e-11 | \n", "1.581835e-04 | \n", "9.790872e-02 | \n", "0.0 | \n", "0.000048 | \n", "0.048844 | \n", "0.158428 | \n", "0.837370 | \n", "
1000 rows × 12 columns
\n", "| \n", " | H | \n", "O | \n", "Charge | \n", "H_0_ | \n", "O_0_ | \n", "Ba | \n", "Cl | \n", "S_2_ | \n", "S_6_ | \n", "Sr | \n", "Barite | \n", "Celestite | \n", "
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | \n", "111.012428 | \n", "55.508682 | \n", "-1.193141e-09 | \n", "3.397941e-15 | \n", "2.128961e-13 | \n", "-0.000012 | \n", "0.000021 | \n", "-1.191799e-17 | \n", "0.000620 | \n", "0.000630 | \n", "0.000985 | \n", "1.000231 | \n", "
| 1 | \n", "111.012428 | \n", "55.508682 | \n", "-1.202185e-09 | \n", "2.918474e-15 | \n", "1.019832e-12 | \n", "-0.000016 | \n", "0.000008 | \n", "-7.920033e-18 | \n", "0.000620 | \n", "0.000630 | \n", "0.000946 | \n", "1.000121 | \n", "
| 2 | \n", "111.012428 | \n", "55.508682 | \n", "-1.203471e-09 | \n", "1.785468e-15 | \n", "2.398433e-12 | \n", "-0.000015 | \n", "-0.000013 | \n", "-9.158671e-18 | \n", "0.000620 | \n", "0.000627 | \n", "0.000913 | \n", "0.999977 | \n", "
| 3 | \n", "111.012428 | \n", "55.508682 | \n", "-1.199235e-09 | \n", "1.746077e-15 | \n", "2.357316e-12 | \n", "-0.000016 | \n", "-0.000011 | \n", "-9.246642e-18 | \n", "0.000619 | \n", "0.000629 | \n", "0.000916 | \n", "0.999936 | \n", "
| 4 | \n", "111.012428 | \n", "55.508682 | \n", "-1.197043e-09 | \n", "1.533956e-15 | \n", "2.670053e-12 | \n", "-0.000019 | \n", "0.000003 | \n", "-9.144569e-18 | \n", "0.000615 | \n", "0.000635 | \n", "0.000943 | \n", "0.999769 | \n", "
| ... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "... | \n", "
| 995 | \n", "111.012428 | \n", "55.506416 | \n", "2.189995e-08 | \n", "-3.792428e-15 | \n", "4.785985e-11 | \n", "0.000279 | \n", "0.097642 | \n", "1.182626e-16 | \n", "0.000051 | \n", "0.048738 | \n", "0.149016 | \n", "0.844585 | \n", "
| 996 | \n", "111.012428 | \n", "55.506416 | \n", "2.188781e-08 | \n", "-3.910681e-15 | \n", "4.822730e-11 | \n", "0.000279 | \n", "0.097665 | \n", "1.169111e-16 | \n", "0.000051 | \n", "0.048751 | \n", "0.151241 | \n", "0.842272 | \n", "
| 997 | \n", "111.012428 | \n", "55.506416 | \n", "2.184875e-08 | \n", "-3.749360e-15 | \n", "4.824932e-11 | \n", "0.000279 | \n", "0.097687 | \n", "1.146696e-16 | \n", "0.000051 | \n", "0.048761 | \n", "0.153477 | \n", "0.840015 | \n", "
| 998 | \n", "111.012428 | \n", "55.506416 | \n", "2.180415e-08 | \n", "-3.500642e-15 | \n", "4.816323e-11 | \n", "0.000279 | \n", "0.097710 | \n", "1.119656e-16 | \n", "0.000051 | \n", "0.048770 | \n", "0.155720 | \n", "0.837773 | \n", "
| 999 | \n", "111.012428 | \n", "55.506416 | \n", "2.177183e-08 | \n", "-3.375572e-15 | \n", "4.822685e-11 | \n", "0.000279 | \n", "0.097732 | \n", "1.095921e-16 | \n", "0.000050 | \n", "0.048780 | \n", "0.157962 | \n", "0.835504 | \n", "
1000 rows × 12 columns
\n", "