model-training/POET_Training.ipynb
2025-01-15 11:50:05 +01:00

1235 lines
125 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"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": 47,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Running Keras in version 3.6.0\n"
]
}
],
"source": [
"import keras\n",
"print(\"Running Keras in version {}\".format(keras.__version__))\n",
"\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 imblearn.over_sampling import SMOTE\n",
"from collections import Counter"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Define parameters"
]
},
{
"cell_type": "code",
"execution_count": 116,
"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 = keras.optimizers.Adam(learning_rate=lr_schedule)\n",
"loss = keras.losses.Huber()\n",
"\n",
"sample_fraction = 0.8"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Setup the model"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">Model: \"sequential\"</span>\n",
"</pre>\n"
],
"text/plain": [
"\u001b[1mModel: \"sequential\"\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
"┃<span style=\"font-weight: bold\"> Layer (type) </span>┃<span style=\"font-weight: bold\"> Output Shape </span>┃<span style=\"font-weight: bold\"> Param # </span>┃\n",
"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
"│ dense (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dense</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">128</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">1,664</span> │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_1 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dense</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">128</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">16,512</span> │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_2 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dense</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">12</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">1,548</span> │\n",
"└─────────────────────────────────┴────────────────────────┴───────────────┘\n",
"</pre>\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": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Total params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">19,724</span> (77.05 KB)\n",
"</pre>\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": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Trainable params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">19,724</span> (77.05 KB)\n",
"</pre>\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": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Non-trainable params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> (0.00 B)\n",
"</pre>\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": [
"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, loss = loss)\n",
"model_simple.summary()"
]
},
{
"cell_type": "code",
"execution_count": 117,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\">Model: \"sequential_4\"</span>\n",
"</pre>\n"
],
"text/plain": [
"\u001b[1mModel: \"sequential_4\"\u001b[0m\n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\">┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
"┃<span style=\"font-weight: bold\"> Layer (type) </span>┃<span style=\"font-weight: bold\"> Output Shape </span>┃<span style=\"font-weight: bold\"> Param # </span>┃\n",
"┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
"│ dense_15 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dense</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">512</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">6,656</span> │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_16 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dense</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">1024</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">525,312</span> │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_17 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dense</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">512</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">524,800</span> │\n",
"├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
"│ dense_18 (<span style=\"color: #0087ff; text-decoration-color: #0087ff\">Dense</span>) │ (<span style=\"color: #00d7ff; text-decoration-color: #00d7ff\">None</span>, <span style=\"color: #00af00; text-decoration-color: #00af00\">12</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">6,156</span> │\n",
"└─────────────────────────────────┴────────────────────────┴───────────────┘\n",
"</pre>\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_15 (\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_16 (\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_17 (\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_18 (\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": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Total params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">1,062,924</span> (4.05 MB)\n",
"</pre>\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": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Trainable params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">1,062,924</span> (4.05 MB)\n",
"</pre>\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": [
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"font-weight: bold\"> Non-trainable params: </span><span style=\"color: #00af00; text-decoration-color: #00af00\">0</span> (0.00 B)\n",
"</pre>\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": [
"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, loss = loss)\n",
"model_large.summary()\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Define some functions and helper classes"
]
},
{
"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\n"
]
},
{
"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": 86,
"metadata": {},
"outputs": [],
"source": [
"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 = design[\"names\"].asstr())\n",
"df_results = pd.DataFrame(np.array(results[\"data\"]).transpose(), columns = results[\"names\"].asstr())\n",
"\n",
"data_file.close()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Classify each cell with kmeans"
]
},
{
"cell_type": "code",
"execution_count": 87,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/home/signer/bin/miniconda3/envs/training/lib/python3.11/site-packages/sklearn/base.py:1473: 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"
]
}
],
"source": [
"# widget with slider for the index\n",
"\n",
"class_label_design = np.array([])\n",
"class_label_result = np.array([])\n",
"\n",
"\n",
"i = 1000\n",
"for i in range(0,1001):\n",
" field_design = np.array(df_design['Barite'][(i*2500):(i*2500+2500)]).reshape(50,50)\n",
" field_result = np.array(df_results['Barite'][(i*2500):(i*2500+2500)]).reshape(50,50)\n",
" \n",
" kmeans_design = KMeans(n_clusters=2, random_state=0).fit(field_design.reshape(-1,1))\n",
" kmeans_result = KMeans(n_clusters=2, random_state=0).fit(field_result.reshape(-1,1))\n",
" \n",
" class_label_design = np.append(class_label_design.astype(int), kmeans_design.labels_)\n",
" class_label_result = np.append(class_label_result.astype(int), kmeans_result.labels_)\n",
" \n",
"\n",
"\n",
"class_label_design = pd.DataFrame(class_label_design, columns = [\"Class\"])\n",
"class_label_result = pd.DataFrame(class_label_result, columns = [\"Class\"])\n"
]
},
{
"cell_type": "code",
"execution_count": 88,
"metadata": {},
"outputs": [],
"source": [
"if(\"Class\" in df_design.columns and \"Class\" in df_results.columns):\n",
" print(\"Class column already exists\")\n",
"else:\n",
" df_design = pd.concat([df_design, class_label_design], axis=1)\n",
" df_results = pd.concat([df_results, class_label_design], axis=1)"
]
},
{
"cell_type": "code",
"execution_count": 89,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.contour.QuadContourSet at 0x7aa0eb5a9e90>"
]
},
"execution_count": 89,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAaEAAAGdCAYAAAC7EMwUAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAKrRJREFUeJzt3X1wXeVh5/Hf85xz77l6xwYsWbWhZlFewIG2kLC4NHYCdpcwlIQ2bQObIUs6QwJk8TC7JMbJxG0TC5wdD+m4oU2bpJntUGe2gYTOEGp1ATkZl13z4sExWwozDlELiiEYXb3dl3POs3+cqyvJko1lyX708v10zgjdeyWdHJL77fOc555jnHNOAAB4YH3vAABg6SJCAABviBAAwBsiBADwhggBALwhQgAAb4gQAMAbIgQA8Cb0vQPHStNUr732mlpaWmSM8b07AIAZcs5pcHBQnZ2dsvbEY515F6HXXntNq1ev9r0bAIBZ6uvr06pVq074mnkXoZaWFknSVfqIQuU87w0AYKZiVfUTPVZ/Pz+ReRehsSm4UDmFhggBwIJTuyLpyZxSYWECAMAbIgQA8IYIAQC8IUIAAG+IEADAGyIEAPCGCAEAvCFCAABviBAAwBsiBADwhggBALwhQgAAb4gQAMAbIgQA8IYIAQC8IUIAAG+IEADAGyIEAPCGCAEAvCFCAABviBAAwBsiBADwhggBALwhQgAAb4gQAMAbIgQA8IYIAQC8IUIAAG+IEADAGyIEAPCGCAEAvCFCAABviBAAwBsiBADwhggBALwhQgAAb4gQAMAbIgQA8IYIAQC8IUIAAG+IEADAGyIEAPCGCAEAvCFCAABviBAAwBsiBADwhggBALwhQgAAb4gQAMAbIgQA8IYIAQC8IUIAAG+IEADAGyIEAPCGCAEAvCFCAABviBAAwBsiBADwhggBALwhQgAAb4gQAMAbIgQA8IYIAQC8mVWEuru7ZYzR5s2b648557Rt2zZ1dnaqoaFBGzZs0KFDh2a7nwCAReiUI7R//35985vf1CWXXDLp8R07dmjnzp3atWuX9u/fr46ODm3cuFGDg4Oz3lkAwOJyShEaGhrSzTffrL/6q7/SsmXL6o875/TAAw9o69atuvHGG7V27Vp997vf1cjIiB566KE522kAwOJwShG64447dN111+maa66Z9Pjhw4fV39+vTZs21R+Lokjr16/Xvn37pv1d5XJZxWJx0gYAWBrCmf7A7t279dxzz2n//v1Tnuvv75cktbe3T3q8vb1dr7766rS/r7u7W3/8x388090AACwCMxoJ9fX16a677tLf/u3fqlAoHPd1xphJ3zvnpjw2ZsuWLRoYGKhvfX19M9klAMACNqOR0LPPPqsjR47osssuqz+WJIn27t2rXbt26aWXXpKUjYhWrlxZf82RI0emjI7GRFGkKIpOZd8BAAvcjEZCV199tQ4ePKgDBw7Ut8svv1w333yzDhw4oAsuuEAdHR3q6emp/0ylUlFvb6/WrVs35zsPAFjYZjQSamlp0dq1ayc91tTUpLPPPrv++ObNm7V9+3Z1dXWpq6tL27dvV2Njo2666aa522sAwKIw44UJ7+See+7R6Oiobr/9dh09elRXXHGF9uzZo5aWlrn+UwCABc4455zvnZioWCyqra1NG3SDQpPzvTsAgBmKXVVP6YcaGBhQa2vrCV/LteMAAN4QIQCAN0QIAOANEQIAeEOEAADeECEAgDdECADgDRECAHhDhAAA3hAhAIA3RAgA4A0RAgB4Q4QAAN4QIQCAN0QIAOANEQIAeEOEAADeECEAgDdECADgDRECAHhDhAAA3hAhAIA3RAgA4A0RAgB4Q4QAAN4QIQCAN0QIAOANEQIAeEOEAADeECEAgDdECADgDRECAHhDhAAA3hAhAIA3RAgA4A0RAgB4Q4QAAN4QIQCAN0QIAOANEQIAeEOEAADeECEAgDdECADgDRECAHhDhAAA3hAhAIA3RAgA4A0RAgB4Q4QAAN4QIQCAN0QIAOANEQIAeEOEAADeECEAgDdECADgDRECAHhDhAAA3hAhAIA3RAgA4A0RAgB4Q4QAAN4QIQCAN0QIAODNjCL04IMP6pJLLlFra6taW1t15ZVX6kc/+lH9eeectm3bps7OTjU0NGjDhg06dOjQnO80AGBxmFGEVq1apfvuu0/PPPOMnnnmGX34wx/WDTfcUA/Njh07tHPnTu3atUv79+9XR0eHNm7cqMHBwdOy8wCAhc0459xsfsHy5cv1ta99Tbfeeqs6Ozu1efNmff7zn5cklctltbe36/7779dtt912Ur+vWCyqra1NG3SDQpObza4BADyIXVVP6YcaGBhQa2vrCV97yueEkiTR7t27NTw8rCuvvFKHDx9Wf3+/Nm3aVH9NFEVav3699u3bd9zfUy6XVSwWJ20AgKVhxhE6ePCgmpubFUWRPvOZz+iRRx7RRRddpP7+fklSe3v7pNe3t7fXn5tOd3e32tra6tvq1atnuksAgAVqxhF697vfrQMHDujpp5/WZz/7Wd1yyy168cUX688bYya93jk35bGJtmzZooGBgfrW19c3010CACxQ4Ux/IJ/P68ILL5QkXX755dq/f7++/vWv188D9ff3a+XKlfXXHzlyZMroaKIoihRF0Ux3AwCwCMz6c0LOOZXLZa1Zs0YdHR3q6empP1epVNTb26t169bN9s8AABahGY2E7r33Xl177bVavXq1BgcHtXv3bj311FN6/PHHZYzR5s2btX37dnV1damrq0vbt29XY2OjbrrpptO1/wCABWxGEfrFL36hT37yk3r99dfV1tamSy65RI8//rg2btwoSbrnnns0Ojqq22+/XUePHtUVV1yhPXv2qKWl5bTsPABgYZv154TmGp8TAoCF7Yx8TggAgNkiQgAAb4gQAMAbIgQA8IYIAQC8IUIAAG+IEADAGyIEAPCGCAEAvCFCAABviBAAwBsiBADwhggBALwhQgAAb4gQAMAbIgQA8IYIAQC8IUIAAG+IEADAGyIEAPCGCAEAvCFCAABviBAAwBsiBADwhggBALwhQgAAb4gQAMAbIgQA8IYIAQC8IUIAAG+IEADAGyIEAPCGCAEAvCFCAABviBAAwBsiBADwhggBALwhQgAAb4gQAMAbIgQA8IYIAQC8IUIAAG+IEADAGyIEAPCGCAEAvCFCAABviBAAwBsiBADwhggBALwhQgAAb4gQAMAbIgQA8IYIAQC8IUIAAG+IEADAGyIEAPCGCAEAvCFCAABviBAAwBsiBADwhggBALwhQgAAb4gQAMCbGUWou7tb73//+9XS0qIVK1boox/9qF566aVJr3HOadu2bers7FRDQ4M2bNigQ4cOzelOAwAWhxlFqLe3V3fccYeefvpp9fT0KI5jbdq0ScPDw/XX7NixQzt37tSuXbu0f/9+dXR0aOPGjRocHJzznQcALGzGOedO9YffeOMNrVixQr29vfrgBz8o55w6Ozu1efNmff7zn5cklctltbe36/7779dtt932jr+zWCyqra1NG3SDQpM71V0DAHgSu6qe0g81MDCg1tbWE752VueEBgYGJEnLly+XJB0+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vIgQAMAbIgQA8IYIAQC8mfcRms+3Cfdh7969uv7669XZ2SljjH7wgx9Met45p23btqmzs1MNDQ3asGGDDh065GdnPenu7tb73/9+tbS0aMWKFfroRz+ql156adJrOE7Sgw8+qEsuuUStra1qbW3VlVdeqR/96Ef15zlG0+vu7pYxRps3b64/xrE6dfM6QmO3Cd+6dauef/55/dZv/ZauvfZa/fznP/e9a94MDw/r0ksv1a5du6Z9fseOHdq5c6d27dql/fv3q6OjQxs3btTg4OAZ3lN/ent7dccdd+jpp59WT0+P4jjWpk2bNDw8XH8Nx0latWqV7rvvPj3zzDN65pln9OEPf1g33HBD/c2TYzTV/v379c1vflOXXHLJpMc5VrMwi+uUnnYf+MAH3Gc+85lJj73nPe9xX/jCFzzt0fwiyT3yyCP179M0dR0dHe6+++6rP1YqlVxbW5v7i7/4Cw97OD8cOXLESXK9vb3OOY7TiSxbtsz99V//NcdoGoODg66rq8v19PS49evXu7vuuss5x3+fZmvejoSW8m3CT9Xhw4fV398/6ZhFUaT169cv6WM2MDAgSVq+fLkkjtN0kiTR7t27NTw8rCuvvJJjNI077rhD1113na655ppJj3OsZue0XEV7Lsz0NuFQ/bhMd8xeffVVH7vknXNOd999t6666iqtXbtWEsdpooMHD+rKK69UqVRSc3OzHnnkEV100UX1N0+OUWb37t167rnntH///inP8d+n2Zm3ERpzsrcJxziO2bg777xTL7zwgn7yk59MeY7jJL373e/WgQMH9Pbbb+v73/++brnlFvX29taf5xhJfX19uuuuu7Rnzx4VCoXjvo5jdWrm7XTcTG8TDqmjo0OSOGY1n/vc5/Too4/qySef1KpVq+qPc5zG5fN5XXjhhbr88svV3d2tSy+9VF//+tc5RhM8++yzOnLkiC677DKFYagwDNXb26s/+7M/UxiG9ePBsTo18zZCE28TPlFPT4/WrVvnaa/mtzVr1qijo2PSMatUKurt7V1Sx8w5pzvvvFMPP/ywnnjiCa1Zs2bS8xyn43POqVwuc4wmuPrqq3Xw4EEdOHCgvl1++eW6+eabdeDAAV1wwQUcq9nwtybinc3mNuGL1eDgoHv++efd888/7yS5nTt3uueff969+uqrzjnn7rvvPtfW1uYefvhhd/DgQfeJT3zCrVy50hWLRc97fuZ89rOfdW1tbe6pp55yr7/+en0bGRmpv4bj5NyWLVvc3r173eHDh90LL7zg7r33XmetdXv27HHOcYxOZOLqOOc4VrMxryPknHN//ud/7s4//3yXz+fdb/zGb9SX2S5VTz755LT3cr/lllucc9ly0S9/+cuuo6PDRVHkPvjBD7qDBw/63ekzbLrjI8l95zvfqb+G4+TcrbfeWv/f1rnnnuuuvvrqeoCc4xidyLER4lidOm7lAADwZt6eEwIALH5ECADgDRECAHhDhAAA3hAhAIA3RAgA4A0RAgB4Q4QAAN4QIQCAN0QIAOANEQIAeEOEAADe/H/cPLC05dn2LgAAAABJRU5ErkJggg==",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"i=1000\n",
"\n",
"plt.imshow(np.array(df_results['Barite'][(i*2500):(i*2500+2500)]).reshape(50,50), interpolation='bicubic', origin='lower')\n",
"plt.contour(np.array(df_results['Class'][(i*2500):(i*2500+2500)]).reshape(50,50), levels=[0.1], colors='red', origin='lower')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Split into Training and Testing datsets"
]
},
{
"cell_type": "code",
"execution_count": 90,
"metadata": {},
"outputs": [],
"source": [
"X_train, X_test, y_train, y_test = sk.train_test_split(df_design, df_results, test_size = 0.2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Perform SMOT Sampling on dataset to balance classes"
]
},
{
"cell_type": "code",
"execution_count": 91,
"metadata": {},
"outputs": [],
"source": [
"Counter(df_design['Class'])\n",
"oversample = SMOTE()\n",
"\n",
"design_resampled, design_classes_resampled = oversample.fit_resample(X_train.iloc[:, :-1], X_train.iloc[:, -1])\n",
"target_resampled, target_classes_resampled = oversample.fit_resample(y_train.iloc[:, :-1], y_train.iloc[:, -1])\n"
]
},
{
"cell_type": "code",
"execution_count": 94,
"metadata": {},
"outputs": [],
"source": [
"X_train = pd.concat([design_resampled, design_classes_resampled], axis=1)\n",
"y_train = pd.concat([target_resampled, target_classes_resampled], axis=1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Define Scaling and Normalization Functions"
]
},
{
"cell_type": "code",
"execution_count": 96,
"metadata": {},
"outputs": [],
"source": [
"def log_scale(df_design, df_result, func_dict):\n",
" \n",
" df_design = df_design.copy()\n",
" df_result = df_result.copy()\n",
" \n",
" for key in df_design.keys():\n",
" if key != \"Class\":\n",
" df_design[key] = np.vectorize(func_dict[key])(df_design[key])\n",
" df_result[key] = np.vectorize(func_dict[key])(df_result[key])\n",
" \n",
" return df_design, df_result\n",
"\n",
"# Get minimum and maximum values for each column\n",
"def get_min_max(df_design, df_result):\n",
" \n",
" min_vals_des = df_design.min()\n",
" max_vals_des = df_design.max()\n",
" \n",
" min_vals_res = df_result.min()\n",
" max_vals_res = df_result.max()\n",
"\n",
" # minimum of input and output data to get global minimum/maximum\n",
" data_min = np.minimum(min_vals_des, min_vals_res).to_dict()\n",
" data_max = np.maximum(max_vals_des, max_vals_res).to_dict()\n",
"\n",
" return data_min, data_max\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df_design_log, df_results_log = log_scale(df_design, df_results, func_dict_in)\n",
"data_min_log, data_max_log = get_min_max(df_design_log, df_results_log)"
]
},
{
"cell_type": "code",
"execution_count": 101,
"metadata": {},
"outputs": [],
"source": [
"X_train_log, y_train_log = log_scale(X_train, y_train, func_dict_in)\n",
"X_test_log, y_test_log = log_scale(X_test, y_test, func_dict_in)"
]
},
{
"cell_type": "code",
"execution_count": 102,
"metadata": {},
"outputs": [],
"source": [
"train_min_log, train_max_log = get_min_max(X_train_log, y_train_log)\n",
"test_min_log, test_max_log = get_min_max(X_test_log, y_test_log)"
]
},
{
"cell_type": "code",
"execution_count": 100,
"metadata": {},
"outputs": [],
"source": [
"def preprocess(data, func_dict, data_min, data_max):\n",
" data = data.copy()\n",
" for key in data.keys():\n",
" if key != \"Class\":\n",
" data[key] = (data[key] - data_min[key]) / (data_max[key] - data_min[key])\n",
"\n",
" return data\n",
"\n",
"def postprocess(data, func_dict, data_min, data_max):\n",
" data = data.copy()\n",
" for key in data.keys():\n",
" if key != \"Class\":\n",
" data[key] = data[key] * (data_max[key] - data_min[key]) + data_min[key]\n",
" data[key] = np.vectorize(func_dict[key])(data[key])\n",
" return data"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Preprocess the data"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"pp_design = preprocess(df_design_log, func_dict_in, data_min_log, data_max_log)\n",
"pp_results = preprocess(df_results_log, func_dict_in, data_min_log, data_max_log)"
]
},
{
"cell_type": "code",
"execution_count": 103,
"metadata": {},
"outputs": [],
"source": [
"X_train_preprocess = preprocess(X_train_log, func_dict_in, train_min_log, train_max_log)\n",
"y_train_preprocess = preprocess(y_train_log, func_dict_in, train_min_log, train_max_log)\n",
"\n",
"X_test_preprocess = preprocess(X_test_log, func_dict_in, test_min_log, test_max_log)\n",
"y_test_preprocess = preprocess(y_test_log, func_dict_in, test_min_log, test_max_log)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Sample the data"
]
},
{
"cell_type": "code",
"execution_count": 105,
"metadata": {},
"outputs": [],
"source": [
"X_train, X_val, y_train, y_val = sk.train_test_split(X_train_preprocess, y_train_preprocess, test_size = 0.1)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Custom Loss function"
]
},
{
"cell_type": "code",
"execution_count": null,
"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": "code",
"execution_count": 106,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(3559968, 12)"
]
},
"execution_count": 106,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"X_train.iloc[:, :-1].shape"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Train the model"
]
},
{
"cell_type": "code",
"execution_count": 118,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 1/50\n",
"\u001b[1m6954/6954\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m91s\u001b[0m 13ms/step - loss: 0.0070 - val_loss: 0.0066\n",
"Epoch 2/50\n",
"\u001b[1m6954/6954\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m104s\u001b[0m 15ms/step - loss: 0.0066 - val_loss: 0.0066\n",
"Epoch 3/50\n",
"\u001b[1m4644/6954\u001b[0m \u001b[32m━━━━━━━━━━━━━\u001b[0m\u001b[37m━━━━━━━\u001b[0m \u001b[1m35s\u001b[0m 15ms/step - loss: 0.0066"
]
},
{
"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[118], line 4\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m# measure time\u001b[39;00m\n\u001b[1;32m 2\u001b[0m start \u001b[38;5;241m=\u001b[39m time\u001b[38;5;241m.\u001b[39mtime()\n\u001b[0;32m----> 4\u001b[0m history \u001b[38;5;241m=\u001b[39m model_large\u001b[38;5;241m.\u001b[39mfit(X_train\u001b[38;5;241m.\u001b[39miloc[:, :\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m1\u001b[39m], \n\u001b[1;32m 5\u001b[0m y_train\u001b[38;5;241m.\u001b[39miloc[:, :\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m1\u001b[39m], \n\u001b[1;32m 6\u001b[0m batch_size \u001b[38;5;241m=\u001b[39m batch_size, \n\u001b[1;32m 7\u001b[0m epochs \u001b[38;5;241m=\u001b[39m epochs, \n\u001b[1;32m 8\u001b[0m validation_data \u001b[38;5;241m=\u001b[39m (X_val\u001b[38;5;241m.\u001b[39miloc[:,:\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m1\u001b[39m], y_val\u001b[38;5;241m.\u001b[39miloc[:, :\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m1\u001b[39m])\n\u001b[1;32m 9\u001b[0m )\n\u001b[1;32m 11\u001b[0m end \u001b[38;5;241m=\u001b[39m time\u001b[38;5;241m.\u001b[39mtime()\n\u001b[1;32m 13\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mTraining took \u001b[39m\u001b[38;5;132;01m{}\u001b[39;00m\u001b[38;5;124m seconds\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;241m.\u001b[39mformat(end \u001b[38;5;241m-\u001b[39m start))\n",
"File \u001b[0;32m~/bin/miniconda3/envs/training/lib/python3.11/site-packages/keras/src/utils/traceback_utils.py:117\u001b[0m, in \u001b[0;36mfilter_traceback.<locals>.error_handler\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 115\u001b[0m filtered_tb \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m 116\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 117\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m fn(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[1;32m 118\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 119\u001b[0m filtered_tb \u001b[38;5;241m=\u001b[39m _process_traceback_frames(e\u001b[38;5;241m.\u001b[39m__traceback__)\n",
"File \u001b[0;32m~/bin/miniconda3/envs/training/lib/python3.11/site-packages/keras/src/backend/tensorflow/trainer.py:320\u001b[0m, in \u001b[0;36mTensorFlowTrainer.fit\u001b[0;34m(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_batch_size, validation_freq)\u001b[0m\n\u001b[1;32m 318\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m step, iterator \u001b[38;5;129;01min\u001b[39;00m epoch_iterator\u001b[38;5;241m.\u001b[39menumerate_epoch():\n\u001b[1;32m 319\u001b[0m callbacks\u001b[38;5;241m.\u001b[39mon_train_batch_begin(step)\n\u001b[0;32m--> 320\u001b[0m logs \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtrain_function(iterator)\n\u001b[1;32m 321\u001b[0m callbacks\u001b[38;5;241m.\u001b[39mon_train_batch_end(step, logs)\n\u001b[1;32m 322\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mstop_training:\n",
"File \u001b[0;32m~/bin/miniconda3/envs/training/lib/python3.11/site-packages/tensorflow/python/util/traceback_utils.py:150\u001b[0m, in \u001b[0;36mfilter_traceback.<locals>.error_handler\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 148\u001b[0m filtered_tb \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m 149\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 150\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m fn(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[1;32m 151\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 152\u001b[0m filtered_tb \u001b[38;5;241m=\u001b[39m _process_traceback_frames(e\u001b[38;5;241m.\u001b[39m__traceback__)\n",
"File \u001b[0;32m~/bin/miniconda3/envs/training/lib/python3.11/site-packages/tensorflow/python/eager/polymorphic_function/polymorphic_function.py:833\u001b[0m, in \u001b[0;36mFunction.__call__\u001b[0;34m(self, *args, **kwds)\u001b[0m\n\u001b[1;32m 830\u001b[0m compiler \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mxla\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_jit_compile \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mnonXla\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 832\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m OptionalXlaContext(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_jit_compile):\n\u001b[0;32m--> 833\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_call(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwds)\n\u001b[1;32m 835\u001b[0m new_tracing_count \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mexperimental_get_tracing_count()\n\u001b[1;32m 836\u001b[0m without_tracing \u001b[38;5;241m=\u001b[39m (tracing_count \u001b[38;5;241m==\u001b[39m new_tracing_count)\n",
"File \u001b[0;32m~/bin/miniconda3/envs/training/lib/python3.11/site-packages/tensorflow/python/eager/polymorphic_function/polymorphic_function.py:878\u001b[0m, in \u001b[0;36mFunction._call\u001b[0;34m(self, *args, **kwds)\u001b[0m\n\u001b[1;32m 875\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_lock\u001b[38;5;241m.\u001b[39mrelease()\n\u001b[1;32m 876\u001b[0m \u001b[38;5;66;03m# In this case we have not created variables on the first call. So we can\u001b[39;00m\n\u001b[1;32m 877\u001b[0m \u001b[38;5;66;03m# run the first trace but we should fail if variables are created.\u001b[39;00m\n\u001b[0;32m--> 878\u001b[0m results \u001b[38;5;241m=\u001b[39m tracing_compilation\u001b[38;5;241m.\u001b[39mcall_function(\n\u001b[1;32m 879\u001b[0m args, kwds, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_variable_creation_config\n\u001b[1;32m 880\u001b[0m )\n\u001b[1;32m 881\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_created_variables:\n\u001b[1;32m 882\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mCreating variables on a non-first call to a function\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 883\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m decorated with tf.function.\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n",
"File \u001b[0;32m~/bin/miniconda3/envs/training/lib/python3.11/site-packages/tensorflow/python/eager/polymorphic_function/tracing_compilation.py:139\u001b[0m, in \u001b[0;36mcall_function\u001b[0;34m(args, kwargs, tracing_options)\u001b[0m\n\u001b[1;32m 137\u001b[0m bound_args \u001b[38;5;241m=\u001b[39m function\u001b[38;5;241m.\u001b[39mfunction_type\u001b[38;5;241m.\u001b[39mbind(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[1;32m 138\u001b[0m flat_inputs \u001b[38;5;241m=\u001b[39m function\u001b[38;5;241m.\u001b[39mfunction_type\u001b[38;5;241m.\u001b[39munpack_inputs(bound_args)\n\u001b[0;32m--> 139\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m function\u001b[38;5;241m.\u001b[39m_call_flat( \u001b[38;5;66;03m# pylint: disable=protected-access\u001b[39;00m\n\u001b[1;32m 140\u001b[0m flat_inputs, captured_inputs\u001b[38;5;241m=\u001b[39mfunction\u001b[38;5;241m.\u001b[39mcaptured_inputs\n\u001b[1;32m 141\u001b[0m )\n",
"File \u001b[0;32m~/bin/miniconda3/envs/training/lib/python3.11/site-packages/tensorflow/python/eager/polymorphic_function/concrete_function.py:1322\u001b[0m, in \u001b[0;36mConcreteFunction._call_flat\u001b[0;34m(self, tensor_inputs, captured_inputs)\u001b[0m\n\u001b[1;32m 1318\u001b[0m possible_gradient_type \u001b[38;5;241m=\u001b[39m gradients_util\u001b[38;5;241m.\u001b[39mPossibleTapeGradientTypes(args)\n\u001b[1;32m 1319\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m (possible_gradient_type \u001b[38;5;241m==\u001b[39m gradients_util\u001b[38;5;241m.\u001b[39mPOSSIBLE_GRADIENT_TYPES_NONE\n\u001b[1;32m 1320\u001b[0m \u001b[38;5;129;01mand\u001b[39;00m executing_eagerly):\n\u001b[1;32m 1321\u001b[0m \u001b[38;5;66;03m# No tape is watching; skip to running the function.\u001b[39;00m\n\u001b[0;32m-> 1322\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_inference_function\u001b[38;5;241m.\u001b[39mcall_preflattened(args)\n\u001b[1;32m 1323\u001b[0m forward_backward \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_select_forward_and_backward_functions(\n\u001b[1;32m 1324\u001b[0m args,\n\u001b[1;32m 1325\u001b[0m possible_gradient_type,\n\u001b[1;32m 1326\u001b[0m executing_eagerly)\n\u001b[1;32m 1327\u001b[0m forward_function, args_with_tangents \u001b[38;5;241m=\u001b[39m forward_backward\u001b[38;5;241m.\u001b[39mforward()\n",
"File \u001b[0;32m~/bin/miniconda3/envs/training/lib/python3.11/site-packages/tensorflow/python/eager/polymorphic_function/atomic_function.py:216\u001b[0m, in \u001b[0;36mAtomicFunction.call_preflattened\u001b[0;34m(self, args)\u001b[0m\n\u001b[1;32m 214\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mcall_preflattened\u001b[39m(\u001b[38;5;28mself\u001b[39m, args: Sequence[core\u001b[38;5;241m.\u001b[39mTensor]) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Any:\n\u001b[1;32m 215\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"Calls with flattened tensor inputs and returns the structured output.\"\"\"\u001b[39;00m\n\u001b[0;32m--> 216\u001b[0m flat_outputs \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mcall_flat(\u001b[38;5;241m*\u001b[39margs)\n\u001b[1;32m 217\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfunction_type\u001b[38;5;241m.\u001b[39mpack_output(flat_outputs)\n",
"File \u001b[0;32m~/bin/miniconda3/envs/training/lib/python3.11/site-packages/tensorflow/python/eager/polymorphic_function/atomic_function.py:251\u001b[0m, in \u001b[0;36mAtomicFunction.call_flat\u001b[0;34m(self, *args)\u001b[0m\n\u001b[1;32m 249\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m record\u001b[38;5;241m.\u001b[39mstop_recording():\n\u001b[1;32m 250\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_bound_context\u001b[38;5;241m.\u001b[39mexecuting_eagerly():\n\u001b[0;32m--> 251\u001b[0m outputs \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_bound_context\u001b[38;5;241m.\u001b[39mcall_function(\n\u001b[1;32m 252\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mname,\n\u001b[1;32m 253\u001b[0m \u001b[38;5;28mlist\u001b[39m(args),\n\u001b[1;32m 254\u001b[0m \u001b[38;5;28mlen\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfunction_type\u001b[38;5;241m.\u001b[39mflat_outputs),\n\u001b[1;32m 255\u001b[0m )\n\u001b[1;32m 256\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 257\u001b[0m outputs \u001b[38;5;241m=\u001b[39m make_call_op_in_graph(\n\u001b[1;32m 258\u001b[0m \u001b[38;5;28mself\u001b[39m,\n\u001b[1;32m 259\u001b[0m \u001b[38;5;28mlist\u001b[39m(args),\n\u001b[1;32m 260\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_bound_context\u001b[38;5;241m.\u001b[39mfunction_call_options\u001b[38;5;241m.\u001b[39mas_attrs(),\n\u001b[1;32m 261\u001b[0m )\n",
"File \u001b[0;32m~/bin/miniconda3/envs/training/lib/python3.11/site-packages/tensorflow/python/eager/context.py:1552\u001b[0m, in \u001b[0;36mContext.call_function\u001b[0;34m(self, name, tensor_inputs, num_outputs)\u001b[0m\n\u001b[1;32m 1550\u001b[0m cancellation_context \u001b[38;5;241m=\u001b[39m cancellation\u001b[38;5;241m.\u001b[39mcontext()\n\u001b[1;32m 1551\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m cancellation_context \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m-> 1552\u001b[0m outputs \u001b[38;5;241m=\u001b[39m execute\u001b[38;5;241m.\u001b[39mexecute(\n\u001b[1;32m 1553\u001b[0m name\u001b[38;5;241m.\u001b[39mdecode(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mutf-8\u001b[39m\u001b[38;5;124m\"\u001b[39m),\n\u001b[1;32m 1554\u001b[0m num_outputs\u001b[38;5;241m=\u001b[39mnum_outputs,\n\u001b[1;32m 1555\u001b[0m inputs\u001b[38;5;241m=\u001b[39mtensor_inputs,\n\u001b[1;32m 1556\u001b[0m attrs\u001b[38;5;241m=\u001b[39mattrs,\n\u001b[1;32m 1557\u001b[0m ctx\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m,\n\u001b[1;32m 1558\u001b[0m )\n\u001b[1;32m 1559\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 1560\u001b[0m outputs \u001b[38;5;241m=\u001b[39m execute\u001b[38;5;241m.\u001b[39mexecute_with_cancellation(\n\u001b[1;32m 1561\u001b[0m name\u001b[38;5;241m.\u001b[39mdecode(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mutf-8\u001b[39m\u001b[38;5;124m\"\u001b[39m),\n\u001b[1;32m 1562\u001b[0m num_outputs\u001b[38;5;241m=\u001b[39mnum_outputs,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 1566\u001b[0m cancellation_manager\u001b[38;5;241m=\u001b[39mcancellation_context,\n\u001b[1;32m 1567\u001b[0m )\n",
"File \u001b[0;32m~/bin/miniconda3/envs/training/lib/python3.11/site-packages/tensorflow/python/eager/execute.py:53\u001b[0m, in \u001b[0;36mquick_execute\u001b[0;34m(op_name, num_outputs, inputs, attrs, ctx, name)\u001b[0m\n\u001b[1;32m 51\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 52\u001b[0m ctx\u001b[38;5;241m.\u001b[39mensure_initialized()\n\u001b[0;32m---> 53\u001b[0m tensors \u001b[38;5;241m=\u001b[39m pywrap_tfe\u001b[38;5;241m.\u001b[39mTFE_Py_Execute(ctx\u001b[38;5;241m.\u001b[39m_handle, device_name, op_name,\n\u001b[1;32m 54\u001b[0m inputs, attrs, num_outputs)\n\u001b[1;32m 55\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m core\u001b[38;5;241m.\u001b[39m_NotOkStatusException \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m 56\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m name \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n",
"\u001b[0;31mKeyboardInterrupt\u001b[0m: "
]
}
],
"source": [
"# measure time\n",
"start = time.time()\n",
"\n",
"history = model_large.fit(X_train.iloc[:, :-1], \n",
" y_train.iloc[:, :-1], \n",
" batch_size = batch_size, \n",
" epochs = epochs, \n",
" validation_data = (X_val.iloc[:,:-1], y_val.iloc[:, :-1])\n",
")\n",
"\n",
"end = time.time()\n",
"\n",
"print(\"Training took {} seconds\".format(end - start))"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAjcAAAHACAYAAABeV0mSAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAASzlJREFUeJzt3XlYVPX+B/D3mWEYFgFZBAZFxV0kCTWVzNQKAo20bLXSbHVp8XKrG9duSnWzureysijLUrOya6lXb2bSr3I3ciEXzBX3QUSEYZFhgPP7A2eUGGAYzpwzy/v1PD5Pc+bM4cMHzPfzPd/v+QqiKIogIiIichMqpQsgIiIikhLDDREREbkVhhsiIiJyKww3RERE5FYYboiIiMitMNwQERGRW2G4ISIiIrfCcENERERuheGGiIiI3ArDDREREbkVjw43GzZsQFpaGqKioiAIAlauXOnwr3n69Gncf//9CA0NhZ+fH66++mrs2LHD4V+XiIjIU3h0uKmoqEB8fDzmzZsny9e7cOEChg0bBo1Gg++//x55eXl488030b59e1m+PhERkScQuHFmPUEQsGLFCowbN85yrLq6Gi+88AK++OILlJSUIC4uDq+//jpGjhxp19d4/vnnsXnzZmzcuFGaoomIiKgRjx65acnkyZOxefNmLF26FLt378add96JlJQUHDp0yK7rrVq1CoMGDcKdd96J8PBwJCQk4OOPP5a4aiIiIs/GkZtL/jxyc+TIEfTs2ROnTp1CVFSU5bybbroJgwcPxquvvtrqr+Hj4wMASE9Px5133omcnBzMmDEDH330ESZOnCjJ90FEROTpvJQuwFnt3LkToiiiV69eDY4bjUaEhoYCAI4dO4aYmJhmrzN9+nTLnJ66ujoMGjTIEowSEhKwb98+ZGVlMdwQERFJhOGmCXV1dVCr1dixYwfUanWD99q1awcA6NixI/bv39/sdYKDgy3/rdPpEBsb2+D9vn374ttvv5WoaiIiImK4aUJCQgJqa2tRWFiI4cOHWz1Ho9GgT58+Nl9z2LBhOHDgQINjBw8eRJcuXdpUKxEREV3m0eGmvLwchw8ftrzOz89Hbm4uQkJC0KtXL9x3332YOHEi3nzzTSQkJKCoqAg//fQTrrrqKowePbrVX+8vf/kLrr32Wrz66qu46667kJOTg/nz52P+/PlSfltEREQezaMnFP/yyy8YNWpUo+OTJk3CwoULYTKZ8Morr2Dx4sU4ffo0QkNDkZiYiMzMTFx11VV2fc3//e9/yMjIwKFDhxATE4P09HQ8+uijbf1WiIiI6BKPDjdERETkfvicGyIiInIrDDdERETkVjxuQnFdXR3OnDmDgIAACIKgdDlERERkA1EUUVZWhqioKKhUzY/NeFy4OXPmDKKjo5Uug4iIiOxw8uRJdOrUqdlzPC7cBAQEAKhvTmBgoKTXNplMWLduHZKTk6HRaCS9NjXGfsuL/ZYX+y0v9lte9vTbYDAgOjra8u94czwu3JhvRQUGBjok3Pj5+SEwMJB/OWTAfsuL/ZYX+y0v9ltebem3LVNKOKGYiIiI3ArDDREREbkVhhsiIiJyKww3RERE5FYYboiIiMitMNwQERGRW2G4ISIiIrfCcENERERuheGGiIiI3ArDjURq60T8ml+MHUUCfs0vRm2dqHRJREREHsnjtl9whLV79chcnQd9aRUANRYf2g5dkA9mpcUiJU6ndHlEREQehSM3bbR2rx5Tl+y8FGwuKyitwtQlO7F2r16hyoiIiDyTouFmw4YNSEtLQ1RUFARBwMqVK1v8jNFoxMyZM9GlSxdotVp0794dn376qeOLtaK2TkTm6jxYuwFlPpa5Oo+3qIiIiGSk6G2piooKxMfHY/LkyRg/frxNn7nrrrtw9uxZLFiwAD169EBhYSFqamocXKl1OfnFjUZsriQC0JdWISe/GIndQ+UrjIiIyIMpGm5SU1ORmppq8/lr167F+vXrcfToUYSEhAAAunbt6qDqWlZY1nSwsec8IiIiajuXmlC8atUqDBo0CG+88QY+//xz+Pv749Zbb8XLL78MX19fq58xGo0wGo2W1waDAQBgMplgMpnaVE+on23tC/XzavPXosbMPWVv5cF+y4v9lhf7LS97+t2ac10q3Bw9ehSbNm2Cj48PVqxYgaKiIkybNg3FxcVNzruZM2cOMjMzGx1ft24d/Pz82lRPnQi091ajpBoABCtniGjvDZzL24Y1+9v0pagZ2dnZSpfgUdhvebHf8mK/5dWafldWVtp8riCKolPMdhUEAStWrMC4ceOaPCc5ORkbN25EQUEBgoKCAADLly/HHXfcgYqKCqujN9ZGbqKjo1FUVITAwMA21/3DvrN4cunvANBgYrE56rx3Tzxu7hfR5q9DjZlMJmRnZyMpKQkajUbpctwe+y0v9lte7Le87Om3wWBAWFgYSktLW/z326VGbnQ6HTp27GgJNgDQt29fiKKIU6dOoWfPno0+o9VqodVqGx3XaDSS/ALfcnUneHmpr3jOTb1IPudGNlL9LMk27Le82G95sd/yak2/W/Nzcann3AwbNgxnzpxBeXm55djBgwehUqnQqVMnxepKidNh099uwMu39gUAtNOqselvNzDYEBERKUDRcFNeXo7c3Fzk5uYCAPLz85Gbm4sTJ04AADIyMjBx4kTL+RMmTEBoaCgmT56MvLw8bNiwAc8++yweeuihJicUy0WtEjA2PgoCRJQba1FSWa1oPURERJ5K0XCzfft2JCQkICEhAQCQnp6OhIQEvPjiiwAAvV5vCToA0K5dO2RnZ6OkpASDBg3Cfffdh7S0NLz77ruK1P9nvt5qhFy6A3aosLz5k4mIiMghFJ1zM3LkSDQ3n3nhwoWNjvXp08epZ7NH+ok4bxRw6GwZhnbjg/uIiIjk5lJzblxB5KW7Yxy5ISIiUgbDjcQifetHog6dZbghIiJSAsONxCL8LoUbjtwQEREpguFGYhGXbksVlRtxoYIrpoiIiOTGcCMxHzUQFeQDADh8jqM3REREcmO4cYAe4f4AOO+GiIhICQw3DtCjQzsAwKHCMoUrISIi8jwMNw5gHrk5zEnFREREsmO4cQDLyA1vSxEREcmO4cYBuneoH7kpMFTBUGVSuBoiIiLPwnDjAIG+GkQE1m8yxVtTRERE8mK4cZCe4QEAgMO8NUVERCQrhhsH6RnBFVNERERKYLhxEPPIDbdhICIikhfDjYNYRm54W4qIiEhWDDcOYl4OfrrkIiqMNQpXQ0RE5DkYbhwk2N8bYe3qV0wd4R5TREREsmG4caCe4bw1RUREJDeGGwe6vGKK4YaIiEguDDcOdHnkhsvBiYiI5MJw40A9uByciIhIdgw3DmS+LXXyQiUuVtcqXA0REZFnYLhxoFB/bwT7aSCKXDFFREQkF4YbBxIE4fIeU7w1RUREJAuGGwfrwT2miIiIZMVw42C9+KwbIiIiWTHcOFjPCN6WIiIikhPDjYOZn3Vz7HwFjDVcMUVERORoDDcO1iFAi0AfL9SJQH5RhdLlEBERuT2GGwcTBMFya4rzboiIiByP4UYGlm0YOO+GiIjI4RhuZNDjUrg5zOXgREREDqdouNmwYQPS0tIQFRUFQRCwcuXKZs//5ZdfIAhCoz9//PGHPAXbibeliIiI5OOl5BevqKhAfHw8Jk+ejPHjx9v8uQMHDiAwMNDyukOHDo4oTzLm21L5RRUw1dZBo+aAGRERkaMoGm5SU1ORmpra6s+Fh4ejffv20hfkILogH/h7q1FRXYvj5yssu4UTERGR9BQNN/ZKSEhAVVUVYmNj8cILL2DUqFFNnms0GmE0Gi2vDQYDAMBkMsFkMklal/l61q7bPdwfu08ZsP9MKboE+0j6dT1Vc/0m6bHf8mK/5cV+y8uefrfmXEEURbHVVTmAIAhYsWIFxo0b1+Q5Bw4cwIYNGzBw4EAYjUZ8/vnn+PDDD/HLL7/g+uuvt/qZ2bNnIzMzs9HxL7/8En5+flKV36IvDquQc06F0dG1uLmTU7SciIjIZVRWVmLChAkoLS1tMDXFGpcKN9akpaVBEASsWrXK6vvWRm6io6NRVFTUYnNay2QyITs7G0lJSdBoNA3e+3hTPt744RDGXBWJuXf1l/Treqrm+k3SY7/lxX7Li/2Wlz39NhgMCAsLsyncuORtqSsNHToUS5YsafJ9rVYLrVbb6LhGo3HYL7C1a/fVtQcAHDlXwb84EnPkz5IaY7/lxX7Li/2WV2v63Zqfi8sv29m1axd0Op3SZbTI/Kybo+cqUFNbp3A1RERE7kvRkZvy8nIcPnzY8jo/Px+5ubkICQlB586dkZGRgdOnT2Px4sUAgLlz56Jr167o168fqqursWTJEnz77bf49ttvlfoWbNaxvS98NWpcNNXiRHElunVop3RJREREbknRcLN9+/YGK53S09MBAJMmTcLChQuh1+tx4sQJy/vV1dV45plncPr0afj6+qJfv3747rvvMHr0aNlrby2VSkCP8HbYc7oUhwrLGW6IiIgcRNFwM3LkSDQ3n3nhwoUNXj/33HN47rnnHFyV4/To4I89p0ux+vczCPTRYHBMCNQqQemyiIiI3IrLTyh2FWv36vHj/kIAwP926/G/3XrognwwKy0WKXHOP2eIiIjIVbj8hGJXsHavHlOX7ESZsabB8YLSKkxdshNr9+oVqoyIiMj9MNw4WG2diMzVebB28818LHN1HmrrnOJxQ0RERC6P4cbBcvKLoS+tavJ9EYC+tAo5+cXyFUVEROTGGG4crLCs6WBjz3lERETUPIYbBwsPsG2TTFvPIyIiouYx3DjY4JgQ6IJ80NSCbwGALsgHg2NC5CyLiIjIbTHcOJhaJWBWWiwANAo45tez0mL5vBsiIiKJMNzIICVOh6z7ByAyqOGtp8ggH2TdP4DPuSEiIpIQH+Ink5Q4HZJiI7Fs+0k8v3wPAny8sOlvN3DEhoiISGIcuZGRWiVgdP/6UZqyqhpUmWoVroiIiMj9MNzILNBHgyBfDQDg1IWLCldDRETkfhhuFBAd4gsAOFlcqXAlRERE7ofhRgHRwX4AgJMXGG6IiIikxnCjgOiQS+GmmLeliIiIpMZwo4Do4Eu3pThyQ0REJDmGGwV0sozcMNwQERFJjeFGAeY5N6cuXIQoigpXQ0RE5F4YbhTQ6dJtqXJjDUoqTQpXQ0RE5F4YbhTgo1EjPEALgPNuiIiIpMZwoxCumCIiInIMhhuFcMUUERGRYzDcKCSaK6aIiIgcguFGIZefUszbUkRERFJiuFFIp0v7S53iyA0REZGkGG4UcuWzburq+KwbIiIiqTDcKEQX5AO1SkB1bR0Ky4xKl0NEROQ2GG4U4qVWQRfkA4ArpoiIiKTEcKMgy6RizrshIiKSDMONgqIvTSrmg/yIiIikw3CjoMuTijlyQ0REJBWGGwVZHuTHcENERCQZRcPNhg0bkJaWhqioKAiCgJUrV9r82c2bN8PLywtXX321w+pzNN6WIiIikp6i4aaiogLx8fGYN29eqz5XWlqKiRMn4sYbb3RQZfIw35bSl16EqbZO4WqIiIjcg5eSXzw1NRWpqamt/tzjjz+OCRMmQK1Wt2q0x9l0CNBC66WCsaYO+pIqdA71U7okIiIil+dyc24+++wzHDlyBLNmzVK6lDYTBAGduDs4ERGRpBQduWmtQ4cO4fnnn8fGjRvh5WVb6UajEUbj5ScAGwwGAIDJZILJZJK0PvP1WnPdTu19ceRcBY6dK8PgLkGS1uPu7Ok32Y/9lhf7LS/2W1729Ls157pMuKmtrcWECROQmZmJXr162fy5OXPmIDMzs9HxdevWwc/PMbeBsrOzbT631qACoMIv2/eiXeFuh9Tj7lrTb2o79lte7Le82G95tabflZW23+EQRFF0il0bBUHAihUrMG7cOKvvl5SUIDg4GGq12nKsrq4OoihCrVZj3bp1uOGGGxp9ztrITXR0NIqKihAYGCjp92AymZCdnY2kpCRoNBqbPvPJpmN4/YeDuOWqSLx9V39J63F39vSb7Md+y4v9lhf7LS97+m0wGBAWFobS0tIW//12mZGbwMBA7Nmzp8GxDz74AD/99BO++eYbxMTEWP2cVquFVqttdFyj0TjsF7g11+4a1g4AcLq0in+h7OTInyU1xn7Li/2WF/str9b0uzU/F0XDTXl5OQ4fPmx5nZ+fj9zcXISEhKBz587IyMjA6dOnsXjxYqhUKsTFxTX4fHh4OHx8fBoddyWWB/nxWTdERESSUDTcbN++HaNGjbK8Tk9PBwBMmjQJCxcuhF6vx4kTJ5QqTxbm1VJF5UZcrK6Fr7e6hU8QERFRcxQNNyNHjkRzU34WLlzY7Odnz56N2bNnS1uUzIJ8NQjQeqHMWINTFyrRMyJA6ZKIiIhcmss958bdCIKATtxjioiISDIMN04gOph7TBEREUmF4cYJXJ5UzJEbIiKitmK4cQLR3IKBiIhIMgw3ToDLwYmIiKTDcOMEojmhmIiISDIMN07A/KybsqoalFZy0zYiIqK2YLhxAn7eXghr5w2AozdERERtxXDjJDoF19+aOsVwQ0RE1CYMN06Ck4qJiIikwXDjJLgcnIiISBoMN06CD/IjIiKSBsONk4gONi8H520pIiKitmC4cRLm5eCnLlQ2u1M6ERERNY/hxklEtfeFIABVpjqcKzcqXQ4REZHLYrhxEt5eKugCfQBwxRQREVFbMNw4kU4hfNYNERFRWzHcOBHLpGKumCIiIrIbw40TiQ659Kwb3pYiIiKyG8ONE7m8HJwjN0RERPZiuHEilgf5MdwQERHZjeHGiZhvS50pqUJNbZ3C1RAREbkmhhsnEhHgA2+1CrV1IvSlVUqXQ0RE5JIYbpyISiWgIzfQJCIiahOGGydj2YaBK6aIiIjswnDjZDipmIiIqG0YbpyMeTn4Ke4OTkREZBeGGyfTsX39/lK5J0uw9ch51NZxh3AiIqLWYLhxImv36pG5Og8AkF9UgXs/3obrXv8Ja/fqFa6MiIjIdTDcOIm1e/WYumQnzldUNzheUFqFqUt2MuAQERHZiOHGCdTWichcnQdrN6DMxzJX5/EWFRERkQ287PnQsWPHsHHjRhw7dgyVlZXo0KEDEhISkJiYCB8fH6lrdHs5+cXNPrRPBKAvrUJOfjESu4fKVxgREZELatXIzZdffomhQ4eiW7duePbZZ7Fy5Ups3LgRn3zyCVJSUhAREYFp06bh+PHjNl1vw4YNSEtLQ1RUFARBwMqVK5s9f9OmTRg2bBhCQ0Ph6+uLPn364O23327Nt+CUCstsexqxrecRERF5MptHbgYMGACVSoUHH3wQ//nPf9C5c+cG7xuNRmzduhVLly7FoEGD8MEHH+DOO+9s9poVFRWIj4/H5MmTMX78+BZr8Pf3xxNPPIH+/fvD398fmzZtwuOPPw5/f3889thjtn4rTic8wLbRLlvPIyIi8mQ2h5uXX34ZY8aMafJ9rVaLkSNHYuTIkXjllVeQn5/f4jVTU1ORmppqawlISEhAQkKC5XXXrl2xfPlybNy40aXDzeCYEOiCfFBQWmV13o0AIDLIB4NjQuQujYiIyOXYfFvKHGxqamqwaNEiFBQUNHluWFgYrrnmmrZX14Jdu3Zhy5YtGDFihMO/liOpVQJmpcUCqA8yVzK/npUWC7Xqz+8SERHRn7V6QrGXlxemTp2K/fv3O6Iem3Tq1Annzp1DTU0NZs+ejUceeaTJc41GI4xGo+W1wWAAAJhMJphMJknrMl/Pnuve2DsM790Tj1fW/IECw+V6OwRo8eKYPrixd5jk9bq6tvSbWo/9lhf7LS/2W1729Ls15wqiKLZ6ffGoUaMwY8YMjB07trUfbboQQcCKFSswbty4Fs/Nz89HeXk5tm3bhueffx7z5s3Dvffea/Xc2bNnIzMzs9HxL7/8En5+fm0tW3J1InDEIGDRQRXKagRM61uL3u25BJyIiDxbZWUlJkyYgNLSUgQGBjZ7rl1LwadNm4b09HScPHkSAwcOhL+/f4P3+/fvb89lbRYTEwMAuOqqq3D27FnMnj27yXCTkZGB9PR0y2uDwYDo6GgkJye32JzWMplMyM7ORlJSEjQaTZuulbdkF346cA5h3fph9NDOLX/AA0nZb2oZ+y0v9lte7Le87Om3+c6LLewKN3fffTcA4KmnnrIcEwQBoihCEATU1tbac1m7iKLY4LbTn2m1Wmi12kbHNRqNw36Bpbh2b10gfjpwDkeKKvkXrQWO/FlSY+y3vNhvebHf8mpNv1vzc7Er3NiyEsoW5eXlOHz4cIPr5ubmIiQkBJ07d0ZGRgZOnz6NxYsXAwDef/99dO7cGX369AFQ/9ybf//733jyySclqceZ9IpoBwA4dLZc4UqIiIhci13hpkuXLpJ88e3bt2PUqFGW1+bbR5MmTcLChQuh1+tx4sQJy/t1dXXIyMhAfn4+vLy80L17d7z22mt4/PHHJanHmfQMDwAAHCwss4yIERERUcvsCjcA8Pnnn+PDDz9Efn4+tm7dii5dumDu3LmIiYmxeaLxyJEj0dx85oULFzZ4/eSTT7rlKI01PcLbQSUAJZUmnCs38gF+RERENrJr48ysrCykp6dj9OjRKCkpscyxad++PebOnStlfR7LR6NG55D61VyHeWuKiIjIZnaFm/feew8ff/wxZs6cCbVabTk+aNAg7NmzR7LiPF0P862ps2UKV0JEROQ67Ao3+fn5DbZBMNNqtaioqGhzUVTPPKn4YCFHboiIiGxlV7iJiYlBbm5uo+Pff/89YmNj21oTXdIron7k5hBHboiIiGxm14TiZ599FtOnT0dVVRVEUUROTg6++uorzJkzB5988onUNXqsnuaRm7PlXDFFRERkI7vCzeTJk1FTU4PnnnvO8jjkjh074p133sE999wjdY0eq3uH+hVTpRe5YoqIiMhWdi8Ff/TRR/Hoo4+iqKgIdXV1CA8Pl7IuQv2KqS6h/sgvqsChs+UMN0RERDawa86NWWFhIfbv34+DBw/i3LlzUtVEV+gZbr41xXk3REREtrAr3BgMBjzwwAOIiorCiBEjcP311yMqKgr3338/SktLpa7Ro10574aIiIhaZle4eeSRR/Drr7/iu+++Q0lJCUpLS/G///0P27dvx6OPPip1jR6NK6aIiIhax645N9999x1++OEHXHfddZZjN998Mz7++GOkpKRIVhxdscfUWe4xRUREZAu7Rm5CQ0MRFBTU6HhQUBCCg4PbXBRd1q2DP1QCYKiqwbkyo9LlEBEROT27ws0LL7yA9PR06PV6y7GCggI8++yz+Mc//iFZcVS/YqprqD8AzrshIiKyhc23pRISEhrcEjl06BC6dOmCzp07AwBOnDgBrVaLc+fO4fHHH5e+Ug/WM6IdjhZV4ODZMlzXM0zpcoiIiJyazeFm3LhxDiyDmtMzPAA/7DuLQ4WcVExERNQSm8PNrFmzHFkHNYPLwYmIiGzXpof4kTzMy8HNK6aIiIioaXYtBVepVM0uSa6trbW7IGqsWwd/qFUCyqpqUFhmREQgt2EgIiJqil3hZsWKFQ1em0wm7Nq1C4sWLUJmZqYkhdFlWi81uoT64ei5+knFDDdERERNsyvcjB07ttGxO+64A/369cPXX3+Nhx9+uM2FUUO9wgMuhZtyDO/ZQelyiIiInJakc26GDBmCH3/8UcpL0iXmScXchoGIiKh5koWbixcv4r333kOnTp2kuiRdoecVk4qJiIioaXbdlgoODm4woVgURZSVlcHPzw9LliyRrDi6rJd55KawnHtMERERNcOucPP22283+MdVpVKhQ4cOGDJkCPeWcpCYsMsrps4ajIgM4qRiIiIia+wKNw8++KDEZVBLtF5qdA31w5FLK6YYboiIiKxrVbjZvXu3Tef179/frmKoeb0iAizh5vpeXDFFRERkTavCzdVXXw1BECxPyTXfmrryqbmCIPAhfg7SM7wdvgdwiNswEBERNalV4SY/P9/y36IoIi4uDmvWrEGXLl0kL4was6yY4gaaRERETWpVuPlziBEEAZ06dWK4kYl5j6nDZ7liioiIqCncONOFxIT5w0sloMxYgwJDldLlEBEROSWGGxfi7aVC1zB/AMBBzrshIiKyqs3hhrdG5NWL2zAQERE1q1VzbhISEhqEmYsXLyItLQ3e3t4Nztu5c6c01VEjPcIDABRwGwYiIqImtCrcjBs3rsFra7uDt8aGDRvwr3/9Czt27IBer8eKFSsafY0rLV++HFlZWcjNzYXRaES/fv0we/Zs3HzzzW2qw5WYR254W4qIiMi6VoWbWbNmSfrFKyoqEB8fj8mTJ2P8+PEtnr9hwwYkJSXh1VdfRfv27fHZZ58hLS0Nv/76KxISEiStzVlZVkxxjykiIiKr7Np+QSqpqalITU21+fy5c+c2eP3qq6/iv//9L1avXu0x4aZraP2KqXJjDfSlVYhq76t0SURERE7F5nCTkpKCF198Eddee22z55WVleGDDz5Au3btMH369DYX2Jy6ujqUlZUhJCSkyXOMRiOMRqPltcFgAACYTCaYTCZJ6zFfT+rrXkkA0DXUD4fPVWD/mRJ08Fc0nypKjn7TZey3vNhvebHf8rKn36051+Z/Ge+8807cddddCAgIwK233opBgwYhKioKPj4+uHDhAvLy8rBp0yasWbMGt9xyC/71r3/ZXIS93nzzTVRUVOCuu+5q8pw5c+YgMzOz0fF169bBz8/PIXVlZ2c75Lpm7epUAFRYtf43lB8SWzzf3Tm639QQ+y0v9lte7Le8WtPvyspKm88VxCs3hmpBdXU1vvnmG3z99dfYuHEjSkpK6i8iCIiNjcXNN9+MRx99FL1797a5AEshgtDihOIrffXVV3jkkUfw3//+FzfddFOT51kbuYmOjkZRURECAwNbXWdzTCYTsrOzkZSUBI1GI+m1r/TeT0fw7s9HMH5AFF67Lc5hX8fZydVvqsd+y4v9lhf7LS97+m0wGBAWFobS0tIW//1u1T0Nb29vTJgwARMmTAAAlJaW4uLFiwgNDZX1l+Hrr7/Gww8/jGXLljUbbABAq9VCq9U2Oq7RaBxWsyOvDQC9dUEAgNyTpVizrxDhAT4YHBMCtcozJxc7ut/UEPstL/ZbXuy3vFrT79b8XNo0YSMoKAhBQUFtuUSrffXVV3jooYfw1VdfYcyYMbJ+bWdx9tLWC0fOVeDppbkAAF2QD2alxSIlTqdgZURERMpTdPuF8vJy5ObmIjc3F0D9ruO5ubk4ceIEACAjIwMTJ060nP/VV19h4sSJePPNNzF06FAUFBSgoKAApaWlSpSviLV79Xj5f3mNjheUVmHqkp1Yu1evQFVERETOQ9Fws337diQkJFiWcaenpyMhIQEvvvgiAECv11uCDgB89NFHqKmpwfTp06HT6Sx/nn76aUXql1ttnYjM1XmwNknKfCxzdR5q6zjJmIiIPJei64hHjhyJ5uYzL1y4sMHrX375xbEFObmc/GLoS5veDVwEoC+tQk5+MRK7h8pXGBERkRPhruAupLCs6WBjz3lERETuyK5wc/LkSZw6dcryOicnBzNmzMD8+fMlK4waCw/wkfQ8IiIid2RXuJkwYQJ+/vlnAEBBQQGSkpKQk5ODv//973jppZckLZAuGxwTAl2QD5pa8C2gftXU4Jimn9hMRETk7uwKN3v37sXgwYMBAP/5z38QFxeHLVu24Msvv2w0T4ako1YJmJUWCwCNAo759ay0WI993g0RERFgZ7gxmUyWB+P9+OOPuPXWWwEAffr0gV7PpciOlBKnQ9b9AxAZ1PDWU2SQD7LuH8Dn3BARkcezK9z069cPH374ITZu3Ijs7GykpKQAAM6cOYPQUK7ScbSUOB02/e0GvDCmLwAg2E+Djc+NYrAhIiKCneHm9ddfx0cffYSRI0fi3nvvRXx8PABg1apVlttV5FhqlYD7h3aBt1qFC5UmnLpwUemSiIiInIJdz7kZOXIkioqKYDAYEBwcbDn+2GOPOWynbWrMR6PG1Z3bIye/GNuOnkfXMH+lSyIiIlKcXSM3Fy9ehNFotASb48ePY+7cuThw4ADCw8MlLZCaN7Rb/W3AbUfPK1wJERGRc7Ar3IwdOxaLFy8GAJSUlGDIkCF48803MW7cOGRlZUlaIDVvaLf6Zd/bjhY3+7RnIiIiT2FXuNm5cyeGDx8OAPjmm28QERGB48ePY/HixXj33XclLZCaN6BzMLzVKhQYqnD8fKXS5RARESnOrnBTWVmJgIAAAMC6detw++23Q6VSYejQoTh+/LikBVLzzPNuAN6aIiIiAuwMNz169MDKlStx8uRJ/PDDD0hOTgYAFBYWIjAwUNICqWWcd0NERHSZXeHmxRdfxDPPPIOuXbti8ODBSExMBFA/ipOQkCBpgdQyzrshIiK6zK6l4HfccQeuu+466PV6yzNuAODGG2/EbbfdJllxZJs/z7vhknAiIvJkdoUbAIiMjERkZCROnToFQRDQsWNHPsBPIXzeDRER0WV23Zaqq6vDSy+9hKCgIHTp0gWdO3dG+/bt8fLLL6Ourk7qGskGnHdDRERUz66Rm5kzZ2LBggV47bXXMGzYMIiiiM2bN2P27NmoqqrCP//5T6nrpBYM7RaCd//v8rwbQeDO4ERE5JnsCjeLFi3CJ598YtkNHADi4+PRsWNHTJs2jeFGAZx3Q0REVM+u21LFxcXo06dPo+N9+vRBcXFxm4ui1uPzboiIiOrZFW7i4+Mxb968RsfnzZvXYPUUyYvzboiIiOy8LfXGG29gzJgx+PHHH5GYmAhBELBlyxacPHkSa9askbpGshHn3RAREdk5cjNixAgcPHgQt912G0pKSlBcXIzbb78dBw4csOw5RfLjPlNERERteM5NVFRUo4nDJ0+exEMPPYRPP/20zYVR6/F5N0RERHaO3DSluLgYixYtkvKS1ErmeTdbOe+GiIg8lKThhpR3eZ+p89xnioiIPBLDjZsxz7s5azDiGOfdEBGRB2K4cTN83g0REXm6Vk0ovv3225t9v6SkpC21kESGdgu1TCq+d3BnpcshIiKSVavCTVBQUIvvT5w4sU0FUdtdft7NeT7vhoiIPE6rws1nn33mqDpIQn+edxPDJeFERORBOOfGDXHeDREReTJFw82GDRuQlpaGqKgoCIKAlStXNnu+Xq/HhAkT0Lt3b6hUKsyYMUOWOl2R+Xk3//v9DP6bexpbj5xHbR2XhhMRkftTNNxUVFQ0uQmnNUajER06dMDMmTO5QWcLVJem2Ww+ch5PL83FvR9vw3Wv/4S1e/XKFkZERORgdm+/IIXU1FSkpqbafH7Xrl3xzjvvAAC3eGjG2r16vPPjoUbHC0qrMHXJTmTdPwApcToFKiMiInI8RcONHIxGI4xGo+W1wWAAAJhMJphMJkm/lvl6Ul+3NWrrRMxetQ/WbkCJAAQAmav3YWTPUKhVrr2Kyhn67UnYb3mx3/Jiv+VlT79bc67bh5s5c+YgMzOz0fF169bBz8/PIV8zOzvbIde1xaFSAQUGdZPviwD0pUbM+3otega5xxwcJfvtidhvebHf8mK/5dWafldW2v7UfbcPNxkZGUhPT7e8NhgMiI6ORnJyMgIDAyX9WiaTCdnZ2UhKSoJGo5H02rZavVsP5O1p8bxu/a7G6P6ufWvKGfrtSdhvebHf8mK/5WVPv813Xmzh9uFGq9VCq9U2Oq7RaBz2C+zIa7dE1962Z9ro2vu7zV9gJfvtidhvebHf8mK/5dWafrfm58Ln3LiZwTEh0AX5oKnZNAIAXZAPBseEyFkWERGRbBQNN+Xl5cjNzUVubi4AID8/H7m5uThx4gSA+ltKf97OwXx+eXk5zp07h9zcXOTl5cldutNSqwTMSosFgCYDzqy0WJefTExERNQURW9Lbd++HaNGjbK8Ns+NmTRpEhYuXAi9Xm8JOmYJCQmW/96xYwe+/PJLdOnSBceOHZOlZleQEqdD1v0DkLk6D/rSKstxrZcK79xzNZeBExGRW1M03IwcORKi2PSKnYULFzY61tz5dFlKnA5JsZHIyS9Gnr4UL/9vP4w1degVEaB0aURERA7FOTduTK0SkNg9FA9f1w039gkHACzeelzhqoiIiByL4cZDPDisKwDgmx2nUG6sUbYYIiIiB2K48RDX9QhD9w7+KDfW4Nsdp5Quh4iIyGEYbjyEIAh48NquAIBFW46hjjuEExGRm2K48SC3D+iEAK0XjhZVYMOhc0qXQ0RE5BAMNx7EX+uFOwdFA6gfvSEiInJHDDceZmJiFwgC8POBc8gvqlC6HCIiIskx3HiYrmH+GNXbvCz8mLLFEBEROQDDjQeadGli8bLtXBZORETuh+HGAw3vEYZul5aFL9/JZeFEROReGG48kEolYFJiVwDAQi4LJyIiN8Nw46HGD+yEdlovHD1XgY83HsV/c09j65HzqGXQISIiF6foxpmknHZaL1wTE4yf/ziHOd//YTmuC/LBrLRY7hxOREQuiyM3HmrtXj1+/qPxg/wKSqswdclOrN2rV6AqIiKitmO48UC1dSIyV+dZfc98UypzdR5vURERkUtiuPFAOfnF0JdWNfm+CEBfWoWc/GL5iiIiIpIIw40HKixrOtjYcx4REZEzYbjxQOEBPpKeR0RE5EwYbjzQ4JgQ6IJ8IDTxvoD6VVODY0LkLIuIiEgSDDceSK0SMCstFgCaDDiz0mKhVjX1LhERkfNiuPFQKXE6ZN0/AJFBjW89PTaiG59zQ0RELosP8fNgKXE6JMVGIie/GIVlVfhpfyH++/sZ5OQXQxRFCAJHboiIyPUw3Hg4tUpAYvdQAMC13cPw/b4C7DpRgpz8YgzpFqpwdURERK3H21Jk0SFAizsGdgIAfLj+iMLVEBER2Yfhhhp4bHg3qATg5wPn8EeBQelyiIiIWo3hhhroGuaP1EuTiT9af1ThaoiIiFqP4YYaeXxENwDAqt/P4NSFSoWrISIiah2GG2qkf6f2uLZ7KGrrRCzYlK90OURERK3CcENWTRnRHQCwNOckLlRUK1wNERGR7RhuyKrhPcMQqwvERVMtFm89rnQ5RERENmO4IasEQbDMvVm09RguVtcqXBEREZFtGG6oSWOu0iE6xBfFFdV4fe0f+G/uaWw9ch61daLSpRERETVJ0XCzYcMGpKWlISoqCoIgYOXKlS1+Zv369Rg4cCB8fHzQrVs3fPjhh44v1EN5qVUY1j0MALBwyzE8vTQX9368Dde9/hPW7tUrXB0REZF1ioabiooKxMfHY968eTadn5+fj9GjR2P48OHYtWsX/v73v+Opp57Ct99+6+BKPdPavXp8/dvJRscLSqswdclOBhwiInJKiu4tlZqaitTUVJvP//DDD9G5c2fMnTsXANC3b19s374d//73vzF+/HgHVemZautEZK7Og7UbUCIAAUDm6jwkxUZCreIGm0RE5DxcauPMrVu3Ijk5ucGxm2++GQsWLIDJZIJGo2n0GaPRCKPRaHltMNRvKWAymWAymSStz3w9qa+rhF/zi6EvrWryfRGAvrQKWw8XYkhMiHyFXcGd+u0K2G95sd/yYr/lZU+/W3OuS4WbgoICRERENDgWERGBmpoaFBUVQafTNfrMnDlzkJmZ2ej4unXr4Ofn55A6s7OzHXJdOe0oEgCoWzxv3cZfcX6/shOM3aHfroT9lhf7LS/2W16t6Xdlpe1PzHepcAPUL1G+kiiKVo+bZWRkID093fLaYDAgOjoaycnJCAwMlLQ2k8mE7OxsJCUlWR1FciWh+cVYfGh7i+clDx+i6MiNu/TbFbDf8mK/5cV+y8uefpvvvNjCpcJNZGQkCgoKGhwrLCyEl5cXQkNDrX5Gq9VCq9U2Oq7RaBz2C+zIa8slsUc4dEE+KCitsjrvBgB0QT5I7BGu+Jwbd+i3K2G/5cV+y4v9lldr+t2an4tLPecmMTGx0RDWunXrMGjQIP4ySkytEjArLRZA/eRhazJS+ygebIiIiP5M0XBTXl6O3Nxc5ObmAqhf6p2bm4sTJ04AqL+lNHHiRMv5U6ZMwfHjx5Geno79+/fj008/xYIFC/DMM88oUb7bS4nTIev+AYgM8mlw3Jxn8vRlClRFRETUPEVvS23fvh2jRo2yvDbPjZk0aRIWLlwIvV5vCToAEBMTgzVr1uAvf/kL3n//fURFReHdd9/lMnAHSonTISk2Ejn5xSgsq0J4gA9KK6sx5Yud+HjjUdwaH4XYKGnnLhEREbWFouFm5MiRlgnB1ixcuLDRsREjRmDnzp0OrIr+TK0SkNi94Zym1LhIfL+3ABnLd2P5tGG8PUVERE7DpebckPOYfWs/BPh44fdTpVi45ZjS5RAREVkw3JBdIgJ98HxqHwDAm+sO4NQF258/QERE5EgMN2S3e6/pjMFdQ1BZXYuZK/Zg65Ei7hxORESKc6nn3JBzUakEvHr7VUiZuwHrDxZh/cEiy3u6IB/MSotFSlzjp0YTERE5EkduqE0OF5ahxsooDXcOJyIipTDckN3MO4dbY447mavzeIuKiIhkxXBDdsuxcefwnPxi+YoiIiKPx3BDdissazrY2HMeERGRFBhuyG7hAT4tn9SK84iIiKTAcEN2GxwTAl2QT5MbawL1q6YGx4TIVhMRERHDDdnNlp3DXxjTl1szEBGRrBhuqE2a2jncHGdOXrgof1FEROTR+BA/ajNrO4efKK7A377dg7ezDyKlXyS6hvkrXSYREXkIjtyQJMw7h4+9uiMSu4firkHRGNYjFMaaOmQs39Ps7u9ERERSYrghhxAEAXNu6w8fjQpbj57Hf7afVLokIiLyEAw35DCdQ/3w16TeAIB/frcfhQY+74aIiByP4YYcavKwrriqYxAMVTWYtWofautEbD1ynruHExGRw3BCMTmUl1qF18ZfhVvnbcb3ewsw8JVslFSaLO9z93AiIpIaR27I4fpFBeGmvuEA0CDYANw9nIiIpMdwQw5XWyfi95MlVt/j7uFERCQ1hhtyuJz8YhQYjE2+z93DiYhISgw35HDcPZyIiOTEcEMOx93DiYhITlwtRQ5n3j28oLQKTc2qCfX3tuweXlsnNtjKYXBMCDffJCIimzHckMOZdw+fumQnBMBqwCmuqEbWL4fRLawdXv4uD/rSy7eouFyciIhag7elSBZN7R4eGeiDITEhEAH8e91BTPtyZ4NgA3C5OBERtQ5Hbkg21nYPN99y+vq3E/jbt3usfk4EIKB+uXhSbCRvURERUbMYbkhW5t3D/6xziH+zn7tyubi1zxMREZnxthQ5BS4XJyIiqTDckFPgcnEiIpIKww05BfNy8eZm0/hr1Ujo3B5A/XLxX/OLsaNIwK/5xdy6gYiILDjnhpyCLcvFK4y1uGf+NtwxsBPe//nwpVVVaiw+tJ3LxYmIyELxkZsPPvgAMTEx8PHxwcCBA7Fx48Zmz3///ffRt29f+Pr6onfv3li8eLFMlZKjNbVcXBfkg8evj0GgjxdyT5bghZV7uVyciIiapOjIzddff40ZM2bggw8+wLBhw/DRRx8hNTUVeXl56Ny5c6Pzs7KykJGRgY8//hjXXHMNcnJy8OijjyI4OBhpaWkKfAckteaWi08Y0gU3vbUeptrG4zpcLk5ERGaKjty89dZbePjhh/HII4+gb9++mDt3LqKjo5GVlWX1/M8//xyPP/447r77bnTr1g333HMPHn74Ybz++usyV06OZF4uPvbqjkjsHmoJKmdKqqwGGzPuLk5ERICC4aa6uho7duxAcnJyg+PJycnYsmWL1c8YjUb4+DS8ZeHr64ucnByYTCaH1UrOgcvFiYjIFordlioqKkJtbS0iIiIaHI+IiEBBQYHVz9x888345JNPMG7cOAwYMAA7duzAp59+CpPJhKKiIuh0jSeTGo1GGI1Gy2uDwQAAMJlMkgci8/UYtBwj1M+2X9dQPy/+DByAv9/yYr/lxX7Ly55+t+ZcxVdLCULDuRGiKDY6ZvaPf/wDBQUFGDp0KERRREREBB588EG88cYbUKvVVj8zZ84cZGZmNjq+bt06+Pn5tf0bsCI7O9sh1/V0dSLQ3luNkmoATSwa16pEnN23DWv2y1qaR+Hvt7zYb3mx3/JqTb8rKyttPlexcBMWFga1Wt1olKawsLDRaI6Zr68vPv30U3z00Uc4e/YsdDod5s+fj4CAAISFhVn9TEZGBtLT0y2vDQYDoqOjkZycjMDAQOm+IdSnyuzsbCQlJUGj0Uh6baqn6XoWTy79HYD15eLGOgGrL0TirTv7w89bje3HL6CwzIjwAC0GdQnmROM24O+3vNhvebHf8rKn3+Y7L7ZQLNx4e3tj4MCByM7Oxm233WY5np2djbFjxzb7WY1Gg06dOgEAli5diltuuQUqlfXpQ1qtFlqt1uo1HPUL7Mhre7pbru4ELy81MlfnNVgOrgvyweirdFiy7Th+OViEMfO2oKZWxLlyY4Nz+CyctuPvt7zYb3mx3/JqTb9b83NR9LZUeno6HnjgAQwaNAiJiYmYP38+Tpw4gSlTpgCoH3U5ffq05Vk2Bw8eRE5ODoYMGYILFy7grbfewt69e7Fo0SIlvw2SmXm5+NbDhVi38VckDx+CxB7hUKsE3BofhQcW/NroOTjA5WfhZN0/wBJwautEq8vOiYjIdSkabu6++26cP38eL730EvR6PeLi4rBmzRp06dIFAKDX63HixAnL+bW1tXjzzTdx4MABaDQajBo1Clu2bEHXrl0V+g5IKWqVgCExITi/X8SQKwJJXMcg+GjUMFTVNPrMn5+Fk51XYHUEiKM7RESuTfEJxdOmTcO0adOsvrdw4cIGr/v27Ytdu3bJUBW5qvpRGGOT75ufhfPG2v2YvyG/0bwda6M7RETkWhTffoFISrY+4+YjK8EGuDxJOXN1HjfjJCJyUQw35FbCA3xaPqkF1p50XFsnYuuR8/hv7mlsPXKewYeIyIkpfluKSEqDY0KgC/JBQWmV1ZEZAUCQrwYlF1t+GFRB6UUAwNq9es7NISJyIRy5IbeiVgmYlRYLoPFj/syvJw/ratO1/vndfjyz7HdMXbLTpl3IObpDROQcOHJDbiclToes+wc0Gm2JvDTakhQbiaW/nWxydAcABAEoqqjGNztOWX2fK6+IiJwXww25JfOzcJp6hs2stFhMXbITAho+6dg8uvPO3Vdj96lSfLIpv8mvYZ6bM++nw5j740GuvCIichIMN+S21CoBid1Drb7X0uhOSpyuyVGdP8taf7jJlVdXju6oVQIfGkhEJAOGG/JYLY3u2LryqspU1+R7V668Kr1YzVtXREQyYLghj9bc6E5LK68AwFejwsVmwo1Zdl4BPtt8zKZbVxzdISJqG4YboiaYV141NzdnyojuePvHQy1ea9HW4zbduuLEZCKituNScKJmmOfmRAY1vEUVGeSDrPsH4IkbekIX5NNo2fmfNbcs/MqJyVx2TkTUdhy5IWpBW1de3TM4Gl/lnGzx68z7+RBHd4iIJMCRGyIbmOfmjL26IxK7hzaYA9PS6M6t8R1t+hqmWmlHdwCO8BCRZ+LIDZEEmhvdqa0TW5yY7O+tRkV1bYtf572fbBvdUasEm7eN4ARmInI3DDdEEmlq5ZUtE5Mfu76bTROTa2yYu/N/+8+itk7EtC92trg6qzUB6Nf8YuwoEhCaX4zEHuEMQETktBhuiGTQ1i0hBADttF4oM9a0+LUe+3xHoxBlduUIT10dMP3L1gYgNRYf2s4RICJyagw3RDJp68TkR4bH2DS6A1gPNle+py+twoyvcx0UgOq1JQAxKBFRWzDcEMmoLVtC2DK6Exnkg78k9cJz3+xusZbq2pafrPz88t2yByApgxJDEpFnYrghciJtHd2ZlRaLIF9vyeoxVDV9G8wcgJ77VtoANHWJNEFJiZDEMEXkHBhuiJxMWzf8bGl1lgAg2F+D4gqTJPWWNzMP6PItsF1NBiCgPgDd0CcCmavzJAlKAGQPSVKHqZYmcMsdyhjcyJUIoih61IMvDAYDgoKCUFpaisDAQEmvbTKZsGbNGowePRoajUbSa1Njntzvlv6hMY+AANZHeN6fkICXv9svWwCyhVYtwNjMs37M2mm9mgxUAoCIQC0AAQWGqibPiQzywT/GxFoNSeYeNReSrjynuREna+dJEabkDmVyj4LJHcpq60RsPVyIdRt/RfLwIS4TJl2134B9//9uzb/fDDcS8uR/bJXAfjevpX+QXDEASamdVo1yY9PPFurQzhsQBJwrM1p93xyS1j87CiP+9XOjByv++TypwpRU59gaylpzLVcMZaxb/hAMMNxIjuHGfbDfLbNlhMdZAtCUEd3w4fqjrf8mFRbsp8GFypa/P1+NGhdNTYep9r5egCCgpJlrhbXzhtBC4LJ15MqWUCb3KJgt50gZyuQ8h3UPaBBwGG4kxnDjPthvaThDALryH1t3HSlyNh3aeeNcebUk19J6qWCsaXr1nb+3GoIgNDs/K0CrBgQBZc1MYg/y1eBvqb3x+vcHUHqx6d+DIF8vAEKz57T39YIgCM0G02A/DQQIKK5suk8hfhpAEFBc0fQ5oe288f6EAZj+xU6cb+48//prnW/m5xLm7w0IQFFz57SrX1TQ3DkdLp3T3O9AeIAWSx4egvs++RXnyq0H6svXEpo8x/x3fNPfbrD8v8XR4YYTiok8XHMTmIHLK7iampNgyyRnlUpocZWXt5eqxdVgr4yNazEomUcbzhrkCUmTErtg0dbjklxLTlIFGwDNBhsANm0tUtbMLUKz0osm/H35XhvOa/lhlyU2nGPLiFyxDeecL6/GPfO3tXyeDb+TRc2EI8s5Nvxsbfn5F5YZkTx3Q5uvZV5YkJNf3Oz/a6TEjTOJqEVqlYAhMSEYGCZiiJUJgilxOmz62w346tGheOeeq/HVo0Ox6W83WIahW9pc1NbzRvePwqy0WACXA4+Z+fXsW/th9q3Nn/PK2DjognwavX/leZGBWkQGNn+OLsgHM8fEtnitEH/nG1m8b0i00iXYJaq9T8snOSF/rVrpEuziJeGKuMIy67c3HYEjN0QkCVtHgFpaSdHSebaMFAFo82jS7Fv7AYBTjThJdU59H+Lw0x/nnGoUzBYPD4vBy9/tl+3rSSX9pl4uWXdGah/J6g4PkC+YMtwQkWxaCkC2nmdLUJIrJNl6LSnClFTn2BrKbLmWnMEtMsgHDyR2xSeb8p0mKLJu2681OCbEyruOwXBDRC7JlqAkR0iy9Twpw5ScocyWa8kV3KQMZa4aJl217llpsbI+9JGrpSTE1TvyYr/lxX5Lw10fKueqz11h3XzOjVtguHEf7Le82G95uWK/XfWJua4YJl253wCXghMRkYuQ4lahredI/fWGxITg/H7rqwGduW5X7LccFF8K/sEHHyAmJgY+Pj4YOHAgNm7c2Oz5X3zxBeLj4+Hn5wedTofJkyfj/PnzMlVLREREzk7RcPP1119jxowZmDlzJnbt2oXhw4cjNTUVJ06csHr+pk2bMHHiRDz88MPYt28fli1bht9++w2PPPKIzJUTERGRs1I03Lz11lt4+OGH8cgjj6Bv376YO3cuoqOjkZWVZfX8bdu2oWvXrnjqqacQExOD6667Do8//ji2b98uc+VERETkrBQLN9XV1dixYweSk5MbHE9OTsaWLVusfubaa6/FqVOnsGbNGoiiiLNnz+Kbb77BmDFj5CiZiIiIXIBiE4qLiopQW1uLiIiIBscjIiJQUFBg9TPXXnstvvjiC9x9992oqqpCTU0Nbr31Vrz33ntNfh2j0Qij8fJmXgaDAUD9TG2TSdqnapqvJ/V1yTr2W17st7zYb3mx3/Kyp9+tOVfx1VKC0HBWuiiKjY6Z5eXl4amnnsKLL76Im2++GXq9Hs8++yymTJmCBQsWWP3MnDlzkJmZ2ej4unXr4Ofn1/ZvwIrs7GyHXJesY7/lxX7Li/2WF/str9b0u7Ky0uZzFXvOTXV1Nfz8/LBs2TLcdtttluNPP/00cnNzsX79+kafeeCBB1BVVYVly5ZZjm3atAnDhw/HmTNnoNPpGn3G2shNdHQ0ioqKHPKcm+zsbCQlJbnMcylcGfstL/ZbXuy3vNhvednTb4PBgLCwMOd+zo23tzcGDhyI7OzsBuEmOzsbY8eOtfqZyspKeHk1LFmtrt9ptamMptVqodVqGx3XaDQO+wV25LWpMfZbXuy3vNhvebHf8mpNv1vzc1F0tVR6ejo++eQTfPrpp9i/fz/+8pe/4MSJE5gyZQoAICMjAxMnTrScn5aWhuXLlyMrKwtHjx7F5s2b8dRTT2Hw4MGIiopS6tsgIiIiJ6LonJu7774b58+fx0svvQS9Xo+4uDisWbMGXbp0AQDo9foGz7x58MEHUVZWhnnz5uGvf/0r2rdvjxtuuAGvv/66zV/TPMJjnlgsJZPJhMrKShgMBiZ/GbDf8mK/5cV+y4v9lpc9/Tb/u23LbBqP21vq1KlTiI6OVroMIiIissPJkyfRqVOnZs/xuHBTV1eHM2fOICAgoMlVWfYyT1Y+efKk5JOVqTH2W17st7zYb3mx3/Kyp9+iKKKsrAxRUVFQqZqfVaP4UnC5qVSqFhNfWwUGBvIvh4zYb3mx3/Jiv+XFfsurtf0OCgqy6TzFN84kIiIikhLDDREREbkVhhsJabVazJo1y+pzdUh67Le82G95sd/yYr/l5eh+e9yEYiIiInJvHLkhIiIit8JwQ0RERG6F4YaIiIjcCsONRD744APExMTAx8cHAwcOxMaNG5UuyW1s2LABaWlpiIqKgiAIWLlyZYP3RVHE7NmzERUVBV9fX4wcORL79u1TplgXN2fOHFxzzTUICAhAeHg4xo0bhwMHDjQ4h/2WTlZWFvr372951kdiYiK+//57y/vstWPNmTMHgiBgxowZlmPsuXRmz54NQRAa/ImMjLS878heM9xI4Ouvv8aMGTMwc+ZM7Nq1C8OHD0dqamqDfbHIfhUVFYiPj8e8efOsvv/GG2/grbfewrx58/Dbb78hMjISSUlJKCsrk7lS17d+/XpMnz4d27ZtQ3Z2NmpqapCcnIyKigrLOey3dDp16oTXXnsN27dvx/bt23HDDTdg7Nixlv/Bs9eO89tvv2H+/Pno379/g+PsubT69esHvV5v+bNnzx7Lew7ttUhtNnjwYHHKlCkNjvXp00d8/vnnFarIfQEQV6xYYXldV1cnRkZGiq+99prlWFVVlRgUFCR++OGHClToXgoLC0UA4vr160VRZL/lEBwcLH7yySfstQOVlZWJPXv2FLOzs8URI0aITz/9tCiK/P2W2qxZs8T4+Hir7zm61xy5aaPq6mrs2LEDycnJDY4nJydjy5YtClXlOfLz81FQUNCg/1qtFiNGjGD/JVBaWgoACAkJAcB+O1JtbS2WLl2KiooKJCYmstcONH36dIwZMwY33XRTg+PsufQOHTqEqKgoxMTE4J577sHRo0cBOL7XHre3lNSKiopQW1uLiIiIBscjIiJQUFCgUFWew9xja/0/fvy4EiW5DVEUkZ6ejuuuuw5xcXEA2G9H2LNnDxITE1FVVYV27dphxYoViI2NtfwPnr2W1tKlS7Fz50789ttvjd7j77e0hgwZgsWLF6NXr144e/YsXnnlFVx77bXYt2+fw3vNcCORP+8wLoqi5LuOU9PYf+k98cQT2L17NzZt2tToPfZbOr1790Zubi5KSkrw7bffYtKkSVi/fr3lffZaOidPnsTTTz+NdevWwcfHp8nz2HNppKamWv77qquuQmJiIrp3745FixZh6NChABzXa96WaqOwsDCo1epGozSFhYWNEilJzzzznv2X1pNPPolVq1bh559/RqdOnSzH2W/peXt7o0ePHhg0aBDmzJmD+Ph4vPPOO+y1A+zYsQOFhYUYOHAgvLy84OXlhfXr1+Pdd9+Fl5eXpa/suWP4+/vjqquuwqFDhxz++81w00be3t4YOHAgsrOzGxzPzs7Gtddeq1BVniMmJgaRkZEN+l9dXY3169ez/3YQRRFPPPEEli9fjp9++gkxMTEN3me/HU8URRiNRvbaAW688Ubs2bMHubm5lj+DBg3Cfffdh9zcXHTr1o09dyCj0Yj9+/dDp9M5/ve7zVOSSVy6dKmo0WjEBQsWiHl5eeKMGTNEf39/8dixY0qX5hbKysrEXbt2ibt27RIBiG+99Za4a9cu8fjx46IoiuJrr70mBgUFicuXLxf37Nkj3nvvvaJOpxMNBoPClbueqVOnikFBQeIvv/wi6vV6y5/KykrLOey3dDIyMsQNGzaI+fn54u7du8W///3vokqlEtetWyeKInsthytXS4kiey6lv/71r+Ivv/wiHj16VNy2bZt4yy23iAEBAZZ/Gx3Za4Ybibz//vtily5dRG9vb3HAgAGWpbPUdj///LMIoNGfSZMmiaJYv6Rw1qxZYmRkpKjVasXrr79e3LNnj7JFuyhrfQYgfvbZZ5Zz2G/pPPTQQ5b/b3To0EG88cYbLcFGFNlrOfw53LDn0rn77rtFnU4najQaMSoqSrz99tvFffv2Wd53ZK+5KzgRERG5Fc65ISIiIrfCcENERERuheGGiIiI3ArDDREREbkVhhsiIiJyKww3RERE5FYYboiIiMitMNwQERGRW2G4ISJC/e7EK1euVLoMIpIAww0RKe7BBx+EIAiN/qSkpChdGhG5IC+lCyAiAoCUlBR89tlnDY5ptVqFqiEiV8aRGyJyClqtFpGRkQ3+BAcHA6i/ZZSVlYXU1FT4+voiJiYGy5Yta/D5PXv24IYbboCvry9CQ0Px2GOPoby8vME5n376Kfr16wetVgudTocnnniiwftFRUW47bbb4Ofnh549e2LVqlWO/aaJyCEYbojIJfzjH//A+PHj8fvvv+P+++/Hvffei/379wMAKisrkZKSguDgYPz2229YtmwZfvzxxwbhJSsrC9OnT8djjz2GPXv2YNWqVejRo0eDr5GZmYm77roLu3fvxujRo3HfffehuLhY1u+TiCQgyd7iRERtMGnSJFGtVov+/v4N/rz00kuiKIoiAHHKlCkNPjNkyBBx6tSpoiiK4vz588Xg4GCxvLzc8v53330nqlQqsaCgQBRFUYyKihJnzpzZZA0AxBdeeMHyury8XBQEQfz+++8l+z6JSB6cc0NETmHUqFHIyspqcCwkJMTy34mJiQ3eS0xMRG5uLgBg//79iI+Ph7+/v+X9YcOGoa6uDgcOHIAgCDhz5gxuvPHGZmvo37+/5b/9/f0REBCAwsJCe78lIlIIww0ROQV/f/9Gt4laIggCAEAURct/WzvH19fXputpNJpGn62rq2tVTUSkPM65ISKXsG3btkav+/TpAwCIjY1Fbm4uKioqLO9v3rwZKpUKvXr1QkBAALp27Yr/+7//k7VmIlIGR26IyCkYjUYUFBQ0OObl5YWwsDAAwLJlyzBo0CBcd911+OKLL5CTk4MFCxYAAO677z7MmjULkyZNwuzZs3Hu3Dk8+eSTeOCBBxAREQEAmD17NqZMmYLw8HCkpqairKwMmzdvxpNPPinvN0pEDsdwQ0ROYe3atdDpdA2O9e7dG3/88QeA+pVMS5cuxbRp0xAZGYkvvvgCsbGxAAA/Pz/88MMPePrpp3HNNdfAz88P48ePx1tvvWW51qRJk1BVVYW3334bzzzzDMLCwnDHHXfI9w0SkWwEURRFpYsgImqOIAhYsWIFxo0bp3QpROQCOOeGiIiI3ArDDREREbkVzrkhIqfHu+dE1BocuSEiIiK3wnBDREREboXhhoiIiNwKww0RERG5FYYbIiIicisMN0RERORWGG6IiIjIrTDcEBERkVthuCEiIiK38v+5I8uzhvuV1AAAAABJRU5ErkJggg==",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"plt.plot(history.history[\"loss\"], \"o-\", label = \"Training Loss\")\n",
"plt.xlabel(\"Epoch\")\n",
"# plt.yscale('log')\n",
"plt.ylabel(\"Loss (Huber)\")\n",
"plt.grid('on')\n",
"\n",
"plt.savefig(\"loss_all.png\", dpi=300)\n"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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3tERbR/kR9yWDsBSba015Mkxbd2a7+lxnqxr1J7jfF0j6diA1dpxsy8eKkkBO5enn3f68fFtrgbuyVythO+D37Pr8nw+V7B/XketPSG24e+alQg8AIKCJ8HJk+PMCk+eHBPogGX2uTw5prOGtc76eR219lkZKZavx8OkZRMxedYa9N0a9N087VnUrbXJ4u09V6AWpAv2tWU64ud11Nrbi7u0fEDgCT703Rr03Rqdte+dffVgM4ImKy23n5mBh0taAAC/M2Oultnnas/njU2O0+Edzd+V6I/P62jnMvPzrMJdWgAAIOgReAAAQNAj8AAAgKBneeB58sknlZycrIiICI0aNUpr165t9fiXXnpJI0aMUGRkpBITE3X99dfr8OHDAaoWAAB0RpYGnldffVUzZszQfffdp82bN+vss89Wenq69u9v/iF/69at09SpU3XDDTdo27Zteu211/T555/rxhtvDHDlAACgM7E08Dz66KO64YYbdOONN+qUU07RY489pv79+2v+/PnNHv/pp59q0KBBuvPOO5WcnKyzzjpLN998szZs2BDgygEAQGdi2W3pR48e1caNG3Xvvfc22j5x4kStX7++2fecccYZuu+++7RixQqlp6ersLBQr7/+ui688MIWP6empkY1NT88abi0tFRSw739TmfbT0ZuD9f5zD4vWkffrUHfrUHfrUHfrXFs333tvWULD37zzTfq27evPv74Y51xxhnu7Q8++KBefPFF7dy5s9n3vf7667r++utVXV2t2tpaXXzxxXr99ddbXIBr9uzZysrKarL95ZdfVmRkYJ++CwAAvFNZWakpU6Z03oUHbbbGCzgZhtFkm8v27dt155136k9/+pPOP/985efn65577tEtt9yi5557rtn3zJw5U5mZme7XpaWl6t+/vyZOnOiXlZazs7M1YcKETrUCamdH361B361B361B361xbN+rqqp8Opdlgadnz54KDQ1VQUFBo+2FhYXq06dPs++ZO3euzjzzTN1zzz2SpOHDhysqKkpnn3225syZo8TEps/qcDgccjgc7teuAa2qqirTf2idTqcqKytVVVWl2tpaU8+NltF3a9B3a9B3a9B3axzbd1fg8fbClGWBJzw8XKNGjVJ2drYuvfRS9/bs7Gxdcsklzb6nsrJSYWGNSw4NDZXkeQPKysokSf379/embAAAYKGy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",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"plt.plot(history.history[\"loss\"][1:], \"o-\", label = \"Training Loss\")\n",
"plt.xlabel(\"Epoch\")\n",
"# plt.yscale('log')\n",
"plt.ylabel(\"Loss (Huber)\")\n",
"plt.grid('on')\n",
"plt.savefig(\"loss_1_to_end.png\", dpi=300)\n"
]
},
{
"cell_type": "code",
"execution_count": 42,
"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>H</th>\n",
" <th>O</th>\n",
" <th>Charge</th>\n",
" <th>H_0_</th>\n",
" <th>O_0_</th>\n",
" <th>Ba</th>\n",
" <th>Cl</th>\n",
" <th>S_2_</th>\n",
" <th>S_6_</th>\n",
" <th>Sr</th>\n",
" <th>Barite</th>\n",
" <th>Celestite</th>\n",
" <th>Class</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>111.012434</td>\n",
" <td>55.508192</td>\n",
" <td>-7.779554e-09</td>\n",
" <td>2.697041e-26</td>\n",
" <td>2.210590e-15</td>\n",
" <td>2.041069e-02</td>\n",
" <td>4.082138e-02</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0.000494</td>\n",
" <td>0.000494</td>\n",
" <td>0.001</td>\n",
" <td>1.000000</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>111.012434</td>\n",
" <td>55.508427</td>\n",
" <td>-4.736083e-09</td>\n",
" <td>1.446346e-26</td>\n",
" <td>2.473481e-15</td>\n",
" <td>1.094567e-02</td>\n",
" <td>2.189133e-02</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0.000553</td>\n",
" <td>0.000553</td>\n",
" <td>0.001</td>\n",
" <td>1.000000</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>111.012434</td>\n",
" <td>55.508691</td>\n",
" <td>-1.311169e-09</td>\n",
" <td>3.889826e-28</td>\n",
" <td>2.769320e-15</td>\n",
" <td>2.943745e-04</td>\n",
" <td>5.887491e-04</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0.000619</td>\n",
" <td>0.000619</td>\n",
" <td>0.001</td>\n",
" <td>1.000000</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>111.012434</td>\n",
" <td>55.508698</td>\n",
" <td>-1.220023e-09</td>\n",
" <td>1.442658e-29</td>\n",
" <td>2.777193e-15</td>\n",
" <td>1.091776e-05</td>\n",
" <td>2.183551e-05</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0.000620</td>\n",
" <td>0.000620</td>\n",
" <td>0.001</td>\n",
" <td>1.000000</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>111.012434</td>\n",
" <td>55.508699</td>\n",
" <td>-1.216643e-09</td>\n",
" <td>5.350528e-31</td>\n",
" <td>2.777485e-15</td>\n",
" <td>4.049176e-07</td>\n",
" <td>8.098352e-07</td>\n",
" <td>0.000000e+00</td>\n",
" <td>0.000620</td>\n",
" <td>0.000620</td>\n",
" <td>0.001</td>\n",
" <td>1.000000</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2502495</th>\n",
" <td>111.012434</td>\n",
" <td>55.507488</td>\n",
" <td>3.573728e-09</td>\n",
" <td>5.424062e-145</td>\n",
" <td>1.375204e-10</td>\n",
" <td>9.953520e-07</td>\n",
" <td>2.266555e-03</td>\n",
" <td>5.509534e-149</td>\n",
" <td>0.000318</td>\n",
" <td>0.001450</td>\n",
" <td>0.001</td>\n",
" <td>1.000014</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2502496</th>\n",
" <td>111.012434</td>\n",
" <td>55.507501</td>\n",
" <td>3.494007e-09</td>\n",
" <td>2.011675e-146</td>\n",
" <td>1.377139e-10</td>\n",
" <td>9.817216e-07</td>\n",
" <td>2.217997e-03</td>\n",
" <td>2.043375e-150</td>\n",
" <td>0.000321</td>\n",
" <td>0.001429</td>\n",
" <td>0.001</td>\n",
" <td>1.000010</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2502497</th>\n",
" <td>111.012434</td>\n",
" <td>55.507512</td>\n",
" <td>3.429764e-09</td>\n",
" <td>7.460897e-148</td>\n",
" <td>1.377819e-10</td>\n",
" <td>9.706451e-07</td>\n",
" <td>2.179066e-03</td>\n",
" <td>7.578467e-152</td>\n",
" <td>0.000324</td>\n",
" <td>0.001412</td>\n",
" <td>0.001</td>\n",
" <td>1.000006</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2502498</th>\n",
" <td>111.012434</td>\n",
" <td>55.507520</td>\n",
" <td>3.381745e-09</td>\n",
" <td>2.767237e-149</td>\n",
" <td>1.371144e-10</td>\n",
" <td>9.621074e-07</td>\n",
" <td>2.149820e-03</td>\n",
" <td>2.810844e-153</td>\n",
" <td>0.000326</td>\n",
" <td>0.001400</td>\n",
" <td>0.001</td>\n",
" <td>1.000004</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2502499</th>\n",
" <td>111.012434</td>\n",
" <td>55.507525</td>\n",
" <td>3.348864e-09</td>\n",
" <td>5.321610e-151</td>\n",
" <td>1.376026e-10</td>\n",
" <td>9.564401e-07</td>\n",
" <td>2.129912e-03</td>\n",
" <td>5.405468e-155</td>\n",
" <td>0.000327</td>\n",
" <td>0.001391</td>\n",
" <td>0.001</td>\n",
" <td>1.000001</td>\n",
" <td>0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>2502500 rows × 13 columns</p>\n",
"</div>"
],
"text/plain": [
" H O Charge H_0_ O_0_ \\\n",
"0 111.012434 55.508192 -7.779554e-09 2.697041e-26 2.210590e-15 \n",
"1 111.012434 55.508427 -4.736083e-09 1.446346e-26 2.473481e-15 \n",
"2 111.012434 55.508691 -1.311169e-09 3.889826e-28 2.769320e-15 \n",
"3 111.012434 55.508698 -1.220023e-09 1.442658e-29 2.777193e-15 \n",
"4 111.012434 55.508699 -1.216643e-09 5.350528e-31 2.777485e-15 \n",
"... ... ... ... ... ... \n",
"2502495 111.012434 55.507488 3.573728e-09 5.424062e-145 1.375204e-10 \n",
"2502496 111.012434 55.507501 3.494007e-09 2.011675e-146 1.377139e-10 \n",
"2502497 111.012434 55.507512 3.429764e-09 7.460897e-148 1.377819e-10 \n",
"2502498 111.012434 55.507520 3.381745e-09 2.767237e-149 1.371144e-10 \n",
"2502499 111.012434 55.507525 3.348864e-09 5.321610e-151 1.376026e-10 \n",
"\n",
" Ba Cl S_2_ S_6_ Sr \\\n",
"0 2.041069e-02 4.082138e-02 0.000000e+00 0.000494 0.000494 \n",
"1 1.094567e-02 2.189133e-02 0.000000e+00 0.000553 0.000553 \n",
"2 2.943745e-04 5.887491e-04 0.000000e+00 0.000619 0.000619 \n",
"3 1.091776e-05 2.183551e-05 0.000000e+00 0.000620 0.000620 \n",
"4 4.049176e-07 8.098352e-07 0.000000e+00 0.000620 0.000620 \n",
"... ... ... ... ... ... \n",
"2502495 9.953520e-07 2.266555e-03 5.509534e-149 0.000318 0.001450 \n",
"2502496 9.817216e-07 2.217997e-03 2.043375e-150 0.000321 0.001429 \n",
"2502497 9.706451e-07 2.179066e-03 7.578467e-152 0.000324 0.001412 \n",
"2502498 9.621074e-07 2.149820e-03 2.810844e-153 0.000326 0.001400 \n",
"2502499 9.564401e-07 2.129912e-03 5.405468e-155 0.000327 0.001391 \n",
"\n",
" Barite Celestite Class \n",
"0 0.001 1.000000 0 \n",
"1 0.001 1.000000 0 \n",
"2 0.001 1.000000 0 \n",
"3 0.001 1.000000 0 \n",
"4 0.001 1.000000 0 \n",
"... ... ... ... \n",
"2502495 0.001 1.000014 0 \n",
"2502496 0.001 1.000010 0 \n",
"2502497 0.001 1.000006 0 \n",
"2502498 0.001 1.000004 0 \n",
"2502499 0.001 1.000001 0 \n",
"\n",
"[2502500 rows x 13 columns]"
]
},
"execution_count": 42,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df_design"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Test the model"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[1m15641/15641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 336us/step - loss: 6.6414e-07\n"
]
},
{
"data": {
"text/plain": [
"8.585521982240607e-07"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# test on all test data\n",
"model.evaluate(X_test.iloc[:,:-1], y_test)"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[1m15454/15454\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m5s\u001b[0m 331us/step - loss: 2.7927e-07\n"
]
},
{
"data": {
"text/plain": [
"3.939527175589319e-07"
]
},
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# test on non-reactive data\n",
"model.evaluate(X_test[X_test['Class'] == 0].iloc[:,:-1], y_test[X_test['Class'] == 0])"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[1m188/188\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 400us/step - loss: 3.3173e-05\n"
]
},
{
"data": {
"text/plain": [
"3.921399184037e-05"
]
},
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# test on reactive data\n",
"model.evaluate(X_test[X_test['Class'] == 1].iloc[:,:-1], y_test[X_test['Class'] == 1])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Save the model"
]
},
{
"cell_type": "code",
"execution_count": 53,
"metadata": {},
"outputs": [],
"source": [
"# Save the model\n",
"model.save(\"Barite_50_Model_additional_species.keras\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "training",
"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.11.11"
}
},
"nbformat": 4,
"nbformat_minor": 2
}