{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Let's have a look at how to implement a neural network in Python. \n", "\n", "### Implementing the Feedforward Part of a Neural Network\n", "\n", "As a small programming exercise and to improve our understanding of neural networks, let's implement the feedforward part of a neural network from scratch. We will have to calculate the output of the network for some given weights and biases, as well as some inputs. Let's start by importing the necessary libraries" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "execution": { "iopub.execute_input": "2025-06-28T20:33:44.258370Z", "iopub.status.busy": "2025-06-28T20:33:44.258043Z", "iopub.status.idle": "2025-06-28T20:33:44.420173Z", "shell.execute_reply": "2025-06-28T20:33:44.419617Z" } }, "outputs": [], "source": [ "import numpy as np" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, we define the activation function for which we use the sigmoid function" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2025-06-28T20:33:44.423211Z", "iopub.status.busy": "2025-06-28T20:33:44.422980Z", "iopub.status.idle": "2025-06-28T20:33:44.425635Z", "shell.execute_reply": "2025-06-28T20:33:44.425244Z" } }, "outputs": [], "source": [ "def activation_function(x):\n", " return 1/(1+np.exp(-x)) # sigmoid function" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, we define the feedforward function which calculates the output of the neural network given some inputs, weights, and biases. The function takes the inputs, weights, and biases as arguments and returns the output of the network" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "execution": { "iopub.execute_input": "2025-06-28T20:33:44.427587Z", "iopub.status.busy": "2025-06-28T20:33:44.427413Z", "iopub.status.idle": "2025-06-28T20:33:44.430285Z", "shell.execute_reply": "2025-06-28T20:33:44.429872Z" } }, "outputs": [], "source": [ "def feedforward(inputs, w1, w2, b1, b2):\n", "\n", " # Compute the pre-activation values for the first layer\n", " z = b1 + np.matmul(w1, inputs)\n", "\n", " # Compute the post-activation values for the first layer\n", " a = activation_function(z)\n", "\n", " # Combine the post-activation values of the first layer to an output\n", " g = b2 + np.matmul(w2, a)\n", "\n", " return g" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Mathematically, the function computes the following\n", "\n", "$$z = b^{1} + w^1 x$$\n", "\n", "$$a = \\phi(z)$$\n", "\n", "$$g = b^2 + w^2 a$$\n", "\n", "and returns $g$ at the end. We have written this using matrix notation to make it more compact. Remember that node $j$ in the hidden layer is given by\n", "\n", "$$z_j = b_{j}^{1} + \\sum_{i=1}^N w_{ji}^{1} x_i$$\n", "\n", "$$a_j = \\phi(z_j)$$\n", "\n", "and the output of the network is given by\n", "\n", "$$g(x ; w) = b^{2}+\\sum_{j=1}^{M} w_{j}^{2} a_j.$$\n", "\n", "\n", "Let's test the function with some example inputs, weights and biases" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "execution": { "iopub.execute_input": "2025-06-28T20:33:44.432323Z", "iopub.status.busy": "2025-06-28T20:33:44.432140Z", "iopub.status.idle": "2025-06-28T20:33:44.438919Z", "shell.execute_reply": "2025-06-28T20:33:44.438187Z" } }, "outputs": [ { "data": { "text/plain": [ "np.float64(1.0943291429384328)" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Define the weights and biases\n", "w1 = np.array([[0.1, 0.2], [0.3, 0.4]]) # 2x2 matrix\n", "w2 = np.array([0.5, 0.6]) # 1-d vector\n", "b1 = np.array([0.1, 0.2]) # 1-d vector\n", "b2 = 0.3\n", "\n", "# Define the inputs\n", "inputs = np.array([1, 2]) # 1-d vector\n", "\n", "# Compute the output of the network\n", "feedforward(inputs, w1, w2, b1, b2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To operationalize this, we would also need to define a loss function and an optimization algorithm to update the weights and biases. However, this is beyond the scope of this course.\n", "\n", "\n", "### Using Neural Networks in Sci-Kit Learn\n", "\n", "Sci-kit learn provides a simple interface to use neural networks. However, it is not as flexible as the more commonly used PyTorch or TensorFlow. We can reuse the **dataset of credit card transactions** from [Kaggle.com](https://www.kaggle.com/datasets/dhanushnarayananr/credit-card-fraud/data) to demonstrate how to use neural networks in scikit-learn." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "execution": { "iopub.execute_input": "2025-06-28T20:33:44.473746Z", "iopub.status.busy": "2025-06-28T20:33:44.473506Z", "iopub.status.idle": "2025-06-28T20:33:49.047398Z", "shell.execute_reply": "2025-06-28T20:33:49.046742Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Dataset already downloaded!\n" ] } ], "source": [ "import pandas as pd\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "import seaborn as sns\n", "from sklearn.preprocessing import StandardScaler, MinMaxScaler\n", "from sklearn.neural_network import MLPClassifier\n", "from sklearn.model_selection import train_test_split\n", "from sklearn.metrics import confusion_matrix, accuracy_score, roc_auc_score, recall_score, precision_score, roc_curve\n", "pd.set_option('display.max_columns', 50) # Display up to 50 columns\n", "from io import BytesIO\n", "from urllib.request import urlopen\n", "from zipfile import ZipFile\n", "import os.path\n", "\n", "# Check if the file exists\n", "if not os.path.isfile('data/card_transdata.csv'):\n", "\n", " print('Downloading dataset...')\n", "\n", " # Define the dataset to be downloaded\n", " zipurl = 'https://www.kaggle.com/api/v1/datasets/download/dhanushnarayananr/credit-card-fraud'\n", "\n", " # Download and unzip the dataset in the data folder\n", " with urlopen(zipurl) as zipresp:\n", " with ZipFile(BytesIO(zipresp.read())) as zfile:\n", " zfile.extractall('data')\n", "\n", " print('DONE!')\n", "\n", "else:\n", "\n", " print('Dataset already downloaded!')\n", "\n", "# Load the data\n", "df = pd.read_csv('data/card_transdata.csv')\n", "\n", "# Split the data into training and test sets\n", "X = df.drop('fraud', axis=1) # All variables except `fraud`\n", "y = df['fraud'] # Only our fraud variables\n", "X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, test_size = 0.3, random_state = 42)\n", "\n", "# Scale the features\n", "def scale_features(scaler, df, col_names, only_transform=False):\n", "\n", " # Extract the features we want to scale\n", " features = df[col_names] \n", "\n", " # Fit the scaler to the features and transform them\n", " if only_transform:\n", " features = scaler.transform(features.values)\n", " else:\n", " features = scaler.fit_transform(features.values)\n", "\n", " # Replace the original features with the scaled features\n", " df[col_names] = features\n", "\n", "col_names = ['distance_from_home', 'distance_from_last_transaction', 'ratio_to_median_purchase_price'] \n", "scaler = StandardScaler() \n", "scale_features(scaler, X_train, col_names)\n", "scale_features(scaler, X_test, col_names, only_transform=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Recall that the target variable $y$ is `fraud`, which indicates whether the transaction is fraudulent or not. The other variables are the features $x$ of the transactions.\n", "\n", "To use a neural network for a classification task, we can use the `MLPClassifier` class from scikit-learn. The following code snippet shows how to use a neural network with one hidden layer with 16 nodes" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "execution": { "iopub.execute_input": "2025-06-28T20:33:49.050383Z", "iopub.status.busy": "2025-06-28T20:33:49.050095Z", "iopub.status.idle": "2025-06-28T20:34:58.669043Z", "shell.execute_reply": "2025-06-28T20:34:58.668402Z" } }, "outputs": [], "source": [ "clf = MLPClassifier(hidden_layer_sizes=(16,), random_state=42, verbose=False).fit(X_train, y_train)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you would like to use a neural network with multiple hidden layers, you can specify the number of nodes per hidden layer using the `hidden_layer_sizes` parameter. For example, the following code snippet shows how to use a neural network with two hidden layers, one with 5 nodes and the other with 4 nodes" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "execution": { "iopub.execute_input": "2025-06-28T20:34:58.671583Z", "iopub.status.busy": "2025-06-28T20:34:58.671370Z", "iopub.status.idle": "2025-06-28T20:35:35.196974Z", "shell.execute_reply": "2025-06-28T20:35:35.196395Z" } }, "outputs": [], "source": [ "#| eval: false\n", "clf = MLPClassifier(alpha=1e-5, hidden_layer_sizes=(5,4), activation='logistic', random_state=42).fit(X_train, y_train)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that the `alpha` parameter specifies the regularization strength, the `activation` parameter specifies the activation function (by default it uses `relu`) and the `random_state` parameter specifies the seed for the random number generator (useful for reproducible results).\n", "\n", "We can check the loss curve to see how the neural network loss declined during training" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "execution": { "iopub.execute_input": "2025-06-28T20:35:35.201050Z", "iopub.status.busy": "2025-06-28T20:35:35.200807Z", "iopub.status.idle": "2025-06-28T20:35:35.365323Z", "shell.execute_reply": "2025-06-28T20:35:35.364814Z" } }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkkAAAHICAYAAABahH7UAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAATktJREFUeJzt3XtcVGXiP/DPmWEugDAiEBdFwPsF1AQvkKTfMgytl26WaKvppu26Xbzlr11jdzPrG9Xu+rVatc10UzfNSi23LMXKO2oSlCatliCkgwgmAyIDzDy/P2BGxxmU28yZGT/v1+u8GJ55zjnP8fRdPt/nec5zJCGEABERERHZUMjdACIiIiJ3xJBERERE5ABDEhEREZEDDElEREREDjAkERERETnAkERERETkAEMSERERkQMMSUREREQOMCQREREROcCQREREROQAQxIRtYvCwkJIkoR7771X7qa0mRACW7ZswQMPPIAuXbpAo9EgICAAAwcOxPz583HixAm5m0hELuAjdwOIiNzJxYsX8dBDD+HLL79Ex44dcc8996Bbt26ora3F999/jxUrVuD111/HF198gVGjRsndXCJyIoYkIqJG9fX1+NWvfoW9e/di6tSpWL58OQIDA23q6PV6ZGRkoKKiQqZWEpGrcLiNiGTx/fffIz09Hbfddhs0Gg1iY2Mxf/58XLx40a7uqVOn8Jvf/AaxsbHQarUICQnB4MGD8fTTT9vU0+v1mDt3Lnr27AlfX1906tQJ8fHxePzxx2EwGG7apvXr12Pv3r248847sXbtWruABAARERFYs2aNzbCiJElN9irFxMQgJibGpmzGjBmQJAmnT5/G//3f/6F///7QaDSYMWMGlixZAkmSsH79eofHe/fddyFJEl544QWb8oKCAsyaNQtdu3aFRqNBREQEZsyYgTNnztz0uonIMUkIIeRuBBF5vsLCQsTGxmLMmDH4/PPPb1j34MGDSE1NhdFoxIMPPoiYmBgcOnQIu3fvRs+ePZGdnY3g4GAAwLlz59C/f39cvnwZ48aNQ+/evVFVVYVTp07hq6++Qm1tLQCguroacXFxKCwsRGpqKgYMGIDa2lqcPn0au3btwokTJ+zCyvVGjBiBAwcOYOfOnbjnnnuafe2SJGHkyJHYvXu33XeWcxYWFlrLZsyYgbVr12Ls2LE4dOgQxo0bh4iICISF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hWHatGkoKyuz7jtq1Cg8+eSTWLBgAUJCQnDPPfcAAJYuXYr4+Hj4+/sjKioKjz/+OKqqqgAAu3fvxm9+8xtUVFRYz7d48WIA9sNtRUVFGD9+PDp06IDAwEBMmjQJ58+ft36/ePFiDBo0COvXr0dMTAx0Oh0mT56MyspKa50PP/wQ8fHx8PX1RXBwMEaPHo3Lly876V+TiFqCIYmI3Nprr72GpKQkPPbYY9Dr9dDr9YiKioJer8fIkSMxaNAgHD16FJ9//jnOnz+PSZMm2ey/du1a+Pj44MCBA/jnP/8JAFAoFHj99ddx/PhxrF27Fl9++SWeeeYZAEBycjKWLVuGwMBA6/kWLlxo1y4hBCZMmICLFy9iz549yMrKwk8//YT09HSbej/99BM++ugjfPLJJ/jkk0+wZ88evPzyywAAvV6PKVOm4NFHH0V+fj52796NBx54AHylJpF74HAbEbk1nU4HtVoNPz8/hIeHW8tXrlyJwYMH46WXXrKWrVmzBlFRUTh58iR69eoFAOjRowdeffVVm2NeO78pNjYWL7zwAn7/+99jxYoVUKvV0Ol0kCTJ5nzX27VrF7777jsUFBQgKioKALB+/Xr0798fX3/9NYYMGQIAMJvNeOeddxAQEAAAmDZtGr744gv87//+L/R6Perr6/HAAw8gOjoaABAfH9+Gfy0iak/sSSIij5STk4OvvvoKHTp0sG59+vQB0NB7Y5GYmGi371dffYV77rkHnTt3RkBAAB555BGUl5e3aJgrPz8fUVFR1oAEAP369UPHjh2Rn59vLYuJibEGJACIiIhAaWkpAGDgwIG4++67ER8fj4ceegirVq3CL7/80vx/BCJyKoYkIvJIZrMZ999/P/Ly8my2U6dO4c4777TW8/f3t9nvzJkzGDt2LOLi4rB582bk5ORg+fLlAIC6urpmn18IAUmSblquUqlsvpckCWazGQCgVCqRlZWFzz77DP369cMbb7yB3r17o6CgoNntICLnYUgiIrenVqthMplsygYPHozvv/8eMTEx6NGjh812fTC61tGjR1FfX4+///3vGD58OHr16oVz587d9HzX69evH4qKilBcXGwtO3HiBCoqKtC3b99mX5skSbjjjjvw/PPPIzc3F2q1Glu3bm32/kTkPAxJROT2YmJicPjwYRQWFqKsrAxmsxlPPPEELl68iClTpuDIkSM4ffo0du7ciUcfffSGAad79+6or6/HG2+8gdOnT2P9+vV488037c5XVVWFL774AmVlZaiurrY7zujRozFgwAD8+te/xjfffIMjR47gkUcewciRIx0O8Tly+PBhvPTSSzh69CiKioqwZcsWXLhwoUUhi4ichyGJiNzewoULoVQq0a9fP4SGhqKoqAiRkZE4cOAATCYTxowZg7i4OMydOxc6nQ4KRdP/0zZo0CAsXboUr7zyCuLi4vDuu+8iMzPTpk5ycjJmz56N9PR0hIaG2k38Bhp6gD766CMEBQXhzjvvxOjRo9GtWzds2rSp2dcVGBiIvXv3YuzYsejVqxf+9Kc/4e9//zvS0tKa/49DRE4jCT5rSkRERGSHPUlEREREDjAkERERETnAkERERETkAEMSERERkQMMSUREREQOMCQREREROcCQREREROQAQxIRERGRAwxJRERERA4wJBERERE5wJBERERE5ABDEhEREZED/x9xXaLcNhhwngAAAABJRU5ErkJggg==", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plt.plot(clf.loss_curve_)\n", "plt.title(\"Loss Curve\", fontsize=14)\n", "plt.xlabel('Iterations')\n", "plt.ylabel('Cost')\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can then use the same way to evaluate the neural network performance as we did for the other ML models" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "execution": { "iopub.execute_input": "2025-06-28T20:35:35.367723Z", "iopub.status.busy": "2025-06-28T20:35:35.367492Z", "iopub.status.idle": "2025-06-28T20:35:35.568067Z", "shell.execute_reply": "2025-06-28T20:35:35.567239Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Accuracy: 0.9955266666666667\n", "Precision: 0.971747127308582\n", "Recall: 0.9772319896266352\n", "ROC AUC: 0.9996638991577014\n" ] } ], "source": [ "y_pred = clf.predict(X_test)\n", "y_proba = clf.predict_proba(X_test)\n", "\n", "print(f\"Accuracy: {accuracy_score(y_test, y_pred)}\")\n", "print(f\"Precision: {precision_score(y_test, y_pred)}\")\n", "print(f\"Recall: {recall_score(y_test, y_pred)}\")\n", "print(f\"ROC AUC: {roc_auc_score(y_test, y_proba[:, 1])}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The neural network performs substantially better than the logistic regression. As in the case of the tree-based methods, the ROC AUC score is much closer to the maximum value of 1 and we have an almost perfect classifier" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "execution": { "iopub.execute_input": "2025-06-28T20:35:35.570987Z", "iopub.status.busy": "2025-06-28T20:35:35.570519Z", "iopub.status.idle": "2025-06-28T20:35:35.702769Z", "shell.execute_reply": "2025-06-28T20:35:35.702129Z" } }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjcAAAHFCAYAAAAOmtghAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAXgJJREFUeJzt3XdYVGfiPvx7CsMgzUIHBSxYY4OoQIyxErALaFYTu5E0o2504/r+YswmcTe7MabZYs+qUUGMiViwi5qoiMaosRJQARWU3mee9w+W+YaAyowDZ2a4P9fFdTmHM2fuOahz85xzniMTQggQERERWQi51AGIiIiIjInlhoiIiCwKyw0RERFZFJYbIiIisigsN0RERGRRWG6IiIjIorDcEBERkUVhuSEiIiKLwnJDREREFoXlhogea926dZDJZLovpVIJd3d3vPTSS7h27VqNzykrK8OyZcsQGBgIR0dH2NjYoH379nj33XeRlZVV43O0Wi2+/fZbDBgwAE5OTrCysoKLiwuGDBmCH374AVqt9olZS0pK8NVXX+G5555DkyZNoFKp4OnpidGjR+PIkSNPtR+IyHyw3BBRraxduxYnT57E/v378eabb2Lnzp147rnn8PDhwyrrFRYWYuDAgXjrrbfQrVs3bN68GXFxcXjllVewcuVKdOvWDVeuXKnynOLiYoSFhWHChAlwcXHBsmXLcPDgQSxfvhweHh6IjIzEDz/88Nh8mZmZCA4OxuzZs9GpUyesW7cOBw4cwKeffgqFQoH+/fvj/PnzRt8vRGSCBBHRY6xdu1YAEKdPn66yfOHChQKAWLNmTZXlr776qgAgvvvuu2rbunLlinB0dBQdO3YU5eXluuWvvfaaACDWr19fY4arV6+K8+fPPzZnaGioUCqV4sCBAzV+/9SpUyIlJeWx26itwsJCo2yHiOoGR26IyCABAQEAgLt37+qWZWRkYM2aNQgJCcGYMWOqPcfPzw9/+9vfcPHiRezYsUP3nFWrViEkJATjx4+v8bXatGmDzp07PzJLYmIidu/ejSlTpqBfv341rvPss8+iRYsWAID3338fMpms2jqVh+B+//133TIfHx8MGTIE27dvR7du3aBWq7Fw4UJ069YNvXv3rrYNjUYDT09PjBo1SrestLQUH374Idq1awdra2s4Oztj0qRJuH///iPfExEZjuWGiAySnJwMoKKwVDp06BDKy8sxYsSIRz6v8nvx8fG655SVlT32OU+yb9++Kts2trNnz2LOnDmYMWMG9uzZg/DwcEyaNAkJCQnVzjvat28f0tLSMGnSJAAV5xINHz4c//znPzF27Fjs2rUL//znPxEfH48XXngBRUVFdZKZqCFTSh2AiMyDRqNBeXk5iouLcfz4cXz44Yd4/vnnMWzYMN06qampAABfX99Hbqfye5Xr1uY5T2KMbTzOvXv3cOnSpSpFrmXLlpgzZw7WrVuHjz76SLd83bp1cHV1RWhoKABg69at2LNnD2JiYqqM5nTp0gXPPvss1q1bh9dee61OchM1VBy5IaJa6dWrF6ysrGBvb48XX3wRTZo0wffffw+l0rDfkWo6LGSqOnfuXKXYAECzZs0wdOhQrF+/Xncl18OHD/H9999j/Pjxuv3y448/onHjxhg6dCjKy8t1X127doWbmxsOHz5c32+HyOKx3BBRrWzYsAGnT5/GwYMHMX36dFy+fBl/+ctfqqxTeU5L5SGrmlR+r3nz5rV+zpMYYxuP4+7uXuPyyZMn486dO7pDbJs3b0ZJSQkmTpyoW+fu3bvIzs6GSqWClZVVla+MjAxkZmbWSWaihozlhohqpX379ggICEDfvn2xfPlyTJ06FXv27EF0dLRunb59+0KpVOpOFq5J5fcGDhyoe46VldVjn/MkISEhVbb9JGq1GkDFvDh/9Kii8ahRppCQEHh4eGDt2rUAKi6X79mzJzp06KBbx8nJCc2aNcPp06dr/Fq6dGmtMhNR7bHcEJFBPvnkEzRp0gTvvfee7rCMm5sbJk+ejL1792LLli3VnnP16lX861//QseOHXUn/7q5uWHq1KnYu3cvNmzYUONr3bhxA7/88ssjs3Tv3h2hoaFYvXo1Dh48WOM6Z86c0Z2b4+PjAwDVtvmkuXT+TKFQ4JVXXsGOHTtw7NgxnDlzBpMnT66yzpAhQ5CVlQWNRoOAgIBqX23bttXrNYmoFqS+Fp2ITNuj5rkRQohPPvlEABDffvutbll+fr7o06ePUCqV4vXXXxe7d+8WBw8eFB9//LFo2rSp8PLyEr/99luV7RQVFYmQkBAhk8nE2LFjxbZt28TRo0fF9u3bxWuvvSbUarXYsWPHY3Pev39f+Pv7C5VKJaKiosT3338vjh49KrZs2SJefvlloVAoxLlz54QQQuTk5IimTZuKZ555RsTGxooffvhBhIeHC19fXwFAJCcn67br7e0tBg8e/MjXvXLligAgvLy8hI2NjcjOzq7y/fLychEaGiqaNm0qFi5cKHbv3i32798v1q1bJyZMmCC2b9/+2PdFRPpjuSGix3pcuSkqKhItWrQQbdq0qTIpX2lpqfj6669Fz549hZ2dnbC2thZt27YVc+fOFZmZmTW+Tnl5uVi/fr3o16+faNq0qVAqlcLZ2VmEhoaKTZs2CY1G88SsRUVF4osvvhCBgYHCwcFBKJVK4eHhIUaNGiV27dpVZd1Tp06JoKAgYWtrKzw9PcWCBQvEqlWr9C43QggRFBQkAIhx48bV+P2ysjLxn//8R3Tp0kWo1WphZ2cn2rVrJ6ZPny6uXbv2xPdFRPqRCSGEhANHREREREbFc26IiIjIorDcEBERkUVhuSEiIiKLwnJDREREFoXlhoiIiCwKyw0RERFZlAZ3V3CtVou0tDTY29ub1Y37iIiIGjIhBPLy8uDh4QG5/PFjMw2u3KSlpelu2EdERETm5datW/Dy8nrsOg2u3Njb2wOo2DkODg4SpyEiIqLayM3NRfPmzXWf44/T4MpN5aEoBwcHlhsiIiIzU5tTSnhCMREREVkUlhsiIiKyKCw3REREZFFYboiIiMiisNwQERGRRWG5ISIiIovCckNEREQWheWGiIiILArLDREREVkUlhsiIiKyKJKWm6NHj2Lo0KHw8PCATCbDjh07nvicI0eOwN/fH2q1Gi1btsTy5cvrPigRERGZDUnLTUFBAbp06YKvvvqqVusnJycjLCwMvXv3RlJSEv7+979jxowZiImJqeOkREREZC4kvXFmaGgoQkNDa73+8uXL0aJFCyxZsgQA0L59e5w5cwb/+c9/EB4eXkcpzUNecRmKSjVSx6g3QuoAEhAN7E2LBvZTbng/34ZFNLAfsEIug7ujjWSvb1Z3BT958iQGDRpUZVlISAhWr16NsrIyWFlZVXtOSUkJSkpKdI9zc3PrPOej3HpQiJM3snDtXh5srBQoLteisLQcuUXlOH87G64OashlgFYAWq2AVghoRcU/Cq2A7rFWK3Dlbh5c7K2RX1KOwgZUaoiIyPS52Fvj1PwBkr2+WZWbjIwMuLq6Vlnm6uqK8vJyZGZmwt3dvdpzFi1ahIULF9ZXxCruZBdh88+p+D2rAFfv5uHq3fzHrp+SVajX9u/llVR5LJfV7lbwDQ33yKPxr0vNZPxbUzPulhpxtwAKaKBGOQpgDQCwtpL2eiWzKjdA9Q/vyqG+R32oz5s3D7Nnz9Y9zs3NRfPmzesuICpGVj4/cA1fHboOjbbqUGRrFzvIALg6qNHe3R5qKwUcbaxga61EQUk5XB3UUMhluqKikMkgl1f8WS6rWC7/35/LtVo0s7VGI5UCzvbWsLU2ux8nERGZuXv37mHbtm2QyWSYNm1ajUdR6ptZfRq6ubkhIyOjyrJ79+5BqVSiWbNmNT7H2toa1tbW9RFP58uD1/H5gWsAgC7NG6OjhwN6t3ZCBw8HeDezrdcsREREdUEIgaSkJOzevRvl5eWwt7fHw4cP4eLiInU08yo3gYGB+OGHH6os27dvHwICAkyiKQJAUakGK4/eAAD8vyEdMOU5X4kTERERGVdJSQl27dqFCxcuAABat26NESNGwNbWNH6Bl7Tc5Ofn4/r167rHycnJOHfuHJo2bYoWLVpg3rx5uHPnDjZs2AAAiIqKwldffYXZs2dj2rRpOHnyJFavXo3NmzdL9RaqOfjbPRSUauDVxAaTg32kjkNERGRUGRkZiI6ORlZWFmQyGfr164fg4GCTOudT0nJz5swZ9O3bV/e48tyYCRMmYN26dUhPT0dqaqru+76+voiLi8OsWbPw9ddfw8PDA1988YVJXQZ+/EYmAGBgB1eT+kETEREZw/79+5GVlQUHBweEh4ejRYsWUkeqRiYa2MX3ubm5cHR0RE5ODhwcHIy+/dErTuJU8gN8/lJXDO/qafTtExERSSk3NxcHDhxASEgIGjVqVK+vW9vPb95bysgycooBAB6NpZu8iIiIyFjS0tKQkJCge+zg4ICRI0fWa7HRl1mdUGwOMvMr5p5xtqvfK7SIiIiMSQiBU6dOIT4+HhqNBs7Ozmjbtq3UsWqF5caIiss0utmCm9qpJE5DRERkmKKiIuzcuRO//fYbAKBdu3YmeW7No7DcGNH9/80YrFLKYc8J9YiIyAzdvn0bMTExyM7OhkKhwMCBA9GjRw+zukiGn8BGlFVQCgBoZqsyq78EREREAHD69Gns2bMHWq0WTZo0QUREBDw8PKSOpTeWGyPKKy4DADioTWNCQSIiIn3Y2tpCq9WiQ4cOGDp0KNRqtdSRDMJyY0T5xeUAAHs1dysREZmH0tJSqFQV54l26NABEydORIsWLcz6CAQvBTeigv+dTMwbWBIRkakTQiAhIQFffvkl8vLydMu9vb3NutgALDdGVVhaMXLTSKWQOAkREdGjFRQUYNOmTThw4ADy8/Nx/vx5qSMZFYcYjKi4rGLkxsaK5YaIiExTSkoKYmJikJeXB6VSidDQUHTr1k3qWEbFcmNExWVaAIC1FQfEiIjItGi1WiQkJODw4cMQQsDJyQmRkZFwcXGROprRsdwYUeXIjZojN0REZGJ++uknHDp0CADQpUsXhIWF6U4ktjQsN0aU+79Lwe14QjEREZmYgIAAXLx4Ec8++yy6du0qdZw6xU9hI/otveJsc47cEBGR1LRaLS5cuIDOnTtDJpNBpVJh6tSpZn8lVG2w3BiRe2MbIOUhcovKpI5CREQNWF5eHmJiYpCSkoL8/HwEBwcDQIMoNgDLjVGVaypOKPZqYiNxEiIiaqiuX7+O2NhYFBYWQqVSwcHBQepI9Y7lxojKtQIAoFTwaikiIqpfWq0WBw8exPHjxwEArq6uiIyMRLNmzSROVv9YboyocuRGIW8Yw35ERGQacnNzERMTg9TUVAAVJw+HhIRAqWyYH/MN813XkcqRGysFyw0REdWf/Px83L59G9bW1hg6dCg6duwodSRJsdwYUbmmotwo5DwsRUREdUsIoTtB2MPDA6NGjYK7uzuaNm0qcTLp8VPYiMr+d1jKioeliIioDmVnZ2P9+vVIT0/XLevYsSOLzf+w3BiRRlSO3LDcEBFR3fjtt9+wYsUKpKSk4Mcff4T432cP/R8eljIije5qKZYbIiIyLo1Gg/j4ePz8888AAE9PT0RERDSYuWv0wXJjRJXlRs6/aEREZEQPHz5EdHQ00tLSAACBgYHo378/FArOiF8Tlhsj0o3c8IRiIiIykvv372P16tUoKSmBjY0NRowYAT8/P6ljmTSWGyPSjdyw2xARkZE4OTnBy8sLpaWlCA8Ph6Ojo9SRTB7LjRFx5IaIiIzhwYMHsLe3h5WVFWQyGSIiImBlZcXDULXET2Ej+r+rpSQOQkREZuvChQtYsWIFdu/erVumVqtZbPTAkRsj4iR+RERkqLKyMuzevRtJSUkAKkZvysrKYGVlJXEy88NyY0SVh6UUvFqKiIj0cP/+fURHR+PevXsAgOeffx59+vSBnL8sG4TlxogqD0vx7yIREdXW+fPnsWvXLpSVlcHW1hajRo1Cy5YtpY5l1lhujEir5QzFRERUe0VFRdi7dy/Kysrg6+uLUaNGwc7OTupYZo/lxoi0goeliIio9mxsbDBy5EikpaWhd+/ePAxlJCw3RvR/89yw3BARUXVCCCQlJaFRo0Zo164dAKBNmzZo06aNxMksC8uNEf2v23DkhoiIqikpKcGuXbtw4cIFqNVqeHp6wt7eXupYFonlxoh4bykiIqpJRkYGoqOjkZWVBZlMhuDgYJ5bU4dYboyIV0sREdEfCSGQmJiIPXv2QKPRwMHBAeHh4WjRooXU0Sway40RCcGrpYiIqIJWq8X27dtx8eJFABXn1owYMQKNGjWSOJnlY7kxIh6WIiKiSnK5HDY2NpDL5ejfvz8CAwMh4+dDvWC5qQP8q0tE1DAJIVBWVgaVSgUACAkJQbdu3eDh4SFxsoaFZ4cQEREZQVFREbZu3YrNmzdDq9UCAJRKJYuNBDhyQ0RE9JTu3LmD6OhoZGdnQy6XIy0tDV5eXlLHarBYboiIiAwkhMBPP/2E/fv3Q6vVokmTJoiIiOBojcRYboiIiAxQVFSEHTt24OrVqwCADh06YOjQoVCr1RInI5YbIiIiA8TExODGjRtQKBQICQlBQEAAr4YyESw3REREBhg4cCDy8/MxYsQIuLm5SR2H/oBXSxEREdVCQUEBLl++rHvs6uqK6dOns9iYIJYbIiKiJ0hJScGKFSsQHR2N27dv65bzMJRp4mEpIxJSByAiIqPSarVISEjA4cOHIYSAk5OTboI+Ml0sN3WBRZ6IyOzl5+dj+/btSE5OBgB06dIFYWFhLDdmgOWGiIjoT5KTkxETE4OCggJYWVkhLCwMXbt2lToW1RLLDRER0Z/cvXsXBQUFcHZ2RmRkJJydnaWORHpguSEiIkLFbMOVJwj37NkTCoUCXbt2hZWVlcTJSF+8WoqIiBq8GzduYN26dSgpKQFQcRXUs88+y2JjplhuiIiowdJqtThw4AD++9//IjU1FQkJCVJHIiPgYSkiImqQcnNzERMTg9TUVACAv78/+vTpI3EqMgbJR26WLl0KX19fqNVq+Pv749ixY49df+PGjejSpQsaNWoEd3d3TJo0CVlZWfWUloiILMHVq1exfPlypKamQqVSISIiAkOGDIFSyd/5LYGk5WbLli2YOXMm5s+fj6SkJPTu3RuhoaG6Fv1nCQkJGD9+PKZMmYKLFy9i27ZtOH36NKZOnVrPyYmIyFwlJSVh8+bNKCoqgru7O6ZPn46OHTtKHYuMSNJys3jxYkyZMgVTp05F+/btsWTJEjRv3hzLli2rcf2ffvoJPj4+mDFjBnx9ffHcc89h+vTpOHPmTD0nr5ngFMVERCavTZs2sLOzQ48ePTB58mQ0bdpU6khkZJKVm9LSUiQmJmLQoEFVlg8aNAgnTpyo8TlBQUG4ffs24uLiIITA3bt3ER0djcGDBz/ydUpKSpCbm1vlq67JOEUxEZFJycjI0P3Zzs4Or7/+OkJDQ3kYykJJVm4yMzOh0Wjg6upaZbmrq2uVv4R/FBQUhI0bN2LMmDFQqVRwc3ND48aN8eWXXz7ydRYtWgRHR0fdV/PmzY36PoiIyHRpNBrs2bMHK1aswIULF3TLbWxsJExFdU3yE4r/fEfVP06i9GeXLl3CjBkz8N577yExMRF79uxBcnIyoqKiHrn9efPmIScnR/d169Yto+YnIiLT9PDhQ6xZswY///wzgIpfqqlhkGw8zsnJCQqFotoozb1796qN5lRatGgRgoODMWfOHABA586dYWtri969e+PDDz+Eu7t7tedYW1vD2tra+G+AiIhM1qVLl7Bz506UlJRArVZjxIgRaNu2rdSxqJ5INnKjUqng7++P+Pj4Ksvj4+MRFBRU43MKCwshl1eNrFAoAFSM+BARUcNWXl6OXbt2Ydu2bSgpKUHz5s0RFRXFYtPASHom1ezZs/HKK68gICAAgYGBWLlyJVJTU3WHmebNm4c7d+5gw4YNAIChQ4di2rRpWLZsGUJCQpCeno6ZM2eiR48e8PDwkPKtEBGRCbh165buCtrg4GD07dtX90swNRySlpsxY8YgKysLH3zwAdLT09GpUyfExcXB29sbAJCenl5lzpuJEyciLy8PX331Ff7617+icePG6NevH/71r39J9RaIiMiE+Pr6om/fvnB3d0ebNm2kjkMSkYkGdjwnNzcXjo6OyMnJgYODg1G37fPuLgDA6fkD4GzP83yIiOpaWVkZDhw4gF69eqFx48ZSx6E6pM/nNy/wJyIis5SZmYlt27bh3r17SEtLw6RJkx55tS01LCw3RERkds6fP49du3ahrKwMtra2eOGFF1hsSIflpg7w3xcRUd0oLS3F7t27ce7cOQAV59iMHDkS9vb20gYjk8JyQ0REZiE7OxubNm3C/fv3IZPJ0KdPH/Tu3bvaFCFELDdERGQW7OzsIJfLYWdnh/DwcPj4+EgdiUwUyw0REZms0tJSKJVKyOVyKJVK3b0FbW1tpY5GJoxjeUREZJIyMjKwcuVKHD16VLesSZMmLDb0RCw3RERkUoQQOHPmDFatWoWsrCycO3cOpaWlUsciM8LDUkREZDJKSkrwww8/4OLFiwCANm3aYMSIEVCpVBInI3PCckNERCYhPT0d27Ztw8OHDyGXy9G/f38EBgZy/hrSG8sNERFJrqSkBOvXr0dJSQkcHR0REREBLy8vqWORmWK5ISIiyVlbW2PgwIG4du0ahg8fDhsbG6kjkRl76nJTUlICa2veJPKP9x/lACoR0ZPduXMHAODp6QkA6N69O7p3787DUPTU9L5aau/evZg4cSJatWoFKysrNGrUCPb29ujTpw8++ugjpKWl1UVOIiKyEEIInDx5EmvWrMG2bdtQVFQEAJDJZCw2ZBS1Ljc7duxA27ZtMWHCBMjlcsyZMwfbt2/H3r17sXr1avTp0wf79+9Hy5YtERUVhfv379dlbiIiMkNFRUX47rvvsG/fPmi1Wnh4eLDQkNHV+rDUxx9/jP/85z8YPHhwjffxGD16NICKYcbPP/8cGzZswF//+lfjJSUiIrN269YtREdHIzc3FwqFAiEhIQgICGC5IaOrdbk5depUrdbz9PTEJ598YnAgIiKyLEIInDhxAgcOHIAQAk2bNkVERATc3d2ljkYWyugzFJ8+fdrYmyQiIjN369YtCCHQqVMnvPrqqyw2VKcMuloqPz8fCoWiyqV6586dw//7f/8PcXFx0Gg0RgtIRETmSQihO0l4+PDhuHLlCrp06cLDUFTn9Bq5uX37NoKDg+Ho6AhHR0fMnj0bhYWFGD9+PJ599llYW1sjISGhrrISEZEZEELg6NGj+P7773XTZNjY2KBr164sNlQv9Bq5effdd5Gfn4/PP/8cMTEx+Pzzz3HkyBF06dIFV69eha+vb13lJCIiM5Cfn4/Y2FjcvHkTANClSxd+NlC906vcHDp0CFu3bkVwcDAiIiLg4eGByMhIvPvuu3WVj4iIzERycjK2b9+O/Px8KJVKhIWFwcfHR+pY1ADpVW4yMjLQqlUrAICbmxtsbGwwfPjwOglmzjjsSkQNiVarxdGjR3HkyBEAgLOzMyIjI+Hs7CxxMmqo9D6hWKFQ6P4sl8uhVquNGshc/eHuC0REDUpsbCx+/fVXAEDXrl0RFhYGKysriVNRQ6ZXuRFCoH///lAqK55WVFSEoUOHQqVSVVnv7NmzxktIREQmrVu3brh27RrCwsLQuXNnqeMQ6VduFixYUOUxD0kRETU8Wq0W9+7dg5ubGwCgZcuWePvtt3knbzIZT1VuiIioYcnNzUVMTAwyMjIwffp0NG3aFABYbMik6H3Ozc8//4ydO3eirKwMAwYMwKBBg+oiFxERmZhr164hNjYWRUVFUKlUePDgga7cEJkSvcpNbGwsIiMjoVaroVQq8emnn+LTTz/FzJkz6ygeERFJTaPR4ODBgzhx4gQAwN3dHRERESw2ZLL0mqH4448/xsSJE5GdnY3s7GwsXLgQH374YV1lIyIiieXk5GDdunW6YvPss89i8uTJLDZk0vQqN1euXMHcuXN1V0vNmTMH2dnZyMzMrJNwREQkrcTERNy+fRvW1taIjIxEWFiY7jOAyFTp9Tc0Pz8fjRs31j22traGjY0NcnNz4eTkZOxsREQksT59+qCwsBDBwcFo0qSJ1HGIakXv+r137144OjrqHmu1Whw4cEA3gRMADBs2zDjpzBTnJyYic/Xw4UMcP34coaGhUCgUUCgUGDJkiNSxiPSid7mZMGFCtWXTp0/X/Vkmk0Gj0TxdKjPECYqJyNxdunQJO3fuRElJCWxtbdG3b1+pIxEZRK9yo9Vq6yoHERFJpLy8HPv27cPp06cBAF5eXujevbvEqYgMp9cJxZMnT0ZeXl5dZSEionr24MEDrF69WldsgoKCMHHixCqnHxCZG73Kzfr161FUVFRXWYiIqB5du3YNK1asQEZGBmxsbDB27FgMHDiwyg2SicyR3jfOJCIiy9CkSRMIIdCiRQuEh4fDwcFB6khERqH3CcUyGa8FIiIyV8XFxVCr1QAAJycnTJo0Ca6urpDL9RrIJzJpepcbPz+/JxacBw8eGByIiIjqxi+//IK4uDi89NJL8PHxAVBxKwUiS6N3uVm4cCFPNCMiMiNlZWWIi4vDuXPnAABnz57VlRsiS6R3uXnppZfg4uJSF1mIiMjI7t27h+joaNy/fx9AxYzDzz//vMSpiOqWXuWG59vUDncTEUlNCIFz584hLi4O5eXlsLOzw6hRo+Dr6yt1NKI6x6uliIgs0O+//46dO3cCAFq2bIlRo0bB1tZW4lRE9YMzFBsJix8RmRIfHx8888wzcHZ2xnPPPceRd2pQan3tX1RUFG7dulWrdbds2YKNGzcaHIqIiPQjhMD58+d1E63KZDKMHDkSvXv3ZrGhBqfWIzfOzs7o1KkTgoKCMGzYMAQEBMDDwwNqtRoPHz7EpUuXkJCQgO+++w6enp5YuXJlXeYmIqL/KSkpwY8//ohff/0V7dq1w+jRoyGTyVhqqMGqdbn5xz/+gbfeegurV6/G8uXL8euvv1b5vr29PQYMGIBVq1Zh0KBBRg9KRETVpaenIzo6Gg8ePIBMJoOXl5fUkYgkp9c5Ny4uLpg3bx7mzZuH7OxspKSkoKioCE5OTmjVqhV/SyAiqidCCJw+fRr79u2DRqOBo6MjwsPD0bx5c6mjEUlO73luKjVu3BiNGzc2YhQiIqqN4uJi7Ny5E5cvXwYAtG3bFsOHD4eNjY3EyYhMg8HlhoiIpKHVanHnzh3I5XIMHDgQPXv25Mg50R+w3BARmYHK6SZkMhkaNWqEyMhIyGQyeHp6SpyMyPTwNrB1QAb+BkVExlNUVIQtW7bo7g0FAF5eXiw2RI/AkRsiIhN269YtxMTEICcnBykpKejQoQOsra2ljkVk0gwuN+Xl5Th8+DBu3LiBsWPHwt7eHmlpaXBwcICdnZ0xM5oFzk9MRMYkhMCJEydw8OBBaLVaNGnSBJGRkSw2RLVgULlJSUnBiy++iNTUVJSUlGDgwIGwt7fHJ598guLiYixfvtzYOYmIGozCwkLs2LED165dAwB07NgRQ4cOZbEhqiWDzrl5++23ERAQgIcPH1a59HDkyJE4cOCAXttaunQpfH19oVar4e/vj2PHjj12/ZKSEsyfPx/e3t6wtrZGq1atsGbNGkPeBhGRySktLcXKlStx7do1KBQKDBkyBOHh4Sw2RHowaOQmISEBx48fh0qlqrLc29sbd+7cqfV2tmzZgpkzZ2Lp0qUIDg7GihUrEBoaikuXLqFFixY1Pmf06NG4e/cuVq9ejdatW+PevXsoLy835G0QEZkclUqFLl264OLFi4iMjISrq6vUkYjMjkHlRqvVQqPRVFt++/Zt2Nvb13o7ixcvxpQpUzB16lQAwJIlS7B3714sW7YMixYtqrb+nj17cOTIEdy8eRNNmzYFUHHnWyIic1ZQUICysjLdxKh9+vRBcHBwtV8giah2DDosNXDgQCxZskT3WCaTIT8/HwsWLEBYWFittlFaWorExMRq96EaNGgQTpw4UeNzdu7ciYCAAHzyySfw9PSEn58f3nnnHd1dcGtSUlKC3NzcKl9ERKYiOTkZy5cvx9atW3Wj0HK5nMWG6CkYNHLz2WefoW/fvujQoQOKi4sxduxYXLt2DU5OTti8eXOttpGZmQmNRlNtyNXV1RUZGRk1PufmzZtISEiAWq1GbGwsMjMz8frrr+PBgwePPO9m0aJFWLhwoX5vkIiojmm1Whw9ehRHjx6FEAI2NjYoKCiAo6Oj1NGIzJ5B5cbDwwPnzp3Dd999h8TERGi1WkyZMgXjxo3T+94mf54yXAjxyGnEtVotZDIZNm7cqPsPYPHixYiIiMDXX39d42vPmzcPs2fP1j3Ozc3ljeWISFJ5eXmIjY1FcnIyAKBr164IDQ3laA2RkRhUbo4ePYqgoCBMmjQJkyZN0i0vLy/H0aNH8fzzzz9xG05OTlAoFNVGae7du/fIE+jc3d3h6elZ5Teb9u3bQwiB27dvo02bNtWeY21tXf9XGXCCYiJ6hBs3biA2NhYFBQWwsrLC4MGD0aVLF6ljEVkUg8656du3Lx48eFBteU5ODvr27VurbahUKvj7+yM+Pr7K8vj4eAQFBdX4nODgYKSlpSE/P1+37OrVq5DL5fDy8tLjHRAR1T8hBA4fPoyCggK4uLjg1VdfZbEhqgMGlZtHHTrKysqCra1trbcze/ZsrFq1CmvWrMHly5cxa9YspKamIioqCkDFIaXx48fr1h87diyaNWuGSZMm4dKlSzh69CjmzJmDyZMn6304zNgEpygmoieQyWQYNWoUevbsialTp8LJyUnqSEQWSa/DUqNGjQJQ8Q904sSJVQ73aDQa/PLLL48cdanJmDFjkJWVhQ8++ADp6eno1KkT4uLi4O3tDQBIT09Hamqqbn07OzvEx8fjrbfeQkBAAJo1a4bRo0fjww8/1OdtEBHVm2vXruHu3bt47rnnAABNmjTBiy++KHEqIsumV7mpPNdFCAF7e/sqoyUqlQq9evXCtGnT9Arw+uuv4/XXX6/xe+vWrau2rF27dtUOZRERmRqNRoODBw/qprbw8vLivFxE9USvcrN27VoAFRPnvfPOO3odgiIiaihycnIQHR2N27dvAwCeffZZnhdIVI8MulpqwYIFxs5BRGQRrly5gh07dqC4uBjW1tYYNmwYOnToIHUsogbFoHIDANHR0di6dStSU1NRWlpa5Xtnz5596mBERObm4MGDupv/enh4ICIiAk2aNJE4FVHDY9DVUl988QUmTZoEFxcXJCUloUePHmjWrBlu3ryJ0NBQY2ckIjILzZo1AwD07NkTkydPZrEhkohBIzdLly7FypUr8Ze//AXr16/H3Llz0bJlS7z33ns1zn9DRGSpioqKdBdXdOnSBS4uLnB3d5c4FVHDZtDITWpqqu6SbxsbG+Tl5QEAXnnllVrfW8qSPeLuEURkQcrLyxEXF4dly5ahoKBAt5zFhkh6BpUbNzc3ZGVlAQC8vb3x008/Aai4u63gbHZEZOEqb9Z7+vRp5OXl4dq1a1JHIqI/MOiwVL9+/fDDDz+ge/fumDJlCmbNmoXo6GicOXNGN9EfEZElunjxInbu3InS0lLY2NhgxIgR8PPzkzoWEf2BQeVm5cqV0Gq1AICoqCg0bdoUCQkJGDp0qO7WCQ2NAEesiCxZWVkZ9u7di8TERABAixYtEB4eDgcHB4mTEdGfGVRu5HI55PL/O6I1evRojB49GgBw584deHp6GicdEZGJOHLkiK7YPPfcc+jbt2+V/weJyHQY7V9mRkYG3nrrLbRu3dpYmyQiMhnPPfccvLy88PLLL6N///4sNkQmTK9/ndnZ2Rg3bhycnZ3h4eGBL774AlqtFu+99x5atmyJn376CWvWrKmrrERE9aasrAynT5/WXSShVqsxefJktGrVSuJkRPQkeh2W+vvf/46jR49iwoQJ2LNnD2bNmoU9e/aguLgYu3fvRp8+feoqJxFRvbl//z62bduG+/fvQwiBHj16AABknOeByCzoVW527dqFtWvXYsCAAXj99dfRunVr+Pn5YcmSJXUUj4iofp07dw5xcXEoKyuDnZ0dnJ2dpY5ERHrSq9ykpaXpbgDXsmVLqNVqTJ06tU6CERHVp9LSUsTFxeH8+fMAKv6PGzlyJOzs7CRORkT60qvcaLVaWFlZ6R4rFArY2toaPZS548A1kXm5e/cuoqOjkZmZCZlMhhdeeAG9e/fmYSgiM6VXuRFCYOLEibC2tgYAFBcXIyoqqlrB2b59u/ESEhHVsZKSEmRlZcHe3h7h4eHw9vaWOhIRPQW9ys2ECROqPH755ZeNGoaIqL4IIXQjMy1atEBERAS8vb05Gk1kAfQqN2vXrq2rHGaPt9QiMh/p6enYuXMnRo0apTthuPJ8QiIyf5yFiogaDCEETp8+jdWrVyMjIwP79u2TOhIR1QGDbr9ARGRuiouL8cMPP+DSpUsAAD8/PwwfPlziVERUF1huiMjipaWlYdu2bcjOzoZcLseAAQPQq1cvXg1FZKFYbojIot26dQvr1q2DVqtF48aNERERwZv7Elk4lhsismienp7w8vKCra0thg0bBrVaLXUkIqpjBp9Q/O233yI4OBgeHh5ISUkBACxZsgTff/+90cIRERkiPT0d5eXlAAC5XI6xY8ciMjKSxYaogTCo3CxbtgyzZ89GWFgYsrOzodFoAACNGzfmfabAm+sRSUUIgRMnTmDVqlWIj4/XLbe2tua/S6IGxKBy8+WXX+Kbb77B/PnzoVAodMsDAgJw4cIFo4UjIqqtwsJCbN68GfHx8dBqtSgoKIBWq5U6FhFJwKBzbpKTk9GtW7dqy62trVFQUPDUoYiI9JGamoro6Gjk5eVBoVDgxRdfhL+/P0driBoog8qNr68vzp07V+3+K7t37+Ysn0RUb4QQSEhIwKFDhyCEQLNmzRAREQE3NzepoxGRhAwqN3PmzMEbb7yB4uJiCCFw6tQpbN68GYsWLcKqVauMnZGIqEZ5eXk4fvw4hBB45plnMHjwYN2NfYmo4TKo3EyaNAnl5eWYO3cuCgsLMXbsWHh6euLzzz/HSy+9ZOyMREQ1cnBwwPDhw1FcXIyuXbvyMBQRAXiKeW6mTZuGadOmITMzE1qtFi4uLsbMRURUjVarxbFjx+Dp6YnWrVsDANq3by9xKiIyNQZdLbVw4ULcuHEDAODk5MRiQ0R1Lj8/H//9739x+PBhxMbGoqioSOpIRGSiDCo3MTEx8PPzQ69evfDVV1/h/v37xs5FRKRz8+ZNLF++HMnJybCyssKgQYNgY2MjdSwiMlEGlZtffvkFv/zyC/r164fFixfD09MTYWFh2LRpEwoLC42dkYgaKK1Wi4MHD+Lbb79FQUEBXFxc8Oqrr6JLly5SRyMiE2bw7Rc6duyIjz/+GDdv3sShQ4fg6+uLmTNn8hJMADylkejplZWVYcOGDTh27BgAoHv37pg6dSqcnJwkTkZEps4oN860tbWFjY0NVCoV8vLyjLFJImrgrKys0LhxY6Snp2Po0KHo1KmT1JGIyEwYPHKTnJyMjz76CB06dEBAQADOnj2L999/HxkZGcbMR0QNiEajQXFxse5xWFgYpk+fzmJDRHoxaOQmMDAQp06dwjPPPINJkybp5rkhIjJUTk4OYmJiYG1tjbFjx0Imk0GlUqFp06ZSRyMiM2NQuenbty9WrVqFjh07GjuP2RJC6gRE5uvKlSv4/vvvUVRUBGtra2RlZfHcGiIymEHl5uOPPzZ2DiJqgDQaDfbv34+ffvoJAODh4YGIiAg0adJE4mREZM5qXW5mz56Nf/zjH7C1tcXs2bMfu+7ixYufOhgRWbbs7GxER0fjzp07AICePXtiwIABUCqNcp0DETVgtf5fJCkpCWVlZbo/ExEZSgiBrVu3Ij09HWq1GsOHD0e7du2kjkVEFqLW5ebQoUM1/pmISF8ymQxDhgzBvn37MGLECDRu3FjqSERkQQy6FHzy5Mk1zmdTUFCAyZMnP3UoIrI8Dx48wKVLl3SPPTw8MGHCBBYbIjI6g8rN+vXra7xpXVFRETZs2PDUoYjIsly8eBErV67E9u3bkZ6erlsuk3E+byIyPr3O3MvNzYUQAkII5OXlQa1W676n0WgQFxfHO4QD4P/XRBXKy8uxd+9enDlzBgDQokUL2NraSpyKiCydXuWmcePGkMlkkMlk8PPzq/Z9mUyGhQsXGi0cEZmvrKwsbNu2DXfv3gUAPPfcc+jbty/kcoMnRiciqhW9ys2hQ4cghEC/fv0QExNTZeZQlUoFb29veHh4GD0kEZmXCxcu4IcffkBZWRkaNWqEUaNGoVWrVlLHIqIGQq9y06dPHwAV95Vq0aIFj5cTUY2ys7NRVlYGHx8fjBo1Cvb29lJHIqIGpNbl5pdffkGnTp0gl8uRk5ODCxcuPHLdzp07GyWcORHg/ReoYRNC6H7hee6552Bvb4/OnTvzMBQR1btal5uuXbsiIyMDLi4u6Nq1K2QyGUQNN1SSyWTQaDRGDUlEpu3cuXM4c+YMJkyYACsrK8hkMnTt2lXqWETUQNW63CQnJ8PZ2Vn3ZyKi0tJSxMXF4fz58wCAM2fOIDAwUOJURNTQ1brceHt71/hnImqY7t69i+joaGRmZkImk+GFF15Az549pY5FRGT4JH67du3SPZ47dy4aN26MoKAgpKSkGC0cEZkeIQTOnj2LVatWITMzE/b29pgwYQKef/55nl9DRCbBoP+JPv74Y9jY2AAATp48ia+++gqffPIJnJycMGvWLKMGJCLTkpCQgB9++AHl5eVo3bo1pk+fztFcIjIpBpWbW7duoXXr1gCAHTt2ICIiAq+++ioWLVqEY8eO6bWtpUuXwtfXF2q1Gv7+/rV+/vHjx6FUKk3ypEUZeIk8Wa4uXbrAzs4OAwYMwNixYznjMBGZHIPKjZ2dHbKysgAA+/btw4ABAwAAarW6xntOPcqWLVswc+ZMzJ8/H0lJSejduzdCQ0ORmpr62Ofl5ORg/Pjx6N+/vyHxiUgPQogq/yYdHBzw1ltvITg4mHNdEZFJMqjcDBw4EFOnTsXUqVNx9epVDB48GEDFzfF8fHxqvZ3FixdjypQpmDp1Ktq3b48lS5agefPmWLZs2WOfN336dIwdO5ZXZRDVseLiYkRHR2Pt2rX47bffdMtVKpWEqYiIHs+gcvP1118jMDAQ9+/fR0xMDJo1awYASExMxF/+8pdabaO0tBSJiYkYNGhQleWDBg3CiRMnHvm8tWvX4saNG1iwYIEh0YmoltLS0rBy5UpcunQJcrkc+fn5UkciIqoVvW6/UKlx48b46quvqi3X56aZmZmZ0Gg0cHV1rbLc1dUVGRkZNT7n2rVrePfdd3Hs2DEolbWLXlJSgpKSEt3j3NzcWmfURw3zGRKZJSEEfv75Z8THx0Or1aJx48aIiIiAp6en1NGIiGrFoHIDVNw7ZvXq1bh8+TJkMhnat2+PKVOmwNHRUa/t/PmY/R+ncP8jjUaDsWPHYuHChTXekfxRFi1axDuVE9VSUVERdu7cqTsE1b59ewwbNgxqtVriZEREtWfQYakzZ86gVatW+Oyzz/DgwQNkZmbis88+Q6tWrXD27NlabcPJyQkKhaLaKM29e/eqjeYAQF5eHs6cOYM333wTSqUSSqUSH3zwAc6fPw+lUomDBw/W+Drz5s1DTk6O7uvWrVv6v2GiBiIlJQW//fYbFAoFQkNDERkZyWJDRGbHoJGbWbNmYdiwYfjmm290h4fKy8sxdepUzJw5E0ePHn3iNlQqFfz9/REfH4+RI0fqlsfHx2P48OHV1ndwcKh2s86lS5fi4MGDiI6Ohq+vb42vY21tDWtra33eHlGD1a5dO/Tt2xetW7eGh4eH1HGIiAxiULk5c+ZMlWIDAEqlEnPnzkVAQECttzN79my88sorCAgIQGBgIFauXInU1FRERUUBqBh1uXPnDjZs2AC5XI5OnTpVeb6LiwvUanW15URUO4WFhdi3bx/69+8Pe3t7AMDzzz8vcSoioqdjULlxcHBAamoq2rVrV2X5rVu3dP9B1saYMWOQlZWFDz74AOnp6ejUqRPi4uJ0s52mp6c/cc4bIjJMamoqYmJikJubi4KCAowbN07qSERERiETQv/rfGbMmIHY2Fj85z//QVBQEGQyGRISEjBnzhyEh4djyZIldRDVOHJzc+Ho6IicnBw4ODgYbbsFJeXouGAvAOC3f7wItZXCaNsmMiYhBI4fP46DBw9CCIFmzZohIiICbm5uUkcjInokfT6/DRq5+c9//gOZTIbx48ejvLwcAGBlZYXXXnsN//znPw3ZJBHVg4KCAuzYsQPXr18HADzzzDMYPHgwz0sjIotiULlRqVT4/PPPsWjRIty4cQNCCLRu3RqNGjUydj4iMpJ79+7hv//9L/Ly8qBUKhEWFoauXbvyFgpEZHH0uhS8sLAQb7zxBjw9PeHi4oKpU6fC3d0dnTt3ZrEhMnGNGzeGtbU1nJycMG3aNHTr1o3Fhogskl4jNwsWLMC6deswbtw4qNVqbN68Ga+99hq2bdtWV/nMBicoJlNUWFgIGxsbyGQyqFQq3V28eW8oIrJkepWb7du3Y/Xq1XjppZcAAC+//DKCg4Oh0WigUPAEWiJTcvPmTWzfvh1BQUEICgoCADRp0kTiVEREdU+vw1K3bt1C7969dY979OgBpVKJtLQ0owcjIsNotVocOnQI3377LQoKCnDhwgVotVqpYxER1Ru9Rm40Gk214WylUqm7YoqIpJWXl4eYmBikpKQAALp3744XX3wRcrlBd1ohIjJLepUbIQQmTpxY5bLR4uJiREVFwdbWVrds+/btxktIRLVy/fp1xMbGorCwECqVCkOGDMEzzzwjdSwionqnV7mZMGFCtWUvv/yy0cIQkWHy8vLw3XffQaPRwM3NDREREWjWrJnUsYiIJKFXuVm7dm1d5SCip2Bvb48BAwYgKysLISEhVe77RkTU0PB/QCIzdfXqVTg4OOhum9CrVy+JExERmQaeZUhkZjQaDfbt24fNmzdj27ZtKCkpkToSEZFJ4cgNkRnJzs5GdHQ07ty5AwBo06YN55giIvoTlhsiM/Hbb7/h+++/R3FxMdRqNYYPH4527dpJHYuIyOSw3BiJELwBA9WNysNQp06dAgB4eXkhPDwcjRs3ljYYEZGJMvicm2+//RbBwcHw8PDQTRi2ZMkSfP/990YLR0SATCZDZmYmACAwMBATJ05ksSEiegyDys2yZcswe/ZshIWFITs7GxqNBkDFXYeXLFlizHxEDVblaKBcLsfIkSMxduxYDBo0iOfYEBE9gUHl5ssvv8Q333yD+fPnV/mPNiAgABcuXDBaOKKGqLy8HLt27cKPP/6oW2ZnZ4c2bdpImIqIyHwYdM5NcnIyunXrVm25tbU1CgoKnjoUUUOVlZWF6OhoZGRkAKi4Oa2rq6vEqYiIzItB5cbX1xfnzp2Dt7d3leW7d+9Ghw4djBLMnMlkUicgc3ThwgX8+OOPKC0tRaNGjTBy5EgWGyIiAxhUbubMmYM33ngDxcXFEELg1KlT2Lx5MxYtWoRVq1YZOyORRSsrK8Pu3buRlJQEAPDx8cGoUaNgb28vcTIiIvNkULmZNGkSysvLMXfuXBQWFmLs2LHw9PTE559/jpdeesnYGYkslhACmzZtwu+//w4AeP7559GnTx/I5Zw8nIjIUAbPczNt2jRMmzYNmZmZ0Gq1cHFxMWYuogZBJpMhMDAQmZmZGDVqFHx9faWORERk9p56Ej8nJydj5CBqMEpLS5GZmQkPDw8AgJ+fH9566y2oVCqJkxERWQaDTyiWPeas2Zs3bxocyFxxfmKqjXv37mHbtm3Iz8/H9OnTdZPxsdgQERmPQeVm5syZVR6XlZUhKSkJe/bswZw5c4yRi8iiCCGQlJSE3bt3o7y8HPb29igoKOBMw0REdcCgcvP222/XuPzrr7/GmTNnnioQkaUpKSnBrl27dBNctm7dGiNGjICtra3EyYiILJNRL8kIDQ1FTEyMMTdJZNYyMjLwzTff4MKFC5DJZOjfvz/Gjh3LYkNEVIeMelfw6OhoNG3a1JibJDJrZ8+eRVZWFhwcHBAeHo4WLVpIHYmIyOIZVG66detW5YRiIQQyMjJw//59LF261GjhzJUMnKKYKlTe6LJ3795o1KiR1HGIiBoEg8rNiBEjqjyWy+VwdnbGCy+8gHbt2hkjF5FZSktLw+nTpzF06FDI5XIolUqEhIRIHYuIqEHRu9yUl5fDx8cHISEhcHNzq4tMRGan8jYk8fHx0Gg0cHFxQWBgoNSxiIgaJL3LjVKpxGuvvYbLly/XRR4is1NUVISdO3fit99+AwC0a9cOXbt2lTYUEVEDZtBhqZ49eyIpKanaXcGJGpo7d+4gOjoa2dnZUCgUGDhwIHr06PHYSS6JiKhuGVRuXn/9dfz1r3/F7du34e/vX+2y1s6dOxslHJEpO3/+PHbu3AmtVosmTZogIiJCd0sFIiKSjl7lZvLkyViyZAnGjBkDAJgxY4buezKZDEIIyGQyaDQa46Y0A4L3X2hw3NzcIJfL0b59ewwZMgRqtVrqSEREBD3Lzfr16/HPf/4TycnJdZWHyKQVFBToRipdXV3x6quvwsnJiYehiIhMiF7lRvxveILn2lBDI4TA8ePHceTIEUyYMAFeXl4AAGdnZ4mTERHRn+l9zg1/Q6WGpqCgADt27MD169cBAJcuXdKVGyIiMj16lxs/P78nFpwHDx4YHMgSsP9ZjpSUFMTExCAvLw9KpRKhoaHo1q2b1LGIiOgx9C43CxcuhKOjY11kITIZWq0WCQkJOHz4MIQQcHJyQmRkJFxcXKSORkRET6B3uXnppZf4HzxZvMuXL+PQoUMAgC5duiAsLAwqlUriVEREVBt6lRueb0MNRYcOHdCpUye0atWKsw0TEZkZuT4rC07mQhZKq9Xi5MmTKCkpAVBR5MPDw1lsiIjMkF4jN1qttq5yEEkmLy8PMTExSElJQXp6OkaNGiV1JCIiegoG3X6BasBBLbN0/fp1xMbGorCwECqVCm3atJE6EhERPSWWG2qQtFotDh48iOPHjwOomG04MjISzZo1kzgZERE9LZYbanByc3MRHR2NW7duAQACAgIQEhICpZL/HIiILAH/N6cGRy6X48GDB7C2tsbQoUPRsWNHqSMREZERsdzUAV4wb3q0Wi3k8oqLA+3s7DBmzBjY2tqiadOmEicjIiJj0+tScCJzlJ2djTVr1uDXX3/VLWvevDmLDRGRheLIDVm03377Dd9//z2Ki4uxf/9+tG/fHgqFQupYRERUh1huyCJpNBrEx8fj559/BgB4enoiIiKCxYaIqAFguSGL8/DhQ0RHRyMtLQ0AEBgYiP79+7PYEBE1ECw3ZFEKCgqwYsUKlJSUwMbGBsOHD0fbtm2ljkVERPWI5cZIBKcoNgm2trbo1q0b7ty5g/DwcDg6OkodiYiI6pnkV0stXboUvr6+UKvV8Pf3x7Fjxx657vbt2zFw4EA4OzvDwcEBgYGB2Lt3bz2mJVOUlZWFnJwc3eMBAwZgwoQJLDZERA2UpOVmy5YtmDlzJubPn4+kpCT07t0boaGhSE1NrXH9o0ePYuDAgYiLi0NiYiL69u2LoUOHIikpqZ6Tk6m4cOECVq5ciZiYGGg0GgCAQqHg+TVERA2YTAgh2fGUnj17onv37li2bJluWfv27TFixAgsWrSoVtvo2LEjxowZg/fee69W6+fm5sLR0RE5OTlwcHAwKHdNsgtL0fWDeADA9Y9CoVRIPihm0crKyrBnzx6cPXsWAODt7Y0xY8bAxsZG4mRERFQX9Pn8luycm9LSUiQmJuLdd9+tsnzQoEE4ceJErbah1WqRl5dncpOxyWSco7guZWZmYtu2bbh37x4A4Pnnn0efPn10MxATEVHDJlm5yczMhEajgaura5Xlrq6uyMjIqNU2Pv30UxQUFGD06NGPXKekpAQlJSW6x7m5uYYFJpNw/vx57Nq1C2VlZbC1tcWoUaPQsmVLqWMREZEJkfxX3T+PcgghajXysXnzZrz//vvYsmULXFxcHrneokWL4OjoqPtq3rz5U2cmaWg0Gpw8eRJlZWXw9fVFVFQUiw0REVUjWblxcnKCQqGoNkpz7969aqM5f7ZlyxZMmTIFW7duxYABAx677rx585CTk6P7unXr1lNnJ2koFApERESgX79+ePnll2FnZyd1JCIiMkGSlRuVSgV/f3/Ex8dXWR4fH4+goKBHPm/z5s2YOHEiNm3ahMGDBz/xdaytreHg4FDli8yDEAJnz57F8ePHdcucnJzQu3dvnl9DRESPJOkkfrNnz8Yrr7yCgIAABAYGYuXKlUhNTUVUVBSAilGXO3fuYMOGDQAqis348ePx+eefo1evXrpRHxsbG85pYmFKSkqwa9cuXLhwATKZDC1btoS7u7vUsYiIyAxIWm7GjBmDrKwsfPDBB0hPT0enTp0QFxcHb29vAEB6enqVOW9WrFiB8vJyvPHGG3jjjTd0yydMmIB169bVd3yqIxkZGYiOjkZWVhZkMhn69esHNzc3qWMREZGZkHSeGynU1Tw3DwtK0e0fFYfYbnwcBoWcl4PrSwiBxMRE7NmzBxqNBg4ODggPD0eLFi2kjkZERBIzi3luiP5s586dOHfuHADAz88Pw4cPR6NGjaQNRUREZodnZZLJ8PT0hFwux8CBA/HSSy+x2BARkUE4clMHeECqdoQQKCgo0F3S7e/vDx8fHzg5OUmcjIiIzBlHbkgSRUVF2Lp1K1avXo3i4mIAFRM6stgQEdHT4sgN1bvbt28jJiYG2dnZkMvlSE1NhZ+fn9SxiIjIQrDcUL0RQuCnn37C/v37odVq0aRJE0RERMDDw0PqaEREZEFYbqheFBYW4vvvv8fVq1cBAB06dMDQoUOhVqslTkZERJaG5Ybqxf79+3H16lUoFAqEhIQgICCgVjdIJSIi0hfLDdWLAQMGIDs7G4MGDeJsw0REVKd4tZSRNKhpnmuhoKAAJ0+eROUE2I0aNcL48eNZbIiIqM5x5IaMLiUlBTExMcjLy4NarUa3bt2kjkRERA0Iyw0ZjVarRUJCAg4fPgwhBJycnHglFBER1TuWmzrQEM+Tzc/PR2xsLG7evAkA6NKlC8LCwqBSqSRORkREDQ3LDT2133//HdHR0SgoKICVlRXCwsLQtWtXqWMREVEDxXJDT02r1aKgoADOzs6IjIyEs7Oz1JGIiKgBY7khg2i1WsjlFRfbtWzZEmPGjEGrVq1gZWUlcTIiImroeCk46e369ev4+uuv8eDBA92ydu3asdgQEZFJYLmhWtNqtThw4AA2btyIBw8e4OjRo1JHIiIiqoaHpahWcnNzERMTg9TUVACAv78/QkJCJE5FRERUHcsNPdHVq1exY8cOFBUVQaVSYdiwYejYsaPUsYiIiGrEcmMklbcZsDRXr17F5s2bAQDu7u6IiIhA06ZNJU5FRET0aCw39FitWrWCp6cnPD09MXDgQCiV/CtDRESmjZ9UdUBm5lMUJycno0WLFlAoFFAoFJg4cSJLDRERmQ1eLUU6Go0Ge/bswYYNG3D48GHdchYbIiIyJ/zUIgDAw4cPER0djbS0NAAVRUcIYfajUERE1PCw3BAuXbqEnTt3oqSkBDY2Nhg+fDjatm0rdSwiIiKDsNw0YOXl5di7dy/OnDkDAGjevDnCw8Ph6OgocTIiIiLDsdw0YDk5OTh//jwAIDg4GH379oVCoZA4FRER0dNhuWnAmjVrhuHDh0OlUqFNmzZSxyEiIjIKXi3VgJSVleHHH39ESkqKblnHjh1ZbIiIyKKw3BiJqc9PnJmZiVWrViExMRHbt29HeXm51JGIiIjqBA9LNQDnz5/Hrl27UFZWBltbWwwbNoxz1xARkcXiJ5wFKy0txe7du3Hu3DkAgK+vL0aOHAl7e3tpgxEREdUhlhsLVVRUhLVr1+L+/fuQyWTo06cPevfuDbmcRyKJiMiysdxYKLVaDWdnZxQVFSE8PBw+Pj5SRyIiIqoXLDcWpLS0FFqtFmq1GjKZDEOHDoVGo4Gtra3U0YiIiOoNj1FYiIyMDKxcuRI7d+6EEBXXbqnVahYbIiJqcDhyY+aEEEhMTMSePXug0WhQWlqK/Px8njRMREQNFsuNGSspKcEPP/yAixcvAgDatGmDESNGoFGjRhInIyIikg7LjZlKT0/Htm3b8PDhQ8jlcvTv3x+BgYGQyWRSRyMiIpIUy40Z0mq1umLj6OiIiIgIeHl5SR2LiIjIJLDcGImox/svyOVyjBgxAj/99BOGDh0KGxub+ntxIiIiE8dyY2R1dVTozp07yMnJQYcOHQAALVq0QIsWLermxYiIiMwYy42JE0Lgp59+wv79+6FQKODs7AxnZ2epYxEREZkslhsTVlRUhB07duDq1asAgLZt2/ISbyIioidguTFRt27dQnR0NHJzc6FQKBASEoKAgABeDUVERPQELDcm6MSJE9i/fz+EEGjatCkiIiLg7u4udSwiIiKzwHJjgoqLiyGEQKdOnTBkyBBYW1tLHYmIiMhssNyYCK1WC7m84lZfL7zwAtzd3dGuXTsehiIiItITb5wpMSEEjh49ijVr1qC8vBxAxTw27du3Z7EhIiIyAEduJJSfn4/Y2FjcvHkTAHDp0iV07txZ4lRERETmjeXGSAT0m6I4OTkZ27dvR35+PpRKJcLCwvDMM8/UUToiIqKGg+XGyJ50IEmr1eLo0aM4cuQIAMDZ2RmRkZGcmI+IiMhIWG7q2d69e3Hq1CkAQNeuXREWFgYrKyuJUxEREVkOlpt61qtXL1y+fBkDBgzg+TVERER1gOWmjmm1WiQnJ6NVq1YAgCZNmmDGjBlQKrnriYiI6gIvBa9Dubm5WL9+Pf773//ixo0buuUsNkRERHVH8nKzdOlS+Pr6Qq1Ww9/fH8eOHXvs+keOHIG/vz/UajVatmyJ5cuX11NS/Vy7dg3Lly9HamoqVCoVSktLpY5ERETUIEhabrZs2YKZM2di/vz5SEpKQu/evREaGorU1NQa109OTkZYWBh69+6NpKQk/P3vf8eMGTMQExNTz8kfTQYt4uPjsWnTJhQVFcHd3R3Tp09H+/btpY5GRETUIMiEEPpN0GJEPXv2RPfu3bFs2TLdsvbt22PEiBFYtGhRtfX/9re/YefOnbh8+bJuWVRUFM6fP4+TJ0/W6jVzc3Ph6OiInJwcODg4PP2b+J97ecXo+3EcXlDdhIu8AADQo0cPDBw4kIehiIiInpI+n9+SjdyUlpYiMTERgwYNqrJ80KBBOHHiRI3POXnyZLX1Q0JCcObMGZSVldX4nJKSEuTm5lb5qitu8ny4yAtgbW2N0aNHIzQ0lMWGiIionklWbjIzM6HRaODq6lpluaurKzIyMmp8TkZGRo3rl5eXIzMzs8bnLFq0CI6Ojrqv5s2bG+cN1OC2zBnnNV48DEVERCQhyYcV/nxzSCHEY28YWdP6NS2vNG/ePMyePVv3ODc3t04Kjou9Glc+DDX6domIiEg/kpUbJycnKBSKaqM09+7dqzY6U8nNza3G9ZVKJZo1a1bjc6ytrWFtbW2c0ERERGTyJDsspVKp4O/vj/j4+CrL4+PjERQUVONzAgMDq62/b98+BAQE8BYGREREBEDiS8Fnz56NVatWYc2aNbh8+TJmzZqF1NRUREVFAag4pDR+/Hjd+lFRUUhJScHs2bNx+fJlrFmzBqtXr8Y777wj1VsgIiIiEyPpOTdjxoxBVlYWPvjgA6Snp6NTp06Ii4uDt7c3ACA9Pb3KnDe+vr6Ii4vDrFmz8PXXX8PDwwNffPEFwsPDpXoLREREZGIknedGCnU1zw0RERHVHbOY54aIiIioLrDcEBERkUVhuSEiIiKLwnJDREREFoXlhoiIiCwKyw0RERFZFJYbIiIisigsN0RERGRRWG6IiIjIokh6+wUpVE7InJubK3ESIiIiqq3Kz+3a3FihwZWbvLw8AEDz5s0lTkJERET6ysvLg6Oj42PXaXD3ltJqtUhLS4O9vT1kMplRt52bm4vmzZvj1q1bvG9VHeJ+rh/cz/WD+7n+cF/Xj7raz0II5OXlwcPDA3L548+qaXAjN3K5HF5eXnX6Gg4ODvyHUw+4n+sH93P94H6uP9zX9aMu9vOTRmwq8YRiIiIisigsN0RERGRRWG6MyNraGgsWLIC1tbXUUSwa93P94H6uH9zP9Yf7un6Ywn5ucCcUExERkWXjyA0RERFZFJYbIiIisigsN0RERGRRWG6IiIjIorDc6Gnp0qXw9fWFWq2Gv78/jh079tj1jxw5An9/f6jVarRs2RLLly+vp6TmTZ/9vH37dgwcOBDOzs5wcHBAYGAg9u7dW49pzZe+f58rHT9+HEqlEl27dq3bgBZC3/1cUlKC+fPnw9vbG9bW1mjVqhXWrFlTT2nNl777eePGjejSpQsaNWoEd3d3TJo0CVlZWfWU1jwdPXoUQ4cOhYeHB2QyGXbs2PHE50jyOSio1r777jthZWUlvvnmG3Hp0iXx9ttvC1tbW5GSklLj+jdv3hSNGjUSb7/9trh06ZL45ptvhJWVlYiOjq7n5OZF3/389ttvi3/961/i1KlT4urVq2LevHnCyspKnD17tp6Tmxd993Ol7Oxs0bJlSzFo0CDRpUuX+glrxgzZz8OGDRM9e/YU8fHxIjk5Wfz888/i+PHj9Zja/Oi7n48dOybkcrn4/PPPxc2bN8WxY8dEx44dxYgRI+o5uXmJi4sT8+fPFzExMQKAiI2Nfez6Un0OstzooUePHiIqKqrKsnbt2ol33323xvXnzp0r2rVrV2XZ9OnTRa9eveosoyXQdz/XpEOHDmLhwoXGjmZRDN3PY8aMEf/f//f/iQULFrDc1IK++3n37t3C0dFRZGVl1Uc8i6Hvfv73v/8tWrZsWWXZF198Iby8vOoso6WpTbmR6nOQh6VqqbS0FImJiRg0aFCV5YMGDcKJEydqfM7JkyerrR8SEoIzZ86grKyszrKaM0P2859ptVrk5eWhadOmdRHRIhi6n9euXYsbN25gwYIFdR3RIhiyn3fu3ImAgAB88skn8PT0hJ+fH9555x0UFRXVR2SzZMh+DgoKwu3btxEXFwchBO7evYvo6GgMHjy4PiI3GFJ9Dja4G2caKjMzExqNBq6urlWWu7q6IiMjo8bnZGRk1Lh+eXk5MjMz4e7uXmd5zZUh+/nPPv30UxQUFGD06NF1EdEiGLKfr127hnfffRfHjh2DUsn/OmrDkP188+ZNJCQkQK1WIzY2FpmZmXj99dfx4MEDnnfzCIbs56CgIGzcuBFjxoxBcXExysvLMWzYMHz55Zf1EbnBkOpzkCM3epLJZFUeCyGqLXvS+jUtp6r03c+VNm/ejPfffx9btmyBi4tLXcWzGLXdzxqNBmPHjsXChQvh5+dXX/Eshj5/n7VaLWQyGTZu3IgePXogLCwMixcvxrp16zh68wT67OdLly5hxowZeO+995CYmIg9e/YgOTkZUVFR9RG1QZHic5C/ftWSk5MTFApFtd8C7t27V62VVnJzc6txfaVSiWbNmtVZVnNmyH6utGXLFkyZMgXbtm3DgAED6jKm2dN3P+fl5eHMmTNISkrCm2++CaDiQ1gIAaVSiX379qFfv371kt2cGPL32d3dHZ6ennB0dNQta9++PYQQuH37Ntq0aVOnmc2RIft50aJFCA4Oxpw5cwAAnTt3hq2tLXr37o0PP/yQI+tGItXnIEduakmlUsHf3x/x8fFVlsfHxyMoKKjG5wQGBlZbf9++fQgICICVlVWdZTVnhuxnoGLEZuLEidi0aROPmdeCvvvZwcEBFy5cwLlz53RfUVFRaNu2Lc6dO4eePXvWV3SzYsjf5+DgYKSlpSE/P1+37OrVq5DL5fDy8qrTvObKkP1cWFgIubzqR6BCoQDwfyML9PQk+xys09OVLUzlpYarV68Wly5dEjNnzhS2trbi999/F0II8e6774pXXnlFt37lJXCzZs0Sly5dEqtXr+al4LWg737etGmTUCqV4uuvvxbp6em6r+zsbKneglnQdz//Ga+Wqh1993NeXp7w8vISERER4uLFi+LIkSOiTZs2YurUqVK9BbOg735eu3atUCqVYunSpeLGjRsiISFBBAQEiB49ekj1FsxCXl6eSEpKEklJSQKAWLx4sUhKStJdcm8qn4MsN3r6+uuvhbe3t1CpVKJ79+7iyJEjuu9NmDBB9OnTp8r6hw8fFt26dRMqlUr4+PiIZcuW1XNi86TPfu7Tp48AUO1rwoQJ9R/czOj79/mPWG5qT9/9fPnyZTFgwABhY2MjvLy8xOzZs0VhYWE9pzY/+u7nL774QnTo0EHY2NgId3d3MW7cOHH79u16Tm1eDh069Nj/b03lc1AmBMffiIiIyHLwnBsiIiKyKCw3REREZFFYboiIiMiisNwQERGRRWG5ISIiIovCckNEREQWheWGiIiILArLDREREVkUlhsiM7Zu3To0btxY6hgG8/HxwZIlSx67zvvvv4+uXbvWSx5Tc/DgQbRr1w5arbZeX/fChQvw8vJCQUFBvb4ukbGw3BBJbOLEiZDJZNW+rl+/LnU0rFu3rkomd3d3jB49GsnJyUbZ/unTp/Hqq6/qHstkMuzYsaPKOu+88w4OHDhglNd7lD+/T1dXVwwdOhQXL17UezvGLJtz587F/PnzdTd4/HPOyq9Vq1bV+P2afl4+Pj6679vY2KBdu3b497//XeVmkc888wx69OiBzz77zGjvhag+sdwQmYAXX3wR6enpVb58fX2ljgWg4o7g6enpSEtLw6ZNm3Du3DkMGzYMGo3mqbft7OyMRo0aPXYdOzs7NGvW7Klf60n++D537dqFgoICDB48GKWlpXX+2jU5ceIErl27hsjIyBpz/vFr3Lhx1b7/uJ/XBx98gPT0dFy+fBnvvPMO/v73v2PlypVVXmfSpElYtmyZUX7ORPWN5YbIBFhbW8PNza3Kl0KhwOLFi/HMM8/A1tYWzZs3x+uvv478/PxHbuf8+fPo27cv7O3t4eDgAH9/f5w5c0b3/RMnTuD555+HjY0NmjdvjhkzZjzx0INMJoObmxvc3d3Rt29fLFiwAL/++qtuZGnZsmVo1aoVVCoV2rZti2+//bbK899//320aNEC1tbW8PDwwIwZM3Tf++NhKR8fHwDAyJEjIZPJdI//eFhq7969UKvVyM7OrvIaM2bMQJ8+fYz2PgMCAjBr1iykpKTgypUrunUe9/M4fPgwJk2ahJycHN3IyPvvvw8AKC0txdy5c+Hp6QlbW1v07NkThw8ffmye7777DoMGDYJara4x5x+/bGxsanwfNf28AMDe3h5ubm7w8fHB1KlT0blzZ+zbt6/K64SEhCArKwtHjhx5bE4iU8RyQ2TC5HI5vvjiC/z6669Yv349Dh48iLlz5z5y/XHjxsHLywunT59GYmIi3n33XVhZWQGoOI8iJCQEo0aNwi+//IItW7YgISEBb775pl6ZKj9Iy8rKEBsbi7fffht//etf8euvv2L69OmYNGkSDh06BACIjo7GZ599hhUrVuDatWvYsWMHnnnmmRq3e/r0aQDA2rVrkZ6ernv8RwMGDEDjxo0RExOjW6bRaLB161bd6IUx3md2djY2bdoEALr9Bzz+5xEUFIQlS5ZUGVl55513AFSMghw/fhzfffcdfvnlF0RGRuLFF1/EtWvXHpnh6NGjCAgIqHXmR/njz+vPhBA4fPgwLl++XOV9AoBKpUKXLl1w7Nixp85AVO/q/L7jRPRYEyZMEAqFQtja2uq+IiIialx369atolmzZrrHa9euFY6OjrrH9vb2Yt26dTU+95VXXhGvvvpqlWXHjh0TcrlcFBUV1ficP2//1q1bolevXsLLy0uUlJSIoKAgMW3atCrPiYyMFGFhYUIIIT799FPh5+cnSktLa9y+t7e3+Oyzz3SPAYjY2Ngq6yxYsEB06dJF93jGjBmiX79+usd79+4VKpVKPHjw4KneJwBha2srGjVqJAAIAGLYsGE1rl/pST8PIYS4fv26kMlk4s6dO1WW9+/fX8ybN++R23Z0dBQbNmx4ZM7KL1dX10e+/p9/XkJU7HOVSiVsbW2FlZWVACDUarU4fvx4tQwjR44UEydOfOw+IDJFSimLFRFV6Nu3L5YtW6Z7bGtrCwA4dOgQPv74Y1y6dAm5ubkoLy9HcXExCgoKdOv80ezZszF16lR8++23GDBgACIjI9GqVSsAQGJiIq5fv46NGzfq1hdCQKvVIjk5Ge3bt68xW05ODuzs7CCEQGFhIbp3747t27dDpVLh8uXLVU4IBoDg4GB8/vnnAIDIyEgsWbIELVu2xIsvvoiwsDAMHToUSqXh//WMGzcOgYGBSEtLg4eHBzZu3IiwsDA0adLkqd6nvb09zp49i/Lychw5cgT//ve/sXz58irr6PvzAICzZ89CCAE/P78qy0tKSh57LlFRUVG1Q1J/zFmp8mTjSo/7eVWaM2cOJk6ciPv372P+/Pno168fgoKCqr2WjY0NCgsLH5mRyFSx3BCZAFtbW7Ru3brKspSUFISFhSEqKgr/+Mc/0LRpUyQkJGDKlCk1HmIAKs5PGTt2LHbt2oXdu3djwYIF+O677zBy5EhotVpMnz69yjkvlVq0aPHIbJUfpnK5HK6urtU+xGUyWZXHQgjdsubNm+PKlSuIj4/H/v378frrr+Pf//43jhw5Uu0wSG316NEDrVq1wnfffYfXXnsNsbGxWLt2re77hr5PuVyu+xm0a9cOGRkZGDNmDI4ePQrAsJ9HZR6FQoHExEQoFIoq37Ozs3vk85ycnPDw4cPH5qzJk35eldtu3bo1WrdujZiYGLRu3Rq9evXCgAEDqqz34MEDXTkmMicsN0Qm6syZMygvL8enn36q++1869atT3yen58f/Pz8MGvWLPzlL3/B2rVrMXLkSHTv3h0XL1587AdjTR73Ydq+fXskJCRg/PjxumUnTpyoMjpiY2ODYcOGYdiwYXjjjTfQrl07XLhwAd27d6+2PSsrq1pdnTN27Fhs3LgRXl5ekMvlGDx4sO57hr7PP5s1axYWL16M2NhYjBw5slY/D5VKVS1/t27doNFocO/ePfTu3bvWr9+tWzdcunRJ79xPKj9/1qRJE7z11lt45513kJSUVKWs/vrrr4iIiNA7A5HUeEIxkYlq1aoVysvL8eWXX+LmzZv49ttvqx0m+aOioiK8+eabOHz4MFJSUnD8+HGcPn1aVzT+9re/4eTJk3jjjTdw7tw5XLt2DTt37sRbb71lcMY5c+Zg3bp1WL58Oa5du4bFixdj+/btuhNp161bh9WrV+PXX3/VvQcbGxt4e3vXuD0fHx8cOHAAGRkZNY5aVBo3bhzOnj2Ljz76CBEREVUO3xjrfTo4OGDq1KlYsGABhBC1+nn4+PggPz8fBw4cQGZmJgoLC+Hn54dx48Zh/Pjx2L59O5KTk3H69Gn861//Qlxc3CNfPyQkBAkJCXplNtQbb7yBK1euVDlR+/fff8edO3eqjeYQmQUJz/chIlFxQvHw4cNr/N7ixYuFu7u7sLGxESEhIWLDhg0CgHj48KEQouoJpCUlJeKll14SzZs3FyqVSnh4eIg333yzykm0p06dEgMHDhR2dnbC1tZWdO7cWXz00UePzFbTCbJ/tnTpUtGyZUthZWUl/Pz8qpwEGxsbK3r27CkcHByEra2t6NWrl9i/f7/u+38+oXjnzp2idevWQqlUCm9vbyFE9ROKKz377LMCgDh48GC17xnrfaakpAilUim2bNkihHjyz0MIIaKiokSzZs0EALFgwQIhhBClpaXivffeEz4+PsLKykq4ubmJkSNHil9++eWRmR48eCBsbGzEb7/99sSctf2+ENX3eaVp06aJjh07Co1GI4QQ4uOPPxYhISGP3RaRqZIJ8YdpKYmIyGTMnTsXOTk5WLFiRb2+bklJCdq0aYPNmzcjODi4Xl+byBh4WIqIyETNnz8f3t7e9T5LcEpKCubPn89iQ2aLIzdERERkUThyQ0RERBaF5YaIiIgsCssNERERWRSWGyIiIrIoLDdERERkUVhuiIiIyKKw3BAREZFFYbkhIiIii8JyQ0RERBbl/wdZui3dN70wBgAAAABJRU5ErkJggg==", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Compute the ROC curve\n", "fpr, tpr, thresholds = roc_curve(y_test, y_proba[:, 1])\n", "\n", "# Plot the ROC curve\n", "plt.plot(fpr, tpr)\n", "plt.plot([0, 1], [0, 1], linestyle='--', color='grey')\n", "plt.xlabel('False Positive Rate (FPR)')\n", "plt.ylabel('True Positive Rate (TPR)')\n", "plt.title('ROC Curve')\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's also check the confusion matrix to see where we still make mistakes" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "execution": { "iopub.execute_input": "2025-06-28T20:35:35.705945Z", "iopub.status.busy": "2025-06-28T20:35:35.705688Z", "iopub.status.idle": "2025-06-28T20:35:35.949913Z", "shell.execute_reply": "2025-06-28T20:35:35.949015Z" } }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjYAAAGwCAYAAAC6ty9tAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAS/RJREFUeJzt3XlcVNX7B/DPsI2IMIKsY4S4QCKmpqWohQuKJhpiqZHolJk7GbhE5W7irom5VCpqltVPMc0kTFNDxAUlwS0tFYlVNoWQzfn9wZdb10EFnLmD0+fd675ezLnPnDmXRB+ec869MrVarQYRERGRATDS9wCIiIiItIWJDRERERkMJjZERERkMJjYEBERkcFgYkNEREQGg4kNERERGQwmNkRERGQwmNgQERGRwTDR9wB0IS2/VN9DIKqXbBqZ6XsIRPVOAwn+JTTvMEkr/RSfXaOVfgwZKzZERERkMAyyYkNERFSvyFhHkAoTGyIiIl2TyfQ9gv8MJjZERES6xoqNZPidJiIiIoPBig0REZGucSpKMkxsiIiIdI1TUZLhd5qIiIgMBis2REREusapKMkwsSEiItI1TkVJht9pIiIiMhis2BAREekap6Ikw8SGiIhI1zgVJRl+p4mIiMhgsGJDRESka5yKkgwTGyIiIl3jVJRkmNgQERHpGis2kmEKSURERAaDFRsiIiJd41SUZJjYEBER6RoTG8nwO01EREQGgxUbIiIiXTPi4mGpMLEhIiLSNU5FSYbfaSIiIjIYrNgQERHpGu9jIxkmNkRERLrGqSjJ8DtNREREBoOJDRERka7JZNo5aiE8PBzPP/88LC0tYW9vD39/f1y+fFkUo1KpIJPJREeXLl1EMSUlJZg8eTJsbW1hYWGBQYMGITU1VRSTl5eHoKAgKBQKKBQKBAUFIT8/XxSTkpKCgQMHwsLCAra2tggODkZpaakoJikpCd7e3jA3N0fTpk0xb948qNXqWl03ExsiIiJdkxlp56iFI0eOYOLEiYiPj8eBAwdQXl6Ovn37oqioSBTXr18/pKenC8ePP/4oOj9lyhRERUVhx44diI2NRWFhIfz8/FBRUSHEBAYGIjExEdHR0YiOjkZiYiKCgoKE8xUVFRgwYACKiooQGxuLHTt2YOfOnQgNDRVibt++jT59+kCpVOLUqVOIiIjAsmXLsGLFilpdt0xd21ToCZCWX/roIKL/IJtGZvoeAlG900CC1abmvsu00k/+nskoKSkRtcnlcsjl8ke+Nzs7G/b29jhy5AheeuklAJUVm/z8fOzevbva9xQUFMDOzg7btm3DsGHDAABpaWlwdnbGjz/+CF9fX1y8eBEeHh6Ij49H586dAQDx8fHw8vLCpUuX4O7ujv3798PPzw83b96EUqkEAOzYsQMqlQpZWVmwsrLCunXrEBYWhszMTOF6Fi1ahIiICKSmpkJWw4oVKzZERERPiPDwcGG6p+oIDw+v0XsLCgoAADY2NqL2w4cPw97eHm5ubhgzZgyysrKEcwkJCSgrK0Pfvn2FNqVSCU9PT8TFxQEAjh8/DoVCISQ1ANClSxcoFApRjKenp5DUAICvry9KSkqQkJAgxHh7e4uSNF9fX6SlpeH69es1ukaAu6KIiIh0T0u7osLCwhASEiJqq0m1Rq1WIyQkBN27d4enp6fQ3r9/f7z22mtwcXHBtWvXMHPmTPTq1QsJCQmQy+XIyMiAmZkZrK2tRf05ODggIyMDAJCRkQF7e3uNz7S3txfFODg4iM5bW1vDzMxMFNOsWTONz6k65+rq+sjrBJjYEBER6Z6W7mNT02mn+02aNAnnzp1DbGysqL1qegkAPD090alTJ7i4uGDfvn0ICAh4YH9qtVo0NVTdNJE2YqpWy9R0GgrgVBQREZFBmzx5Mvbs2YNffvkFTz311ENjnZyc4OLigitXrgAAHB0dUVpairy8PFFcVlaWUE1xdHREZmamRl/Z2dmimKrKTJW8vDyUlZU9NKZqWuz+as/DMLEhIiLSNT3silKr1Zg0aRJ27dqFQ4cO1WgqJycnBzdv3oSTkxMAoGPHjjA1NcWBAweEmPT0dCQnJ6Nr164AAC8vLxQUFODkyZNCzIkTJ1BQUCCKSU5ORnp6uhATExMDuVyOjh07CjFHjx4VbQGPiYmBUqnUmKJ6GO6KIvoP4a4oIk2S7IoasFor/RTvC65x7IQJE/DVV1/h+++/h7u7u9CuUChgbm6OwsJCzJkzB0OGDIGTkxOuX7+ODz74ACkpKbh48SIsLS0BAOPHj8cPP/yAyMhI2NjYYOrUqcjJyUFCQgKMjY0BVK7VSUtLw4YNGwAA77zzDlxcXLB3714Aldu927dvDwcHByxduhS5ublQqVTw9/dHREQEgMrFze7u7ujVqxc++OADXLlyBSqVCrNmzRJtC38UJjZE/yFMbIg0GWpi86B1KZs3b4ZKpUJxcTH8/f1x9uxZ5Ofnw8nJCT179sT8+fPh7OwsxN+9exfTpk3DV199heLiYvTu3Rtr164VxeTm5iI4OBh79uwBAAwaNAhr1qxB48aNhZiUlBRMmDABhw4dgrm5OQIDA7Fs2TLRmqGkpCRMnDgRJ0+ehLW1NcaNG4dZs2bVao0NExui/xAmNkSaJEls/NZopZ/iHyZppR9Dxl1RREREusaHYEqG32kiIiIyGKzYEBER6ZqW7mNDj8bEhoiISNc4FSUZJjZERES6xoqNZJhCEhERkcFgxYaIiEjXOBUlGSY2REREusapKMkwhSQiIiKDwYoNERGRjtXmkQD0eJjYEBER6RgTG+lwKoqIiIgMBis2REREusaCjWSY2BAREekYp6Kkw6koIiIiMhis2BAREekYKzbSYWJDRESkY0xspMPEhoiISMeY2EiHa2yIiIjIYLBiQ0REpGss2EiGiQ0REZGOcSpKOpyKIiIiIoPBig0REZGOsWIjHSY2REREOsbERjqciiIiIiKDwYoNERGRjrFiIx0mNkRERLrGvEYynIoiIiIig8GKDRERkY5xKko6TGyIiIh0jImNdJjYEBER6RgTG+lwjQ0REREZDFZsiIiIdI0FG8kwsSEiItIxTkVJh1NRREREZDBYsSEiItIxVmykw8SGiIhIx5jYSIdTUURERGQwWLEhIiLSMVZspKO3xCYgIKDGsbt27dLhSIiIiHSMeY1k9DYVpVAohMPKygoHDx7E6dOnhfMJCQk4ePAgFAqFvoZIRERETxi9VWw2b94sfD1jxgwMHToU69evh7GxMQCgoqICEyZMgJWVlb6GSEREpBWcipKOTK1Wq/U9CDs7O8TGxsLd3V3UfvnyZXTt2hU5OTm16i8tv1SbwyMyGDaNzPQ9BKJ6p4EEv+I/NWG3VvpJXeuvlX4MWb3YFVVeXo6LFy9qtF+8eBH37t3Tw4iIiIi0RyaTaeWgR6sXu6LefPNNvPXWW7h69Sq6dOkCAIiPj8eiRYvw5ptv6nl0RERE9KSoF4nNsmXL4OjoiJUrVyI9PR0A4OTkhOnTpyM0NFTPoyMiInpMLLZIpl6ssfm327dvA8BjLRrmGhui6nGNDZEmKdbYPD15j1b6SYkYpJV+DFm9qNj8G3dBERERUV3Vi8TG1dX1oYui/vzzTwlH89+1PfIL/Hr4Z6TcuAa5vAHatG2Hdya9h6ddXIWYRfM+xE/7xL95tG7zLNZu2i5qO5+UiI3rInDxfBKMTUzQ0s0di1eug7xBA2Sk/YWtmzbg7OmTyM29BVtbO/j088OIN9+BqampxrgKCvLx9htDcCs7C3t/PoZGlkx+qf7p36cX0tL+0mgfNjwQH8ycLWqbN2cWdn73DabNCMOIkSqhfbQqCKdPnRTF+vZ/GUuWrdTJmEk6XPgrnXqR2EyZMkX0uqysDGfPnkV0dDSmTZumn0H9B/129jT8Xx0Odw9PVJRXYOP61ZgePBabd+yGuXlDIe4Fr26YMXOB8NrERJyMnE9KxIx3xyNw1GhMnhoGUxNT/HHlMmRGlZvwUm5cg/rePYS8PwtNnZ1x7Y+rWL5wDu4WF2P8u1M1xrV0wSy0aOmGW9lZOrpyose3/Zv/w72KCuH11atXMPbtN9HHt58o7tDBn5F87jfY2dtX28+QV4diwqRg4bW8QQPdDJgkxcRGOvUisXn33Xerbf/0009FdyMm3VryyXrR6xkz52NwP2/8fukC2nXoJLSbmprBpontA/v5dOVSBAwNROCot4W2p552Eb5+was7XvDqLrxWNnXGzRvXsWfXNxqJzfc7v0Fh4R2MHD0OJ47H1vnaiHTNxsZG9HrTF5/B2flpdHr+BaEtMzMT4R/Pw7rPNmLy+LHV9tOgQQPY2tnpdKxEhqxe3MfmQfr374+dO3fqexj/WUWFhQAAKyvxYy0Sz5zG4H7eCHrVD8sWzkFe7j83UMzLzcHF8+fQ2MYGk94egYB+3nh3nApJiWce/llFd2B53+dc//MPbN24HmGzF8JIVq//qBKJlJWWYt8Pe+AfMET4Tf3evXv48P1pUL05Gi1btnrge3/ctxfe3Tpj8KABWL50MYqKCqUaNukQ72MjnXpRsXmQ//u//9P4LYikoVarsfaTpWjb7jm4tvjnL+EXvF6Edy9fODo5IT3tL2zasAYhE9/Ghi3fwMzMDOl/pQIAtny+DuOCQ9HS7RnE/LgHoZPexqavokSVmyp/pd5E1Ldfi6o1paWlmD9zOsZNDoGDo5PQL9GT4NChn3Hnzh0M8h8stG3e+DmMTUwQOGLkA9/38oCBaPrUU2hia4urV65g9arl+P3yJWz4YvMD30NPCOYkkqkXiU2HDh1EmaharUZGRgays7Oxdu3ah763pKQEJSUl97XJIJfLdTLW/4pPln6MP67+jogNW0Ttvfr8s17AtUUruLdug+Gv9EX8saN4qacP7v3v7gF+g19D/4GVf6m3cm+NM6dPYP/eKIyZOEXU363sLMx4dxy8e/fFgFeGCO2fr10Fl2bN0af/QB1dIZHuRO3ciW7dX4K9vQMA4ML5ZGzfthU7/m/XQ3/rHvLaUOHrVq3c4OLigteHDsHFC+fR2qONzsdNZAjqRWLj7+8vem1kZAQ7Ozv06NEDzzzzzEPfGx4ejrlz54raQmZ8hND3Z2p7mP8Zq5ctRNyvh/HJhkjYOTg+NLaJrR0cHJX46+aN/72uXHvTzLW5KO7pZs2RmZkuaruVnYWQCaPh0bYdQsPEu0bOnj6Ja39cQe+uByob/pcwveL7EkaoxuDNdybW9fKIdCot7S+ciI/Dik8ihLYzCaeRm5uDfj49hbaKigosX7oY27dtxf4Dh6rtq7VHG5iYmOLGjRtMbJ5wnEaSTr1IbGbPnv3ooAcICwtDSEiIqC2nmH+A6kKtVmP1soWIPXIIK9dugpPyqUe+p6AgH1lZGbCxrVzs6OjUFLZ29rh547ooLjXlhmjBcHZWJkImjIbbMx6YMXM+jIzEa2jmLlqJ0pK7wutLF5KxZMEsrN4QCWVT58e4SiLd+j5qF2xsmuDFl3oIbX6DXkFnr66iuPHvjIbfwFfgPzjggX1dvXoF5eVlsONi4iceExvp1IvE5t+Ki4tRVlYmanvYTfvkcrnGtFPhPd55uC5WLf0YB3/6EQuWfoKGFhbIzbkFALCwaAR5gwYo/vtvRH6+Fi/18kGTJnbISE/DF+s+gULRGC969wZQ+cM77A0VIj9fixat3NHS7Rn8tO97pNy4hjnhKwBUVmreG/8W7B2dMC44FAX5ecIYqnZbNX1KnLwU5OcDAFyaNed9bKjeunfvHr6P2oWBr/jDxOSfv14bN7ZG48bWolhTE1PY2toK1c2bKSnY98MevPiSNxpbW+PPP/7A8qWL8ExrD7Tv8Jyk10Hax7xGOvViq0lRUREmTZoEe3t7NGrUCNbW1qKDpLFn5zcoKryD98a/hSEv9xSOX36OBlA5RfjnH1fw0bR3EfSaHxbN+xBPPe2CTzduR0MLC6GfV18PQuCo0fh01RK8PeJVnDl9AstWfyYkK6dPxOGv1BScPX0CQwf6iD6L6EkWfzwO6elp8A8Y8ujg+5iamuLkiXiMf+dtvDKgHxYvXACvrt3w2RebYWxsrIPRkqELDw/H888/D0tLS9jb28Pf3x+XL18WxajVasyZMwdKpRLm5ubo0aMHzp8/L4opKSnB5MmTYWtrCwsLCwwaNAipqeINHXl5eQgKCoJCoYBCoUBQUBDy//cLaZWUlBQMHDgQFhYWsLW1RXBwMEpLxYWIpKQkeHt7w9zcHE2bNsW8efNQ2yc/1YtnRU2cOBG//PIL5s2bh5EjR+LTTz/FX3/9hQ0bNmDRokV44403atUfnxVFVD0+K4pIkxTPimo1LVor/VxZ2u/RQf/Tr18/DB8+HM8//zzKy8vx4YcfIikpCRcuXIDF/34ZXbx4MT7++GNERkbCzc0NCxYswNGjR3H58mVYWloCAMaPH4+9e/ciMjISTZo0QWhoKHJzc5GQkCAk3f3790dqaio+++wzAMA777yDZs2aYe/evQAq15S1b98ednZ2WL58OXJycjBq1CgEBAQgIqJyPdrt27fh5uaGnj174sMPP8Tvv/8OlUqF2bNn1+qB2PUisXn66aexdetW9OjRA1ZWVjhz5gxatmyJbdu24euvv8aPP/5Yq/6Y2BBVj4kNkSYpEhu36dpJbJLm99TYCVzdkozqZGdnw97eHkeOHMFLL70EtVoNpVKJKVOmYMaMGQAqqzMODg5YvHgxxo4di4KCAtjZ2WHbtm0YNmwYACAtLQ3Ozs748ccf4evri4sXL8LDwwPx8fHo3LkzACA+Ph5eXl64dOkS3N3dsX//fvj5+eHmzZtQKpUAgB07dkClUiErKwtWVlZYt24dwsLCkJmZKVzPokWLEBERgdTU1BqvU6oXU1G5ublwda18HpGVlRVyc3MBAN27d8fRo0f1OTQiIqJ6Izw8XJjuqTrCw8Nr9N6CggIA/9wl+9q1a8jIyEDfvn2FGLlcDm9vb8TFxQEAEhISUFZWJopRKpXw9PQUYo4fPw6FQiEkNQDQpUsXKBQKUYynp6eQ1ACAr68vSkpKkJCQIMR4e3uLkjRfX1+kpaXh+vXrNf4e1YvEpnnz5sKgPTw88O233wIA9u7di8aNG+tvYERERFqgrTsPh4WFoaCgQHSEhYU98vPVajVCQkLQvXt3eHp6AgAyMjIAAA4ODqJYBwcH4VxGRgbMzMw01rveH2NfzbPP7O3tRTH3f461tTXMzMweGlP1uiqmJurFrqg333wTv/32G7y9vREWFoYBAwYgIiIC5eXlWLFihb6HR0RE9Fi0tSuqptNO95s0aRLOnTuH2FjNZ+7dP8WjVqsfOe1zf0x18dqIqVotU5vt8vUisXnvvfeEr3v27IlLly7h9OnTaNGiBdq1a6fHkRERET3ZJk+ejD179uDo0aN46ql/7k/m6Fh5A9aMjAw4OTkJ7VlZWUKlxNHREaWlpcjLyxNVbbKystC1a1chJjMzU+Nzs7OzRf2cOHFCdD4vLw9lZWWimPsrM1lZWQA0q0oPo/epqLKyMvTs2RO///670Pb0008jICCASQ0RERkEIyOZVo7aUKvVmDRpEnbt2oVDhw4Ja1mruLq6wtHREQcOHBDaSktLceTIESFp6dixI0xNTUUx6enpSE5OFmK8vLxQUFCAkydPCjEnTpxAQUGBKCY5ORnp6f/cgT4mJgZyuRwdO3YUYo4ePSraAh4TEwOlUolmzZrV+Lr1ntiYmpoiOTmZd2UkIiKDJZNp56iNiRMn4ssvv8RXX30FS0tLZGRkICMjA8XFxf8bkwxTpkzBwoULERUVheTkZKhUKjRs2BCBgYEAAIVCgdGjRyM0NBQHDx7E2bNnMWLECLRt2xY+Pj4AgNatW6Nfv34YM2YM4uPjER8fjzFjxsDPzw/u7u4AgL59+8LDwwNBQUE4e/YsDh48iKlTp2LMmDHCTXgDAwMhl8uhUqmQnJyMqKgoLFy4ECEhIbXKEerFdu/Q0FCYmppi0aJFWumP272Jqsft3kSapNju3ebDGK30c/7jvo8O+p8HJQObN2+GSqUCUFnVmTt3LjZs2IC8vDx07twZn376qbDAGADu3r2LadOm4auvvkJxcTF69+6NtWvXwtn5nzvE5+bmIjg4GHv27AEADBo0CGvWrBFtAEpJScGECRNw6NAhmJubIzAwEMuWLROtGUpKSsLEiRNx8uRJWFtbY9y4cZg1a9aTl9hMnjwZW7duRcuWLdGpUyfhxkFVaruAmIkNUfWY2BBpkiKx8fzowKODaiB5QR+t9GPI9Lp4+M8//0SzZs2QnJyM556rfBbKv9faAHxwGBERPfn4T5l09JrYtGrVCunp6fjll18AAMOGDcPq1atrtfqZiIiovuMv6dLR6+Lh+2fB9u/fj6KiIj2NhoiIiJ509eI+NlXqwXIfIiIirWPFRjp6TWyqbhF9fxsREZEh4T9t0tFrYqNWq6FSqYStXnfv3sW4ceM0dkXt2rVLH8MjIiKiJ4xeE5tRo0aJXo8YMUJPIyEiItIdzkZIR6+JzebNm/X58URERJJgXiMdvT9SgYiIiEhb6tWuKCIiIkPEqSjpMLEhIiLSMeY10uFUFBERERkMVmyIiIh0jFNR0mFiQ0REpGPMa6TDxIaIiEjHWLGRDtfYEBERkcFgxYaIiEjHWLCRDhMbIiIiHeNUlHQ4FUVEREQGgxUbIiIiHWPBRjpMbIiIiHSMU1HS4VQUERERGQxWbIiIiHSMBRvpMLEhIiLSMU5FSYdTUURERGQwWLEhIiLSMVZspMPEhoiISMeY10iHiQ0REZGOsWIjHa6xISIiIoPBig0REZGOsWAjHSY2REREOsapKOlwKoqIiIgMBis2REREOsaCjXSY2BAREemYETMbyXAqioiIiAwGKzZEREQ6xoKNdJjYEBER6Rh3RUmHiQ0REZGOGTGvkQzX2BAREZHBYMWGiIhIxzgVJR0mNkRERDrGvEY6nIoiIiIig8GKDRERkY7JwJKNVJjYEBER6Rh3RUmHU1FERERkMFixISIi0jHuipIOExsiIiIdY14jHU5FERERkcFgxYaIiEjHjFiykQwTGyIiIh1jXiOdGic2586dq3Gnzz77bJ0GQ0REZIi4eFg6NU5s2rdvD5lMBrVa/cj/QRUVFY89MCIiIqLaqvHi4WvXruHPP//EtWvXsHPnTri6umLt2rU4e/Yszp49i7Vr16JFixbYuXOnLsdLRET0xJHJtHPQo9W4YuPi4iJ8/dprr2H16tV4+eWXhbZnn30Wzs7OmDlzJvz9/bU6SCIioicZFw9Lp07bvZOSkuDq6qrR7urqigsXLjz2oIiIiIjqok6JTevWrbFgwQLcvXtXaCspKcGCBQvQunVrrQ2OiIjIEMi0dNCj1SmxWb9+PX7++Wc4OzvDx8cHPj4+eOqpp3DgwAGsX79e22MkIiJ6oslkMq0ctXX06FEMHDgQSqUSMpkMu3fvFp1XqVQan9GlSxdRTElJCSZPngxbW1tYWFhg0KBBSE1NFcXk5eUhKCgICoUCCoUCQUFByM/PF8WkpKRg4MCBsLCwgK2tLYKDg1FaWiqKSUpKgre3N8zNzdG0aVPMmzcParW6Vtdcp/vYvPDCC7h27Rq+/PJLXLp0CWq1GsOGDUNgYCAsLCzq0iURERFpWVFREdq1a4c333wTQ4YMqTamX79+2Lx5s/DazMxMdH7KlCnYu3cvduzYgSZNmiA0NBR+fn5ISEiAsbExACAwMBCpqamIjo4GALzzzjsICgrC3r17AVTulh4wYADs7OwQGxuLnJwcjBo1Cmq1GhEREQCA27dvo0+fPujZsydOnTqF33//HSqVChYWFggNDa3xNcvUtU2FngBp+aWPDiL6D7JpZPboIKL/mAYS3Kr2jW2JWulne1D7Or9XJpMhKipKtMFHpVIhPz9fo5JTpaCgAHZ2dti2bRuGDRsGAEhLS4OzszN+/PFH+Pr64uLFi/Dw8EB8fDw6d+4MAIiPj4eXlxcuXboEd3d37N+/H35+frh58yaUSiUAYMeOHVCpVMjKyoKVlRXWrVuHsLAwZGZmQi6XAwAWLVqEiIgIpKam1rhiVednRW3btg3du3eHUqnEjRs3AAArV67E999/X9cuiYiIDJK2pqJKSkpw+/Zt0VFSUvJYYzt8+DDs7e3h5uaGMWPGICsrSziXkJCAsrIy9O3bV2hTKpXw9PREXFwcAOD48eNQKBRCUgMAXbp0gUKhEMV4enoKSQ0A+Pr6oqSkBAkJCUKMt7e3kNRUxaSlpeH69es1vp46JTbr1q1DSEgI+vfvj7y8POGGfNbW1li1alVduiQiIqJHCA8PF9axVB3h4eF17q9///7Yvn07Dh06hOXLl+PUqVPo1auXkCxlZGTAzMwM1tbWovc5ODggIyNDiLG3t9fo297eXhTj4OAgOm9tbQ0zM7OHxlS9roqpiToV4CIiIvD555/D398fixYtEto7deqEqVOn1qVLIiIig6Wt29iEhYUhJCRE1PbvCkdtVU0vAYCnpyc6deoEFxcX7Nu3DwEBAQ983/1PIahumkgbMVWrZWqzcLpOFZtr166hQ4cOGu1yuRxFRUV16ZKIiMhgaWsqSi6Xw8rKSnQ8TmJzPycnJ7i4uODKlSsAAEdHR5SWliIvL08Ul5WVJVRTHB0dkZmZqdFXdna2KOb+qkteXh7KysoeGlM1LXZ/Jedh6pTYuLq6IjExUaN9//798PDwqEuXREREBstIpp1D13JycnDz5k04OTkBADp27AhTU1McOHBAiElPT0dycjK6du0KAPDy8kJBQQFOnjwpxJw4cQIFBQWimOTkZKSnpwsxMTExkMvl6NixoxBz9OhR0RbwmJgYKJVKNGvWrMbXUKepqGnTpmHixIm4e/cu1Go1Tp48ia+//hrh4eH44osv6tIlERERaVlhYSGuXr0qvL527RoSExNhY2MDGxsbzJkzB0OGDIGTkxOuX7+ODz74ALa2thg8eDAAQKFQYPTo0QgNDUWTJk1gY2ODqVOnom3btvDx8QFQedPefv36YcyYMdiwYQOAyu3efn5+cHd3BwD07dsXHh4eCAoKwtKlS5Gbm4upU6dizJgxsLKyAlC5ZXzu3LlQqVT44IMPcOXKFSxcuBCzZs2q1VRUnRKbN998E+Xl5Zg+fTr+/vtvBAYGomnTpvjkk08wfPjwunRJRERksOpycz1tOH36NHr27Cm8rlqfM2rUKKxbtw5JSUnYunUr8vPz4eTkhJ49e+Kbb76BpaWl8J6VK1fCxMQEQ4cORXFxMXr37o3IyEjhHjYAsH37dgQHBwu7pwYNGoQ1a9YI542NjbFv3z5MmDAB3bp1g7m5OQIDA7Fs2TIhRqFQ4MCBA5g4cSI6deoEa2trhISEaKwpepTHvo/NrVu3cO/evWpXROsL72NDVD3ex4ZIkxT3sXlrR5JW+tk0vK1W+jFkdVpj06tXL+FWyba2tkJSc/v2bfTq1UtrgyMiIiKqjTrlqYcPH9Z4vgMA3L17F7/++utjD4qIiMiQGOlpKuq/qFaJzblz54SvL1y4INqWVVFRgejoaDRt2lR7oyMiIjIAzGukU6vEpn379sJe+uqmnMzNzYWHWRERERFJrVaJzbVr16BWq9G8eXOcPHkSdnZ2wjkzMzPY29uLVkkTERGR/nZF/RfVKrFxcXEBANy7d08ngyEiIjJEzGukU6ddUeHh4di0aZNG+6ZNm7B48eLHHhQRERFRXdQpsdmwYQOeeeYZjfY2bdpg/fr1jz0oIiIiQ2Ikk2nloEer03bvjIwM4TkS/2ZnZyd6DgQRERFxKkpKdarYODs749ixYxrtx44dg1KpfOxBERERGRJtPd2bHq1OFZu3334bU6ZMQVlZmbDt++DBg5g+fTpCQ0O1OkAiIiKimqpTYjN9+nTk5uZiwoQJwh2IGzRogBkzZiAsLEyrA6wLPg+HqHrWz0/S9xCI6p3is2seHfSY6jQ9QnVSp8RGJpNh8eLFmDlzJi5evAhzc3O0atUKcrlc2+MjIiJ64nEaSTqP9UzTRo0a4fnnn9fWWIiIiIgeS40Tm4CAAERGRsLKygoBAQEPjd21a9djD4yIiMhQGLFgI5kaJzYKhUIopSkUCp0NiIiIyNAwsZFOjRObzZs3V/s1ERERUX3xWGtsiIiI6NG4eFg6NU5sOnToUOP/MWfOnKnzgIiIiAwNp6KkU+PExt/fX/j67t27WLt2LTw8PODl5QUAiI+Px/nz5zFhwgStD5KIiIioJmqc2MyePVv4+u2330ZwcDDmz5+vEXPz5k3tjY6IiMgAcCZKOnW6GeJ3332HkSNHarSPGDECO3fufOxBERERGRI+3Vs6dUpszM3NERsbq9EeGxuLBg0aPPagiIiIDImRlg56tDrtipoyZQrGjx+PhIQEdOnSBUDlGptNmzZh1qxZWh0gERERUU3VKbF5//330bx5c3zyySf46quvAACtW7dGZGQkhg4dqtUBEhERPek4iySdOt/HZujQoUxiiIiIaoDrY6RT5ym7/Px8fPHFF/jggw+Qm5sLoPL+NX/99ZfWBkdERERUG3Wq2Jw7dw4+Pj5QKBS4fv063n77bdjY2CAqKgo3btzA1q1btT1OIiKiJxYLNtKpU8UmJCQEKpUKV65cEe2C6t+/P44ePaq1wRERERkCI5l2Dnq0OiU2p06dwtixYzXamzZtioyMjMceFBEREVFd1GkqqkGDBrh9+7ZG++XLl2FnZ/fYgyIiIjIkXDwsnTpVbF555RXMmzcPZWVlACqfWpqSkoL3338fQ4YM0eoAiYiInnQymXYOerQ6JTbLli1DdnY27O3tUVxcDG9vb7Rs2RKWlpb4+OOPtT1GIiIiohqp01SUlZUVYmNjcejQIZw5cwb37t3Dc889Bx8fH22Pj4iI6InHhb/SqXViU15ejgYNGiAxMRG9evVCr169dDEuIiIigyEDMxup1DqxMTExgYuLCyoqKnQxHiIiIoPDio106rTG5qOPPkJYWJhwx2EiIiKi+qBOa2xWr16Nq1evQqlUwsXFBRYWFqLzZ86c0crgiIiIDAErNtKpU2Lj7+8PmUwGtVqt7fEQEREZHBn3akumVonN33//jWnTpmH37t0oKytD7969ERERAVtbW12Nj4iIiKjGarXGZvbs2YiMjMSAAQPw+uuv4+eff8b48eN1NTYiIiKDwGdFSadWFZtdu3Zh48aNGD58OADgjTfeQLdu3VBRUQFjY2OdDJCIiOhJx5ko6dSqYnPz5k28+OKLwusXXngBJiYmSEtL0/rAiIiIiGqrVhWbiooKmJmZiTswMUF5eblWB0VERGRI+BBM6dQqsVGr1VCpVJDL5ULb3bt3MW7cONGW7127dmlvhERERE84ro+RTq0Sm1GjRmm0jRgxQmuDISIiInoctUpsNm/erKtxEBERGSzOREmnTjfoIyIiopoz4kMwJcPEhoiISMdYsZFOnR6CSURERFQfsWJDRESkY9wVJR0mNkRERDrG+9hIh1NRREREZDBYsSEiItIxFmykw8SGiIhIxzgVJR1ORREREZHBYMWGiIhIx1iwkQ4rNkRERDpmpKWjto4ePYqBAwdCqVRCJpNh9+7dovNqtRpz5syBUqmEubk5evTogfPnz4tiSkpKMHnyZNja2sLCwgKDBg1CamqqKCYvLw9BQUFQKBRQKBQICgpCfn6+KCYlJQUDBw6EhYUFbG1tERwcjNLSUlFMUlISvL29YW5ujqZNm2LevHlQq9W1umYmNkRERAaqqKgI7dq1w5o1a6o9v2TJEqxYsQJr1qzBqVOn4OjoiD59+uDOnTtCzJQpUxAVFYUdO3YgNjYWhYWF8PPzQ0VFhRATGBiIxMREREdHIzo6GomJiQgKChLOV1RUYMCAASgqKkJsbCx27NiBnTt3IjQ0VIi5ffs2+vTpA6VSiVOnTiEiIgLLli3DihUranXNMnVtU6EnwN1yfY+AqH6yfn6SvodAVO8Un63+H31t2nL6plb6GdXJuc7vlclkiIqKgr+/P4DKao1SqcSUKVMwY8YMAJXVGQcHByxevBhjx45FQUEB7OzssG3bNgwbNgwAkJaWBmdnZ/z444/w9fXFxYsX4eHhgfj4eHTu3BkAEB8fDy8vL1y6dAnu7u7Yv38//Pz8cPPmTSiVSgDAjh07oFKpkJWVBSsrK6xbtw5hYWHIzMyEXC4HACxatAgRERFITU2FrIbzeazYEBER6ZhMS0dJSQlu374tOkpKSuo0pmvXriEjIwN9+/YV2uRyOby9vREXFwcASEhIQFlZmShGqVTC09NTiDl+/DgUCoWQ1ABAly5doFAoRDGenp5CUgMAvr6+KCkpQUJCghDj7e0tJDVVMWlpabh+/XqNr4uJDRERkY4ZyWRaOcLDw4V1LFVHeHh4ncaUkZEBAHBwcBC1Ozg4COcyMjJgZmYGa2vrh8bY29tr9G9vby+Kuf9zrK2tYWZm9tCYqtdVMTXBXVFERERPiLCwMISEhIja/l3hqIv7p3jUavUjp33uj6kuXhsxVatlajoNBbBiQ0REpHPamoqSy+WwsrISHXVNbBwdHQFoVkOysrKESomjoyNKS0uRl5f30JjMzEyN/rOzs0Ux939OXl4eysrKHhqTlZUFQLOq9DBMbIiIiHRMJtPOoU2urq5wdHTEgQMHhLbS0lIcOXIEXbt2BQB07NgRpqamopj09HQkJycLMV5eXigoKMDJkyeFmBMnTqCgoEAUk5ycjPT0dCEmJiYGcrkcHTt2FGKOHj0q2gIeExMDpVKJZs2a1fi6mNgQEREZqMLCQiQmJiIxMRFA5YLhxMREpKSkQCaTYcqUKVi4cCGioqKQnJwMlUqFhg0bIjAwEACgUCgwevRohIaG4uDBgzh79ixGjBiBtm3bwsfHBwDQunVr9OvXD2PGjEF8fDzi4+MxZswY+Pn5wd3dHQDQt29feHh4ICgoCGfPnsXBgwcxdepUjBkzBlZWVgAqt4zL5XKoVCokJycjKioKCxcuREhISK2morjGhoiISMdq8w+zNp0+fRo9e/YUXletzxk1ahQiIyMxffp0FBcXY8KECcjLy0Pnzp0RExMDS0tL4T0rV66EiYkJhg4diuLiYvTu3RuRkZEwNjYWYrZv347g4GBh99SgQYNE984xNjbGvn37MGHCBHTr1g3m5uYIDAzEsmXLhBiFQoEDBw5g4sSJ6NSpE6ytrRESEqKxpuhReB8bov8Q3seGSJMU97H55uxfWulnWIemWunHkHEqioiIiAwGp6KIiIh0TF9TUf9FTGyIiIh0jGmNdDgVRURERAaDFRsiIiId41SUdJjYEBER6RinR6TDxIaIiEjHWLGRjl4SG2tr6xr/T87NzdXxaIiIiMhQ6CWxWbVqlfB1Tk4OFixYAF9fX3h5eQEAjh8/jp9++gkzZ87Ux/CIiIi0ivUa6ej9zsNDhgxBz549MWmS+I6oa9aswc8//4zdu3fXuk/eeZioerzzMJEmKe48/H1SxqODauCVto5a6ceQ6X09008//YR+/fpptPv6+uLnn3/Ww4iIiIjoSaX3xKZJkyaIiorSaN+9ezeaNGmihxERERFplxFkWjno0fS+K2ru3LkYPXo0Dh8+LKyxiY+PR3R0NL744gs9j46IiOjxcVOUdPSe2KhUKrRu3RqrV6/Grl27oFar4eHhgWPHjqFz5876Hh4RERE9QfSe2ABA586dsX37dn0Pg4iISCdknEaSjN4Tm5SUlIeef/rppyUaCRERkW5wKko6ek9smjVr9tCb9VVUVEg4GiIiInqS6T2xOXv2rOh1WVkZzp49ixUrVuDjjz/W06iIiIi0hzuapKP3xKZdu3YabZ06dYJSqcTSpUsREBCgh1ERERFpD6eipKP3xOZB3NzccOrUKX0Pg4iI6LExsZGO3hOb27dvi16r1Wqkp6djzpw5aNWqlZ5GRURERE8ivSc2jRs31lg8rFar4ezsjB07duhpVERERNrD7d7S0Xti88svv4heGxkZwc7ODi1btoSJid6HR0RE9NiMmNdIRu+Zg7e3t76HQERERAZC74lNlQsXLiAlJQWlpaWi9kGDBulpRERERNrBqSjp6D2x+fPPPzF48GAkJSVBJpNBrVYDgLDuhjfoIyKiJx13RUnHSN8DePfdd+Hq6orMzEw0bNgQ58+fx9GjR9GpUyccPnxY38MjIiKiJ4jeKzbHjx/HoUOHYGdnByMjIxgZGaF79+4IDw9HcHCwxp2JiYiInjScipKO3is2FRUVaNSoEQDA1tYWaWlpAAAXFxdcvnxZn0MjIiLSCiOZdg56NL1XbDw9PXHu3Dk0b94cnTt3xpIlS2BmZobPPvsMzZs31/fwiIiI6Ami98Tmo48+QlFREQBgwYIF8PPzw4svvogmTZrgm2++0fPo6H7rPo3A+rVrRG1Nmtji0NFjAICcW7ewasUyHI+LxZ07d/Bcx054/8OZcHFpBgD4669UvNy3d7V9L12xCn19++t0/ESPMvWtvvDv1Q5uzRxQXFKGE7/9iQ8/+R5XbmQJMcVn11T73g9WRmHl1oMAgIgPh6NXZ3c42SlQWFyC+N+u4aNPvsfv1zOF+MaW5lg+/TUM8G4LANh3JAkhi79DQWExAMBGYYHNH49CW7emsFE0RHZuIX44fA6z1uzFnaK7Gp/f3NkW8V+/j4p79+D00nStfU/o8XEqSjoyddU2pHokNzcX1tbWGnckrqm75VoeEAnWfRqBAzE/4bMvNgttRsbGsLGxgVqtxsg3hsPExASh02agUaNG2LolEnGxv2LXnn1o2LAhKioqkJebK+rz/777BpGbNuLQkVg0tLCQ+pL+U6yfn6TvIdR736+ZgO9+SkDC+RswMTHGnIkD4dlKiQ4BC/D33crbUTg0sRS9p2+3Nlg/OxBtBs3F9b9yAABvBXTD5esZuJmeBxtFQ3w4bgDauTXFM36zce9e5V+7u9eMR1N7a0xa8DUAYM1Hr+NGWg5enbIBQGXi81q/jkg4n4JbeXfQ3NkOq94fisRLqVB9ECkag4mJEQ5HhiI7rxBd2rkysamFByWq2hR7JU8r/XRvZa2VfgyZXis25eXlaNCgARITE+Hp6Sm029jY6HFU9CgmxsawtbPTaL9x4zrO/ZaInd//gJYtK5/z9eHM2ej5YldE/7gPAa++BuNq3nvo4M/w7d+fSQ3VC69MWit6PXbOl7h5aBE6eDjj2Jk/AACZOXdEMQN7tMWRU1eEpAYANu06Jnydkp6LuZ/uxalvP4CLsgmupd6Cu6sDfLu1wUtBS3Eq+QYAYOL8r3Bk61S0crHHlRtZyL9TjM+/i/1XP3n47Ltf8d5IH41xz5kwEJevZeKXk5fRpZ3r438jSKtYr5GOXhcPm5iYwMXFhfeqecLcSLkBnx7d0b9vL0yf+h5Sb94EAJT97+aKcjO5EGtsbAxTU1OcPZNQbV8Xzifj8qWLGBzwqu4HTlQHVo0aAADyCv6u9ry9jSX6dffElt3HH9hHwwZmGDmoC66l3kJqRuVv7p2fdUX+nb+FpAYATiZdR/6dv9GlXfXrC53sFHilV3v8mnBF1O79vBsC+nTAlEXf1uraiAyR3ndFffTRRwgLC0PufdMTNVVSUoLbt2+LjpKSEi2Pkqq0ffZZfLxwMdZ9thGz5y5Azq1bGPnGcOTn56GZa3MolU2xetVy3C4oQFlpKTZ+/hlu3cpGdnZ2tf1F7fw/NG/eAu07PCfxlRDVzOLQITh25iou/JFe7fkRAzvjzt93sftQosa5d157EdnHliPn+Ar06eqBAePXoKy88hc5hyZWyM4t1HhPdm4hHGytRG1bwlXIiVuBP2M+xu2iuxg/7yvhnI3CAp/PHYExs7dVu+6G6gcjmUwrBz2a3hOb1atX49dff4VSqYS7uzuee+450fEo4eHhUCgUomPp4nAJRv7f1P1Fb/j09UUrN3d08eqKiLWVawH27N4NU1NTLF+1GjeuX8eLXV9A507tcfrUCXR/8SUYG2v+Ubt79y72//gD/IewWkP108r3h6JtKyVGhUU+MGbkK13wzf7TKCnVXNy3Y/8pdHl9EXxGr8TVm9n4cvFbkJv9swKguiWOMhmA+9qnL9sJr8DFeO29DWj+lC0WhwYI59bOfB3fRJ8WpsmofpJp6aBH0/uuKH9//8d6f1hYGEJCQkRtamP5A6JJ2xo2bIhWbm5ISbkOAPBo44lvd32PO3fuoKysDDY2Nnhj+Gto08ZT470HYqJRXHwXAwf5SztoohpYMeM1+Hm3hc/oVfgrK7/amG4dWsDd1RFB72+u9vztwru4XXgXf6Rk4+S560g/ugSv9GqHb6MTkJlzG/b3LUIGAFvrRhpreDJz7iAz5w5+v56J3PwiHNwcgkWfRyPj1m14v+CGAd5tMSWocrehTCaDsbER7pz6BBMXfI2t38c/3jeC6Amjt8Rm06ZNeOONNzB79uzH6kcul0MuFycy3BUlndLSUvz55x/o8FxHUbulZeVf2DduXMeF88mYOPldjffu3rUTPXr24mJxqndWzngNg3q1Q98xn+BGWs4D40b5eyHhQgqSfv+rRv3KIIOZaeVfuyfOXUNjy4bo1MYFp89XrrN53tMFjS0bIv63Px/cx/+mI6r66TFqOYyN/qmI+vV4FqEqH/RUrUDaAxIy0gOWWySjt8RmzJgx8PPzg729PQBAqVQiLi4OzZo109eQqAaWL10M7x494ejkhNzcXHy+fh2KCgsxyH8wACDmp/2wtraBk5MSV65cxpLwhejZywddu3UX9ZNy4wYSTp/Cp+s+08dlED3QqrChGNa/E1577zMUFt0VtnYXFN7F3ZIyIc7SogEC+nTA+yuiNPpo1rQJXvXtiIPHL+JWXiGU9o0RqvJBcUkZfoo9DwC4fC0TPx07j09nvY7JC3YAqNzuve9IknDPHN/uHrC3sULC+Rso/LsErVs44uN3/RF39g+kpOcK/fzbcx5P455a/cA1QaQfvI+NdPSW2Nw/t3znzh3cu3dPT6OhmsrMzMD700KQl5cPaxtrPPtse2z76lsolU0BANnZ2Vi2ZBFybuXAzs4OfoNewdhxEzT62R21E/YODvC6L+Eh0rexQ18CABz4Yoqofcysbfhy7wnh9Wu+HSGDDN9Gn9boo6S0HN06tMCkwB6wtmqIrJw7iD1zFT1Vy5Gd98+C4Tc/2ILl01/F3rUTAVTeoO+9Rd8J54vvluGtgK5YMjUAclMTpGbm4/tDiVi26YA2L5nIoOjtBn1GRkbIyMgQKjaWlpb47bfftPIYBU5FEVWPN+gj0iTFDfpO/lmglX5eaK7QSj+GTG8VG5lMJrqz8P2viYiIDAX/dZOOXqei3NzchGSmsLAQHTp0gJGReFtwXe9vQ0RERP89ektsNm+ufnskERGRwWHJRjJ6S2xGjRqlr48mIiKSFHdFSUfvN+gjIiIydFxCKh29P1KBiIiISFtYsSEiItIxFmykw8SGiIhI15jZSKZeTUWp1epqn3ZLREREVBP1IrHZunUr2rZtC3Nzc5ibm+PZZ5/Ftm3b9D0sIiIirZBp6T96NL1PRa1YsQIzZ87EpEmT0K1bN6jVahw7dgzjxo3DrVu38N577+l7iERERI+Fu6Kko/fEJiIiAuvWrcPIkSOFtldeeQVt2rTBnDlzmNgQERFRjek9sUlPT0fXrl012rt27Yr09HQ9jIiIiEi7WLCRjt7X2LRs2RLffvutRvs333yDVq1a6WFEREREWibT0kGPpPeKzdy5czFs2DAcPXoU3bp1g0wmQ2xsLA4ePFhtwkNERET0IHpPbIYMGYITJ05g5cqV2L17N9RqNTw8PHDy5El06NBB38MjIiJ6bNzRJB29T0UBQMeOHfHll18iISEBZ86cwZdffsmkhoiIDIZMpp2jNubMmQOZTCY6HB0dhfNqtRpz5syBUqmEubk5evTogfPnz4v6KCkpweTJk2FrawsLCwsMGjQIqampopi8vDwEBQVBoVBAoVAgKCgI+fn5opiUlBQMHDgQFhYWsLW1RXBwMEpLS2t3QTVULxIbIiIiQ6avJTZt2rRBenq6cCQlJQnnlixZghUrVmDNmjU4deoUHB0d0adPH9y5c0eImTJlCqKiorBjxw7ExsaisLAQfn5+qKioEGICAwORmJiI6OhoREdHIzExEUFBQcL5iooKDBgwAEVFRYiNjcWOHTuwc+dOhIaG1uGKHk1vU1FGRkaQPSL9lMlkKC8vl2hEREREhsXExERUpamiVquxatUqfPjhhwgICAAAbNmyBQ4ODvjqq68wduxYFBQUYOPGjdi2bRt8fHwAAF9++SWcnZ3x888/w9fXFxcvXkR0dDTi4+PRuXNnAMDnn38OLy8vXL58Ge7u7oiJicGFCxdw8+ZNKJVKAMDy5cuhUqnw8ccfw8rKSrvXrNXeaiEqKuqB5+Li4hAREcHHKxARkWHQ0hKbkpISlJSUiNrkcjnkcnm18VeuXIFSqYRcLkfnzp2xcOFCNG/eHNeuXUNGRgb69u0r6sfb2xtxcXEYO3YsEhISUFZWJopRKpXw9PREXFwcfH19cfz4cSgUCiGpAYAuXbpAoVAgLi4O7u7uOH78ODw9PYWkBgB8fX1RUlKChIQE9OzZUzvfnP/RW2LzyiuvaLRdunQJYWFh2Lt3L9544w3Mnz9fDyMjIiLSLm0tHg4PD8fcuXNFbbNnz8acOXM0Yjt37oytW7fCzc0NmZmZWLBgAbp27Yrz588jIyMDAODg4CB6j4ODA27cuAEAyMjIgJmZGaytrTViqt6fkZEBe3t7jc+2t7cXxdz/OdbW1jAzMxNitEnvu6IAIC0tDbNnz8aWLVvg6+uLxMREeHp66ntYRERE9UpYWBhCQkJEbQ+q1vTv31/4um3btvDy8kKLFi2wZcsWdOnSBQA0loSo1epHLhO5P6a6+LrEaIteFw8XFBRgxowZaNmyJc6fP4+DBw9i7969TGqIiMigaGtXlFwuh5WVleh4UGJzPwsLC7Rt2xZXrlwR1t3cXzHJysoSqiuOjo4oLS1FXl7eQ2MyMzM1Pis7O1sUc//n5OXloaysTKOSow16S2yWLFmC5s2b44cffsDXX3+NuLg4vPjii/oaDhERkc7UhxsPl5SU4OLFi3BycoKrqyscHR1x4MAB4XxpaSmOHDkiPOaoY8eOMDU1FcWkp6cjOTlZiPHy8kJBQQFOnjwpxJw4cQIFBQWimOTkZNFjkmJiYiCXy9GxY8fHvCpNMrWeVugaGRnB3NwcPj4+MDY2fmDcrl27at33XW6kIqqW9fOT9D0Eonqn+OwanX/GxbQirfTTWmlR49ipU6di4MCBePrpp5GVlYUFCxbgyJEjSEpKgouLCxYvXozw8HBs3rwZrVq1wsKFC3H48GFcvnwZlpaWAIDx48fjhx9+QGRkJGxsbDB16lTk5OQgISFB+Le7f//+SEtLw4YNGwAA77zzDlxcXLB3714Aldu927dvDwcHByxduhS5ublQqVTw9/dHRESEVr4v/6a3NTYjR47UydwaERFRvaOHf+5SU1Px+uuv49atW7Czs0OXLl0QHx8PFxcXAMD06dNRXFyMCRMmIC8vD507d0ZMTIyQ1ADAypUrYWJigqFDh6K4uBi9e/dGZGSkqCCxfft2BAcHC7unBg0ahDVr/kkWjY2NsW/fPkyYMAHdunWDubk5AgMDsWzZMp1ct94qNrrEig1R9VixIdIkRcXmUvrfWunnGaeGWunHkPHOw0RERGQw6sV2byIiIkPGlRfSYWJDRESkY8xrpMPEhoiISNeY2UiGa2yIiIjIYLBiQ0REpGPaelYUPRoTGyIiIh3j4mHpcCqKiIiIDAYrNkRERDrGgo10mNgQERHpGjMbyXAqioiIiAwGKzZEREQ6xl1R0mFiQ0REpGPcFSUdTkURERGRwWDFhoiISMdYsJEOExsiIiJdY2YjGSY2REREOsbFw9LhGhsiIiIyGKzYEBER6Rh3RUmHiQ0REZGOMa+RDqeiiIiIyGCwYkNERKRjnIqSDhMbIiIinWNmIxVORREREZHBYMWGiIhIxzgVJR0mNkRERDrGvEY6nIoiIiIig8GKDRERkY5xKko6TGyIiIh0jM+Kkg4TGyIiIl1jXiMZrrEhIiIig8GKDRERkY6xYCMdJjZEREQ6xsXD0uFUFBERERkMVmyIiIh0jLuipMPEhoiISNeY10iGU1FERERkMFixISIi0jEWbKTDxIaIiEjHuCtKOpyKIiIiIoPBig0REZGOcVeUdJjYEBER6RinoqTDqSgiIiIyGExsiIiIyGBwKoqIiEjHOBUlHSY2REREOsbFw9LhVBQREREZDFZsiIiIdIxTUdJhYkNERKRjzGukw6koIiIiMhis2BAREekaSzaSYWJDRESkY9wVJR1ORREREZHBYMWGiIhIx7grSjpMbIiIiHSMeY10mNgQERHpGjMbyXCNDRERERkMVmyIiIh0jLuipMPEhoiISMe4eFg6nIoiIiIigyFTq9VqfQ+CDFNJSQnCw8MRFhYGuVyu7+EQ1Rv82SDSHSY2pDO3b9+GQqFAQUEBrKys9D0conqDPxtEusOpKCIiIjIYTGyIiIjIYDCxISIiIoPBxIZ0Ri6XY/bs2VwcSXQf/mwQ6Q4XDxMREZHBYMWGiIiIDAYTGyIiIjIYTGyIiIjIYDCxoXpNpVLB399f38MgeuJFRkaicePG+h4Gkc4xsaFqqVQqyGQyjePq1av6HhqRVlX9WV+0aJGofffu3ZA95pMLIyMjq/05+uKLLx6rXyJ6MD7dmx6oX79+2Lx5s6jNzs5O9Lq0tBRmZmZSDotI6xo0aIDFixdj7NixsLa21mrfVlZWuHz5sqhNoVBoxJWVlcHU1FSrn030X8SKDT2QXC6Ho6Oj6OjduzcmTZqEkJAQ2Nraok+fPgCAFStWoG3btrCwsICzszMmTJiAwsJCoa85c+agffv2ov5XrVqFZs2aCa8rKioQEhKCxo0bo0mTJpg+fTp4NwKSgo+PDxwdHREeHv7QuJ07d6JNmzaQy+Vo1qwZli9f/si+ZTKZxs+Rubm58DOxadMmNG/eHHK5HGq1GtHR0ejevbvwc+Dn54c//vhD6O/w4cOQyWTIz88X2hITEyGTyXD9+nWhLTIyEk8//TQaNmyIwYMHIycnp9bfF6InERMbqrUtW7bAxMQEx44dw4YNGwAARkZGWL16NZKTk7FlyxYcOnQI06dPr1W/y5cvx6ZNm7Bx40bExsYiNzcXUVFRurgEIhFjY2MsXLgQERERSE1NrTYmISEBQ4cOxfDhw5GUlIQ5c+Zg5syZiIyMrPPnXr16Fd9++y127tyJxMREAEBRURFCQkJw6tQpHDx4EEZGRhg8eDDu3btX435PnDiBt956CxMmTEBiYiJ69uyJBQsW1HmcRE8STkXRA/3www9o1KiR8Lp///4AgJYtW2LJkiWi2ClTpghfu7q6Yv78+Rg/fjzWrl1b489btWoVwsLCMGTIEADA+vXr8dNPPz3GFRDV3ODBg9G+fXvMnj0bGzdu1Di/YsUK9O7dGzNnzgQAuLm54cKFC1i6dClUKtUD+y0oKBD9HDVq1AgZGRkAKqdyt23bJprirfrzX2Xjxo2wt7fHhQsX4OnpWaNr+eSTT+Dr64v3339fGGtcXByio6Nr9H6iJxkrNvRAPXv2RGJionCsXr0aANCpUyeN2F9++QV9+vRB06ZNYWlpiZEjRyInJwdFRUU1+qyCggKkp6fDy8tLaDMxMan2s4h0ZfHixdiyZQsuXLigce7ixYvo1q2bqK1bt264cuUKKioqHtinpaWl6OcoLi5OOOfi4qKxbu2PP/5AYGAgmjdvDisrK7i6ugIAUlJSanwdFy9eFP0sAdB4TWSoWLGhB7KwsEDLli2rbf+3Gzdu4OWXX8a4ceMwf/582NjYIDY2FqNHj0ZZWRmAyqmq+9fLVJ0jqi9eeukl+Pr64oMPPtCowqjVao1dUjVZA2ZkZFTtzxGg+bMEAAMHDoSzszM+//xzKJVK3Lt3D56enigtLRX6u/+z7/9Z4to0+i9jxYYe2+nTp1FeXo7ly5ejS5cucHNzQ1pamijGzs4OGRkZor9wq9YUAJW7RJycnBAfHy+0lZeXIyEhQefjJ/q3RYsWYe/evaLKCgB4eHggNjZW1BYXFwc3NzcYGxtr5bNzcnJw8eJFfPTRR+jduzdat26NvLw8UUxVhSc9PV1o+/fPUtVY//2zBEDjNZGhYsWGHluLFi1QXl6OiIgIDBw4EMeOHcP69etFMT169EB2djaWLFmCV199FdHR0di/fz+srKyEmHfffReLFi1Cq1at0Lp1a6xYsUK084NICm3btsUbb7yBiIgIUXtoaCief/55zJ8/H8OGDcPx48exZs2aWq0jexRra2s0adIEn332GZycnJCSkiKsk6nSsmVLODs7Y86cOViwYAGuXLmisTsrODgYXbt2xZIlS+Dv74+YmBiur6H/DFZs6LG1b98eK1aswOLFi+Hp6Ynt27drbJtt3bo11q5di08//RTt2rXDyZMnMXXqVFFMaGgoRo4cCZVKBS8vL1haWmLw4MFSXgoRAGD+/Pka0znPPfccvv32W+zYsQOenp6YNWsW5s2b99CFw7VlZGSEHTt2ICEhAZ6ennjvvfewdOlSUYypqSm+/vprXLp0Ce3atcPixYs1djx16dIFX3zxBSIiItC+fXvExMTgo48+0to4ieozmZqTsURERGQgWLEhIiIig8HEhoiIiAwGExsiIiIyGExsiIiIyGAwsSEiIiKDwcSGiIiIDAYTGyIiIjIYTGyIiIjIYDCxIaJak8lk2L17t76HQUSkgYkNUT0XFxcHY2Nj9OvXr1bva9asGVatWqWbQRER1VNMbIjquU2bNmHy5MmIjY1FSkqKvodDRFSvMbEhqseKiorw7bffYvz48fDz80NkZKTo/J49e9CpUyc0aNAAtra2CAgIAFD5NPUbN27gvffeg0wmg0wmAwDMmTMH7du3F/WxatUqNGvWTHh96tQp9OnTB7a2tlAoFPD29saZM2d0eZlERFrDxIaoHvvmm2/g7u4Od3d3jBgxAps3bxaeOr1v3z4EBARgwIABOHv2LA4ePIhOnToBAHbt2oWnnnoK8+bNQ3p6OtLT02v8mXfu3MGoUaPw66+/Ij4+Hq1atcLLL7+MO3fu6OQaiYi0yUTfAyCiB9u4cSNGjBgBAOjXrx8KCwtx8OBB+Pj44OOPP8bw4cMxd+5cIb5du3YAABsbGxgbG8PS0hKOjo61+sxevXqJXm/YsAHW1tY4cuQI/Pz8HvOKiIh0ixUbonrq8uXLOHnyJIYPHw4AMDExwbBhw7Bp0yYAQGJiInr37q31z83KysK4cePg5uYGhUIBhUKBwsJCru8hoicCKzZE9dTGjRtRXl6Opk2bCm1qtRqmpqbIy8uDubl5rfs0MjISprKqlJWViV6rVCpkZ2dj1apVcHFxgVwuh5eXF0pLS+t2IUREEmLFhqgeKi8vx9atW7F8+XIkJiYKx2+//QYXFxds374dzz77LA4ePPjAPszMzFBRUSFqs7OzQ0ZGhii5SUxMFMX8+uuvCA4Oxssvv4w2bdpALpfj1q1bWr0+IiJdYcWGqB764YcfkJeXh9GjR0OhUIjOvfrqq9i4cSNWrlyJ3r17o0WLFhg+fDjKy8uxf/9+TJ8+HUDlfWyOHj2K4cOHQy6Xw9bWFj169EB2djaWLFmCV199FdHR0di/fz+srKyE/lu2bIlt27ahU6dOuH37NqZNm1an6hARkT6wYkNUD23cuBE+Pj4aSQ0ADBkyBImJibCyssJ3332HPXv2oH379ujVqxdOnDghxM2bNw/Xr19HixYtYGdnBwBo3bo11q5di08//RTt2rXDyZMnMXXqVFH/mzZtQl5eHjp06ICgoCAEBwfD3t5etxdMRKQlMvX9E+5ERERETyhWbIiIiMhgMLEhIiIig8HEhoiIiAwGExsiIiIyGExsiIiIyGAwsSEiIiKDwcSGiIiIDAYTGyIiIjIYTGyIiIjIYDCxISIiIoPBxIaIiIgMxv8DwA3yMRtEmW4AAAAASUVORK5CYII=", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "conf_mat = confusion_matrix(y_test, y_pred, labels=[1, 0]).transpose() # Transpose the sklearn confusion matrix to match the convention in the lecture\n", "sns.heatmap(conf_mat, annot=True, cmap='Blues', fmt='g', xticklabels=['Fraud', 'No Fraud'], yticklabels=['Fraud', 'No Fraud'])\n", "plt.xlabel(\"Actual\")\n", "plt.ylabel(\"Predicted\")\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are around 270 false negatives, i.e., a fraudulent transaction that we did not detect. There are also around 980 false positives, i.e., \"false alarms\", where non-fraudulent transactions were classified as fraudulent.\n", "\n", "\n", "### Using Neural Networks in PyTorch\n", "\n", "While it is possible to use neural networks in scikit-learn, it is more common to use PyTorch or TensorFlow for neural networks. PyTorch is a popular deep-learning library that is widely used in academia and industry. In this section, we will show how to use PyTorch to build a simple neural network for the same credit card fraud detection task.\n", "\n", "::: {.callout-warning}\n", "### Feel Free to Skip This Section\n", "\n", "This section might be a bit more challenging than what we have looked at previously. If you think that you are not ready for this, feel free to skip this section. This is mainly meant to be a starting point for those who are interested in learning more about neural networks.\n", "\n", "For a more in-depth introduction to PyTorch, I recommend that you check out the [official PyTorch tutorials](https://pytorch.org/tutorials/). This section, in particular, builds on the [Learning PyTorch with Examples](https://pytorch.org/tutorials/beginner/pytorch_with_examples.html) tutorial.\n", "\n", ":::\n", "\n", "\n", "Let's start by importing the necessary libraries" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "execution": { "iopub.execute_input": "2025-06-28T20:35:35.952828Z", "iopub.status.busy": "2025-06-28T20:35:35.952626Z", "iopub.status.idle": "2025-06-28T20:35:38.316751Z", "shell.execute_reply": "2025-06-28T20:35:38.316262Z" } }, "outputs": [], "source": [ "import torch\n", "from torch.utils.data import DataLoader, TensorDataset" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then, let's prepare the data for PyTorch. We need to convert the data in our DataFrame to PyTorch tensors" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "execution": { "iopub.execute_input": "2025-06-28T20:35:38.319321Z", "iopub.status.busy": "2025-06-28T20:35:38.319072Z", "iopub.status.idle": "2025-06-28T20:35:38.353325Z", "shell.execute_reply": "2025-06-28T20:35:38.352597Z" } }, "outputs": [], "source": [ "X_train_tensor = torch.tensor(X_train.values, dtype=torch.float32)\n", "y_train_tensor = torch.tensor(y_train.values, dtype=torch.long)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that we also converted the input values to `float32` for improved training speed and the target values to `long` which is a type of integer (remember our target `y` can only take values zero or one). Next, we need to create a `DataLoader` object to load the data in mini-batches during the training process" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "execution": { "iopub.execute_input": "2025-06-28T20:35:38.356217Z", "iopub.status.busy": "2025-06-28T20:35:38.355931Z", "iopub.status.idle": "2025-06-28T20:35:38.359843Z", "shell.execute_reply": "2025-06-28T20:35:38.359265Z" } }, "outputs": [], "source": [ "dataset = TensorDataset(X_train_tensor, y_train_tensor)\n", "dataloader = DataLoader(dataset, batch_size=200, shuffle=True)\n", "dataset_size = len(dataloader.dataset)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, we define the neural network model using the `nn` module from PyTorch" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "execution": { "iopub.execute_input": "2025-06-28T20:35:38.362347Z", "iopub.status.busy": "2025-06-28T20:35:38.362078Z", "iopub.status.idle": "2025-06-28T20:35:38.369820Z", "shell.execute_reply": "2025-06-28T20:35:38.369181Z" } }, "outputs": [], "source": [ "model = torch.nn.Sequential(\n", " torch.nn.Linear(7, 16), # 7 input features, 16 nodes in the hidden layer\n", " torch.nn.ReLU(), # ReLU activation function\n", " torch.nn.Linear(16, 2) # 16 nodes in the hidden layer, 2 output nodes (fraud or no fraud)\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We also need to define the loss function and the optimizer. We will use the cross-entropy loss function and the Adam optimizer" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "execution": { "iopub.execute_input": "2025-06-28T20:35:38.372486Z", "iopub.status.busy": "2025-06-28T20:35:38.372269Z", "iopub.status.idle": "2025-06-28T20:35:39.521619Z", "shell.execute_reply": "2025-06-28T20:35:39.521133Z" } }, "outputs": [], "source": [ "loss_fn = torch.nn.CrossEntropyLoss()\n", "optimizer = torch.optim.Adam(model.parameters(), lr=1e-3, weight_decay=1e-5) # Adam optimizer with learning rate of 0.001 and L2 regularization (analogous to alpha in scikit-learn)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can now train the neural network using the following code snippet" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "execution": { "iopub.execute_input": "2025-06-28T20:35:39.523956Z", "iopub.status.busy": "2025-06-28T20:35:39.523668Z", "iopub.status.idle": "2025-06-28T20:44:21.029710Z", "shell.execute_reply": "2025-06-28T20:44:21.029036Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Epoch 9 loss: 0.024499\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 19 loss: 0.008713\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 29 loss: 0.016122\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 39 loss: 0.007585\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 49 loss: 0.005461\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 59 loss: 0.020942\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 69 loss: 0.016723\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 79 loss: 0.007653\n" ] } ], "source": [ "for epoch in range(80):\n", "\n", " # Loop over batches in an epoch using DataLoader\n", " for id_batch, (X_batch, y_batch) in enumerate(dataloader):\n", "\n", " # Compute the predicted y using the neural network model with the current weights\n", " y_batch_pred = model(X_batch)\n", "\n", " # Compute the loss\n", " loss = loss_fn(y_batch_pred, y_batch)\n", "\n", " # Reset the gradients of the loss function to zero\n", " optimizer.zero_grad()\n", "\n", " # Compute the gradient of the loss with respect to model parameters\n", " loss.backward()\n", "\n", " # Update the weights by taking a \"step\" in the direction that reduces the loss\n", " optimizer.step()\n", "\n", " if epoch % 10 == 9:\n", " print(f\"Epoch {epoch} loss: {loss.item():>7f}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that here we are updating the model weights for each mini-batch in the dataset and go over the whole dataset 80 times (epochs). We print the loss every epoch to see how the loss decreases over time.\n", "\n", "The following snippet shows how to use full-batch gradient descent instead of mini-batch gradient descent" ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "execution": { "iopub.execute_input": "2025-06-28T20:44:21.032470Z", "iopub.status.busy": "2025-06-28T20:44:21.032215Z", "iopub.status.idle": "2025-06-28T20:47:30.939881Z", "shell.execute_reply": "2025-06-28T20:47:30.939004Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Epoch 99 loss: 0.009982\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 199 loss: 0.009945\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 299 loss: 0.009928\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 399 loss: 0.009920\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 499 loss: 0.009914\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 599 loss: 0.009910\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 699 loss: 0.009907\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 799 loss: 0.009904\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 899 loss: 0.009901\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 999 loss: 0.009899\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 1099 loss: 0.009897\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 1199 loss: 0.009895\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 1299 loss: 0.009893\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 1399 loss: 0.009891\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 1499 loss: 0.009890\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 1599 loss: 0.009888\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 1699 loss: 0.009886\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 1799 loss: 0.009885\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 1899 loss: 0.009883\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Epoch 1999 loss: 0.009881\n" ] } ], "source": [ "#| eval: false\n", "for epoch in range(2000):\n", "\n", " # Compute the predicted y using the neural network model with the current weights\n", " y_epoch_pred = model(X_train_tensor)\n", "\n", " # Compute the loss\n", " loss = loss_fn(y_epoch_pred, y_train_tensor)\n", "\n", " # Reset the gradients of the loss function to zero\n", " optimizer.zero_grad()\n", "\n", " # Compute the gradient of the loss with respect to model parameters\n", " loss.backward()\n", "\n", " # Update the weights by taking a \"step\" in the direction that reduces the loss\n", " optimizer.step()\n", "\n", " # Print the loss every 100 epochs\n", " if epoch % 100 == 99:\n", " print(f\"Epoch {epoch} loss: {loss.item():>7f}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that in this version we are updating the model weights 2000 times (epochs) and printing the loss every 100 epochs. We can now evaluate the model on the test set" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "execution": { "iopub.execute_input": "2025-06-28T20:47:30.943432Z", "iopub.status.busy": "2025-06-28T20:47:30.943096Z", "iopub.status.idle": "2025-06-28T20:47:31.064948Z", "shell.execute_reply": "2025-06-28T20:47:31.064126Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Accuracy: 0.9965833333333334\n", "Precision: 0.9775587566338135\n", "Recall: 0.9834865184394188\n" ] } ], "source": [ "X_test_tensor = torch.tensor(X_test.values, dtype=torch.float32)\n", "y_pred = torch.argmax(model(X_test_tensor), dim=1).numpy()\n", "\n", "print(f\"Accuracy: {accuracy_score(y_test, y_pred)}\")\n", "print(f\"Precision: {precision_score(y_test, y_pred)}\")\n", "print(f\"Recall: {recall_score(y_test, y_pred)}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that for simplicity we are reusing the sci-kit learn metrics to evaluate the model. \n", "\n", "However, our neural network trained in PyTorch does not perform exactly the same as the neural network trained in scikit-learn. This is likely because of different hyperparameters or different initializations of the weights. In practice, it is common to experiment with different hyperparameters to find the best model or to use grid search and cross-validation to try many values and find the best-performing ones.\n", "\n", "\n", "### Conclusions\n", "\n", "In this chapter, we have learned about neural networks, which are the foundation of deep learning. We have seen how to implement parts of a simple neural network from scratch and how to use neural networks in scikit-learn and PyTorch." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.13.4" } }, "nbformat": 4, "nbformat_minor": 4 }