From a0145576f4e3e0e4c10a4a97c66f2b060784f45d Mon Sep 17 00:00:00 2001 From: Hannes Signer Date: Tue, 11 Feb 2025 17:17:43 +0100 Subject: [PATCH] add new model architecture --- POET_Training.ipynb | 488 ++++++++++++++++++++++++++++++++------------ preprocessing.py | 4 +- 2 files changed, 361 insertions(+), 131 deletions(-) diff --git a/POET_Training.ipynb b/POET_Training.ipynb index 20450db..65767b4 100644 --- a/POET_Training.ipynb +++ b/POET_Training.ipynb @@ -34,8 +34,8 @@ "name": "stderr", "output_type": "stream", "text": [ - "2025-01-23 14:37:53.766781: I tensorflow/core/util/port.cc:153] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.\n", - "2025-01-23 14:37:53.786741: I tensorflow/core/platform/cpu_feature_guard.cc:210] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.\n", + "2025-02-11 15:40:37.253319: I tensorflow/core/util/port.cc:153] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.\n", + "2025-02-11 15:40:37.275142: I tensorflow/core/platform/cpu_feature_guard.cc:210] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.\n", "To enable the following instructions: SSE4.1 SSE4.2 AVX AVX2 AVX_VNNI FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags.\n" ] }, @@ -77,7 +77,7 @@ }, { "cell_type": "code", - "execution_count": 40, + "execution_count": 85, "metadata": {}, "outputs": [], "source": [ @@ -97,6 +97,8 @@ "\n", "optimizer_simple = keras.optimizers.Adam(learning_rate=lr_schedule)\n", "optimizer_large = keras.optimizers.Adam(learning_rate=lr_schedule)\n", + "optimizer_paper = keras.optimizers.Adam(learning_rate=lr_schedule)\n", + "\n", "\n", "loss = keras.losses.MeanSquaredError()\n", "\n", @@ -112,17 +114,17 @@ }, { "cell_type": "code", - "execution_count": 41, + "execution_count": 86, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
Model: \"sequential_2\"\n",
+       "
Model: \"sequential_4\"\n",
        "
\n" ], "text/plain": [ - "\u001b[1mModel: \"sequential_2\"\u001b[0m\n" + "\u001b[1mModel: \"sequential_4\"\u001b[0m\n" ] }, "metadata": {}, @@ -134,11 +136,11 @@ "
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
        "┃ Layer (type)                     Output Shape                  Param # ┃\n",
        "┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
-       "│ dense_7 (Dense)                 │ (None, 128)            │         1,664 │\n",
+       "│ dense_17 (Dense)                │ (None, 128)            │         1,664 │\n",
        "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
-       "│ dense_8 (Dense)                 │ (None, 128)            │        16,512 │\n",
+       "│ dense_18 (Dense)                │ (None, 128)            │        16,512 │\n",
        "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
-       "│ dense_9 (Dense)                 │ (None, 12)             │         1,548 │\n",
+       "│ dense_19 (Dense)                │ (None, 12)             │         1,548 │\n",
        "└─────────────────────────────────┴────────────────────────┴───────────────┘\n",
        "
\n" ], @@ -146,11 +148,11 @@ "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\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_7 (\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", + "│ dense_17 (\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_8 (\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", + "│ dense_18 (\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_9 (\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", + "│ dense_19 (\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" ] }, @@ -214,17 +216,17 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 87, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
Model: \"sequential_1\"\n",
+       "
Model: \"sequential_5\"\n",
        "
\n" ], "text/plain": [ - "\u001b[1mModel: \"sequential_1\"\u001b[0m\n" + "\u001b[1mModel: \"sequential_5\"\u001b[0m\n" ] }, "metadata": {}, @@ -236,13 +238,13 @@ "
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
        "┃ Layer (type)                     Output Shape                  Param # ┃\n",
        "┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
-       "│ dense_3 (Dense)                 │ (None, 512)            │         6,656 │\n",
+       "│ dense_20 (Dense)                │ (None, 512)            │         6,656 │\n",
        "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
-       "│ dense_4 (Dense)                 │ (None, 1024)           │       525,312 │\n",
+       "│ dense_21 (Dense)                │ (None, 1024)           │       525,312 │\n",
        "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
-       "│ dense_5 (Dense)                 │ (None, 512)            │       524,800 │\n",
+       "│ dense_22 (Dense)                │ (None, 512)            │       524,800 │\n",
        "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
-       "│ dense_6 (Dense)                 │ (None, 12)             │         6,156 │\n",
+       "│ dense_23 (Dense)                │ (None, 12)             │         6,156 │\n",
        "└─────────────────────────────────┴────────────────────────┴───────────────┘\n",
        "
\n" ], @@ -250,13 +252,13 @@ "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\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", + "│ dense_20 (\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", + "│ dense_21 (\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", + "│ dense_22 (\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", + "│ dense_23 (\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" ] }, @@ -319,11 +321,113 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 88, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
Model: \"sequential_6\"\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1mModel: \"sequential_6\"\u001b[0m\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓\n",
+       "┃ Layer (type)                     Output Shape                  Param # ┃\n",
+       "┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩\n",
+       "│ dense_24 (Dense)                │ (None, 128)            │         1,664 │\n",
+       "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+       "│ dense_25 (Dense)                │ (None, 256)            │        33,024 │\n",
+       "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+       "│ dense_26 (Dense)                │ (None, 512)            │       131,584 │\n",
+       "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+       "│ dense_27 (Dense)                │ (None, 256)            │       131,328 │\n",
+       "├─────────────────────────────────┼────────────────────────┼───────────────┤\n",
+       "│ dense_28 (Dense)                │ (None, 12)             │         3,084 │\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_24 (\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_25 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m256\u001b[0m) │ \u001b[38;5;34m33,024\u001b[0m │\n", + "├─────────────────────────────────┼────────────────────────┼───────────────┤\n", + "│ dense_26 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m512\u001b[0m) │ \u001b[38;5;34m131,584\u001b[0m │\n", + "├─────────────────────────────────┼────────────────────────┼───────────────┤\n", + "│ dense_27 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m256\u001b[0m) │ \u001b[38;5;34m131,328\u001b[0m │\n", + "├─────────────────────────────────┼────────────────────────┼───────────────┤\n", + "│ dense_28 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m12\u001b[0m) │ \u001b[38;5;34m3,084\u001b[0m │\n", + "└─────────────────────────────────┴────────────────────────┴───────────────┘\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
 Total params: 300,684 (1.15 MB)\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m Total params: \u001b[0m\u001b[38;5;34m300,684\u001b[0m (1.15 MB)\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
 Trainable params: 300,684 (1.15 MB)\n",
+       "
\n" + ], + "text/plain": [ + "\u001b[1m Trainable params: \u001b[0m\u001b[38;5;34m300,684\u001b[0m (1.15 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": [ - "# model from paper" + "# model from paper\n", + "# (see https://doi.org/10.1007/s11242-022-01779-3 model for the complex chemistry)\n", + "model_paper = keras.Sequential(\n", + " [keras.layers.Input(shape=(12,), dtype=dtype),\n", + " keras.layers.Dense(128, activation='relu', dtype=dtype),\n", + " keras.layers.Dense(256, activation='relu', dtype=dtype),\n", + " keras.layers.Dense(512, activation='relu', dtype=dtype),\n", + " keras.layers.Dense(256, activation='relu', dtype=dtype),\n", + " keras.layers.Dense(12, dtype=dtype)\n", + " ])\n", + "\n", + "model_paper.compile(optimizer=optimizer_paper, loss = loss)\n", + "model_paper.summary()" ] }, { @@ -335,7 +439,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 89, "metadata": {}, "outputs": [], "source": [ @@ -359,7 +463,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 90, "metadata": {}, "outputs": [], "source": [ @@ -405,7 +509,7 @@ }, { "cell_type": "code", - "execution_count": 59, + "execution_count": 91, "metadata": {}, "outputs": [], "source": [ @@ -439,7 +543,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 92, "metadata": {}, "outputs": [ { @@ -455,15 +559,12 @@ "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" + "Amount class 1 before: 0.012083028083028084\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\", 'individual', 0.1)" + "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, \"off\", 'individual', 0.1)" ] }, { @@ -475,7 +576,7 @@ }, { "cell_type": "code", - "execution_count": 164, + "execution_count": 93, "metadata": {}, "outputs": [], "source": [ @@ -498,88 +599,130 @@ }, { "cell_type": "code", - "execution_count": 42, + "execution_count": 117, "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.0018 - val_loss: 3.6601e-05\n", - "Epoch 2/20\n", - "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m13s\u001b[0m 2ms/step - loss: 3.6899e-05 - val_loss: 3.6822e-05\n", - "Epoch 3/20\n", - "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m13s\u001b[0m 2ms/step - loss: 3.5005e-05 - val_loss: 3.5655e-05\n", - "Epoch 4/20\n", - "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m13s\u001b[0m 2ms/step - loss: 3.4032e-05 - val_loss: 3.3455e-05\n", - "Epoch 5/20\n", - "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m14s\u001b[0m 2ms/step - loss: 3.3279e-05 - val_loss: 3.3064e-05\n", - "Epoch 6/20\n", - "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m14s\u001b[0m 2ms/step - loss: 3.3023e-05 - val_loss: 3.3338e-05\n", - "Epoch 7/20\n", - "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m14s\u001b[0m 2ms/step - loss: 3.2532e-05 - val_loss: 3.2765e-05\n", - "Epoch 8/20\n", - "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m13s\u001b[0m 2ms/step - loss: 3.2749e-05 - val_loss: 3.2730e-05\n", - "Epoch 9/20\n", - "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m13s\u001b[0m 2ms/step - loss: 3.2961e-05 - val_loss: 3.2593e-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.2573e-05 - val_loss: 3.2576e-05\n", - "Epoch 11/20\n", - "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m13s\u001b[0m 2ms/step - loss: 3.2442e-05 - val_loss: 3.2507e-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.2135e-05 - val_loss: 3.2548e-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.2451e-05 - val_loss: 3.2482e-05\n", - "Epoch 14/20\n", - "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m14s\u001b[0m 2ms/step - loss: 3.2296e-05 - val_loss: 3.2475e-05\n", - "Epoch 15/20\n", - "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m14s\u001b[0m 2ms/step - loss: 3.2081e-05 - val_loss: 3.2470e-05\n", - "Epoch 16/20\n", - "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m14s\u001b[0m 2ms/step - loss: 3.2440e-05 - val_loss: 3.2471e-05\n", - "Epoch 17/20\n", - "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m14s\u001b[0m 2ms/step - loss: 3.2050e-05 - val_loss: 3.2460e-05\n", - "Epoch 18/20\n", - "\u001b[1m7823/7823\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m14s\u001b[0m 2ms/step - loss: 3.2444e-05 - val_loss: 3.2452e-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.2259e-05 - val_loss: 3.2452e-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.2442e-05 - val_loss: 3.2448e-05\n", - "Training took 276.5459449291229 seconds\n" - ] - } - ], + "outputs": [], "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", + "def model_training(model):\n", + " start = time.time()\n", + " callback = keras.callbacks.EarlyStopping(monitor='loss', patience=3)\n", + " history = model.fit(X_train.iloc[:, X_train.columns != \"Class\"], \n", + " y_train.iloc[:, y_train.columns != \"Class\"], \n", + " batch_size = batch_size, \n", + " epochs = 40, \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", + " end = time.time()\n", "\n", - "print(\"Training took {} seconds\".format(end - start))" + " print(\"Training took {} seconds\".format(end - start))" ] }, { "cell_type": "code", - "execution_count": 69, + "execution_count": 118, "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 1ms/step \n" + "Epoch 1/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 2ms/step - loss: 1.8876e-06 - val_loss: 1.8770e-06\n", + "Epoch 2/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.9907e-06 - val_loss: 1.8834e-06\n", + "Epoch 3/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.6876e-06 - val_loss: 1.8772e-06\n", + "Epoch 4/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.5167e-06 - val_loss: 1.8927e-06\n", + "Epoch 5/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 2.0424e-06 - val_loss: 1.8783e-06\n", + "Epoch 6/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m6s\u001b[0m 2ms/step - loss: 1.5759e-06 - val_loss: 1.8775e-06\n", + "Epoch 7/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.7919e-06 - val_loss: 1.8742e-06\n", + "Epoch 8/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.9016e-06 - val_loss: 1.8740e-06\n", + "Epoch 9/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.7540e-06 - val_loss: 1.8810e-06\n", + "Epoch 10/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.9548e-06 - val_loss: 1.8773e-06\n", + "Epoch 11/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 2.0289e-06 - val_loss: 1.8712e-06\n", + "Epoch 12/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.6964e-06 - val_loss: 1.8717e-06\n", + "Epoch 13/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 2.1222e-06 - val_loss: 1.8696e-06\n", + "Epoch 14/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.9142e-06 - val_loss: 1.8694e-06\n", + "Epoch 15/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.6718e-06 - val_loss: 1.8697e-06\n", + "Epoch 16/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.5208e-06 - val_loss: 1.8694e-06\n", + "Epoch 17/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.8481e-06 - val_loss: 1.8691e-06\n", + "Epoch 18/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.6943e-06 - val_loss: 1.8693e-06\n", + "Epoch 19/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.8389e-06 - val_loss: 1.8690e-06\n", + "Epoch 20/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.9054e-06 - val_loss: 1.8691e-06\n", + "Epoch 21/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.6646e-06 - val_loss: 1.8702e-06\n", + "Epoch 22/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.8724e-06 - val_loss: 1.8692e-06\n", + "Epoch 23/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.7165e-06 - val_loss: 1.8690e-06\n", + "Epoch 24/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.8717e-06 - val_loss: 1.8690e-06\n", + "Epoch 25/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.8996e-06 - val_loss: 1.8690e-06\n", + "Epoch 26/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.8146e-06 - val_loss: 1.8691e-06\n", + "Epoch 27/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.9670e-06 - val_loss: 1.8689e-06\n", + "Epoch 28/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.7449e-06 - val_loss: 1.8690e-06\n", + "Epoch 29/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 2.0738e-06 - val_loss: 1.8690e-06\n", + "Epoch 30/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m8s\u001b[0m 2ms/step - loss: 1.5405e-06 - val_loss: 1.8690e-06\n", + "Epoch 31/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.6470e-06 - val_loss: 1.8692e-06\n", + "Epoch 32/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.7679e-06 - val_loss: 1.8690e-06\n", + "Epoch 33/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.7011e-06 - val_loss: 1.8690e-06\n", + "Epoch 34/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 2.0628e-06 - val_loss: 1.8690e-06\n", + "Epoch 35/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.7559e-06 - val_loss: 1.8690e-06\n", + "Epoch 36/40\n", + "\u001b[1m3960/3960\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m7s\u001b[0m 2ms/step - loss: 1.8712e-06 - val_loss: 1.8690e-06\n", + "Training took 245.66379165649414 seconds\n" + ] + } + ], + "source": [ + "model_training(model_simple)" + ] + }, + { + "cell_type": "code", + "execution_count": 102, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1m1/1\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 14ms/step\n" ] }, { "data": { - "image/png": "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bNkymzZtmvl8PrvmmmuCwogkO++886xdu3Y2Z84cW758uX3++edmZjZ06FB78cUXLSsry7Kysuyxxx6zqKiowPvmRHVUFmbee+89q127tnXs2NHmzZtnCxcutPT0dPN4PDZ37txAv/Iw06JFC7vnnnvsnXfesRdeeMHq1atnV199daBfbm6uRUZGWvfu3W3hwoX23nvv2WuvvWaDBw+uEHzx74UwA+fk5eWZJBswYMBx+916660myXbu3HnMPq1btw7MOpxIaWmpJSQkWNu2ba20tDTQXlRUZI0bN7YuXboE2soDwaRJk4K2MWLECIuMjAx8wLz//vsmycaPH3/M/W7dutXCw8PtnnvuCWovKioyv99vt9xyS6BtyJAhJsn++te/BvXt3bu3tWrVKvD4hx9+MEn28MMPV9hfee0PPfTQcUbjZyUlJbZv3z6LiYkJCl9/+9vfTJKtWLGiwnOODjPlwerosZo3b55Jsueeey7QVj4j9O233wbaDh48aPXr17dhw4Ydt9Znn3220rF56qmnTJItXbrUzMx27dplERER9sADDwT1u+WWWyw+Pt5++uknMzN7/fXXTZLNnz8/qF9OTo5JshkzZgTVHRYWZl9++eVxayx3dJgxM7vooossLS2tQt/MzEyrVauW5eTkBLX//e9/N0n21ltvBdokmc/nsx9//PG4+y8tLbWffvrJHn30UWvQoEFQIDpWHZWFmcsuu8waN25sRUVFgbaSkhJLSUmxpk2bBrZbHmZGjBgRtM1JkyaZJNuxY0fQMX366afHrR//fjgBGOcsM5MkeTyeKtnel19+qe+//16DBw9WrVr/96dTp04d3Xjjjfr444914MCBoOf86le/Cnrcrl07HTp0SPn5+ZKkt99+W5I0cuTIY+73nXfeUUlJiW6//XaVlJQElsjISKWlpVU4idfj8ahfv34V9vvtt9+e0vHeeOONFdr27dunsWPH6oILLlB4eLjCw8NVp04d7d+/X1988cUpbb/c8uXLJf18Bc+Rbr75ZsXExOjdd98Nam/fvr2aNWsWeBwZGalf/OIXJzy+5cuXKyYmRjfddFNQe/l+y/fToEED9evXT7Nnz1ZZWZkkac+ePVq0aJFuv/32wPlZixcvVt26ddWvX7+g16V9+/by+/0VXpd27drpF7/4xYkH5BQtXrxYKSkpat++fVAdPXr0kMfjqVDHNddco3r16lXYzvLly9WtWzf5fD6FhYWpdu3aeuihh7R79+7A+/VU7N+/X6tXr9ZNN90UdGVWWFiYBg8erO3bt+vLL78Mek5lfy+SAq9t+/btFRERobvuukuzZ8/WN998c8p14dxEmIFzGjZsqOjoaOXm5h6335YtWxQdHa369esfs0+zZs30ww8/aP/+/Sfc7+7duyX9fNXG0RISElRWVqY9e/YEtTdo0CDosdfrlfTzyZ+S9MMPPygsLEx+v/+Y+925c6ck6ZJLLlHt2rWDlnnz5mnXrl1B/aOjoxUZGVlhv4cOHTrhMR6psuMcOHCgpk+frt/+9rd65513tGbNGuXk5KhRo0aBYzpVu3fvVnh4uBo1ahTU7vF45Pf7A+Ne7ugxlX4+vhPtf/fu3fL7/RXCbePGjRUeHh60nzvvvFPfffedsrKyJEmvv/66iouLgwLXzp07tXfvXkVERFR4XfLy8iq8LpWNZ1XYuXOnPvvsswo1xMbGysxOqo41a9YoPT1dkvT888/ro48+Uk5OjsaPHy9Jp/Xa7tmzR2Z2zL8XSSd8bY/+ezn//PO1bNkyNW7cWCNHjtT555+v888/X9OmTTvl+nBu4WomOCcsLExXX321lixZou3btwddgVRu+/btWrdunXr16qWwsLBjbqtHjx5aunSp/vGPf2jAgAHH3W/5P7Q7duyosO77779XrVq1Kv0/3uNp1KiRSktLlZeXd8wPu4YNG0qS/v73vyspKemUtn8mjv7QLygo0OLFi/Xwww/r/vvvD7QXFxfrxx9/PO39NGjQQCUlJfrhhx+CAo2ZKS8vT5dccslpb/vo/axevVpmFnRs+fn5KikpCYyz9PP7IiEhQbNmzVKPHj00a9Yspaamqk2bNoE+DRs2VIMGDbRkyZJK9xcbGxv0uKpmCI/WsGFDRUVF6aWXXjrm+hPVMXfuXNWuXVuLFy8OCsILFy487brq1aunWrVqHfPvpbLaTsaVV16pK6+8UqWlpVq7dq3+/Oc/KyMjQ/Hx8Sf8G8a5i5kZOGncuHEyM40YMUKlpaVB60pLS3X33XfLzDRu3Ljjbuc3v/mN/H6/xowZo++++67SPgsWLJAktWrVSuedd57mzJkT+ApL+nk6ff78+ercufMpX77cq1cvSdLMmTOP2adHjx4KDw/X119/rU6dOlW6nKqj/4/3ZHg8HplZ4LnlXnjhhQqvwals/9prr5Ukvfrqq0Ht8+fP1/79+wPrz9S1116rffv2VfiA/stf/hJUh/R/X4UsXLhQH3zwgdauXas777wz6Hl9+/bV7t27VVpaWulr0qpVqyqpu9yxZp/69u2rr7/+Wg0aNKi0jpO5QaHH41F4eHhQ8D948KBeeeWVk67jaDExMUpNTdWCBQuC+peVlenVV19V06ZNz+hrt7CwMKWmpuqZZ56RJK1fv/60twX3MTMDJ11++eWaOnWqMjIydMUVV2jUqFFq1qyZtm7dqmeeeUarV6/W1KlT1aVLl+Nux+fzadGiRerbt686dOigUaNGqXPnzoqIiNDmzZv16quv6p///Kf69++vWrVqadKkSRo0aJD69u2rYcOGqbi4WH/84x+1d+9ePfnkk6d8HFdeeaUGDx6sxx9/XDt37lTfvn3l9Xr1ySefKDo6Wvfcc4+aN2+uRx99VOPHj9c333yjnj17ql69etq5c6fWrFmjmJgYPfLII6e039jYWCUlJWnRokW69tprVb9+fTVs2PC4H3xxcXG66qqr9Mc//jHQNzs7Wy+++KLq1q0b1DclJUWS9Nxzzyk2NlaRkZFKTk6u9Cui7t27q0ePHho7dqwKCwt1+eWX67PPPtPDDz+sDh06aPDgwad0bMdy++2365lnntGQIUO0ZcsWtW3bVh9++KEmTpyo3r17q1u3bkH977zzTj311FMaOHCgoqKidOuttwatHzBggF577TX17t1bo0eP1qWXXqratWtr+/btWrFiha677jrdcMMNVVK7JLVt21Zz587VvHnz1KJFC0VGRqpt27bKyMjQ/PnzddVVV+l3v/ud2rVrp7KyMm3dulVLly7V73//e6Wmph5323369NGUKVM0cOBA3XXXXdq9e7cmT55cIbger47KZGZmqnv37rr66qt13333KSIiQjNmzNDnn3+u119//ZRnq5599lktX75cffr0UbNmzXTo0KHAjNTRrx/+zYTs1GOgCqxatcpuuukmi4+Pt/DwcGvcuLH179+/wn1fTiQvL8/Gjh1rF110kUVHR5vX67ULLrjAhg0bZhs2bAjqu3DhQktNTbXIyEiLiYmxa6+91j766KOgPuVXBJVfrlyu/KqN3NzcQFtpaan96U9/spSUFIuIiDCfz2edO3e2f/zjHxX2e/XVV1tcXJx5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3XXW6gBwdoWHugAAOJHDhw8rIiLitJ/fqFGjKqwGQE3DzAyAajF06FBlZ2dr2rRp8ng88ng82rJliyRp06ZN6t27t+rUqaP4+HgNHjxYu3btCjy3a9euGjVqlO699141bNhQ3bt3lyRNmTJFbdu2VUxMjBITEzVixAjt27dPkvTee+/pjjvuUEFBQWB/EyZMkFTxa6atW7fquuuuU506dRQXF6dbbrlFO3fuDKyfMGGC2rdvr1deeUXNmzeXz+fTgAEDVFRUVL2DBuC0EGYAVItp06apc+fO+o//+A/t2LFDO3bsUGJionbs2KG0tDS1b99ea9eu1ZIlS7Rz507dcsstQc+fPXu2wsPD9dFHH+m///u/JUm1atXS008/rc8//1yzZ8/W8uXLNWbMGElSly5dNHXqVMXFxQX2d99991Woy8x0/fXX68cff1R2draysrL09ddf69Zbbw3q9/XXX2vhwoVavHixFi9erOzsbD355JPVNFoAzgRfMwGoFj6fTxEREYqOjpbf7w+0z5w5UxdffLEmTpwYaHvppZeUmJior776Sr/4xS8kSRdccIEmTZoUtM0jz79JTk7WY489prvvvlszZsxQRESEfD6fPB5P0P6OtmzZMn322WfKzc1VYmKiJOmVV17RRRddpJycHF1yySWSpLKyMr388suKjY2VJA0ePFjvvvuunnjiiTMbGABVjpkZAGfVunXrtGLFCtWpUyewtG7dWtLPsyHlOnXqVOG5K1asUPfu3XXeeecpNjZWt99+u3bv3q39+/ef9P6/+OILJSYmBoKMJLVp00Z169bVF198EWhr3rx5IMhIUpMmTZSfn39Kxwrg7GBmBsBZVVZWpn79+umpp56qsK5JkyaB/46JiQla9+2336p3794aPny4HnvsMdWvX18ffvihfvOb3+inn3466f2bmTwezwnba9euHbTe4/GorKzspPcD4OwhzACoNhERESotLQ1qu/jiizV//nw1b95c4eEn/0/Q2rVrVVJSov/6r/9SrVo/Tyr/9a9/PeH+jtamTRtt3bpV27ZtC8zObNq0SQUFBbrwwgtPuh4ANQdfMwGoNs2bN9fq1au1ZcsW7dq1S2VlZRo5cqR+/PFH3XbbbVqzZo2++eYbLV26VHfeeedxg8j555+vkpIS/fnPf9Y333yjV155Rc8++2yF/e3bt0/vvvuudu3apQMHDlTYTrdu3dSuXTsNGjRI69ev15o1a3T77bcrLS2t0q+2ANR8hBkA1ea+++5TWFiY2rRpo0aNGmnr1q1KSEjQRx99pNLSUvXo0UMpKSkaPXq0fD5fYMalMu3bt9eUKVP01FNPKSUlRa+99poyMzOD+nTp0kXDhw/XrbfeqkaNGlU4gVj6+euihQsXql69errqqqvUrVs3tWjRQvPmzavy4wdwdnjMzEJdBAAAwOliZgYAADiNMAMAAJxGmAEAAE4jzAAAAKcRZgAAgNMIMwAAwGmEGQAA4DTCDAAAcBphBgAAOI0wAwAAnEaYAQAATiPMAAAAp/1/7MgGXoPfaWQAAAAASUVORK5CYII=", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlQAAAHFCAYAAAA0SmdSAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAQlhJREFUeJzt3Xl4VOX5xvF7JpmshAESskGEaJGAQNkqEBdQVm1MtVVUbBClUAuIYSmKVQlaiVALLlQWa0EtFWwVq6gpqSg/kQCREimrVVEQEoIQJoCQ9f39QXOaIQuBAwwD3891zWXmPc/7nufMkM7dM2cmDmOMEQAAAE6b09cNAAAA+DsCFQAAgE0EKgAAAJsIVAAAADYRqAAAAGwiUAEAANhEoAIAALCJQAUAAGATgQoAAMAmAhVwChYuXCiHw+F1a968ufr06aNly5adlX1+/PHHGjx4sFq0aKGgoCC53W4lJydrzpw5OnLkyFnZpy+tXr1aGRkZOnjw4FlZ/y9/+YueeeaZWrc5HA5lZGSclf1eKBwOh8aMGWPd37NnjzIyMpSXl+e7pk7SR0ZGhhwOx7lvChcVAhVwGhYsWKCcnBytXr1a8+fPV0BAgG666Sa98847Z3Q/U6ZM0bXXXqvdu3friSeeUHZ2thYvXqy+ffsqIyNDjzzyyBnd3/lg9erVmjp1qk8CVU5Ojn7xi1+clf1eqPbs2aOpU6eeF4Gqrj5+8YtfKCcn59w3hYtKoK8bAPxRhw4d1L17d+v+oEGD1LRpU7322mu66aabzsg+/vrXv+rxxx/X8OHD9eKLL3r9P+wbbrhBkyZN4kVC0tGjRxUaGnpG1urZs+cZWceflZWVyeFwKDDQty8PR48eVUhIyBk5s9SyZUu1bNnyDHQF1I0zVMAZEBISoqCgILlcLq/xqVOnqkePHmrWrJkaN26srl276qWXXlJD/ib5448/rqZNm+q5556r9UUlIiJCAwYMsO4fO3ZMkydPVmJiooKCgtSiRQuNHj26xpme1q1bKyUlRVlZWeratatCQ0OVlJSkP/3pTzX2sXv3bo0cOVIJCQkKCgpSfHy8br31Vu3du9eqKS4u1sSJE732m56eXuPtyKq3il599VW1a9dOYWFh+uEPf+j1VmlGRoZ+/etfS5ISExOtt1U/+ugjr97ffPNNdenSRSEhIZo6daok6Q9/+IOuvfZaRUdHKzw8XB07dtSMGTNUVlZmrd+nTx+9++67+uabb7zetq3e44lv+W3atEk/+clP1LRpU4WEhKhz5856+eWXvWo++ugjORwOvfbaa/rNb36j+Ph4NW7cWP369dP27dtrPK61WbVqlfr27auIiAiFhYUpOTlZ7777rrX9s88+k8Ph0EsvvVRj7vvvvy+Hw6G3337bGvvPf/6jIUOGKDo6WsHBwWrXrp3+8Ic/1Nr3q6++qgkTJqhFixYKDg7WF1980aCeP/roI/3oRz+SJN1zzz3W41n9Mfz000+VmpqqZs2aKSQkRF26dNHrr7/utU7VW+nLly/Xvffeq+bNmyssLEwlJSX64osvdM8996hNmzYKCwtTixYtdNNNN+nf//53g/uo7S2/yspKzZgxQ0lJSQoODlZ0dLSGDh2qb7/91quuT58+6tChg3Jzc3XNNdcoLCxMl156qZ566ilVVlZ6rffb3/5Wbdu2VWhoqJo0aaJOnTrp2WefbdBjiQuAAdBgCxYsMJLMmjVrTFlZmSktLTW7du0yY8eONU6n02RlZXnVDxs2zLz00ksmOzvbZGdnmyeeeMKEhoaaqVOn1rufPXv2GEnm9ttvb1BflZWVZuDAgSYwMNA8+uijZvny5ebpp5824eHhpkuXLubYsWNWbatWrUzLli1N+/btzSuvvGL+8Y9/mNtuu81IMitXrrTqvv32WxMXF2eioqLMzJkzzT//+U+zZMkSc++995qtW7caY4w5cuSI6dy5s1fNs88+a9xut7n++utNZWWltZ4k07p1a3PllVea119/3bz33numT58+JjAw0Hz55ZfGGGN27dpl7r//fiPJvPnmmyYnJ8fk5OQYj8dj9R4XF2cuvfRS86c//cl8+OGHZt26dcYYY8aNG2fmzJljsrKyzIoVK8ysWbNMVFSUueeee6weNm/ebK666ioTGxtrrZ2Tk+PV45QpU6z727ZtMxEREeayyy4zr7zyinn33XfNnXfeaSSZ6dOnW3UffvihdXx33XWXeffdd81rr71mLrnkEtOmTRtTXl5e7/P30UcfGZfLZbp162aWLFli3nrrLTNgwADjcDjM4sWLrbouXbqYq666qsb8wYMHm+joaFNWVmYdp9vtNh07djSvvPKKWb58uZkwYYJxOp0mIyOjRt8tWrQwt956q3n77bfNsmXLzP79++vs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i091b7zxho4cOWJtPxU33HCDPvzww3o/pZaSkqIvv/xSkZGR1hm76rfWrVuf8n4bclbnRFUvxFVzpeNh8sUXX6x1/Yau3bdvX61YscIKNlVeeeUVhYWFnZGvWQgPD1ePHj305ptvevVVWVmpP//5z2rZsqXXW5wDBgxQixYttGDBAi1YsEAhISG68847re1hYWG67rrrtGHDBnXq1KnW56W2My6nq67nq23btmrTpo0+++yzWnvo3r2719u/dXE4HF7PqyS9++672r17d4P6qM31118vqebvS25urrZu3Xpavy/VNWnSRLfeeqtGjx6tAwcO6Ouvv7a1HvwDZ6iA07Bp0yaVl5dLOv72wZtvvqns7Gzdcsst1v/7//GPf6yZM2dqyJAhGjlypPbv36+nn366xotDXW677TY9+uijeuKJJ7Rt2zYNHz5cl112mb7//nutXbtW8+bN0+23364BAwaof//+GjhwoB588EEVFxfrqquu0saNGzVlyhR16dJFaWlpp3yMjz/+uN5//31de+21evjhh9WxY0cdPHhQWVlZGj9+vJKSkpSenq433nhD1157rcaNG6dOnTqpsrJSO3fu1PLlyzVhwgT16NHjlPbbsWNHSdKzzz6ru+++Wy6XS23btq33xbd///4KCgrSnXfeqUmTJunYsWOaM2eOioqKal3/zTff1Jw5c9StWzc5nU6v7xSrbsqUKVq2bJmuu+46PfbYY2rWrJkWLVqkd999VzNmzJDb7T6lY6tLZmam+vfvr+uuu04TJ05UUFCQXnjhBW3atEmvvfaa15mbgIAADR06VDNnzlTjxo3105/+tEYfzz77rK6++mpdc801+tWvfqXWrVvr0KFD+uKLL/TOO+9Y19ydCZdddplCQ0O1aNEitWvXTo0aNVJ8fLzi4+M1b9483XDDDRo4cKCGDRumFi1a6MCBA9q6dav+9a9/6a9//etJ109JSdHChQuVlJSkTp06af369frd735X48xSfX2cqG3btho5cqSef/55OZ1O3XDDDfr666/16KOPKiEhQePGjTvlx+Gmm26yvp+uefPm+uabb/TMM8+oVatWatOmzSmvBz/k00viAT9T26f83G636dy5s5k5c6bX1xMYY8yf/vQn07ZtWxMcHGwuvfRSk5mZaV566aU6P8VWm5UrV5pbb73VxMXFGZfLZRo3bmx69eplfve733l9Yu7o0aPmwQcfNK1atTIul8vExcWZX/3qV6aoqMhrvVatWpkf//jHNfbTu3dv07t3b6+xXbt2mXvvvdfExsYal8tl4uPjzeDBg83evXutmsOHD5tHHnnEtG3b1gQFBVkf1x83bpwpKCiw6nTCp8Oq93P33Xd7jU2ePNnEx8cbp9NpJJkPP/yw3t6NMeadd94xP/zhD01ISIhp0aKF+fWvf23ef/99r/nGHP9U3K233mqaNGliHA6H16e/dMKn/Iwx5t///re56aabjNvtNkFBQeaHP/xhjU+SVX1a7q9//avX+I4dO+r85NmJPv74Y3P99deb8PBwExoaanr27GneeeedWms///xz699fdnZ2rTU7duww9957r2nRooVxuVymefPmJjk52fz2t789ad/1qe15fO2110xSUpJxuVw1HsPPPvvM+loHl8tlYmNjzfXXX2/mzp1r1VT9Xp34aVFjjCkqKjLDhw830dHRJiwszFx99dXm448/rvXfa1191Pa1CRUVFWb69Onm8ssvNy6Xy0RFRZmf//zn1lctVOndu7e54ooravR19913e31a9Pe//71JTk42UVFRJigoyFxyySVm+PDh5uuvv67v4cQFxGFMA75hEAAAAHXiGioAAACbCFQAAAA2EagAAABsIlABAADYRKACAACwiUAFAABgE1/seY5UVlZqz549ioiIOCt/5gEAAJx5xhgdOnRI8fHxcjrrPg9FoDpH9uzZU+Mv1gMAAP+wa9euev9gPIHqHKn6sxm7du1S48aNfdwNAABoiOLiYiUkJJz0b08SqM6Rqrf5GjduTKACAMDPnOxyHS5KBwAAsIlABQAAYBOBCgAAwCYCFQAAgE0EKgAAAJsIVAAAADYRqAAAAGwiUAEAANhEoAIAALCJQAUAAGCT3wWqF154QYmJiQoJCVG3bt308ccf11u/cuVKdevWTSEhIbr00ks1d+7cGjVvvPGG2rdvr+DgYLVv315Lly61vV8AAHDx8KtAtWTJEqWnp+s3v/mNNmzYoGuuuUY33HCDdu7cWWv9jh07dOONN+qaa67Rhg0b9PDDD2vs2LF64403rJqcnBzdfvvtSktL02effaa0tDQNHjxYa9euPe39AgCAi4vDGGN83URD9ejRQ127dtWcOXOssXbt2unmm29WZmZmjfoHH3xQb7/9trZu3WqN3Xffffrss8+Uk5MjSbr99ttVXFys999/36oZNGiQmjZtqtdee+209lub4uJiud1ueTyeM/fHkY3RQc9BlVZU1r653rknWbqegvr+xZzsH5P//GsDAPibyCZNFBIUeEbXbOjr95nd61lUWlqq9evX66GHHvIaHzBggFavXl3rnJycHA0YMMBrbODAgXrppZdUVlYml8ulnJwcjRs3rkbNM888c9r7laSSkhKVlJRY94uLi096jKes7Hs1eab1mV8XAAA/tGrwRl3dvpVP9u03b/l99913qqioUExMjNd4TEyMCgoKap1TUFBQa315ebm+++67emuq1jyd/UpSZmam3G63dUtISGjYgQIAgNPidDh8tm+/OUNVxXHCg2WMqTF2svoTxxuy5qnud/LkyRo/frx1v7i4+MyHKleY9PCeM7smAAB+KtkV5rN9+02gioqKUkBAQI2zQoWFhTXOHlWJjY2ttT4wMFCRkZH11lSteTr7laTg4GAFBwc37OBOl8MhBYWf3X0AAICT8pu3/IKCgtStWzdlZ2d7jWdnZys5ObnWOb169apRv3z5cnXv3l0ul6vemqo1T2e/AADg4uI3Z6gkafz48UpLS1P37t3Vq1cvzZ8/Xzt37tR9990n6fjbbLt379Yrr7wi6fgn+mbPnq3x48drxIgRysnJ0UsvvWR9ek+SHnjgAV177bWaPn26fvKTn+jvf/+7/vnPf2rVqlUN3i8AALi4+VWguv3227V//349/vjjys/PV4cOHfTee++pVavjV/Tn5+d7fTdUYmKi3nvvPY0bN05/+MMfFB8fr+eee04/+9nPrJrk5GQtXrxYjzzyiB599FFddtllWrJkiXr06NHg/QIAgIubX30PlT87K99DBQAAzqqGvn77zTVUAAAA5ysCFQAAgE0EKgAAAJsIVAAAADYRqAAAAGwiUAEAANhEoAIAALCJQAUAAGATgQoAAMAmAhUAAIBNBCoAAACbCFQAAAA2EagAAABsIlABAADYRKACAACwiUAFAABgE4EKAADAJgIVAACATQQqAAAAmwhUAAAANhGoAAAAbCJQAQAA2ESgAgAAsIlABQAAYBOBCgAAwCYCFQAAgE0EKgAAAJsIVAAAADYRqAAAAGwiUAEAANhEoAIAALCJQAUAAGATgQoAAMAmAhUAAIBNBCoAAACbCFQAAAA2EagA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QMuXL1dISIiv27noVVZWqnv37po2bZokqUuXLtq8ebPmzJlDoPKRJUuW6M9//rP+8pe/6IorrlBeXp7S09MVHx+vu+++29ft+SUClZ+KiopSQEBAjbNRhYWFNc5a4dy5//779fbbb+v//u//1LJlS1+3c9Fav369CgsL1a1bN2usoqJC//d//6fZs2erpKREAQEBPuzw4hIXF6f27dt7jbVr105vvPGGjzrCr3/9az300EO64447JEkdO3bUN998o8zMTALVaeIaKj8VFBSkbt26KTs722s8OztbycnJPurq4mWM0ZgxY/Tmm29qxYoVSkxM9HVLF7W+ffvq3//+t/Ly8qxb9+7ddddddykvL48wdY5dddVVNb5G5PPPP1erVq181BG+//57OZ3eESAgIICvTbCBM1R+bPz48UpLS1P37t3Vq1cvzZ8/Xzt37tR9993n69YuOqNHj9Zf/vIX/f3vf1dERIR15tDtdis0NNTH3V18IiIialy/Fh4ersjISK5r84Fx48YpOTlZ06ZN0+DBg7Vu3TrNnz9f8+fP93VrF62bbrpJTz75pC655BJdccUV2rBhg2bOnKl7773X1635Lb42wc+98MILmjFjhvLz89WhQwfNmjWLj+n7QF3XrS1YsEDDhg07t82gVn369OFrE3xo2bJlmjx5sv7zn/8oMTFR48eP14gRI3zd1kXr0KFDevTRR7V06VIVFhYqPj5ed955px577DEFBQX5uj2/RKACAACwiWuoAAAAbCJQAQAA2ESgAgAAsIlABQAAYBOBCgAAwCYCFQAAgE0EKgAAAJsIVABwjrRu3ZovFgUuUAQqABekYcOG6eabb5Z0/FvS09PTz9m+Fy5cqCZNmtQYz83N1ciRI89ZHwDOHf6WHwA0UGlpqa0/y9G8efMz2A2A8wlnqABc0IYNG6aVK1fq2WeflcPhkMPh0Ndffy1J2rJli2688UY1atRIMTExSktL03fffWfN7dOnj8aMGaPx48crKipK/fv3lyTNnDlTHTt2VHh4uBISEjRq1CgdPnxYkvTRRx/pnnvukcfjsfaXkZEhqeZbfjt37tRPfvITNWrUSI0bN9bgwYO1d+9ea3tGRoY6d+6sV199Va1bt5bb7dYdd9yhQ4cOnd0HDcApI1ABuKA9++yz6tWrl0aMGKH8/Hzl5+crISFB+fn56t27tzp37qxPP/1UWVlZ2rt3rwYPHuw1/+WXX1ZgYKA++eQTzZs3T5LkdDr13HPPadOmTXr55Ze1YsUKTZo0SZKUnJysZ555Ro0bN7b2N3HixBp9GWN0880368CBA1q5cqWys7P15Zdf6vbbb/eq+/LLL/XWW29p2bJlWrZsmVauXKmnnnrqLD1aAE4Xb/kBuKC53W4FBQUpLCxMsbGx1vicOXPUtWtXTZs2zRr705/+pISEBH3++ee6/PLLJUk/+MEPNGPGDK81q1+PlZiYqCeeeEK/+tWv9MILLygoKEhut1sOh8Nrfyf65z//qY0bN2rHjh1KSEiQJL366qu64oorlJubqx/96EeSpMrKSi1cuFARERGSpLS0NH3wwQd68skn7T0wAM4ozlABuCitX79eH374oRo1amTdkpKSJB0/K1Sle/fuNeZ++OGH6t+/v1q0aKGIiAgNHTpU+/fv15EjRxq8/61btyohIcEKU5LUvn17NWnSRFu3brXGWrdubYUpSYqLi1NhYeEpHSuAs48zVAAuSpWVlbrppps0ffr0Gtvi4uKsn8PDw722ffPNN7rxxht133336YknnlCzZs20atUqDR8+XGVlZQ3evzFGDofjpOMul8tru8PhUGVlZYP3A+DcIFABuOAFBQWpoqLCa6xr165644031Lp1awUGNvx/Cj/99FOVl5fr97//vZzO4yf5X3/99ZPu70Tt27fXzp07tWvXLuss1ZYtW+TxeNSuXbsG9wPg/MBbfgAueK1bt9batWv19ddf67vvvlNlZaVGjx6tAwcO6M4779S6dev01Vdfafny5br33nvrDUOXXXaZysvL9fzzz+urr77Sq6++qrlz59bY3+HDh/XBBx/ou+++0/fff19jnX79+qlTp06666679K9//Uvr1q3T0KFD1bt371rfZgRwfiNQAbjgTZw4UQEBAWrfvr2aN2+unTt3Kj4+Xp988okqKio0cOBAdejQQQ888IDcbrd15qk2nTt31syZMzV9+nR16NBBixYtUmZmpldNcnKy7rvvPt1+++1q3rx5jYvapeNv3b311ltq2rSprr32WvXr10+XXnqplixZcsaPH8DZ5zDGGF83AQAA4M84QwUAAGATgQoAAMAmAhUAAIBNBCoAAACbCFQAAAA2EagAAABsIlABAADYRKACAACwiUAFAABgE4EKAADAJgIVAACATQQqAAAAm/4fMTXyCTMHn44AAAAASUVORK5CYII=", "text/plain": [ "
" ] @@ -590,16 +733,16 @@ { "data": { "text/plain": [ - "" + "" ] }, - "execution_count": 69, + "execution_count": 102, "metadata": {}, "output_type": "execute_result" }, { "data": { - "image/png": "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6PHHH9djjz2Wt5+1mp5Z+RTtmVDs14RDuXWZaM3Onj1rMSVzzjlt375dDz/8sJYvXy6Jdbpef3+/6urqdPnyZd1xxx06ePCgHnjggdwvT9boU52dnTpx4oR6e3vHjfHf0/SUbISuudmvCcdnWLPPbN26VadOndIHH3wwbox1ku677z719fXpr3/9q37/+99r06ZNisfjuXHWSEokEtq2bZu6urq0aNGiSY9jraamZP8cV+zXhEMKh8OSxJr9zbPPPqu33npL77//viorK3P7WafPLFy4UPfee69WrVqlWCymFStW6KWXXmKNrnP8+HENDQ1p5cqVKisrU1lZmeLxuH72s5+prKwstx6s1dSUbISu/5rw63V3d2vNmjVGsypt1dXVCofDeWs2MjKieDx+S62Zc05bt27VgQMH9N5776m6ujpvnHWanHNO2WyWNbrO2rVr1d/fr76+vty2atUqbdy4UX19fbrnnntYq+mwuyfixqbzNeHzVSaTcSdPnnQnT550klx7e7s7efKkO3v2rHPOud27d7tgMOgOHDjg+vv73Xe/+123bNkyl06njWf+xXnmmWdcMBh0hw8fdufOncttFy9ezB3DOjnX2trqenp63ODgoDt16pR7/vnn3YIFC1xXV5dzjjUq5Pq745xjraajpCPknHM///nP3d133+0WLlzoHnzwwdxttreq999/f8Lvct+0aZNz7tPbRV944QUXDoedz+dzjzzyiOvv77ed9BdsovWR5F599dXcMayTc0899VTu/62vfOUrbu3atbkAOccaFfL5CLFWU8dXOQAAzJTsa0IAgPmPCAEAzBAhAIAZIgQAMEOEAABmiBAAwAwRAgCYIUIAADNECABghggBAMwQIQCAGSIEADDz/94uwpOWVe9JAAAAAElFTkSuQmCC", + "image/png": "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/XrwwQdVVVUliXW60fDwsGpqanT16lXdcccdOn78uO6///70L0/W6Evd3d364IMPNDAwMGMf/z0tzJKN0HW3+jXh+Apr9pW9e/fq7Nmzev/992fsY52k++67T0NDQ/r888/1t7/9Tbt27VIkEknvZ42kaDSqffv2qaenR2vWrJnzONZqfpbsn+Ny/ZpwSMFgUJJYs3979tln9eabb+q9995TWVlZepx1+kpRUZHuvfdebdmyReFwWJs2bdJLL73EGt3g9OnTGhsb0+bNm1VQUKCCggJFIhH95je/UUFBQXo9WKv5WbIRuvFrwm/U29ur2tpao1ktbRUVFQoGgxlrNjExoUgkclutmXNOe/fu1bFjx/Tuu++qoqIiYz/rNDfnnFKpFGt0g23btml4eFhDQ0PpbcuWLdq5c6eGhoZ0zz33sFYLYXdPxM0t5GvCV6pkMunOnDnjzpw54yS5zs5Od+bMGXfhwgXnnHOHDh1yfr/fHTt2zA0PD7sf//jHbuPGjS6RSBjP/OvzzDPPOL/f706ePOkuXryY3r744ov0MayTc62tra6vr8+Njo66s2fPuueff96tWrXK9fT0OOdYo2xuvDvOOdZqIZZ0hJxz7re//a27++67XVFRkfvud7+bvs32dvXee+/N+l3uu3btcs59ebvoCy+84ILBoPN6ve7hhx92w8PDtpP+ms22PpLca6+9lj6GdXLuqaeeSv+/9a1vfctt27YtHSDnWKNs/jNCrNX88VUOAAAzS/Y1IQDAykeEAABmiBAAwAwRAgCYIUIAADNECABghggBAMwQIQCAGSIEADBDhAAAZogQAMAMEQIAmPl/qGKdNepT4hUAAAAASUVORK5CYII=", "text/plain": [ "
" ] @@ -609,12 +752,11 @@ } ], "source": [ - "\n", "import matplotlib.pyplot as plt\n", "\n", - "species = \"O\"\n", - "iterations = 1000\n", - "cell_offset = 60\n", + "species = \"Ba\"\n", + "iterations = 10\n", + "cell_offset = 50\n", "y_design = []\n", "y_results = []\n", "for i in range(0,iterations):\n", @@ -641,7 +783,7 @@ "plt.show()\n", "\n", "timestep = 1000\n", - "plt.imshow(np.array(df_results[\"Barite\"][(timestep*2500):(timestep*2500+2500)]).reshape(50,50), origin='lower')" + "plt.imshow(np.array(df_results[species][(timestep*2500):(timestep*2500+2500)]).reshape(50,50), origin='lower')" ] }, { @@ -704,93 +846,181 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 103, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "\u001b[1m 20/7821\u001b[0m \u001b[37m━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[1m44s\u001b[0m 6ms/step - loss: 5.1914e-06" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[1m7821/7821\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m29s\u001b[0m 4ms/step - loss: 1.0395e-06\n" + "\u001b[1m7821/7821\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 354us/step - loss: 2.4332e-06\n" ] }, { "data": { "text/plain": [ - "9.875676596493577e-07" + "2.221618160547223e-06" ] }, - "execution_count": 15, + "execution_count": 103, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# test on all test data\n", - "model_large.evaluate(X_test.iloc[:,X_test.columns != \"Class\"], y_test.iloc[:, y_test.columns != \"Class\"])" + "model_simple.evaluate(X_test.iloc[:,X_test.columns != \"Class\"], y_test.iloc[:, y_test.columns != \"Class\"])" ] }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 104, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "\u001b[1m7727/7727\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m29s\u001b[0m 4ms/step - loss: 5.4493e-07\n" + "\u001b[1m7727/7727\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 309us/step - loss: 1.3519e-06\n" ] }, { "data": { "text/plain": [ - "5.075861508885282e-07" + "1.1662884844554355e-06" ] }, - "execution_count": 16, + "execution_count": 104, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# test on non-reactive data\n", - "model_large.evaluate(X_test[X_test['Class'] == 0].iloc[:,:-1], y_test[X_test['Class'] == 0].iloc[:,:-1])" + "model_simple.evaluate(X_test[X_test['Class'] == 0].iloc[:,:-1], y_test[X_test['Class'] == 0].iloc[:,:-1])" ] }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 105, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "\u001b[1m94/94\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 4ms/step - loss: 4.0710e-05\n" + "\u001b[1m94/94\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 347us/step - loss: 8.9877e-05\n" ] }, { "data": { "text/plain": [ - "4.047931361128576e-05" + "8.905206777853891e-05" ] }, - "execution_count": 17, + "execution_count": 105, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# test on reactive data\n", - "model_large.evaluate(X_test[X_test['Class'] == 1].iloc[:,:-1], y_test[X_test['Class'] == 1].iloc[:, :-1])" + "model_simple.evaluate(X_test[X_test['Class'] == 1].iloc[:,:-1], y_test[X_test['Class'] == 1].iloc[:, :-1])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Test Mass Balance" + ] + }, + { + "cell_type": "code", + "execution_count": 106, + "metadata": {}, + "outputs": [], + "source": [ + "def mass_balance(model, X, scaler_X, func_dict_in, func_dict_out):\n", + " # backtransform min/max\n", + " columns = X.iloc[:, X.columns != \"Class\"].columns\n", + " X = pd.DataFrame(scaler_X.inverse_transform(X.iloc[:, X.columns != \"Class\"]), columns = columns)\n", + " \n", + " # backtransform log\n", + " X = FuncTransform(func_dict_in, func_dict_out).inverse_transform(X)\n", + " \n", + " # calculate mass balance\n", + " predicton = model.predict(X)\n", + " dBa = np.abs((prediction[\"Ba\"] + prediction[\"Barite\"]) - (X[\"Ba\"] + X[\"Barite\"]))\n", + " dSr = np.abs((prediction[\"Sr\"] + prediction[\"Celestite\"]) - (X[\"Sr\"] + X[\"Celestite\"]))\n", + " \n", + " return dBa + dSr" + ] + }, + { + "cell_type": "code", + "execution_count": 107, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1m7821/7821\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 345us/step\n" + ] + } + ], + "source": [ + "columns = X_test.columns[X_test.columns != \"Class\"]\n", + "prediction = pd.DataFrame(model_simple.predict(X_test[columns]), columns = columns)" + ] + }, + { + "cell_type": "code", + "execution_count": 108, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1m7821/7821\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 357us/step\n" + ] + } + ], + "source": [ + "mass_balance = mass_balance(model_simple, X_test, scaler_X, func_dict_in, func_dict_out)" + ] + }, + { + "cell_type": "code", + "execution_count": 116, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1163 0.000526\n", + "1175 0.000948\n", + "2425 0.000854\n", + "3231 0.000993\n", + "3964 0.000145\n", + " ... \n", + "243165 0.000928\n", + "248138 0.000698\n", + "248832 0.000915\n", + "248963 0.000696\n", + "249253 0.000932\n", + "Length: 115, dtype: float64" + ] + }, + "execution_count": 116, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mass_balance[mass_balance < 0.001]" ] }, { diff --git a/preprocessing.py b/preprocessing.py index 2de066a..8e74238 100644 --- a/preprocessing.py +++ b/preprocessing.py @@ -70,7 +70,7 @@ class FuncTransform(): return X_log -def clustering(X, n_clusters=2, random_state=42, x_length=50, y_length=50): +def clustering(X, n_clusters=2, random_state=42, x_length=50, y_length=50, species='Barite'): ''' Function to cluster data with KMeans. ''' @@ -80,7 +80,7 @@ def clustering(X, n_clusters=2, random_state=42, x_length=50, y_length=50): iterations = int(len(X) / grid_length) for i in range(0, iterations): - field = np.array(X['Barite'][(i*grid_length):(i*grid_length+grid_length)] + field = np.array(X[species][(i*grid_length):(i*grid_length+grid_length)] ).reshape(x_length, y_length) kmeans = KMeans(n_clusters=n_clusters, random_state=random_state).fit( field.reshape(-1, 1))