machinelearning

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 53cfb87457de6a8a7f2ef8c901d0fb0bbf32d2d5
parent 580d6fd0595d8b065e89313dd0ebec6a4ed5b387
Author: Andrew <andrewlaack1@gmail.com>
Date:   Tue, 11 Jun 2024 11:05:48 -0500

Completed mnist using NNs. The first time I was being really stupid and used regression and rounding to find the nearest int (stupid) while the second time I did it right with onehot encoding and softmax functions.

Diffstat:
AhousingPricePredictions/WideAndDeepHousing.ipynb | 199+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amnist/MNISTProperNNClassification.ipynb | 325+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amnist/MNISTRegressionClassificationNN.ipynb | 405+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 929 insertions(+), 0 deletions(-)

diff --git a/housingPricePredictions/WideAndDeepHousing.ipynb b/housingPricePredictions/WideAndDeepHousing.ipynb @@ -0,0 +1,199 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# Wide and deep neural network where some inputs connect directly\n", + "# to the output layer.\n", + "\n", + "from sklearn.datasets import fetch_california_housing\n", + "from sklearn.model_selection import train_test_split\n", + "\n", + "housing = fetch_california_housing()\n", + "\n", + "# Split train, validation, and test (in that order).\n", + "X_train_full, X_test, y_train_full, y_test = train_test_split(housing.data,housing.target,random_state=10)\n", + "X_train, X_valid, y_train, y_valid = train_test_split(X_train_full, y_train_full, random_state=10)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "import tensorflow as tf" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2024-06-11 07:16:44.447110: I external/local_xla/xla/stream_executor/cuda/cuda_executor.cc:998] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355\n", + "2024-06-11 07:16:44.447612: W tensorflow/core/common_runtime/gpu/gpu_device.cc:2251] Cannot dlopen some GPU libraries. Please make sure the missing libraries mentioned above are installed properly if you would like to use GPU. Follow the guide at https://www.tensorflow.org/install/gpu for how to download and setup the required libraries for your platform.\n", + "Skipping registering GPU devices...\n" + ] + } + ], + "source": [ + "# Normalize input layer\n", + "normalization_layer = tf.keras.layers.Normalization()\n", + "\n", + "hidden_layer1 = tf.keras.layers.Dense(30,activation='relu')\n", + "hidden_layer2 = tf.keras.layers.Dense(30, activation='relu')\n", + "concat_layer = tf.keras.layers.Concatenate()\n", + "output_layer = tf.keras.layers.Dense(1)\n", + "\n", + "input_ = tf.keras.layers.Input(shape=X_train.shape[1:])\n", + "normalized = normalization_layer(input_)\n", + "hidden1 = hidden_layer1(normalized)\n", + "hidden2 = hidden_layer2(hidden1)\n", + "concat = concat_layer([normalized,hidden2])\n", + "output = output_layer(concat)\n", + "\n", + "model=tf.keras.Model(inputs=[input_], outputs=[output])" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 1/20\n", + "\u001b[1m363/363\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m1s\u001b[0m 1ms/step - RootMeanSquaredError: 1.4987 - loss: 2.3452 - val_RootMeanSquaredError: 0.7227 - val_loss: 0.5223\n", + "Epoch 2/20\n", + "\u001b[1m363/363\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 919us/step - RootMeanSquaredError: 0.6972 - loss: 0.4863 - val_RootMeanSquaredError: 0.6341 - val_loss: 0.4021\n", + "Epoch 3/20\n", + "\u001b[1m363/363\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 933us/step - RootMeanSquaredError: 0.6157 - loss: 0.3793 - val_RootMeanSquaredError: 0.6213 - val_loss: 0.3860\n", + "Epoch 4/20\n", + "\u001b[1m363/363\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m1s\u001b[0m 907us/step - RootMeanSquaredError: 0.5996 - loss: 0.3596 - val_RootMeanSquaredError: 0.6070 - val_loss: 0.3684\n", + "Epoch 5/20\n", + "\u001b[1m363/363\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 941us/step - RootMeanSquaredError: 0.5886 - loss: 0.3465 - val_RootMeanSquaredError: 0.6063 - val_loss: 0.3677\n", + "Epoch 6/20\n", + "\u001b[1m363/363\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 1ms/step - RootMeanSquaredError: 0.6041 - loss: 0.3655 - val_RootMeanSquaredError: 0.6038 - val_loss: 0.3645\n", + "Epoch 7/20\n", + "\u001b[1m363/363\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 1ms/step - RootMeanSquaredError: 0.5711 - loss: 0.3265 - val_RootMeanSquaredError: 0.5917 - val_loss: 0.3501\n", + "Epoch 8/20\n", + "\u001b[1m363/363\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 986us/step - RootMeanSquaredError: 0.5671 - loss: 0.3218 - val_RootMeanSquaredError: 0.5876 - val_loss: 0.3453\n", + "Epoch 9/20\n", + "\u001b[1m363/363\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m1s\u001b[0m 978us/step - RootMeanSquaredError: 0.5696 - loss: 0.3246 - val_RootMeanSquaredError: 0.5761 - val_loss: 0.3319\n", + "Epoch 10/20\n", + "\u001b[1m363/363\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 992us/step - RootMeanSquaredError: 0.5517 - loss: 0.3050 - val_RootMeanSquaredError: 0.5794 - val_loss: 0.3357\n", + "Epoch 11/20\n", + "\u001b[1m363/363\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 1ms/step - RootMeanSquaredError: 0.5696 - loss: 0.3246 - val_RootMeanSquaredError: 0.5742 - val_loss: 0.3297\n", + "Epoch 12/20\n", + "\u001b[1m363/363\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m1s\u001b[0m 1ms/step - RootMeanSquaredError: 0.5562 - loss: 0.3095 - val_RootMeanSquaredError: 0.5681 - val_loss: 0.3227\n", + "Epoch 13/20\n", + "\u001b[1m363/363\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 876us/step - RootMeanSquaredError: 0.5655 - loss: 0.3199 - val_RootMeanSquaredError: 0.5703 - val_loss: 0.3252\n", + "Epoch 14/20\n", + "\u001b[1m363/363\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m1s\u001b[0m 991us/step - RootMeanSquaredError: 0.5426 - loss: 0.2946 - val_RootMeanSquaredError: 0.5660 - val_loss: 0.3204\n", + "Epoch 15/20\n", + "\u001b[1m363/363\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 933us/step - RootMeanSquaredError: 0.5347 - loss: 0.2861 - val_RootMeanSquaredError: 0.5627 - val_loss: 0.3166\n", + "Epoch 16/20\n", + "\u001b[1m363/363\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 962us/step - RootMeanSquaredError: 0.5326 - loss: 0.2838 - val_RootMeanSquaredError: 0.5628 - val_loss: 0.3167\n", + "Epoch 17/20\n", + "\u001b[1m363/363\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 920us/step - RootMeanSquaredError: 0.5451 - loss: 0.2972 - val_RootMeanSquaredError: 0.5665 - val_loss: 0.3209\n", + "Epoch 18/20\n", + "\u001b[1m363/363\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m1s\u001b[0m 1ms/step - RootMeanSquaredError: 0.5404 - loss: 0.2921 - val_RootMeanSquaredError: 0.5643 - val_loss: 0.3184\n", + "Epoch 19/20\n", + "\u001b[1m363/363\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 1ms/step - RootMeanSquaredError: 0.5490 - loss: 0.3018 - val_RootMeanSquaredError: 0.5578 - val_loss: 0.3112\n", + "Epoch 20/20\n", + "\u001b[1m363/363\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m1s\u001b[0m 1ms/step - RootMeanSquaredError: 0.5252 - loss: 0.2759 - val_RootMeanSquaredError: 0.5604 - val_loss: 0.3140\n" + ] + } + ], + "source": [ + "optimizer = tf.keras.optimizers.Adam(learning_rate=1e-3)\n", + "model.compile(loss=\"mse\", optimizer=optimizer, metrics=[\"RootMeanSquaredError\"])\n", + "\n", + "normalization_layer.adapt(X_train)\n", + "\n", + "history = model.fit(X_train , y_train, epochs=20,\n", + " validation_data=(X_valid, y_valid)\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "<Axes: >" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiMAAAGdCAYAAADAAnMpAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAAB0HUlEQVR4nO3dd5gTdeIG8HfSy+4m2wssLL27dETsohRFEM+KChb8KaAgYuFOxI6eilixnIB62MVypwciAiogIopKlbKwCNvYkuyml/n9MUk22Zpsy5b38zzzTDKZmXxns0tevm0EURRFEBEREUWJLNoFICIioo6NYYSIiIiiimGEiIiIoophhIiIiKKKYYSIiIiiimGEiIiIoophhIiIiKKKYYSIiIiiShHtAoTD6/Xi5MmTiI2NhSAI0S4OERERhUEURZSXlyMjIwMyWe31H20ijJw8eRKZmZnRLgYRERE1wPHjx9G5c+daX28TYSQ2NhaAdDFxcXFRLg0RERGFw2w2IzMzM/A9Xps2EUb8TTNxcXEMI0RERG1MfV0s2IGViIiIoophhIiIiKKKYYSIiIiiqk30GSGijkMURbjdbng8nmgXhYjqIZfLoVAoGj3tBsMIEbUaTqcTeXl5sFqt0S4KEYVJp9MhPT0dKpWqwedgGCGiVsHr9SInJwdyuRwZGRlQqVSc5JCoFRNFEU6nE0VFRcjJyUGvXr3qnNisLgwjRNQqOJ1OeL1eZGZmQqfTRbs4RBQGrVYLpVKJY8eOwel0QqPRNOg87MBKRK1KQ/9nRUTR0RR/s/yrJyIioqhiGCEiIgrDqlWrYDQao12MdolhhIiokWbMmAFBECAIApRKJbp164Z7770Xdru9yd7j3HPPxbx580K2HT16FIIgQC6X48SJEyGv5eXlBYZcHj16tMnKEa433ngD2dnZiImJgdFoxJAhQ7BkyZIWL0dzWrVqVeBzD14a2m+iI2MHViKiJjB+/HisXLkSLpcLO3fuxPTp0yEIAp566qlmf+9OnTrh7bffxsKFCwPb3nrrLXTq1Am5ubnN/v5VrVixAvPmzcMLL7yAc845Bw6HA7///jt2797d4mWpyuPxQBCEJuubFBcXhwMHDoRsq2sUmNPprDYEVhRFeDweKBSRfSU39LjWqGPXjPz4KvDfu4CiA/XvS0RUB7VajbS0NGRmZmLKlCkYO3Ys1q9fDwBwOBy48847kZKSAo1GgzPPPBM7duwIOX7z5s0YOXIk1Go10tPTcf/998PtdgOQal42b96M559/PvC/7+DajunTp2PlypUh51u5ciWmT59erZy7d+/GhAkTEBMTg9TUVFx//fU4depU4PW1a9fizDPPhNFoRGJiIi655BIcPnw48Lq/NmbNmjU477zzoNPpkJ2djW3btgX2+eKLL3DllVfi5ptvRs+ePTFgwABcc801ePzxxwP7eDwezJ8/P/A+9957L6ZPn44pU6YE9snKysKyZctCyj948GA89NBDgedLly7FoEGDoNfrkZmZiVmzZqGioiLwur9p5YsvvkD//v2hVquRm5sLh8OBBQsWoFOnTtDr9Rg1ahQ2bdoU8l6rVq1Cly5doNPpcNlll6G4uLjaz1MQBKSlpYUsqampgdfPPfdczJkzB/PmzUNSUhLGjRuHTZs2QRAE/O9//8OwYcOgVqvxww8/1Pt7Uttx7UHHDiO7PwZ+XgGc+jPaJSGiKkRRhNXpjsoiimKjyr57925s3bo18D/ge++9F5988gneeust/PLLL+jZsyfGjRuHkpISAMCJEycwceJEjBgxAr/99huWL1+ON998E4899hgA4Pnnn8fo0aMxc+ZM5OXlIS8vD5mZmYH3u/TSS1FaWhr4Yvrhhx9QWlqKSZMmhZSrrKwM559/PoYMGYKff/4Za9euRUFBAa688srAPhaLBfPnz8fPP/+MDRs2QCaT4bLLLoPX6w051z/+8Q8sWLAAu3btQu/evXHNNdcEwlNaWhp+/PFHHDt2rNaf0bPPPotVq1ZhxYoV+OGHH1BSUoJPP/004p+1TCbDCy+8gD179uCtt97Ct99+i3vvvTdkH6vViqeeegr/+te/sGfPHqSkpGDOnDnYtm0b3n//ffz++++44oorMH78eBw8eBAAsH37dtx8882YM2cOdu3ahfPOOy/weUTqrbfegkqlwpYtW/Dqq68Gtt9///148sknsW/fPpx22mn1/p7Udlx70PbrdhpDnyytLUXRLQcRVWNzedD/wXVRee+9j4yDThXZP4///e9/ERMTA7fbDYfDAZlMhpdeegkWiwXLly/HqlWrMGHCBABSf4r169fjzTffxD333INXXnkFmZmZeOmllyAIAvr27YuTJ0/ivvvuw4MPPgiDwQCVSgWdToe0tLRq761UKnHddddhxYoVOPPMM7FixQpcd911UCqVIfu99NJLGDJkCJ544onAthUrViAzMxN//vknevfujcsvvzzkmBUrViA5ORl79+7FwIEDA9sXLFiAiy++GADw8MMPY8CAATh06BD69u2LxYsXY+rUqcjKykLv3r0xevRoTJw4EX/7298CzSPLli3DwoULMXXqVADAq6++inXrIv+8g/vRZGVl4bHHHsNtt92GV155JbDd5XLhlVdeQXZ2NgAgNzcXK1euRG5uLjIyMgLXs3btWqxcuRJPPPEEnn/+eYwfPz4QbHr37o2tW7di7dq1Ie9vMpkQExMTsu2ss87C//73v8DzXr164Z///GfgeV5eHgDgkUcewYUXXggAYf2e+AUf11507DCiS5TWlupVb0REkTjvvPOwfPlyWCwWPPfcc1AoFLj88svx+++/w+VyYcyYMYF9lUolRo4ciX379gEA9u3bh9GjR4f0NRgzZgwqKirw119/oUuXLvW+/0033YQzzjgDTzzxBD766CNs27YtUFPh99tvv2Hjxo3VvjwB4PDhw+jduzcOHjyIBx98ENu3b8epU6cCNSK5ubkhYST4f+Tp6ekAgMLCQvTt2xfp6enYtm0bdu/eje+++w5bt27F9OnT8a9//Qtr165FeXk58vLyMGrUqMA5FAoFhg8fHnGt1DfffIMlS5Zg//79MJvNcLvdsNvtsFqtgcnzVCpVSHn/+OMPeDwe9O7dO+RcDocDiYnS98K+fftw2WWXhbw+evToamEkNjYWv/zyS8g2rVYb8nzYsGE1ln348OGBx4cPH67396Sm49qLjh1GWDNC1GpplXLsfWRc1N47Unq9Hj179gQg1SZkZ2fjzTffxIgRI5q6eDUaNGgQ+vbti2uuuQb9+vXDwIEDsWvXrpB9KioqMGnSpBo71foDxaRJk9C1a1e88cYbyMjIgNfrxcCBA+F0OkP2D6518Yeoqk05AwcOxMCBAzFr1izcdtttOOuss7B582YMHTo0rGuSyWTVwonL5Qo8Pnr0KC655BLcfvvtePzxx5GQkIAffvgBN998M5xOZyCMaLXakKBXUVEBuVyOnTt3Qi4P/axrCmr1ldH/uddGr9dHtL0+DT2uNWMYARhGiFohQRAibippLWQyGf7+979j/vz5OHToUKC/QNeuXQFIX6g7duwINDH069cPn3zyCURRDHxpbtmyBbGxsejcuTMA6X/39d3J+KabbsKsWbOwfPnyGl8fOnQoPvnkE2RlZdU4AqO4uBgHDhzAG2+8gbPOOgsAmqyDZP/+/QFIzREGgwHp6enYvn07zj77bACA2+3Gzp07Q4JKcnJyoEkDAMxmM3JycgLPd+7cCa/Xi2effTbQ/PPhhx/WW5YhQ4bA4/GgsLAwcJ1V9evXD9u3bw/Z9uOPP4Z5tZHr0aNHvb8n7VnH7sDKMEJEzeSKK66AXC7H8uXLcfvtt+Oee+7B2rVrsXfvXsycORNWqxU333wzAGDWrFk4fvw47rjjDuzfvx+ff/45Fi9ejPnz5we+ZLOysrB9+3YcPXo0pPkk2MyZM1FUVIRbbrmlxjLNnj0bJSUluOaaa7Bjxw4cPnwY69atw4033giPx4P4+HgkJibi9ddfx6FDh/Dtt99i/vz5EV/77bffjkcffRRbtmzBsWPH8OOPP+KGG25AcnIyRo8eDQCYO3cunnzySXz22WfYv38/Zs2ahbKyspDznH/++XjnnXfw/fff448//sD06dNDajJ69uwJl8uFF198EUeOHME777wT0kG0Nr1798a0adNwww03YM2aNcjJycFPP/2EJUuW4MsvvwQA3HnnnVi7di2eeeYZHDx4EC+99FK1JhpA6midn59fbanp86mLXq+v9/ekPevgYSRJWltO1b0fEVGEFAoF5syZg3/+8594/PHHcfnll+P666/H0KFDcejQIaxbtw7x8fEApHlCvvrqK/z000/Izs7GbbfdhptvvhkPPPBA4HwLFiyAXC5H//79kZycXOP8IQqFAklJSbXOO5GRkYEtW7bA4/HgoosuwqBBgzBv3jwYjUbIZDLIZDK8//772LlzJwYOHIi77roLTz/9dMTXPnbsWPz444+44oorAp1iNRoNNmzYEOiTcffdd+P666/H9OnTMXr0aMTGxlbro7Fw4UKcc845uOSSS3DxxRdjypQp6NGjR+D17OxsLF26FE899RQGDhyI1atXhz2x2sqVK3HDDTfg7rvvRp8+fTBlyhTs2LEj0D/n9NNPxxtvvIHnn38e2dnZ+Prrr0M+Dz+z2Yz09PRqS2FhYcQ/tyeffLLO35P2TBAbO4atBZjNZhgMBphMJsTFxTXdifN3A6+OAXRJwL2H69+fiJqN3W5HTk4OunXrxhksO6gZM2agrKwMn332WbSLQhGo62833O/vDl4z4mumsRYD3rrbYomIiKh5dOww4h/aCxGwltS5KxERETWPttlVvanIFYA2HrCVAtZTQExytEtERNRhrVq1KtpFoCjp2DUjAEfUEBERRRnDCMMIERFRVDGMcHgvERFRVDGMsGaEiIgoqhhGGEaIiIiiimGEzTRERERRxTDCmhEiaoRzzz23Q9zIjKg5MYzoWDNCREQUTQwjgZoRhhEiIqJoYBjx9xlxmAC3I7plIaI2rbS0FDfccAPi4+Oh0+kwYcIEHDx4MPD6sWPHMGnSJMTHx0Ov12PAgAH46quvAsdOmzYNycnJ0Gq16NWrF1auXBmtSyFqUR17OngA0BgBmQLwuqXaEUOnaJeIiABAFAGXNTrvrdQBghDxYTNmzMDBgwfxxRdfIC4uDvfddx8mTpyIvXv3QqlUYvbs2XA6nfjuu++g1+uxd+9exMTEAAAWLVqEvXv34n//+x+SkpJw6NAh2Gy2pr4yolaJYUQmk/qNVORLnVgZRohaB5cVeCIjOu/995OASh/RIf4QsmXLFpxxxhkAgNWrVyMzMxOfffYZrrjiCuTm5uLyyy/HoEGDAADdu3cPHJ+bm4shQ4Zg+PDhAICsrKymuRaiNoDNNAD7jRBRo+3btw8KhQKjRo0KbEtMTESfPn2wb98+AMCdd96Jxx57DGPGjMHixYvx+++/B/a9/fbb8f7772Pw4MG49957sXXr1ha/BqJoYc0IEDTXCIf3ErUaSp1UQxGt924Gt9xyC8aNG4cvv/wSX3/9NZYsWYJnn30Wd9xxByZMmIBjx47hq6++wvr163HBBRdg9uzZeOaZZ5qlLEStCWtGAM41QtQaCYLUVBKNpQH9Rfr16we3243t27cHthUXF+PAgQPo379/YFtmZiZuu+02rFmzBnfffTfeeOONwGvJycmYPn06/v3vf2PZsmV4/fXXG/czJGojWDMCVNaMWNlMQ0QN06tXL0yePBkzZ87Ea6+9htjYWNx///3o1KkTJk+eDACYN28eJkyYgN69e6O0tBQbN25Ev379AAAPPvgghg0bhgEDBsDhcOC///1v4DWi9o41IwCnhCeiJrFy5UoMGzYMl1xyCUaPHg1RFPHVV19BqVQCADweD2bPno1+/fph/Pjx6N27N1555RUAgEqlwsKFC3Haaafh7LPPhlwux/vvvx/NyyFqMYIoimK0C1Efs9kMg8EAk8mEuLi4pn+DX94GvrgD6HURMO2jpj8/EdXLbrcjJycH3bp1g0ajiXZxiChMdf3thvv9zZoRgH1GiIiIoijiMPLdd99h0qRJyMjIgCAI+Oyzz+rcf82aNbjwwguRnJyMuLg4jB49GuvWrWtoeZsHh/YSERFFTcRhxGKxIDs7Gy+//HJY+3/33Xe48MIL8dVXX2Hnzp0477zzMGnSJPz6668RF7bZBA/tbf2tVkRERO1KxKNpJkyYgAkTJoS9/7Jly0KeP/HEE/j888/xn//8B0OGDIn07ZuHv2bEbQecFYA6NrrlISIi6kBafGiv1+tFeXk5EhISat3H4XDA4ai8aZ3ZbG7eQqn00iRHLqvUVMMwQkRE1GJavAPrM888g4qKClx55ZW17rNkyRIYDIbAkpmZ2fwF03F4LxERUTS0aBh599138fDDD+PDDz9ESkpKrfstXLgQJpMpsBw/frz5C8cp4YmIiKKixZpp3n//fdxyyy346KOPMHbs2Dr3VavVUKvVLVQyHw7vJSIiiooWqRl57733cOONN+K9997DxRdf3BJvGTmGESIioqiIuGakoqIChw4dCjzPycnBrl27kJCQgC5dumDhwoU4ceIE3n77bQBS08z06dPx/PPPY9SoUcjPzwcAaLVaGAyGJrqMJsAp4YmIiKIi4pqRn3/+GUOGDAkMy50/fz6GDBmCBx98EACQl5eH3NzcwP6vv/463G43Zs+ejfT09MAyd+7cJrqEJsKaESKKkqysrGrTIBDNmDEDU6ZMiXYxWkTEYeTcc8+FKIrVllWrVgEAVq1ahU2bNgX237RpU537txoMI0TUBmRlZUEQBAiCAJ1Oh0GDBuFf//pXk79PTTNsr1q1CoIg1Hg34Y8++giCICArK6vJy1Ifq9WKhQsXokePHtBoNEhOTsY555yDzz//vMXL0pxmzJgR+OyDl/Hjx0e7aI3W4vOMtFr+ZhprcXTLQURUj0ceeQQzZ86E1WrFRx99hJkzZ6JTp04RTUjZUHq9HoWFhdi2bRtGjx4d2P7mm2+iS5cuzf7+Nbntttuwfft2vPjii+jfvz+Ki4uxdetWFBdH/99zp9MJlUrVZOcbP348Vq5cGbKtrgEfLpcrcNfoxpapqa8lGG+U58ehvUStiiiKsLqsUVkiuZn566+/joyMDHi93pDtkydPxk033YTDhw9j8uTJSE1NRUxMDEaMGIFvvvmmUT+b2NhYpKWloXv37rjvvvuQkJCA9evXB17Pzc3F5MmTERMTg7i4OFx55ZUoKCgIOcfy5cvRo0cPqFQq9OnTB++8807gNX/txmWXXVattkOhUODaa6/FihUrAtv++usvbNq0Cddee221sn7++ecYOnQoNBoNunfvjocffhhutzvw+tKlSzFo0CDo9XpkZmZi1qxZqKioCLy+atUqGI1GrFu3Dv369UNMTAzGjx+PvLy8wD5ffPEF/v73v2PixInIysrCsGHDcMcdd+Cmm24K7FNYWIhJkyZBq9WiW7duWL16dUjz2NGjRyEIAnbt2hU4pqysDIIgBGr7PR4Pbr75ZnTr1g1arRZ9+vTB888/H3K9/qaVxx9/HBkZGejTpw8A4Pjx47jyyithNBqRkJCAyZMn4+jRo4HjPB4P5s+fD6PRiMTERNx77701/h6q1WqkpaWFLPHx8YHXBUHA8uXLcemll0Kv1+Pxxx/HQw89hMGDB+Nf//pXyJ116/s9qe245sCaEb/gm+V5vYCMOY0ommxuG0a9Oyoq77392u3QKXVh7XvFFVfgjjvuwMaNG3HBBRcAAEpKSrB27Vp89dVXqKiowMSJE/H4449DrVbj7bffxqRJk3DgwIFG1yR4vV58+umnKC0tDfyP1ev1Br5gNm/eHOizd9VVVwW+VD/99FPMnTsXy5Ytw9ixY/Hf//4XN954Izp37ozzzjsPO3bsQEpKClauXInx48dDLpeHvO9NN92Ec889F88//zx0Oh1WrVqF8ePHIzU1NWS/77//HjfccANeeOEFnHXWWTh8+DBuvfVWAMDixYsBADKZDC+88AK6deuGI0eOYNasWbj33nvxyiuvBM5jtVrxzDPP4J133oFMJsN1112HBQsWYPXq1QCAtLQ0fPXVV5g6dSpiY2ueQXvGjBk4efIkNm7cCKVSiTvvvBOFhYUR/7w7d+6Mjz76CImJidi6dStuvfVWpKenh0zkuWHDBsTFxQUCosvlwrhx4zB69Gh8//33UCgUeOyxxzB+/Hj8/vvvUKlUePbZZ7Fq1SqsWLEC/fr1w7PPPotPP/0U559/fkRlBKQQ8eSTT2LZsmVQKBRYsWIFDh06hE8++QRr1qyBXC4P6/cEQLXjmo3YBphMJhGAaDKZmu9NXA5RXBwnLZbi5nsfIqqRzWYT9+7dK9psNlEURdHitIgDVw2MymJxWiIq++TJk8Wbbrop8Py1114TMzIyRI/HU+P+AwYMEF988cXA865du4rPPfdcWO/VtWtXUaVSiXq9XlQoFCIAMSEhQTx48KAoiqL49ddfi3K5XMzNzQ0cs2fPHhGA+NNPP4miKIpnnHGGOHPmzJDzXnHFFeLEiRMDzwGIn376acg+K1euFA0GgyiKojh48GDxrbfeEr1er9ijRw/x888/F5977jmxa9eugf0vuOAC8Yknngg5xzvvvCOmp6fXen0fffSRmJiYGPKeAMRDhw4Ftr388stiampq4PnmzZvFzp07i0qlUhw+fLg4b9488Ycffgi8fuDAgZDrF0VR3Ldvnwgg8HPPyckRAYi//vprYJ/S0lIRgLhx48Zayzt79mzx8ssvDzyfPn26mJqaKjocjpBr7tOnj+j1egPbHA6HqNVqxXXr1omiKIrp6eniP//5z8DrLpdL7Ny5szh58uSQc8vlclGv14csjz/+eGAfAOK8efNCyrh48WJRqVSKhYWFgW3h/J7UdFxNqv7tBgv3+5s1I34KFaAxAHaT1FSjq/3eOUTU/LQKLbZfuz1q7x2JadOmYebMmXjllVegVquxevVqXH311ZDJZKioqMBDDz2EL7/8Enl5eXC73bDZbCGjDiN1zz33YMaMGcjLy8M999yDWbNmoWfPngCAffv2ITMzM+Q2Gv3794fRaMS+ffswYsQI7Nu3L1BD4TdmzJhqTQ51uemmm7By5Up06dIFFosFEydOxEsvvRSyz2+//YYtW7bg8ccfD2zzeDyw2+2wWq3Q6XT45ptvsGTJEuzfvx9msxlutzvkdQDQ6XTo0aNH4Bzp6ekhtRpnn302jhw5gh9//BFbt27Fhg0b8Pzzz+Phhx/GokWLsG/fPigUCgwbNixwTN++fWE0GsO+Xr+XX34ZK1asQG5uLmw2G5xOJwYPHhyyz6BBg0L6Vvz22284dOhQtVobu92Ow4cPw2QyIS8vD6NGVdYEKhQKDB8+vFpTzXnnnYfly5eHbKt6r7fhw4dXK3fXrl2RnJwceB7O70lNxzUXhpFg+uTKMJLcJ9qlIerQBEEIu6kk2iZNmgRRFPHll19ixIgR+P777/Hcc88BABYsWID169fjmWeeQc+ePaHVavG3v/0NTqezwe+XlJSEnj17omfPnvjoo48waNAgDB8+HP3792+qS6rXtGnTcO+99+Khhx7C9ddfD4Wi+tdJRUUFHn74YUydOrXaaxqNBkePHsUll1yC22+/HY8//jgSEhLwww8/4Oabb4bT6QyEkaodMAVBqPYlrVQqcdZZZ+Gss87Cfffdh8ceewyPPPII7rvvvrCuR+Zrmg8+r8vlCtnn/fffx4IFC/Dss89i9OjRiI2NxdNPP43t20NDs16vr/ZzGDZsWKBZKVikX/R6vT4QPOvaJ5xt4b5fS2DHiGAc3ktEDaDRaDB16lSsXr0a7733Hvr06YOhQ4cCALZs2YIZM2bgsssuw6BBg5CWlhbScbGxMjMzcdVVV2HhwoUAgH79+uH48eMh9/Tau3cvysrKAmGlX79+2LJlS8h5tmzZEhJmlEolPB5Pre+bkJCASy+9FJs3bw7pKBps6NChOHDgQCA4BS8ymQw7d+6E1+vFs88+i9NPPx29e/fGyZMnG/yzCNa/f/9ALUvfvn3hdruxc+fOwOsHDhxAWVlZ4Lk/FAR3jA3uzApIP6MzzjgDs2bNwpAhQ9CzZ08cPny43rIMHToUBw8eREpKSrWfg/+GsOnp6SGhpmp5m1o4vyctiTUjwTgLKxE10LRp03DJJZdgz549uO666wLbe/XqhTVr1mDSpEkQBAGLFi2qNvKmsebOnYuBAwfi559/xtixYzFo0CBMmzYNy5Ytg9vtxqxZs3DOOecEqu/vueceXHnllRgyZAjGjh2L//znP1izZk3IKJ+srCxs2LABY8aMgVqtDhmx4bdq1Sq88sorSExMrLFcDz74IC655BJ06dIFf/vb3yCTyfDbb79h9+7deOyxx9CzZ0+4XC68+OKLmDRpErZs2YJXX3014us/99xzcc0112D48OFITEzE3r178fe//x3nnXce4uLiEBcXh/Hjx+P//u//sHz5cigUCsybNw9abWVznFarxemnn44nn3wS3bp1Q2FhIR544IGQ9+nVqxfefvttrFu3Dt26dcM777yDHTt2oFu3bnWWb9q0aXj66acxefJkPPLII+jcuTOOHTuGNWvW4N5770Xnzp0xd+5cPPnkk+jVqxf69u2LpUuXhoQlP4fDEZjJ3E+hUCApKSmin1k4vyctiTUjwYJH1BARReD8889HQkICDhw4EDLEdenSpYiPj8cZZ5yBSZMmYdy4cYFak6bSv39/XHTRRXjwwQchCAI+//xzxMfH4+yzz8bYsWPRvXt3fPDBB4H9p0yZgueffx7PPPMMBgwYgNdeew0rV67EueeeG9jn2Wefxfr165GZmRmYcbsqrVZbaxABgHHjxuG///0vvv76a4wYMQKnn346nnvuOXTt2hUAkJ2djaVLl+Kpp57CwIEDsXr1aixZsiTi6x83bhzeeustXHTRRejXrx/uuOMOjBs3Dh9++GFgn5UrVyIjIwPnnHMOpk6diltvvbXa3eNXrFgBt9uNYcOGYd68eXjsscdCXv+///s/TJ06FVdddRVGjRqF4uJizJo1q97y6XQ6fPfdd+jSpQumTp2Kfv364eabb4bdbkdcXBwA4O6778b111+P6dOnB5qALrvssmrnWrt2bchs5unp6TjzzDMj/pmF83vSkgSxasNbK2Q2m2EwGGAymQIfXLP49nHgu38Cw28GLlnafO9DRNXY7Xbk5OQ0+3wGRH5ZWVmYN28e5s2bF+2itGl1/e2G+/3NmpFg7DNCRETU4jp0GPl2fwFe3ngIBWa7tIF9RogoilavXo2YmJgalwEDBkS7eETNpkN3YH1m3Z/Ym2dGn9RYpPbXsGaEiKLq0ksvDZlrIljV4a3UeE05qokap0OHkR4pMdibZ8bhogqMRSrDCBFFVWxsbK3TmRO1Zx26maZHsjSZy+Ei302Z/GHEXga4Gz4hEREREYWvg4eRGADA4SKLtEEbDwi+H4k1+reeJiIi6ggYRhBUMyKTATpfJ1YrO7ESERG1hA4dRrolSc00ZVYXSiy+ZpnAiBr2GyEiImoJHTqMaFVydDJK0wFX9hvh8F4iIqKW1KHDCCCNqAGAw4VVOrGyZoSIWkhWVhaWLVsW1r6CIOCzzz5r1vIQtTSGkdpG1DCMEBERtQiGkaojathnhIiIqEV1+DDS3VczcqRazQj7jBBFkyiK8FqtUVkiuX/o66+/joyMDHi93pDtkydPxk033YTDhw9j8uTJSE1NRUxMDEaMGIFvvvmmyX5Of/zxB84///zAHXRvvfVWVFRUBF7ftGkTRo4cCb1eD6PRiDFjxuDYsWMAgN9++w3nnXceYmNjERcXh2HDhuHnn39usrIRhatDz8AKAD19NSO5JVY43B6o2UxD1CqINhsODB0Wlffu88tOCDpdWPteccUVuOOOO7Bx40ZccMEFAICSkhKsXbsWX331FSoqKjBx4kQ8/vjjUKvVePvttzFp0iQcOHAAXbp0aVQ5LRYLxo0bh9GjR2PHjh0oLCzELbfcgjlz5mDVqlVwu92YMmUKZs6ciffeew9OpxM//fQTBEEAAEybNg1DhgzB8uXLIZfLsWvXLk47T1HR4cNIcqwasWoFyh1uHCu2ojdrRogoAvHx8ZgwYQLefffdQBj5+OOPkZSUhPPOOw8ymQzZ2dmB/R999FF8+umn+OKLLzBnzpxGvfe7774Lu92Ot99+G3q9VMv70ksvYdKkSXjqqaegVCphMplwySWXoEePHgCAfv36BY7Pzc3FPffcg759+wIAevXq1ajyEDVUhw8jgiCge0oMfjtehsOFFeidkSi9wDBCFFWCVos+v+yM2ntHYtq0aZg5cyZeeeUVqNVqrF69GldffTVkMhkqKirw0EMP4csvv0ReXh7cbjdsNhtyc3MbXc59+/YhOzs7EEQAYMyYMfB6vThw4ADOPvtszJgxA+PGjcOFF16IsWPH4sorr0R6ejoAYP78+bjlllvwzjvvYOzYsbjiiisCoYWoJXX4PiNAlRE1/poRlwVwWqJYKqKOTRAEyHS6qCz+ZoxwTZo0CaIo4ssvv8Tx48fx/fffY9q0aQCABQsW4NNPP8UTTzyB77//Hrt27cKgQYPgdLbM/a9WrlyJbdu24YwzzsAHH3yA3r1748cffwQAPPTQQ9izZw8uvvhifPvtt+jfvz8+/fTTFikXUTCGEVQZUaOOBeRq6QXWjhBRGDQaDaZOnYrVq1fjvffeQ58+fTB06FAAwJYtWzBjxgxcdtllGDRoENLS0prs1vX9+vXDb7/9Boul8j9OW7ZsgUwmQ58+fQLbhgwZgoULF2Lr1q0YOHAg3n333cBrvXv3xl133YWvv/4aU6dOxcqVK5ukbESRYBhBZc3IkaIKQBA4ooaIIjZt2jR8+eWXWLFiRaBWBJD6YaxZswa7du3Cb7/9hmuvvbbayJvGvKdGo8H06dOxe/dubNy4EXfccQeuv/56pKamIicnBwsXLsS2bdtw7NgxfP311zh48CD69esHm82GOXPmYNOmTTh27Bi2bNmCHTt2hPQpIWopHb7PCBBaMyKKIgR9EmD+iyNqiChs559/PhISEnDgwAFce+21ge1Lly7FTTfdhDPOOANJSUm47777YDabm+Q9dTod1q1bh7lz52LEiBHQ6XS4/PLLsXTp0sDr+/fvx1tvvYXi4mKkp6dj9uzZ+L//+z+43W4UFxfjhhtuQEFBAZKSkjB16lQ8/PDDTVI2okgwjADokqiDXCagwuFGYbkDqRzeS0QRkslkOHnyZLXtWVlZ+Pbbb0O2zZ49O+R5JM02VedAGTRoULXz+6WmptbaB0SlUuG9994L+32JmhObaQCoFXJ0SZDmFDhcWMEp4YmIiFoQw4hP6Iga35Tw1uIoloiIOprVq1cjJiamxmXAgAHRLh5Rs2EzjU/35BhgX6E0oiaR96chopZ36aWXYtSoUTW+xplRqT1jGPEJqRnpwmYaImp5sbGxiI2NjXYxiFocm2l8/CNqjhRZ2GeEKIoiuUkdEUVfU/zNMoz4+MPIiTIbbKp4aSPnGSFqMf5mCKvVGuWSEFEk/H+zjWlKZDONT7xehQS9CiUWJ3LtevQBpJoRUZQmQiOiZiWXy2E0GlFYWAhAmiMj0mnZiajliKIIq9WKwsJCGI1GyOXyBp+LYSRIj2Q9SixO/FmhlsKI1w3YywBtfJRLRtQxpKWlAUAgkBBR62c0GgN/uw3FMBKke1IMdhwtxaESN6COAxxmqamGYYSoRQiCgPT0dKSkpMDlckW7OERUD6VS2agaET+GkSA9UqrMNeIPI0m9olwyoo5FLpc3yT9wRNQ2sANrkJC79+o41wgREVFLYBgJUjm8twKinmGEiIioJTCMBOkcr4VKLoPD7YVFweG9RERELYFhJIhCLkPXROmGecWIkzayZoSIiKhZMYxU4W+qyXP5pmRmGCEiImpWDCNV+EfUHLVLNSRspiEiImpeDCNV+GtGDlo00gbWjBARETUrhpEq/GFkj0ktbbCyZoSIiKg5MYxU0T1ZaqY5VOGrGbGWAB53FEtERETUvjGMVBGrUSIlVo1SxECEAEAEbCXRLhYREVG7xTBSgx7JMfBADqfKKG1gvxEiIqJmwzBSA/+ImnK5UdrAMEJERNRsGEZq4O/EWiz6Jz5jJ1YiIqLmwjBSg8DEZ25OfEZERNTcIg4j3333HSZNmoSMjAwIgoDPPvus3mM2bdqEoUOHQq1Wo2fPnli1alUDitpyeqRIYSTXwYnPiIiImlvEYcRisSA7Oxsvv/xyWPvn5OTg4osvxnnnnYddu3Zh3rx5uOWWW7Bu3bqIC9tS0uM00ChlKPLy/jRERETNTRHpARMmTMCECRPC3v/VV19Ft27d8OyzzwIA+vXrhx9++AHPPfccxo0bF+nbtwiZTED3pBiUFLLPCBERUXNr9j4j27Ztw9ixY0O2jRs3Dtu2bav1GIfDAbPZHLK0tB4pMTglsmaEiIiouTV7GMnPz0dqamrIttTUVJjNZthsthqPWbJkCQwGQ2DJzMxs7mJW0yNZHzSahmGEiIioubTK0TQLFy6EyWQKLMePH2/xMvRIjkExDNITNtMQERE1m4j7jEQqLS0NBQUFIdsKCgoQFxcHrVZb4zFqtRpqtbq5i1an7sE1I85ywGUDlDWXl4iIiBqu2WtGRo8ejQ0bNoRsW79+PUaPHt3cb90o3ZNiYIYOTlEubWDtCBERUbOIOIxUVFRg165d2LVrFwBp6O6uXbuQm5sLQGpiueGGGwL733bbbThy5Ajuvfde7N+/H6+88go+/PBD3HXXXU1zBc1Eq5Kjk1FX2VRjZRghIiJqDhGHkZ9//hlDhgzBkCFDAADz58/HkCFD8OCDDwIA8vLyAsEEALp164Yvv/wS69evR3Z2Np599ln861//arXDeoP1SInhlPBERETNLOI+I+eeey5EUaz19ZpmVz333HPx66+/RvpWUdcjWY+SHE4JT0RE1Jxa5Wia1qJHcgxOBUbUMIwQERE1B4aROnTnXCNERETNjmGkDj2TK/uMeMoZRoiIiJoDw0gdkmPVsCjiAQD2svwol4aIiKh9YhipgyAIUBqkqezd5YVRLg0REVH7xDBSj9jENACAzFYc5ZIQERG1Twwj9UhM6QwA0DhLgTqGNBMREVHDMIzUIy29EwBAKToBR3mUS0NERNT+MIzUo1t6MiyidNM+kcN7iYiImhzDSD26JFben6a06GSUS0NERNT+MIzUQ62Qo0JuBAAU5h2PbmGIiIjaIYaRMDg1iQCAMtaMEBERNTmGkXDokwAA1lJOfEZERNTUGEbCoIqTJj5zcUp4IiKiJscwEoaYhHQAgMx6KsolISIian8YRsKQkCLNNaJzlcLqdEe5NERERO0Lw0gYYhKkZppEwYwjRZYol4aIiKh9YRgJhz4ZAJAomHC4qCLKhSEiImpfGEbC4QsjCShHTqE5yoUhIiJqXxhGwqGT5hmRCyLy8/OiXBgiIqL2hWEkHHIlXCojAKD0FCc+IyIiakoMI2ESgyY+83rFKJeGiIio/WAYCZMyNgUAEOcx4USZLcqlISIiaj8YRsIkxHBEDRERUXNgGAmXTmqm4VwjRERETYthJFy+4b1JMLNmhIiIqAkxjIRLX1kzwjBCRETUdBhGwhUyCyubaYiIiJoKw0i4/GEEZhSVO2CyuaJcICIiovaBYSRc/j4jsnIAwBE21RARETUJhpFw+fqMxMECJdwcUUNERNREGEbCpTECMgUAIIEjaoiIiJoMw0i4ZLLADfOSOKKGiIioyTCMRIIjaoiIiJocw0gk/HONwIxjxRa4Pd4oF4iIiKjtYxiJhK9mJE1RDpdHxPFS3jCPiIiosRhGIuELI921Ugg5XMh+I0RERI3FMBIJXzNNZ7UVANiJlYiIqAkwjETCVzOSKpcmPmMYISIiajyGkUj4wkg8TADAETVERERNgGEkEjqpmUbvKgXAmhEiIqKmwDASCV+fEaW9GICIMqsLJRZndMtERETUxjGMRMLXTCO4behpEACwdoSIiKixGEYiodIDCi0AIDvRDYDDe4mIiBqLYSQSghCoHekXawfAmhEiIqLGYhiJlK/fSA+9P4xwRA0REVFjMIxEylczkqmSQghrRoiIiBqHYSRSQfenAYDjJVY43J5oloiIiKhNYxiJlD5RWrlKEatWwCsCx4qtUS4UERFR28UwEin/8F7rKXRPiQHAETVERESNwTASKV8YgaUIPZL0ANhvhIiIqDEYRiLlG00Dyyn08NeMcEQNERFRgzGMRCpQM3IKPZKlmpEjrBkhIiJqMIaRSPnDiPUUeiTpAEg1I6IoRrFQREREbRfDSKR8d+6F140uehfkMgEVDjcKyx3RLRcREVEb1aAw8vLLLyMrKwsajQajRo3CTz/9VOf+y5YtQ58+faDVapGZmYm77roLdru9QQWOOoUK0BgAAGp7Cbok+GpHOKKGiIioQSIOIx988AHmz5+PxYsX45dffkF2djbGjRuHwsLCGvd/9913cf/992Px4sXYt28f3nzzTXzwwQf4+9//3ujCR42/dsRShO4cUUNERNQoEYeRpUuXYubMmbjxxhvRv39/vPrqq9DpdFixYkWN+2/duhVjxozBtddei6ysLFx00UW45ppr6q1NadWCh/dyRA0REVGjRBRGnE4ndu7cibFjx1aeQCbD2LFjsW3bthqPOeOMM7Bz585A+Dhy5Ai++uorTJw4sdb3cTgcMJvNIUuroq+sGfGPqGHNCBERUcMoItn51KlT8Hg8SE1NDdmempqK/fv313jMtddei1OnTuHMM8+EKIpwu9247bbb6mymWbJkCR5++OFIitaygof3dpNqRo6wZoSIiKhBmn00zaZNm/DEE0/glVdewS+//II1a9bgyy+/xKOPPlrrMQsXLoTJZAosx48fb+5iRiZ4eG+yFEZOlNlgdbqjWCgiIqK2KaKakaSkJMjlchQUFIRsLygoQFpaWo3HLFq0CNdffz1uueUWAMCgQYNgsVhw66234h//+Adksup5SK1WQ61WR1K0lhXUZyRer0K8TolSqwtHiiwY2MkQ3bIRERG1MRHVjKhUKgwbNgwbNmwIbPN6vdiwYQNGjx5d4zFWq7Va4JDL5QDQdicKC5oSHkCgdoT9RoiIiCIXUc0IAMyfPx/Tp0/H8OHDMXLkSCxbtgwWiwU33ngjAOCGG25Ap06dsGTJEgDApEmTsHTpUgwZMgSjRo3CoUOHsGjRIkyaNCkQStqcoJoRQAojPx8r5YgaIiKiBog4jFx11VUoKirCgw8+iPz8fAwePBhr164NdGrNzc0NqQl54IEHIAgCHnjgAZw4cQLJycmYNGkSHn/88aa7ipYWNJoGAHqk8B41REREDSWIbaCtxGw2w2AwwGQyIS4uLtrFkZpnnu4hPV50Chv+LMHNb/2Mfulx+N/cs6JbNiIiolYi3O9v3pumIbTxgOD70VmLA31GjhRVwOtt9dmOiIioVWEYaQiZHNAlSo8tRegcr4VSLsDh9uJEmS26ZSMiImpjGEYaKmjiM4VchqxEzsRKRETUEAwjDVXL8F7OxEpERBQZhpGGqjq8N4U1I0RERA3BMNJQNcw1AjCMEBERRYphpKF0VeYaCYQRNtMQERFFgmGkoar0GemeLDXTFJU7YLK5olUqIiKiNodhpKGqNNPEapRIiZVu7seZWImIiMLHMNJQVcIIwBE1REREDcEw0lD+ZhprcWATR9QQERFFjmGkofw1I84KwGkFwBE1REREDcEw0lDqWEAu9RGB1d+JlSNqiIiIIsUw0lCCUMNcI1IzzbFiC1web7RKRkRE1KYwjDSG3n+zPKlmJMOghUYpg8sj4niJNYoFIyIiajsYRhqjSs2ITCagexJH1BAREUWCYaQxahrem8JOrERERJHo0GHE7rZj8/HNDT9BlVlYgcp+IwwjRERE4emwYcTqsmLG2hm449s78N1f3zXsJIGakcowwhE1REREkemwYUSn1GFA4gCIEHHfd/fhiOlI5CepcRZW1owQERFFosOGEQC4f+T9GJoyFBWuCsz9di7MTnNkJ6ghjPg7sJZZXSixOJuqqERERO1Whw4jSrkSS89dijR9Go6aj+L+7+6Hx+sJ/wQ19BnRquToZNQCYO0IERFRODp0GAGARG0inj/veajlanx/4nu8+OuL4R+s84eRIkAUA5sDI2oKGUaIiIjq0+HDCAD0T+yPR854BADw5u43sTZnbXgH+mtGvC7Abgps7p7EfiNEREThYhjxmdh9Im4ceCMAYNGWRdhXvK/+g5RaQBUrPQ4e3pvCETVEREThYhgJMnfIXIzpNAZ2jx1zN85Fib2k/oP0QU01PhxRQ0REFD6GkSBymRxPnfUUusZ1RZ4lD/M3zYfL66r7IP+IGmtlzUhP31wjx0uscLgj6BBLRETUATGMVGFQG/DCeS9Ar9RjZ8FO/POnf9Z9QA3De5Nj1YhVK+AVgWPFvGEeERFRXRhGatDd2B1PnvUkBAh4/8D7+OTPT2rfuYbhvYIgoDtH1BAREYWFYaQW52aei9mDZwMAHtv+GHYV7qp5xxpqRgCgB0fUEBERhYVhpA63nnYrLux6IdxeN+ZtnId8S371nWrowApwRA0REVG4GEbqIAgCHhvzGHrF90KxvRjzNs6D3W0P3amGm+UBHFFDREQULoaReuiUOrxw3gswqA3YU7wHj2x7BGLQbKu11owkV/YZMdvrGZFDRETUgTGMhKFzbGc8c84zkAty/OfIf/DO3ncqX6ylz0jXRD2SY9WwOD248tVtKDBXqVEhIiIiAAwjYTs9/XQsGL4AAPDszmex7eQ26YXAPCMlQNBN9lQKGVbOGIHkWDX255dj6itbcaiwvKWLTURE1OoxjERgWr9pmNxjMryiFws2L8Bx83FAmwBAACBKgSTIwE4GrLn9DHRP0uNEmQ2XL9+Gn4+GMasrERFRB8IwEgFBELBo9CIMShoEs9OMOzfeCYvXAegSpB2qNNUAQGaCDh/ffgaGdDHCZHNh2r+2Y92eGkblEBERdVAMIxFSy9VYdt4yJGuTcajsEP7xwz/graUTq1+CXoV3bzkdY/ulwOH24vZ/78Q7Px5rwVITERG1XgwjDZCiS8Fz5z0HpUyJDbkb8JpOJb1QSxgBAK1KjlevG4ZrRmbCKwKLPtuNp9ftDx2ZQ0RE1AExjDRQdnI2Fp2+CADwisyEDTpttblGqlLIZXjiskGYf2FvAMDLGw9jwUe/w+XxNnt5iYiIWiuGkUa4rNdluLbvtQCAvycn4lDZoXqPEQQBd17QC09OHQS5TMAnv/yFW976GRaHu7mLS0RE1CoxjDTSghELMFKdCqtMhjuLvoPJYQrruKtHdsHr1w+DRinD5j+LcM0bP+JUhaOZS0tERNT6MIw0klKmxDNdp6CTy43jXhvu2XwP3N7wajku6JeK92aejgS9Cr//ZcLly7fi6Cney4aIiDoWhpEmEG/ogucLi6AVBWzL24ZlO5eFfeyQLvH4+LbRyEzQ4lixFZcv34pdx8uaraxEREStDcNIU9Ano4/ThUetAgDgrb1v4T+H/xP24d2TY7Dm9jEY2CkOxRYnrnn9R2zcX9hcpSUiImpVGEaagm9K+HGmEswcNBMA8NDWh7Dn1J6wT5Ecq8b7t47G2b2TYXN5cMvbP+PDn483S3GJiIhaE4aRpqBPlNYOM+YMvAXndD4HTq8TczfOxSlb3cN9g8WoFXhz+nBMHdoJHq+Iez/+HS9uOMi5SIiIqF1jGGkKGiMgUwAAZLYSLDlrCbLislBgLcB1X12HxVsXY/W+1diRv6Pe0TZKuQzPXpGNWef2AAA8u/5PPPDZbni8DCRERNQ+KaJdgHZBEKSmmvI8wFKEWENnvHj+i7juf9fhRMUJrDm4JmT3FF0Kesf3DlmyDFlQypS+0wm4d3xfpMZp8NB/9mD19lwUljvwwtVDoFXJo3GFREREzUYQ20AbgNlshsFggMlkQlxcXLSLU7NXzwTy/wCmfQL0GgsAKLWXYkf+DvxZ+mdgOVFxosbDFTIFehh6hIaUhN7YcciJuR/8Bqfbi6FdjHhz+gjE61UteWVEREQNEu73N2tGmoqvE2vw/WniNfG4KOsiXJR1UWBbhbMCh8oOhQSUP0v/hMVlwYHSAzhQeiDktAmaBAwekYV9x/T43ZSKS984jJXTLkHP5IQWuSwiIqLmxjDSVGoIIzWJUcVgcMpgDE4ZHNgmiiLyLHnVAsox8zGU2EtQYi8BDIDWAJQBuOzLZ5AR0wWDkvuib0Jf9E/oj/6J/WHUGJvr6oiIiJoNw0hTCTOM1EQQBGTEZCAjJgPnZp4b2G5323HYdBh/lkjhZHfRfvxeuA9emQUnLcdw0nIM646uC+yfoc9A/8T+IUu8Jr6xV0ZERNSsGEaaij5JWtdz595IaBQaDEgcgAGJAwLbyqxO3PzvDdhVsB9KbR66dyqDVTiGYsdJnLRIyze53wT2T9OnBWpO/EuiNrHJykhERNRYDCNNRecPI5HXjETCqFPh3ZsuwvwPU/Hl73nY688+MhuSEoqQllwMpe4kyr1HUWA/jnxLPvIt+fj2+LeBc6TqUqvVoCRpk5q13ERERLVpUBh5+eWX8fTTTyM/Px/Z2dl48cUXMXLkyFr3Lysrwz/+8Q+sWbMGJSUl6Nq1K5YtW4aJEyc2uOCtTiOaaSKlVsjx4tVDMG5AGrYdLsZvx8twoEDAqVNdcOpUFwBDAACC3I4uqaVITiqCXHMCZZ4c5FmPo8BagAJrATYe3xg4Z4o2pVpASdYlN/u1EBERRRxGPvjgA8yfPx+vvvoqRo0ahWXLlmHcuHE4cOAAUlJSqu3vdDpx4YUXIiUlBR9//DE6deqEY8eOwWg0NkX5W49AGGm6Zpq6yGQCLs3OwKXZGQAAq9ON3SfM+O14GXb5lhNlwLGT6Th2Mh3AaQAAjcqJ7p3MSEwoBNQnUOw6jL8qjqHQVojCvwqx6a9NgfeIV8dDo9BAJshCF8ggCAJkggxyQS49hgwymfSaTJBer+81uSCHRqGBWq6GRqGBRl7lsUIdus2/r1wTcpxaroZCxko+IqK2KuJ5RkaNGoURI0bgpZdeAgB4vV5kZmbijjvuwP33319t/1dffRVPP/009u/fD6VS2aBCtol5RkqPAc+fBig0wD/ypYnQoqyw3I7fjpsCAeW342Uod7ir7ZcYK6JHJxOMxkJ4lMdR5DyCY+U58IreKJS6YRQyRbUwk6RNQg9jD/Qw9kBPY0/0MPaAQW2IdlGJiDqMcL+/IwojTqcTOp0OH3/8MaZMmRLYPn36dJSVleHzzz+vdszEiRORkJAAnU6Hzz//HMnJybj22mtx3333QS6veTZRh8MBh8MRcjGZmZmtO4w4LcATUi0FFv4FqGOjW54aeL0ijpyyBILJruNl2JdnhruGqea7JSnQPcOGlDglkmKVSIhRIlGvRLxeCbVCgBdeeMXKRRRFeEQPRFGEF97Kx2KV/VC5n8vrgsPjgMPtgM1jg8PtgMPjgN1jr3Gb3S1tt3vs0nEeRw1XWbdkbXIgnPgDSg9jD8SqWt/nRUTU1jXLpGenTp2Cx+NBampqyPbU1FTs37+/xmOOHDmCb7/9FtOmTcNXX32FQ4cOYdasWXC5XFi8eHGNxyxZsgQPP/xwJEWLPpUeUOoBl0XqN9IKw4hMJqBnSgx6psTgb8M6AwDsLg/2nDSHBJTcEityTrmRc8pfk+XyLZJYjQKdjFqkGzRIN2qRYdAg3aBFhlGLDKMGaQYN1Irmn7beK3oDYcYfUOxueyC4nKw4icNlh3HIdAiHyw4j35KPIlsRimxF+DHvx5BzpepSA+EkOKTolfpmvw4ioo6u2RvavV4vUlJS8Prrr0Mul2PYsGE4ceIEnn766VrDyMKFCzF//vzAc3/NSKunTwLKLFK/kYTu0S5NWDRKOYZ1jcewrpXzkRRXOPD7XybsOWnCiTI78kw25JXZcdJkQ7ndjXK7G/vzy7E/v7zW8ybFqHwBRVNtnWHUIiVWA7mscU1ZMkEGrUILrUIb1v4VzgocNh2WAkrZocC60FoY6NS75eSWkGPS9ekhAaWnsSe6G7pDp9Q1quxERFQpojCSlJQEuVyOgoKCkO0FBQVIS0ur8Zj09HQolcqQJpl+/fohPz8fTqcTKlX1+6yo1Wqo1epIitY66JOBsmMtMqKmOSXGqHFe3xSc17d6h+Ryuwt5JjtOltmQZ7Ijr8yGk0HPT5bZ4HB7carCiVMVTvxxoua7FMtlAlJi1UiOVQfWyTG+dawaybGawHaNsmlqWWJUMchOzkZ2cnbIdrPTjCNlR0ICyuGywyiyFSHPkoc8Sx5+OPFDyDGdYjohUZMIvVKPGFUMYpQxiFHFIFYZC71Sj1hVbK2vaRVaCK2gTxERUWsRURhRqVQYNmwYNmzYEOgz4vV6sWHDBsyZM6fGY8aMGYN3330XXq8XMpkMAPDnn38iPT29xiDSpulbZq6RaIrVKBGrUaJ3as3NUKIootTqCgknJ301K3kmG06W2ZFvtsPjFaUwY7LX/55qBZJj1UgKDi5B4SUlVoPkWDUS9KoG1bbEqeKqTdEPACaHKSSc+B8X24txouJErTc9rI9ckIcGFmVM4LF/bVAb0DWuK7obuiMzNpOjhYioXYv4X7j58+dj+vTpGD58OEaOHIlly5bBYrHgxhtvBADccMMN6NSpE5YsWQIAuP322/HSSy9h7ty5uOOOO3Dw4EE88cQTuPPOO5v2SlqDDhBG6iMIAhL0KiToVRjYqeaRKx6viKJyB/LNdhSVOyqXCjsKzQ4UVUjPC8sdcLq9KHe4Ue5w48gpS53vLROkWp3kGDVS4qTgkhqnCSxpcRqkxqmRGKMOK7QY1AYMTR2KoalDQ7aX2kuRY8pBmaMMFpcF5c5yae0qh8UprSucFdW2WVwWeEWpc6/ZaYbZaQ7rZ6qQKdA1tiu6G7ujm6Ebuhu6o7uhO7IMWWE3URERtWYRh5GrrroKRUVFePDBB5Gfn4/Bgwdj7dq1gU6tubm5gRoQAMjMzMS6detw11134bTTTkOnTp0wd+5c3HfffU13Fa1FC8810lbJZQLSDFJH17qIoohyh1sKJkEhxb8Ulkth5lSFA8UWJ7wiAq/tzav7/ZNj1Eg1aJAaq0aaQRMUWtRIi9MgJU6DOI2ixuaUeE18g+75I4oibG4bKlwVqHBWhK6rPC6xlyDHlIMcUw5sbpvU18V0OOR8AqR7GgUHlO5Gac0hzETUlkQ8z0g0tIl5RgBg28vAur8DA/8G/O3NaJemQ3F7vCixOFEYFFQKzQ4UlNuRb5Ke55vsOFXhQA0jmWukVcqRGldZu5JmkPqxBMJLrAYpcU3Xp6UmXtGLAksBjpiOVC5lR5BjykGpo7TW4xI0CSEBxR9YUnWp9fZXcXvdsLqtsLqssLltoY+rbAte+1+3uq1Qy9UwqAwwqKXFqDZWe2xUGxGrioVMkNVZHiJqu5plaC/VowWnhKdQCrkMKb4ajbq4PVLn2gKz1Hel0LcuMDtQYLZL2012mO1u2FweHC224mixtc5zGrTKQJOQ1DykCYQY//aGdsSVCTKkx6QjPSYdYzqNCXmtxF6CI2VSQMkx5QTCSr4lHyX2EpTYS/Bzwc8hx+iVenSL64YkbVK1UOEPE06vM+JyNpQAAXHqOCmg1BVeVAYYNAYYVNJzvVLPTsBE7QjDSFNqhjv3UtNSyGWBJqLsOvazOT2V4cQs1bLk+54Hb3O4vTDZXDDZXDhYWFHnexu0ykBISfb3Z4lVI8XXPOTviBtuaEnQJCAhLQHD04aHbLe6rCHhxB9Yjpcfh8Vlwe7i3WGdXyEooFVqoVPooFPqoFVUPq5pm/+xVqmF0+NEmb0MJqcJJoe0lDnKQh5b3VaIEAPbIqGUKaXr1yQgQZuARE0i4tXxSNAmBLYnahIRr4lHgiYBGkXdIZWIoothpCmxZqTd0KrkyErSIyup9knPRFGE2eZGYXllzUphuX9d2UxUYJY64vpDy58FdYcWo06JRL0KKoUcCpkAhVyQ1jJZ4LFcJoNSLkAuE6CUy3xr6blCJvMd1wsKWW9kyQT0MgiA0QOLNx9l7hMQBStSYmKRFmtARpwBibrYkJChU+iglDfs9g3hcnlcMDlNgdBS5iiD2WFGmaMsJLj4X/M/d3gccHldgblhwqFT6ALBJUGdEBJaEjQJiNfEI1GTiARNAmJUMXB5XXB6nHB6nHB4HIG1/7HT44TD66jxdZfHFbJvyNrrhAABsapYxKpiA8O+41RxIUPAY1WxgccxqhiOpqJ2j7/hTckfRqynAK8XkLEtvD0TBAEGnRIGnRK9ahnqDFSGFimYVIaUQrMjEGQKg0JLmdWFMqur1vM1ntG3AIAXQCli1OVIM2iQbpBGHaUbNEgzaH1r6blBq2zSphGlXIkkbRKStEkRHWdz21BqLw00RRXbilHqKEWJrSSwLXhxeV1Sc1SFFX9V/NVk5W9JWoU2JKTUFFr8j/UKfa21V0pZ036GrYXH64HFbYHVZZVGsrktsDgtsLgtqHBWwOq2BkazqeVqqOQqqOXqkMc1bpOpQrYrZDV3aqfGYxhpSrpEaS16AVspoE+MbnmoVQgOLbXNzwJIocVkc6HQN0LI7RHh8YpwebzS2ivC4/XC5dvu9njh9opwe0TfWnou7euFx7/d6622j9nuRoFJmvvFbHejwuHGocIKHKqjqUmjlCG9SkBJM2iRHlf5PEGvavZ/rLUKLbQxWmTEZNS7ryiKgdFJJfYSnDAX4UhJAY6bCpFXUYRiWwlMzjLYPGVwoRyQWyAIQT2cRSVkUEIuKKGUqaCSqaBRSDdj1CvV0Ks00Ks09X7BBX+peURPYPRUubM8MBQ8+HGFswLlrnLY3DYAUgCzuW0otBU26mcX3PSmVWir1YZV3Rbc9OZ/XUDo5yui/h7hNY2TqOk4t9cNi8tS41LhqoDVZQ0JGP61/+fU3AQIdQYYo9qIRG0iEjWJNa7jVHEMM7VgGGlKciWgMQL2MqmphmGEIiAIAow6FYw6VZ2hpalZHG7k+zru5pnsyDfZfGvfc7MdJRYn7C4vck5ZkFPHfC8qhQxpcRokxqgQr1PBqFX6rknpW6Rt8b5tBp0Sseqm+9+mw+3BiVIbjpfacLzEKi2lVhwvseF4qdVX45TgW/pWO14QvIjReFFuAwA5gPrLpZLLpMn3gua20ceqkRSnQYq2cjRWvC7yWgmX1yXNUxMcWlzlKHdWf1zhqoDZaYbNZas2usl/U0m36JbO5az9Vg5tmUKmQIwyBnqlvsZFJsiqNbmFNL3V0rTmJ0KU7n3lqX+yxtrKV1tQqbo2qA0NGmnmvwmp/4ajgZuM+u7dFXLj0eBtbjv+1vtvSNYlN+jaGothpKnpkyvDSA3/2BG1Nnq1Aj2SY9AjOabWfewuqUNvSEjxhxbf9lMVUjNTbokVuSV1j0AKJpcJMGqlYFItwGiVMOr926TX9WoFCs32GgNHQbkd9U1WEK9TIjNBJy3xOmQmaH1rHTKM0k0eHW4PisodKDA7UFQe1BfI7EBBuQOFvv5BJRYnnB4vTpTZcKKs7v+dK+UCUmI16GTUom96LPqkxaJvWhz6pMUiRl3zP8VKmRJGjRFGjTHsn2dN3F53oHal6pBsq9taY4CpaRh3XTUQVWtM6t1eQzCTCTLEKGOgU+oCoSL4cdWl6r4qedPP6u0VvYE7jNcWZPxf5qWOUhTbiqXFLq39TYnlrnK4ve6w+zopBAXiNfFI0iYhQZsAo9oIlyc0ZATfHDR4m1f0Nuhax3QawzDSbuiTgeKDUr8RonZCo5Sja6IeXRNr79DrdHtRWC4FkxKLE2VWJ8qsLpRaXTDZ/I+dgT4xZTaptsXjFVFscaLY4gRQ9yy74dAq5SEBQwod2sDj2r74g6kVcnSO16FzfN03RHS6vSiqkMKJP7gUhPQFkl4rtjjh8oiB0PLT0ZKQ82QmaNEnNQ79gkJKVqIOCnnT9DtTyBSBTrMUGZkgCzTFNIbD40CJrSQQUortxThlOxUSXPxrs9MMt+gO3GW8sWXXyDVQK6S1RqGpdZtRbWzUNTYGw0hT4/Be6qBUCllYX+DB7C5PIJiUWoJDi7TNVEOAKbe7kRSjrjVwJLZAvxU/lUKGTkYtOhnrnpbf6fbiVIVUu3K02CLd9TqvHAfyy5FvtkvNSCU2fLOv8n/MKoUMvVNjqoWU5Ng2eBNRglquDswZVB+XxyUFE39I8QUUpUwZEiYCj4PWwSGjLXVYZhhpahzeSxQ2jVKONIO83lsDtHUqhQwZRi0yjFoM6RJ6K4Eyq9MXTszSOl8KKTaXB7tPmLH7ROg9jBL1KqmZJzUOfdNj0TctFr1SYqFVNd9MwNSylHIl0vRpSNOnRbsoLYZhpKkxjBBRBIw6FU7vnojTu1d2ePd6RRwvtWKfr/Zkf74ZB/LLkVNsQbHFiS2HirHlUHFgf5kAZCXq0SctFukGrdQ5WBu0VHmubKLmH2o+TrcXBWY7TpTZkGeyocTiQiejFj2S9eiSqINa0b7CJ8NIU+Ode4mokWQyIdBHZ/zAyv8d25weHCyUmnj2+0LK/vxylFicOHLKUu+drf30KjkMWiXifOGkenhRhTw3+tZxWmVYd7yOBlEU4XB74XB5YXd7YHd54HB7Q9YKmcx3HQoYtErENOFIrkjLWmxx4mSZDSfL7L611CH8hO9xUYWj1s7YMgHITNChe5Ie3ZNj0D1Zj+5JMeiRrEdyrLrNNM0EYxhpauwzQkTNRKuS47TORpzW2RjYJooiiioc2J9Xjj8LylFU4YDJ6grM+GuySf1tzDYXyh1uAIDF6YHF6cFJU+RDVP2zAivlMt8izfqrUlQ+VipkUPpmB1bIBah8+/ofVz1eek0GmQDYXV443J7A2uHy1hgs7EGv2d1eON2RjyCRywTEaRSB0BWnrRLKqixxQetYtQKyWoKZxeFGnik0aJw0hT4Op7wqhQwZBg0yjFJt1/ESG44UVcDi9OBYsRXHiq3YeCD0P76xagW6JeurBZVuSfpW3ZTHMNLU2ExDRC1IEKQhwymxGpzdu+5hmW6PF+V2txRQbKGBxWR1hj4PCjEmmwsWp0c6h1eaQM/uatjw0ZYgE6T+SGqFDBqlPPDY5fHCZHPDbHPB6ZtMsNTXYboh7xGrqQwqsRoFSq0u5JlsYc2gLAhAcowaGb4O0Om+0CEt0uOaOmOLoojCcgcOF1XgSJFFWk5Jj/8qtaLc4cbvf5nw+1/V7/fUyaj1hZOgoJIcg/Q4Ta3BqqUwjDQ1hhEiaqUUchni9SrE6yOfj8PlCzIuj1QL4fLN5ut0S2uXxwuX2wuXV4TL7YXb64XTE/rY7ZGOc3l8+3uk2YGdvrVHFKFRyKFRyqAOrEMDhX+tVlbdT1prlNI9nepqqhBFKUxVDV8mW2X4qvo4eHG4vfCKCDyvSaxaEQgW6b7AkWHUIN0gPU6N00CliLzvjiAIgYn0zugReisFh1uqMTlSVIHDVYKKyeYKDC3//mBozb1WKd2L67EpAzGsa2gH65bCMNLU/GHEbgLcTkDR9JPwEBG1NKVchoQGhJjWSBAEaFVyaFUNG8lld3mqBZVyuxsGrRIZRi3SjRrEaZr3RpM1USvk6J0aW20GZ1EUK/sV+WpUDvuCSm6xFTaXB/vyzNCGecfw5sAw0tQ0RkCQA6IHsBYDcfWPKSciorbDX1OTEtc2hqQLgoDEGDUSY9QYkZUQ8prL48XxEiuOFFnQPbn2SQ2bW4cf3+UuLW3aE8pkHFFDRERtglIuQ/fkGIztnwpNFGtGOmwY8TocyHvoIRy6YCycf51o2pOz3wgREVHYOmwYEVQqOA8fgWi1ovCpJ5v25BzeS0REFLaOG0YEAamLHgDkcpSv/wYV3//QdCfXsZmGiIgoXB02jACApndvJFx3HQCg4LHH4HU6m+bEbKYhIiIKW4cOIwCQNGc25ElJcB47hpKVq5rmpGymISIiCluHDyPy2Fik3rMAAHDq1VfhOnmy8Sf114xYGUaIiIjq0+HDCADEXXoptMOGQbTZUPDUPxt/QjbTEBERhY1hBFJn1rRFDwAyGcrXrYNl69bGnZBhhIiIKGwMIz6avn0Rf+21AID8xx6H2JjOrOwzQkREFDaGkSDJd94BeWIinEeOoOSddxp+In/NiMsKOC1NUzgiIqJ2imEkiDwuDil33w0AKHr5FbgKChp2IpUeUPjuWcCmGiIiojoxjFRhmDIZ2sGDfTOzNrAzqyAE9RthUw0REVFdGEaqEGQypD24CJDJYP7qK1h+3N6wE/FmeURERGFhGKmBpn9/xF99FQAg/7FHIbpckZ+ENSNERERhYRipRfKdd0JuNMJ56DBK/r068hNweC8REVFYGEZqITcakXz3fADAqZdegquwMLITcHgvERFRWBhG6mC8/HJoTjsNXosFhU8/E9nBrBkhIiIKC8NIHQSZDGmLFgGCAPN//gPrjh3hH8wwQkREFBaGkXpoBw2E8YorAAD5jz4G0e0O70Adm2mIiIjCwTAShuS75kFuMMDx558offe98A7i0F4iIqKwMIyEQREfj+S77gIAFL3wAtynwqjt8DfTWE8B7kbc54aIiKidYxgJk/GKv0EzYAC8FRUofObZ+g+ISQF0iYDXDXxxByCKzV9IIiKiNohhJEyCXC7NzArA9NlnsP7ya90HyJXA1NcBQQ78/j6w+akWKCUREVHbwzASAW12NgyXTwUA5D/6KESPp+4Deo4FLlkqPd60BNgVZn8TIiKiDoRhJEIpd98NWVwcHPv2ofT99+s/YNgM4Eypvwm+uAPI+a5Zy0dERNTWMIxESJGQgOS5dwIAip5/Ae6SkvoPOv9BYMBUwOsC3r8OKNzfzKUkIiJqOxhGGiD+6quh7tcPXrMZhUuX1n+ATAZMWQ5kng44TMC7VwAVEU4vT0RE1E4xjDSAIJdLM7MCMH38CWy//Vb/QUoNcPW7QEJ3oCwXePcqwGlt5pISERG1fgwjDaQbOgSGKVMAAPmPhNGZFQD0icC0jwFtAnDyF2DNTMAbxnFERETtGMNII6QsuBuy2FjY9+xB2Ucfh3dQYg/gmvcAuRrY/1/g60XNW0giIqJWjmGkERRJSUi+4w4AQNFzz8FdWhregV1OBy5bLj3+8WVg++vNVEIiIqLWj2GkkeKvvQbqPn3gMZlQ9Nyy8A8ceDlwwWLp8dr7gAP/a5byERERtXYMI40kKBRIW/QAAKDso49g+2N3+AefeRcw9AZA9AIf3wScrGdWVyIionaIYaQJ6IYPR9ykSYAoSjOzer3hHSgIwMVLgR7nAy6rNMKm7HjzFpaIiKiVYRhpIin3LIBMr4f9999hWrMm/APlSuCKt4CUAUBFAbD6CsBuar6CEhERtTIMI01EmZKCpDlzAACFzy6Fp6ws/IM1ccC0D4GYNKBoH/DhDYDH1TwFJSIiamUYRppQwnXToO7VE57SUhS98EJkBxs6S4FEqQeObAL+Ow8QxeYoJhERUavSoDDy8ssvIysrCxqNBqNGjcJPP/0U1nHvv/8+BEHAFN9kYe2NoFQi9QFp3pDS9z+Afe/eyE6Qng1csRIQZMCv/wa+f7YZSklERNS6RBxGPvjgA8yfPx+LFy/GL7/8guzsbIwbNw6FhXXfa+Xo0aNYsGABzjrrrAYXti3QjxqJuIkTAa9Xmpk13M6sfr3HARP+KT3+9lHgjzAnUyMiImqjIg4jS5cuxcyZM3HjjTeif//+ePXVV6HT6bBixYpaj/F4PJg2bRoefvhhdO/evVEFbgtS7rsXMp0Otl27YPrs88hPMHImMFrqf4LPbgeObW3aAhIREbUiEYURp9OJnTt3YuzYsZUnkMkwduxYbNu2rdbjHnnkEaSkpODmm29ueEnbEGVqKpJmzwIA5P3jHzgyaRLyFi1C2Sdr4DiSAzGcviAXPgr0mwR4nMD71wKnDjZzqYmIiKJDEcnOp06dgsfjQWpqasj21NRU7N+/v8ZjfvjhB7z55pvYtWtX2O/jcDjgcDgCz81mcyTFbBUSrr8elp9+gmXzd3AcPATHwUOB+9fIDQZoBw+GdsgQaX3aIMh0utATyGTAZa8D5knAiZ+B1X8DbtkA6JOicDVERETNJ6IwEqny8nJcf/31eOONN5CUFP6X6JIlS/Dwww83Y8man6BSoctrr8F96hRsu3bBtmsXrL/ugn33bnhMJlRs3oyKzZulneVyaPr0qQwoQ4ZA2SkDgkoHXPM+8K8LgNKjwHvXANO/AJTaqF4bERFRUxLEsNoMJE6nEzqdDh9//HHIiJjp06ejrKwMn38e2j9i165dGDJkCORyeWCb19ehUyaT4cCBA+jRo0e196mpZiQzMxMmkwlxcXFhX1xrJDqdsO/fD9uvv8K6axdsv+6COz+/2n7y5CToBkvBRJuVAM3WOyBzm4D+k4G/rZJqToiIiFoxs9kMg8FQ7/d3RGEEAEaNGoWRI0fixRdfBCCFiy5dumDOnDm4//77Q/a12+04dOhQyLYHHngA5eXleP7559G7d2+oVKomu5i2ypWX56s5+RW2Xb9JQ4Ld7pB9BKUCGoMN2kQHtGdeCO30J6FMSYlSiYmIiOoX7vd3xM008+fPx/Tp0zF8+HCMHDkSy5Ytg8ViwY033ggAuOGGG9CpUycsWbIEGo0GAwcODDneaDQCQLXtHZkyPR3K9HTETZgAAPDa7bDv3h1o2rHt2gVPcTFsp5SwnVICB7YBb54DZUYGtMOGQTdiOHTDR0DVLQuCIET5aoiIiCITcRi56qqrUFRUhAcffBD5+fkYPHgw1q5dG+jUmpubCxmbEBpFptFAN3w4dMOHIxGAKIpwHT8uNe18uRK233fDYVLAdfIkXCdPwvyf/wAA5ElJ0nG+cKLu1RMCPwsiImrlIm6miYb23kwTEVEEPpsFz8/vwW6KgzXxMlgPF8P2+x8Qnc6QXeUGA7RB4UTTry+EoP47REREzanZ+oxEA8NIFW4nsPpyIOc76blCA2/GSNjFvrAWaWD98wSsv+6CaLOFHCaLiYF26BDoRoyAbvhwaAcOhKBURuECiIioI2AYae9sZcDXDwB/rgMsVabiV8dB7HwG7LK+sBaqYN1/HNadO+GtqAjZTdBqoR2cXRlOsrMhU6tb7hqIiKhdYxjpKEQRKNov1ZLkfAcc/R6wm0L30SVB7HoWHPK+sBapYN2TA+vPP8NTVhaym6BUQpN9mq/fyQjoBg+GTK9vuWshIqJ2hWGko/J6gLzffOFkM3BsG+AOba6BIRNi17PgVPWHpVAB2+6DsOzYAU/RqernEwRAJpM6wsrlgXVN2wRBCH0ul0l3IK5tH6UCMq0OMp0OMq0WMp0WglZbuU2nhUwbtE3v20+rheA7RlCrOYKIiKiVYhghidsBnNgJHNksBZS/dgBeV+g+ib0gdjsbLs0AWArksP2+D5YdO+A+mRedMkdCJvOFE19g0WoD4UaRngbtwIHQDBgAdZ8+bIIiImphDCNUM6cFyN0mBZMjm6VaFAT/CghA2iCg29nwJA6FaMiCqE8DIED0ioDXA9HjAbxeaS2KgMcD0eP1veZbe72V+wStpce+fVwueK02eG02eG1WiDab9Nxqrdzmf923TfSvq4wcqpdCAXWvXtAM6B8aUMKYdI+IiBqGYYTCYysFjm6RmnRyvpP6n1QlUwCGTCChGxDfDYjPCn2sjmnpUkN0u+G12+G1WCHa/OHFF2ZsVngtFjiPHoV9z17pfkClpdVPolRC3asntAOkcCIFlN4MKERETYRhhBqmPB/I+V4KJ8d/km7Q53HUfYw+xRdOsqSA4g8qCd0AfbLU7ySKRFGEOy8Ptt27pXCyZ48UUKp04AUAKJXQ9OoFzcDKgKLp3QsCAwoRUcQYRqhpeL1A+UkplJTkAKU5levSo1LNSl2U+qCalKzQGhVjF0AenXlORFGE++RJ2HbvkcKJP6CYTNX2FZRKqHv39gUUqZlH3bMnAwoRUT0YRqhl2MqqB5QS39r0F0L7o1QhyICYVCAuA4jrJC2GTr7nnaV1bFqLBRZRFOE6cRL23bsDAcW2Zw+8tQQUeWIi5HFxkBsMkBniII8z+J7HQWYwSM8NcZDHxUEWFwe50Qh5bCwERcR3YSAiapMYRij63A6g7HhoWPEHldKj1Ycc1yTKgUUKKCcCAcXf1OM1mxt8TpleXxleDFKACQkzRgPkxnioe/WEKiuLU/gTUZvFMEKtmygCFYWA+QRgPulbnwBMwc9PVh+GXJNaA0snqSnIkCn1XWmimwb6m3jcJSXwmMzwmk3wmM3wmMzwmEzwmE3wmszSNrMZHlMZvCYzvBZLxO8laDRSE1GfPlD36wtN337Q9OnNyeiIqE1gGKG2z+sFrKek5p4aA8tfgDkvvMAiVwOGztJizAQMXXzrTGkd16nZm4NEtxue8nJ4Tf7wYpICjNkEb5Uw4y4sguPgwWr3FwIACAKUXTKlYNKvL9R9+0LTty8UqamcAI6IWhWGEeoYvF7AUlQZVPyhxXRCCjGm40B5HiB66zmRAMSmhwYUQ5XHLTyEWfR44DyWC8eB/bDv2w/7/n1w7D8Ad2FhjfvLjcbK2pO+faDu2w/q7t1a5GaIoscjzQVTUQGvxQJBrYYiIQGCTseARNSBMYwQ+XlcUkApOy6FE9NfQFmu9LjM97y+4csAoI33hZMulbUshs5S3xVDZ6mpqImaguriLi6Gff9+OPYf8K33wXEkB/B4qu0rKJVQ9erpCyh9pZqUPn0gj4uD6PVK87JYpADhraiAt6ICHosF3gpL5TaLBV5LBTwVFfBaKgOHtK+0TbRaayyroFZDnpgARXwC5AkJUCT41okJkMcnSK8lVL4m0+ma+8dHRC2IYYQoXP7aFdNfgCm3MrQErx3VR9RUI1NUdqw1dJb6rQSHFUMnQGNslnlXvA4HHAcPwbF/H+z7D0i1KPv219pPRabTwWuzSX13mpJSCblOB6/DAdFuj/hwQaMJhJNAiPEHlnhfiElIgCIpCYqkpBap9SGihmMYIWpKdpOvRsUfUHJ9zUF/SU1C5XmAWL1mohpVjK+DrT+sZAY9940OUmqbpMii1yuNBNq/H459+321KPvhOnkydEeZDLKYGMhi9JDr9ZDpY6Tnej1kMXrI9HrIY2Kk7Xq97zWdtC0meJsegkoVaJbxWq1SJ9+SEriLi+EpKYW7RFp7SkoqX/OtRUcYtVNVyOPjoUhOrr6kJEuBxfecNS5E0cEwQtSSPG6gIt/XV+V4aFDxP7cWh3cuXZLUf0WhAmRKqWOtTAHIVUGPlb7XFFX2UVZ/LleFvOaxueFxCJCldIMsozcEQ1LU+3WIogivxQpPqT+8lMBT6luXlISGmOJiuIuLAbc77PPL9PoaQktStW0ygyHkZyGKIkRfLY+/tsdrd0B02OG12yE6HNI6sC3oNbsDXocdosMZcjxksurz0xiC5qQxVA755pw01NYxjBC1Nk5r5SigqkHF/9wV+fDfRtPGS/1gjF18o4z8i69/jMbQ8mWqh+j1wlNWBndREdyFRdLav5w6FfK8xhFJtRBUKsgMcRCdLoi+sBFNgTlpDEYpwPjmoZHFhYYYWZxvH0McZDExkPtqqToqURQh2u3S6LWKCnjLy+ExlwOiF4JaA5lWI601aggaDWRqaS2o1VEP5u0NwwhRWyOK0vT65hNAeQHgcUrDlj0uwOv2rV1SLUxge5XngW1Vj6ny3FYqNTnZy+ovl8ZQc0jxz+GijY/6/YdqI9W4WKoHlqJCuE/mwp1/QnpeaobXWs8QcZlM+tLSanxfYJqQL7LAWqOGoNZA0Kh9+6gh01R++Yker28uGv/Q7qD5acqkYd/eiopGX7ugUklhJqgZLdC8ptdDpgveHtQkp6+6PSak+a0leB0OKUBUCRPeinJ4yn3PK8rhLa+Ap9wMb2BbReC4SGrOgglVP88q65DP1f87oFFD0GihSIiHIiUlsMiNRggt0Km9NWMYIaL62c2VfWDKjgNlx4JGGuWG17Skiq0eUmLSAH2i1OSkSwT0SYBC3fzXE0wUAcspoOQwUHwIKD7se3xEWrtCRwB5PYDbJofXJUCQAYJchEwhSmu5CCH4O0WXWNnXxz/ZXvDjuIxGXW/InDSm4En1yqQ5aXyhJXhSPf9+Dek4XC+Fwhdgqg/VFmu65UPVTTV9zdSwTXS74S0vh+h0NqKwQQRBClaxMZDHxAJyua/JzNe05ms+q2kkWpNQKqFIToIyOUXqx5ScEhJWFCnJUKakVGsebGmiKEJ0OiEoFE0+4zPDCBE1nqOicih01aBSliuNQgqXKqYymOj8QSXB9zypymuJUo1MOP9AW0uAkiNBYcMfPI4Ajjqm7RfkUnBK7AEk9gQSegCJ3aXZeisKfZPt+eau8T82nQjvNgaAdJ6aAkt8NyC1f5N1VK5KdLl8w7Et0jDt4KHavmHaIa8Hv1YR+lptQ7Zbikyvhyw2FvLYWMhiYwOhQhYb49sWB3lsDGQh24L21+nCqpkQXa5a+wSFbquhT5B/m80Od0mxVAtXWAhPcZh9xCDVYlUNKYpkKagEalkSEqTmQ5sVXrsdXpsNos0W+thmh9dug2iTttX2WLT79g06B7xeZH3yMbQDBjTmI6sm3O9v9o4iotqpY4CUvtJSE6c1aN6W3MqQUlEo1ar4F68bcFZIS9mx8N5bpqghtCQC6jgpIPiDR513jhakpqTE7r6wERQ8jF2kTsKRCDSlnazs61PTY7ddCmqWIiBvVw3FkgMp/YD07MolbRCgavw0/4JSKd2U0WhEYwc+ix6P9EXmDyp1hpNagmNtgbKGzYJcXhkk9PoWuy+ToFRCrlQCMU03saHockmdrQsL4S4shMu39ocV/+IpK4PodML1119w/fVXk71/g8rcHLVqYWLNCBE1L1GU+qZYS6RmE2uxNM1/4LFvCX7ujLDPRGy6L2R0lwKHP3jEdwOUmma5rFqJonStgdsXBAeWE0DRfun6qxGApN6V4SRjsBRQWmEHYmo6XqfT16epelBxF/lDTJF0c065HDKtFoJWA5lWJ/VFqvpYo63cR6OFTKf19WvRSh13tdLr0v46aZtGA5lOJx3HZpraMYwQdTAue2VosRYDlqDHtjLpTs2JPX3Bo3uT1Ci0GFGUwkneb0HLLmmumpokdAfSB4fWougSWrLE1AqIHk+bvIM3wwgRUVtSXgDk/y4Fk5O7gLzfpaavmhi7BIWTwdISk9xyZSUKE8MIEVFbZy2RwklwLUrJkZr3jc2Qwomxi1Rzoo0HtAmALj7ocYLU56aVDsWmIF4PUJ5f2Q/LegqIzwKS+0prWduoJWEHViKitk6XAPQ4X1r8bGVA/h+hTTynDgLlJ6WlPoJcCie6BCmgBB7H17LdF2KaafRPsxBFaZ4el03qTOyySYtcKV2XxijNXhxNXq80a7M/bJQeqxyxVpYr9TXy1jL3jVwNJPUCkvtI4cS/TuguXWMbxJoRIqK2zlEBFOyWmnYq8qURP9YSwFYCWEul57aSanOrREShkb7IFWrfrQlUlbcbCHnsX6treb2mfX2PBUHqL+S2Ba2rPq4SMPz7Bj922wDRW/f1qOMqA1jVQOavSar6WiQhxusFKgqChsUHBQ1/2PDUM5+KTCENBzd2kcpTmgMU/Vn78HKZUupLVTWkJPZo+Xl+fNhMQ0REoVx2KZSEhJWSyrASHFz8r9tKpaHZbZUgA5Q6KUx5XOHdgbsuVUOMP6yo46QO1oGwcbz+sCHIpRtmGrv6li6hS2x69fDj9Up9iYoOSCOzCvdL66IDtd9OQpBLtSaBkOILKkm9mr3Gi2GEiIgaTxQBR7kvmJRJX7CBxRX+Y3cYx4le6ctRoZHWSi2g0ErDs/2Botr2evbx17j4edzSXbj9octWGhTOSoOW4NdKGxZiBBkQ56vZiK8pbGQ0XXOR1ysNH/eHlKKgkFLb5H+CrLIfSnIfYMj1Ui1KE2IYISIiair1hRh7mdSUEhw24jKi34dDFKVh4/5g4l8X7qt+b6qbvga6jGrSt2cHViIioqYiV0j3W9InRrskkREE3+0IMkI7QouiNFNycEhJ7hO1YjKMEBERdTSCAMSmSkv3c6JdGnTsexsTERFR1DGMEBERUVQxjBAREVFUMYwQERFRVDGMEBERUVQxjBAREVFUMYwQERFRVDGMEBERUVQxjBAREVFUMYwQERFRVDGMEBERUVQxjBAREVFUMYwQERFRVLWJu/aKoggAMJvNUS4JERERhcv/ve3/Hq9Nmwgj5eXlAIDMzMwol4SIiIgiVV5eDoPBUOvrglhfXGkFvF4vTp48idjYWAiC0GTnNZvNyMzMxPHjxxEXF9dk522tOtL18lrbr450vbzW9qujXK8oiigvL0dGRgZkstp7hrSJmhGZTIbOnTs32/nj4uLa9S9DVR3penmt7VdHul5ea/vVEa63rhoRP3ZgJSIioqhiGCEiIqKo6tBhRK1WY/HixVCr1dEuSovoSNfLa22/OtL18lrbr452vfVpEx1YiYiIqP3q0DUjREREFH0MI0RERBRVDCNEREQUVQwjREREFFXtPoy8/PLLyMrKgkajwahRo/DTTz/Vuf9HH32Evn37QqPRYNCgQfjqq69aqKSNs2TJEowYMQKxsbFISUnBlClTcODAgTqPWbVqFQRBCFk0Gk0LlbjhHnrooWrl7tu3b53HtNXPNSsrq9q1CoKA2bNn17h/W/tMv/vuO0yaNAkZGRkQBAGfffZZyOuiKOLBBx9Eeno6tFotxo4di4MHD9Z73kj/7ltCXdfqcrlw3333YdCgQdDr9cjIyMANN9yAkydP1nnOhvwttIT6PtcZM2ZUK/f48ePrPW9r/FyB+q+3pr9hQRDw9NNP13rO1vrZNpd2HUY++OADzJ8/H4sXL8Yvv/yC7OxsjBs3DoWFhTXuv3XrVlxzzTW4+eab8euvv2LKlCmYMmUKdu/e3cIlj9zmzZsxe/Zs/Pjjj1i/fj1cLhcuuugiWCyWOo+Li4tDXl5eYDl27FgLlbhxBgwYEFLuH374odZ92/LnumPHjpDrXL9+PQDgiiuuqPWYtvSZWiwWZGdn4+WXX67x9X/+85944YUX8Oqrr2L79u3Q6/UYN24c7HZ7reeM9O++pdR1rVarFb/88gsWLVqEX375BWvWrMGBAwdw6aWX1nveSP4WWkp9nysAjB8/PqTc7733Xp3nbK2fK1D/9QZfZ15eHlasWAFBEHD55ZfXed7W+Nk2G7EdGzlypDh79uzAc4/HI2ZkZIhLliypcf8rr7xSvPjii0O2jRo1Svy///u/Zi1ncygsLBQBiJs3b651n5UrV4oGg6HlCtVEFi9eLGZnZ4e9f3v6XOfOnSv26NFD9Hq9Nb7eVj9TURRFAOKnn34aeO71esW0tDTx6aefDmwrKysT1Wq1+N5779V6nkj/7qOh6rXW5KeffhIBiMeOHat1n0j/FqKhpmudPn26OHny5IjO0xY+V1EM77OdPHmyeP7559e5T1v4bJtSu60ZcTqd2LlzJ8aOHRvYJpPJMHbsWGzbtq3GY7Zt2xayPwCMGzeu1v1bM5PJBABISEioc7+Kigp07doVmZmZmDx5Mvbs2dMSxWu0gwcPIiMjA927d8e0adOQm5tb677t5XN1Op3497//jZtuuqnOG0a21c+0qpycHOTn54d8dgaDAaNGjar1s2vI331rZTKZIAgCjEZjnftF8rfQmmzatAkpKSno06cPbr/9dhQXF9e6b3v6XAsKCvDll1/i5ptvrnfftvrZNkS7DSOnTp2Cx+NBampqyPbU1FTk5+fXeEx+fn5E+7dWXq8X8+bNw5gxYzBw4MBa9+vTpw9WrFiBzz//HP/+97/h9Xpxxhln4K+//mrB0kZu1KhRWLVqFdauXYvly5cjJycHZ511FsrLy2vcv718rp999hnKysowY8aMWvdpq59pTfyfTySfXUP+7lsju92O++67D9dcc02dN1GL9G+htRg/fjzefvttbNiwAU899RQ2b96MCRMmwOPx1Lh/e/lcAeCtt95CbGwspk6dWud+bfWzbag2cddeiszs2bOxe/fuetsXR48ejdGjRween3HGGejXrx9ee+01PProo81dzAabMGFC4PFpp52GUaNGoWvXrvjwww/D+t9GW/Xmm29iwoQJyMjIqHWftvqZUiWXy4Urr7wSoihi+fLlde7bVv8Wrr766sDjQYMG4bTTTkOPHj2wadMmXHDBBVEsWfNbsWIFpk2bVm/H8rb62TZUu60ZSUpKglwuR0FBQcj2goICpKWl1XhMWlpaRPu3RnPmzMF///tfbNy4EZ07d47oWKVSiSFDhuDQoUPNVLrmYTQa0bt371rL3R4+12PHjuGbb77BLbfcEtFxbfUzBRD4fCL57Bryd9+a+IPIsWPHsH79+ohvLV/f30Jr1b17dyQlJdVa7rb+ufp9//33OHDgQMR/x0Db/WzD1W7DiEqlwrBhw7Bhw4bANq/Xiw0bNoT8zzHY6NGjQ/YHgPXr19e6f2siiiLmzJmDTz/9FN9++y26desW8Tk8Hg/++OMPpKenN0MJm09FRQUOHz5ca7nb8ufqt3LlSqSkpODiiy+O6Li2+pkCQLdu3ZCWlhby2ZnNZmzfvr3Wz64hf/ethT+IHDx4EN988w0SExMjPkd9fwut1V9//YXi4uJay92WP9dgb775JoYNG4bs7OyIj22rn23Yot2Dtjm9//77olqtFletWiXu3btXvPXWW0Wj0Sjm5+eLoiiK119/vXj//fcH9t+yZYuoUCjEZ555Rty3b5+4ePFiUalUin/88Ue0LiFst99+u2gwGMRNmzaJeXl5gcVqtQb2qXq9Dz/8sLhu3Trx8OHD4s6dO8Wrr75a1Gg04p49e6JxCWG7++67xU2bNok5OTnili1bxLFjx4pJSUliYWGhKIrt63MVRWnUQJcuXcT77ruv2mtt/TMtLy8Xf/31V/HXX38VAYhLly4Vf/3118AIkieffFI0Go3i559/Lv7+++/i5MmTxW7duok2my1wjvPPP1988cUXA8/r+7uPlrqu1el0ipdeeqnYuXNncdeuXSF/ww6HI3COqtda399CtNR1reXl5eKCBQvEbdu2iTk5OeI333wjDh06VOzVq5dot9sD52grn6so1v97LIqiaDKZRJ1OJy5fvrzGc7SVz7a5tOswIoqi+OKLL4pdunQRVSqVOHLkSPHHH38MvHbOOeeI06dPD9n/ww8/FHv37i2qVCpxwIAB4pdfftnCJW4YADUuK1euDOxT9XrnzZsX+NmkpqaKEydOFH/55ZeWL3yErrrqKjE9PV1UqVRip06dxKuuuko8dOhQ4PX29LmKoiiuW7dOBCAeOHCg2mtt/TPduHFjjb+3/mvyer3iokWLxNTUVFGtVosXXHBBtZ9D165dxcWLF4dsq+vvPlrqutacnJxa/4Y3btwYOEfVa63vbyFa6rpWq9UqXnTRRWJycrKoVCrFrl27ijNnzqwWKtrK5yqK9f8ei6Iovvbaa6JWqxXLyspqPEdb+WybiyCKotisVS9EREREdWi3fUaIiIiobWAYISIioqhiGCEiIqKoYhghIiKiqGIYISIioqhiGCEiIqKoYhghIiKiqGIYISIioqhiGCEiIqKoYhghIiKiqGIYISIioqhiGCEiIqKo+n8T9WzYLHY/ZgAAAABJRU5ErkJggg==", + "text/plain": [ + "<Figure size 640x480 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import pandas as pd\n", + "\n", + "pd.DataFrame(history.history).plot()" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1m162/162\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 578us/step - RootMeanSquaredError: 0.5904 - loss: 0.3498\n" + ] + } + ], + "source": [ + "mse_test = model.evaluate(X_test, y_test)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "notebook", + "language": "python", + "name": "notebook" + }, + "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.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/mnist/MNISTProperNNClassification.ipynb b/mnist/MNISTProperNNClassification.ipynb @@ -0,0 +1,325 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This is how it should be done. One hot encode inputs then train model with softmax function being applied on the output layer. This will calculate probability of the inputs being members of each class. When compiling the model make sure to add the accuracy metric so accuracy is visible at the end not just the loss function calculation which is categorical cross entropy. \n", + "\n", + "One thing, yes, I should have split the training set one more time so I would have a training, validation, and testing set, but that does not seem too important as this is a proof of concept.\n", + "\n", + "Current accuracy:\n", + "96.4%" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2024-06-11 10:44:46.272808: I external/local_tsl/tsl/cuda/cudart_stub.cc:32] Could not find cuda drivers on your machine, GPU will not be used.\n", + "2024-06-11 10:44:46.276173: I external/local_tsl/tsl/cuda/cudart_stub.cc:32] Could not find cuda drivers on your machine, GPU will not be used.\n", + "2024-06-11 10:44:46.319606: 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: AVX2 FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags.\n", + "2024-06-11 10:44:47.042758: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:38] TF-TRT Warning: Could not find TensorRT\n" + ] + } + ], + "source": [ + "import tensorflow as tf\n", + "from sklearn.datasets import fetch_openml\n", + "from tensorflow.keras.models import Sequential\n", + "from tensorflow.keras import layers\n", + "import numpy as np\n", + "\n", + "np.random.seed(10)\n", + "\n", + "mnist = fetch_openml(\"mnist_784\", as_frame=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(70000, 784)" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from tensorflow.keras.utils import to_categorical\n", + "y = mnist.target\n", + "X = mnist.data\n", + "\n", + "y = to_categorical(y,10)\n", + "X.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.decomposition import PCA\n", + "from sklearn.model_selection import train_test_split\n", + "\n", + "pca = PCA(n_components=.95)\n", + "X = pca.fit_transform(X)\n", + "\n", + "X_train , X_test, y_train, y_test = train_test_split(X,y)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2024-06-11 10:45:01.973478: I external/local_xla/xla/stream_executor/cuda/cuda_executor.cc:998] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355\n", + "2024-06-11 10:45:01.974054: W tensorflow/core/common_runtime/gpu/gpu_device.cc:2251] Cannot dlopen some GPU libraries. Please make sure the missing libraries mentioned above are installed properly if you would like to use GPU. Follow the guide at https://www.tensorflow.org/install/gpu for how to download and setup the required libraries for your platform.\n", + "Skipping registering GPU devices...\n" + ] + } + ], + "source": [ + "model = Sequential()\n", + "input_1 = tf.keras.layers.Input([len(X[0])])\n", + "hidden_1 = tf.keras.layers.Dense(100 , 'relu')\n", + "hidden_2 = tf.keras.layers.Dense(100 , 'relu')\n", + "hidden_3 = tf.keras.layers.Dense(100 , 'relu')\n", + "output_1 = tf.keras.layers.Dense(10, 'softmax')\n", + "\n", + "model.add(input_1)\n", + "model.add(hidden_1)\n", + "model.add(hidden_2)\n", + "model.add(hidden_3)\n", + "model.add(output_1)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "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\">100</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">15,500</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\">100</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">10,100</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\">100</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">10,100</span> │\n", + "├─────────────────────────────────┼────────────────────────┼───────────────┤\n", + "│ dense_3 (<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\">10</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">1,010</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;34m100\u001b[0m) │ \u001b[38;5;34m15,500\u001b[0m │\n", + "├─────────────────────────────────┼────────────────────────┼───────────────┤\n", + "│ dense_1 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m100\u001b[0m) │ \u001b[38;5;34m10,100\u001b[0m │\n", + "├─────────────────────────────────┼────────────────────────┼───────────────┤\n", + "│ dense_2 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m100\u001b[0m) │ \u001b[38;5;34m10,100\u001b[0m │\n", + "├─────────────────────────────────┼────────────────────────┼───────────────┤\n", + "│ dense_3 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m10\u001b[0m) │ \u001b[38;5;34m1,010\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\">36,710</span> (143.40 KB)\n", + "</pre>\n" + ], + "text/plain": [ + "\u001b[1m Total params: \u001b[0m\u001b[38;5;34m36,710\u001b[0m (143.40 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\">36,710</span> (143.40 KB)\n", + "</pre>\n" + ], + "text/plain": [ + "\u001b[1m Trainable params: \u001b[0m\u001b[38;5;34m36,710\u001b[0m (143.40 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.summary()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "optimize = tf.keras.optimizers.Adam()\n", + "model.compile(optimizer=optimize,\n", + " loss='categorical_crossentropy',\n", + " metrics=['accuracy']\n", + ")\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 1/10\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 1ms/step - loss: 6.3211 - val_loss: 0.5532\n", + "Epoch 2/10\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - loss: 0.3455 - val_loss: 0.3746\n", + "Epoch 3/10\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 1ms/step - loss: 0.1859 - val_loss: 0.2747\n", + "Epoch 4/10\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - loss: 0.1428 - val_loss: 0.2256\n", + "Epoch 5/10\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - loss: 0.1143 - val_loss: 0.2141\n", + "Epoch 6/10\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - loss: 0.1031 - val_loss: 0.1912\n", + "Epoch 7/10\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - loss: 0.0922 - val_loss: 0.1822\n", + "Epoch 8/10\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - loss: 0.0778 - val_loss: 0.1734\n", + "Epoch 9/10\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - loss: 0.0781 - val_loss: 0.1852\n", + "Epoch 10/10\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 1ms/step - loss: 0.0636 - val_loss: 0.1755\n" + ] + }, + { + "data": { + "text/plain": [ + "<keras.src.callbacks.history.History at 0x7f9c4306db10>" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import numpy as np\n", + "\n", + "X_train = np.asarray(X_train).astype('float32')\n", + "y_train = np.asarray(y_train).astype('float32')\n", + "X_test = np.asarray(X_test).astype('float32')\n", + "y_test = np.asarray(y_test).astype('float32')\n", + "\n", + "model.fit(epochs=10, x=X_train, y=y_train, validation_data=(X_test, y_test))" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1m547/547\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m1s\u001b[0m 580us/step - accuracy: 0.9633 - loss: 0.1776\n" + ] + }, + { + "data": { + "text/plain": [ + "[0.1755135953426361, 0.9642857313156128]" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model.evaluate(x=X_test, y=y_test)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "myvenv", + "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.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/mnist/MNISTRegressionClassificationNN.ipynb b/mnist/MNISTRegressionClassificationNN.ipynb @@ -0,0 +1,405 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This model is dump. I used regression for this... smh. \n", + "\n", + "I should have used binary classification and softmax for the output instead of a regression that outputted the correct value.\n", + "\n", + "Despite this, it is still fairly accurate." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2024-06-11 11:01:32.011039: I external/local_tsl/tsl/cuda/cudart_stub.cc:32] Could not find cuda drivers on your machine, GPU will not be used.\n", + "2024-06-11 11:01:32.014718: I external/local_tsl/tsl/cuda/cudart_stub.cc:32] Could not find cuda drivers on your machine, GPU will not be used.\n", + "2024-06-11 11:01:32.057818: 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: AVX2 FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags.\n", + "2024-06-11 11:01:32.797741: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:38] TF-TRT Warning: Could not find TensorRT\n" + ] + } + ], + "source": [ + "import tensorflow as tf\n", + "from sklearn.datasets import fetch_openml\n", + "from tensorflow.keras import Sequential\n", + "\n", + "mnist = fetch_openml(\"mnist_784\", as_frame=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(70000, 784)" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "y = mnist.target\n", + "X = mnist.data\n", + "X.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.decomposition import PCA\n", + "from sklearn.model_selection import train_test_split\n", + "\n", + "pca = PCA(n_components=.95)\n", + "X = pca.fit_transform(X)\n", + "\n", + "count = 0\n", + "for i in y:\n", + " y[count] = float(i)\n", + " count += 1\n", + "\n", + "X_train , X_test, y_train, y_test = train_test_split(X,y)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2024-06-11 11:01:47.515719: I external/local_xla/xla/stream_executor/cuda/cuda_executor.cc:998] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero. See more at https://github.com/torvalds/linux/blob/v6.0/Documentation/ABI/testing/sysfs-bus-pci#L344-L355\n", + "2024-06-11 11:01:47.516239: W tensorflow/core/common_runtime/gpu/gpu_device.cc:2251] Cannot dlopen some GPU libraries. Please make sure the missing libraries mentioned above are installed properly if you would like to use GPU. Follow the guide at https://www.tensorflow.org/install/gpu for how to download and setup the required libraries for your platform.\n", + "Skipping registering GPU devices...\n" + ] + } + ], + "source": [ + "model = Sequential()\n", + "input_1 = tf.keras.layers.Input([len(X[0])])\n", + "hidden_1 = tf.keras.layers.Dense(100 , 'relu')\n", + "hidden_2 = tf.keras.layers.Dense(100 , 'relu')\n", + "hidden_3 = tf.keras.layers.Dense(100 , 'relu')\n", + "output_1 = tf.keras.layers.Dense(1)\n", + "\n", + "model.add(input_1)\n", + "model.add(hidden_1)\n", + "model.add(hidden_2)\n", + "model.add(hidden_3)\n", + "model.add(output_1)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "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\">100</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">15,500</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\">100</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">10,100</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\">100</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">10,100</span> │\n", + "├─────────────────────────────────┼────────────────────────┼───────────────┤\n", + "│ dense_3 (<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\">1</span>) │ <span style=\"color: #00af00; text-decoration-color: #00af00\">101</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;34m100\u001b[0m) │ \u001b[38;5;34m15,500\u001b[0m │\n", + "├─────────────────────────────────┼────────────────────────┼───────────────┤\n", + "│ dense_1 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m100\u001b[0m) │ \u001b[38;5;34m10,100\u001b[0m │\n", + "├─────────────────────────────────┼────────────────────────┼───────────────┤\n", + "│ dense_2 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m100\u001b[0m) │ \u001b[38;5;34m10,100\u001b[0m │\n", + "├─────────────────────────────────┼────────────────────────┼───────────────┤\n", + "│ dense_3 (\u001b[38;5;33mDense\u001b[0m) │ (\u001b[38;5;45mNone\u001b[0m, \u001b[38;5;34m1\u001b[0m) │ \u001b[38;5;34m101\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\">35,801</span> (139.85 KB)\n", + "</pre>\n" + ], + "text/plain": [ + "\u001b[1m Total params: \u001b[0m\u001b[38;5;34m35,801\u001b[0m (139.85 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\">35,801</span> (139.85 KB)\n", + "</pre>\n" + ], + "text/plain": [ + "\u001b[1m Trainable params: \u001b[0m\u001b[38;5;34m35,801\u001b[0m (139.85 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.summary()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "optimize = tf.keras.optimizers.Adam()\n", + "model.compile(optimizer=optimize,loss='mse', metrics=['mae'])" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Epoch 1/30\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 1ms/step - accuracy: 0.1138 - loss: 222.9251 - val_accuracy: 0.1199 - val_loss: 7.9898\n", + "Epoch 2/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - accuracy: 0.1301 - loss: 5.0046 - val_accuracy: 0.1330 - val_loss: 3.2245\n", + "Epoch 3/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 1ms/step - accuracy: 0.1341 - loss: 3.3604 - val_accuracy: 0.1118 - val_loss: 4.7502\n", + "Epoch 4/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - accuracy: 0.1357 - loss: 2.6554 - val_accuracy: 0.1126 - val_loss: 2.4580\n", + "Epoch 5/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - accuracy: 0.1494 - loss: 1.7955 - val_accuracy: 0.1631 - val_loss: 1.7636\n", + "Epoch 6/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 1ms/step - accuracy: 0.1558 - loss: 1.3815 - val_accuracy: 0.1415 - val_loss: 1.2325\n", + "Epoch 7/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - accuracy: 0.1644 - loss: 1.0503 - val_accuracy: 0.1847 - val_loss: 1.0859\n", + "Epoch 8/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - accuracy: 0.1766 - loss: 0.8273 - val_accuracy: 0.1707 - val_loss: 1.0465\n", + "Epoch 9/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - accuracy: 0.1835 - loss: 0.7227 - val_accuracy: 0.1813 - val_loss: 0.7586\n", + "Epoch 10/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m3s\u001b[0m 1ms/step - accuracy: 0.1827 - loss: 0.6235 - val_accuracy: 0.1931 - val_loss: 0.7283\n", + "Epoch 11/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - accuracy: 0.1825 - loss: 0.5756 - val_accuracy: 0.1542 - val_loss: 0.7893\n", + "Epoch 12/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - accuracy: 0.1900 - loss: 0.4808 - val_accuracy: 0.1903 - val_loss: 0.7062\n", + "Epoch 13/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - accuracy: 0.1955 - loss: 0.4436 - val_accuracy: 0.1995 - val_loss: 0.7161\n", + "Epoch 14/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - accuracy: 0.1892 - loss: 0.4469 - val_accuracy: 0.1789 - val_loss: 0.6684\n", + "Epoch 15/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - accuracy: 0.1950 - loss: 0.3970 - val_accuracy: 0.1193 - val_loss: 0.7309\n", + "Epoch 16/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - accuracy: 0.1945 - loss: 0.3584 - val_accuracy: 0.1604 - val_loss: 0.5815\n", + "Epoch 17/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - accuracy: 0.1989 - loss: 0.3285 - val_accuracy: 0.2011 - val_loss: 0.6027\n", + "Epoch 18/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - accuracy: 0.1927 - loss: 0.3314 - val_accuracy: 0.2016 - val_loss: 0.5064\n", + "Epoch 19/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - accuracy: 0.1990 - loss: 0.2962 - val_accuracy: 0.2012 - val_loss: 0.5226\n", + "Epoch 20/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - accuracy: 0.2079 - loss: 0.2676 - val_accuracy: 0.1995 - val_loss: 0.5952\n", + "Epoch 21/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - accuracy: 0.2021 - loss: 0.2709 - val_accuracy: 0.2036 - val_loss: 0.5544\n", + "Epoch 22/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - accuracy: 0.2027 - loss: 0.2493 - val_accuracy: 0.2012 - val_loss: 0.5411\n", + "Epoch 23/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - accuracy: 0.2090 - loss: 0.2353 - val_accuracy: 0.2035 - val_loss: 0.4856\n", + "Epoch 24/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - accuracy: 0.2064 - loss: 0.2244 - val_accuracy: 0.1806 - val_loss: 0.5377\n", + "Epoch 25/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - accuracy: 0.2076 - loss: 0.2348 - val_accuracy: 0.2038 - val_loss: 0.5044\n", + "Epoch 26/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - accuracy: 0.2053 - loss: 0.2084 - val_accuracy: 0.2024 - val_loss: 0.4909\n", + "Epoch 27/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - accuracy: 0.2112 - loss: 0.1926 - val_accuracy: 0.2032 - val_loss: 0.5354\n", + "Epoch 28/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - accuracy: 0.2056 - loss: 0.1908 - val_accuracy: 0.2018 - val_loss: 0.4798\n", + "Epoch 29/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - accuracy: 0.2100 - loss: 0.1958 - val_accuracy: 0.2008 - val_loss: 0.5213\n", + "Epoch 30/30\n", + "\u001b[1m1641/1641\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m2s\u001b[0m 1ms/step - accuracy: 0.2081 - loss: 0.2056 - val_accuracy: 0.2031 - val_loss: 0.4574\n" + ] + }, + { + "data": { + "text/plain": [ + "<keras.src.callbacks.history.History at 0x7fcc41b0b510>" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import numpy as np\n", + "X_train = np.asarray(X_train).astype('float32')\n", + "y_train = np.asarray(y_train).astype('float32')\n", + "X_test = np.asarray(X_test).astype('float32')\n", + "y_test = np.asarray(y_test).astype('float32')\n", + "\n", + "\n", + "model.fit(epochs=30, x=X_train, y=y_train, validation_data=(X_test, y_test))" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[1m547/547\u001b[0m \u001b[32m━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[37m\u001b[0m \u001b[1m0s\u001b[0m 652us/step\n" + ] + } + ], + "source": [ + "y_pred = model.predict(X_test)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "count = 0\n", + "for i in y_pred:\n", + " y_pred[count] = i.round()\n", + " count += 1" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "correct = 0\n", + "wrong = 0\n", + "\n", + "count = 0\n", + "for i in y_pred:\n", + " if i != y_test[count]:\n", + " wrong += 1\n", + " else:\n", + " correct += 1\n", + " count += 1\n" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "15378\n", + "2122\n", + "0.8787428571428572\n" + ] + } + ], + "source": [ + "print(correct)\n", + "print(wrong)\n", + "print(correct / (correct + wrong))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "myvenv", + "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.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}