{ "cells": [ { "cell_type": "markdown", "id": "268e92dc-f5f5-4b6c-86df-67358aec18a6", "metadata": {}, "source": [ "# Learning a Simple Linear Model with PyTorch\n", "\n", "**Authors:** Jeffrey Huang and Alex Michels\n", "\n", "In this notebook, we will use PyTorch for a simple linear regression model." ] }, { "cell_type": "code", "execution_count": 1, "id": "0d186bbb-3290-4cef-bd0d-760fd6d5d84e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'2.1.0+cu121'" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import matplotlib.pyplot as plt\n", "import numpy as np\n", "from pathlib import Path\n", "import time\n", "import torch\n", "from torch import nn # nn contains all of PyTorch's building blocks for neural networks\n", "\n", "# Check PyTorch version\n", "torch.__version__" ] }, { "cell_type": "markdown", "id": "4ae430a7", "metadata": {}, "source": [ "This notebook is a quick overview of the general ML workflow. In this scenario, we don't have data to start off with. After importing the necessary libraries, we instead create our own data that approximates a linear shape. This can be done using PyTorch's built in function for generating arrays, which are called tensors in an ML context." ] }, { "cell_type": "code", "execution_count": 2, "id": "942dde0e-0f32-43e5-a0bb-2dc6b6725870", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(tensor([[0.0000],\n", " [0.0200],\n", " [0.0400],\n", " [0.0600],\n", " [0.0800],\n", " [0.1000],\n", " [0.1200],\n", " [0.1400],\n", " [0.1600],\n", " [0.1800]]),\n", " tensor([[0.3000],\n", " [0.3140],\n", " [0.3280],\n", " [0.3420],\n", " [0.3560],\n", " [0.3700],\n", " [0.3840],\n", " [0.3980],\n", " [0.4120],\n", " [0.4260]]))" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Create *known* parameters, our model will try to predict these\n", "weight = 0.7\n", "bias = 0.3\n", "\n", "# Create data\n", "start = 0\n", "end = 1\n", "step = 0.02\n", "X = torch.arange(start, end, step).unsqueeze(dim=1)\n", "y = weight * X + bias\n", "\n", "X[:10], y[:10]" ] }, { "cell_type": "markdown", "id": "d4db6553", "metadata": {}, "source": [ "Next, it is necessary to split our generated dataset into training and validation sets. This is a necessary step in order to test the performance of model on data that it hasn't seen before, so called \"out-of-sample\" data. The normal ratio for a train test split is 80-20." ] }, { "cell_type": "code", "execution_count": 3, "id": "7129a675-2eab-4151-b3c5-94a9ee097055", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(40, 40, 10, 10)" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Create random train/test split\n", "train_split = int(0.8 * len(X)) # 80% of data used for training set, 20% for testing\n", "indices = np.random.permutation(X.shape[0]) # shuffle the data so our partitions are random\n", "training_idx, test_idx = indices[:train_split], indices[train_split:]\n", "X_train, y_train = X[training_idx, :], y[training_idx, :]\n", "X_test, y_test = X[test_idx, :], y[test_idx, :]\n", "\n", "len(X_train), len(y_train), len(X_test), len(y_test)" ] }, { "cell_type": "markdown", "id": "d69b659d", "metadata": {}, "source": [ "We can next define a function to help visualize the data. This is especially effective with data of simple dimensions that would be plotted on a 2D plane, such as our generated data. More complex, higher dimensional data may require some other form of representation." ] }, { "cell_type": "code", "execution_count": 4, "id": "56eecfa0-ea57-427e-982d-e5350158a74b", "metadata": {}, "outputs": [], "source": [ "def plot_predictions(train_data=X_train, \n", " train_labels=y_train, \n", " test_data=X_test, \n", " test_labels=y_test, \n", " predictions=None):\n", " \"\"\"\n", " Plots training data, test data and compares predictions.\n", " \"\"\"\n", " plt.figure(figsize=(10, 7))\n", " # Plot training data in blue\n", " plt.scatter(train_data, train_labels, c=\"b\", s=4, label=\"Training data\")\n", " # Plot test data in green\n", " plt.scatter(test_data, test_labels, c=\"orange\", s=4, label=\"Testing data\")\n", " if predictions is not None:\n", " # Plot the predictions in red (predictions were made on the test data)\n", " plt.scatter(test_data, predictions, c=\"r\", s=4, label=\"Predictions\")\n", " # Show the legend\n", " plt.legend(prop={\"size\": 14});" ] }, { "cell_type": "markdown", "id": "3e07c4fa", "metadata": {}, "source": [ "We can test this function below. Understandably, we only see a straight line at first. The prediction points are not present yet because we haven't yet made a model for our data, let alone train or predict points with it." ] }, { "cell_type": "code", "execution_count": 5, "id": "2bf4c854-0895-4446-9417-65d53179b107", "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAzoAAAJGCAYAAACTJvC6AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABKc0lEQVR4nO3dfXhU5Z3/8c8wIQlPGRaRMZAYoqKiKC1JQUB0RmlYtM5Q1yWtXXxCV7ZVLpJVV5YqD9WmVkvRKFQrSK2oVEHnaKk1rhMedZUUuwoWFdDwEBKDmqBggOH8/ji/JI6ZQCYkmZkz79d1zXWcO+ec+Q6ecM2H+57zdZimaQoAAAAAbKRbrAsAAAAAgI5G0AEAAABgOwQdAAAAALZD0AEAAABgOwQdAAAAALZD0AEAAABgOwQdAAAAALaTEusC2uLo0aPas2eP+vTpI4fDEetyAAAAAMSIaZrav3+/Bg4cqG7dWp+3SYigs2fPHmVnZ8e6DAAAAABxYufOncrKymr15wkRdPr06SPJejMZGRkxrgYAAABArNTX1ys7O7spI7QmIYJO43K1jIwMgg4AAACA436lhZsRAAAAALAdgg4AAAAA2yHoAAAAALAdgg4AAAAA2yHoAAAAALAdgg4AAAAA20mI20u3RygU0uHDh2NdBhAT3bt3l9PpjHUZAAAAMWO7oGOapvbu3au6ujqZphnrcoCYcDgccrlcOuWUU457j3kAAAA7ijrorFmzRvfff78qKipUVVWlF154QZMmTTrmMatXr1ZxcbE2b96sgQMH6o477tC0adPaW/Mx1dXV6YsvvtDJJ5+sXr168SEPScc0TX311Vf69NNP1aNHD/Xt2zfWJQEAAHS5qIPOV199peHDh+v666/Xv/zLvxx3/x07duiyyy7TTTfdpKeeekrr16/XT3/6U5188sltOj4apmmqpqZGGRkZ6t+/f4eeG0gkPXr0UENDg2pqauRyuQj8AAAg6UQddCZOnKiJEye2ef/f/e53OvXUU7VgwQJJ0tChQ7Vx40Y98MADHR50QqGQQqGQMjIyOvS8QCLKyMhQfX29QqGQUlJst0oVAADgmDr9rmtvvPGGCgoKwsYmTJigjRs3tnqzgIaGBtXX14c92uLIkSOSxIc6QM2/B42/FwAAAMmk04PO3r175Xa7w8bcbreOHDmi2traiMeUlJTI5XI1PbKzs6N6TZbpAPweAACA5NYlfXS+/YGr8W5orX0Qmzlzpurq6poeO3fu7PQaAQAAANhHp6/xOuWUU7R3796wsZqaGqWkpOikk06KeExaWprS0tI6uzQAAAAANtXpMzqjR49WWVlZ2Nirr76q/Px8de/evbNfHl3A4XDI4/Gc0DnKy8vlcDg0Z86cDqmps3XEewYAAEDniTrofPnll3rnnXf0zjvvSLJuH/3OO++osrJSkrXs7Jprrmnaf9q0afrkk09UXFys999/X0uWLNHixYt12223dcw7gCTrg3c0D8Te4MGDNXjw4FiXAQAAYEtRL13buHGjvF5v0/Pi4mJJ0rXXXqulS5eqqqqqKfRIUm5urlatWqWioiI98sgjGjhwoB566KEOv7V0sps9e3aLsblz58rlcmnGjBmd+trvv/++evbseULnGDlypN5//336HwEAAKBDOMzGOwPEsfr6erlcLtXV1R2zR87XX3+tHTt2KDc3V+np6V1YYXxyOBzKycnRxx9/HOtSbMfhcOjiiy9WeXl5u8/ROJvTWf9/+H0AAAB21NZs0CV3XUP8+Pjjj+VwOHTdddfpH//4h6688kr1799fDoej6QP3Cy+8oB//+Mc644wz1LNnT7lcLo0bN04rVqyIeM5I31e57rrrms65cOFCDR06VOnp6crJydHcuXN19OjRsP1b+45O4/Kur776SsXFxRo0aJDS0tJ0/vnn6/nnn2/1PRYWFqpfv37q3bu3Lr74Yq1Zs0Zz5syRw+GIKpw8/vjjGjZsmNLT05Wdna077rhDX3/9dcR9KyoqdMstt2jYsGFyuVzq0aOHzjvvPP3qV78K6xnV+P/gk08+0SeffBK2pLDx/R86dEilpaWaMGGCsrOzlZaWpgEDBujKK6/Upk2b2lw/AABAsqKzZpL66KOPdMEFF+jcc8/Vtddeq88++0ypqamSrO9Zpaam6sILL1RmZqY+/fRTGYahq666Sg899JBuvfXWNr/O7bffrvLycv3gBz9QQUGBXnzxRc2ZM0eHDh3Svffe26ZzHD58WAUFBfrss8905ZVX6sCBA3r22Wc1efJkvfLKK2ENaXfv3q0xY8aoqqpKl112mYYPH66tW7eqoKAgbMllW/ziF7/Q3XffLbfbrZtuukndu3fX8uXL9f7770fc//e//71eeuklXXTRRbrssst04MABlZeXa+bMmXr77bebgmLfvn01e/ZsLViwQJLClhY2BsbPPvtMM2bM0Lhx43TZZZfpn/7pn7R9+3YZhqG//OUvWrNmjb73ve9F9X4AAADabZchVQclt1fK8sW6mrYxE0BdXZ0pyayrqzvmfgcPHjS3bNliHjx4sIsqi2+SzJycnLCxHTt2mJJMSeZdd90V8bht27a1GNu/f7953nnnmS6Xy/zqq69avM7FF18cNnbttdeakszc3Fxzz549TeOffvqp2bdvX7NPnz5mQ0ND03gwGDQlmbNnzw47T05OjinJ9Pv9Yfu/9tprpiRzwoQJYfv/27/9mynJvP/++8PGn3jiiab3HQwGI77vb/rwww/NlJQUc9CgQWZ1dXXTeF1dnXnWWWdFfM8ff/yxeeTIkbCxo0ePmjfccIMpyVy3bl2L9/bt/z+Nvv76a3PXrl0txt977z2zd+/e5vjx44/7Hvh9AAAAHWJnwDSXyTSfdlrbnYGYltPWbMDStSR1yimn6Oc//3nEn5122mktxnr37q3rrrtOdXV1evvtt9v8OnfddZcyMzObnvfv319+v1/79+/X1q1b23ye3/72t00zTpJ06aWXKicnJ6yWhoYGPffcc3K73Zo+fXrY8ddee63OPvvsNr/e008/rSNHjqi4uFgDBgxoGs/IyGj1zy0nJ0dOpzNszOFw6Gc/+5kk6bXXXmvz66elpWnQoEEtxs8991x5vV6tWbMmbDkcAABAp6kOSg6nZIasbXV5rCtqE4JOOxmGVFRkbRPR8OHDw4LDN9XU1Ki4uFhDhw5Vz549m74/8p//+Z+SpD179rT5dUaMGNFiLCsrS5L0xRdftOkcffv2VW5ubsTzfPMcW7duVUNDg/Lz81u8N4fDodGjR7e57r///e+SpHHjxrX4WaQxyfpezfz58zVy5EhlZGSoW7ducjgcysvLkxTdn5skvfPOO7r66qt16qmnKjU1ten/w0svvaRDhw6ptrY2qvMBAAC0i9vbHHLMkOT2xLqiNuE7Ou1gGJLfLzmd0oIFUiAg+RJkqWIjt9sdcfyzzz7T9773PVVWVmrs2LEaP368+vbtK6fTqXfeeUeBQEANDQ1tfh2Xy9ViLCXFuuxCoVC7z9F4nm/e1KC+vl6SdPLJJ0fcv7X3HEldXZ0khc3mHO88V111lV566SWdeeaZKiws1IABA9S9e3d98cUXevDBB6P6c9uwYYMuueQSSVJBQYGGDBmi3r17y+Fw6MUXX9Tf//73qM4HAADQblk+6aKANZPj9iTMd3QIOu0QDFohJxSytuXliRd0WmsaunjxYlVWVuqee+7RrFmzwn72q1/9SoFAoCvKa5fG2wt++umnEX9eXV3d5nM1hquamhrl5OQc9zxvv/22XnrpJU2YMEF//vOfw5awvfnmm3rwwQfb/NqSdO+996qhoUHr1q3T2LFjw3725ptvNs04AQAAdIksX8IEnEYsXWsHr7c55IRC0rfurJzQtm3bJknyRUhua9eu7epyonLWWWcpLS1NFRUVOnToUNjPTNPUm2++2eZzDR8+XFLk9xxprPHP7fLLL2/xPZ3W/tycTmers1rbtm1Tv379WoScAwcO6G9/+9vx3wAAAECSI+i0g89nLVebPj0xl60dS+Psxbp168LGn376aa1atSoWJbVZWlqarrrqKu3du1cPPfRQ2M+efPLJVm8LHcnVV18tp9Op+fPnq6ampmm8vr5e99xzT4v9W/tz27x5s0pKSiK+Rr9+/VRbWxuxL09OTo4+//xzbd68uWksFArptttua3XGCgAAAM1YutZOPp+9Ak6jKVOm6L777tOtt96qYDConJwc/d///Z9ee+01XXnllVq5cmWsSzymkpISvfbaa7r99tsVDAb1ne98R1u3btXLL7+sf/7nf9Yrr7yibt2On+/POOMM3X333Zo9e7bOP/98TZ48WSkpKVqxYoXOO++8FneMGzlypEaOHKk//elPqqqq0gUXXKDKykoZhqHLL788YnPTSy65RBs3btQVV1yhcePGNfUuuvDCC3Xrrbfq1Vdf1YUXXqjJkycrPT1d5eXl2r17tzweT1RNTwEAAJIRMzoIk5WVpdWrV+vSSy/Va6+9pkcffVQNDQ169dVXdcUVV8S6vOPKzs7WG2+8oX/913/V+vXrtWDBAtXU1OjVV1/VGWecIan5uzzHc/fdd+v3v/+9TjrpJD366KN67rnnNHnyZD333HMt9nU6nXr55Zd1ww03aNu2bSotLdWWLVv0wAMP6Ne//nXE899111266aabtHnzZs2dO1czZ85sugX1D37wAz3//PM67bTT9NRTT+npp5/W2WefrbfeeqvFd4YAAADQksM0TTPWRRxPfX29XC6X6urqjvkh9euvv9aOHTuUm5ur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unVT//792/R6dXV1kqQBAwZE/Lnb7W4x9tFHH2nkyJGqr6+X1+vVFVdcoYyMDHXr1k3l5eVavXp1i+BzLNOnT9fDDz+s7Oxs+Xw+ZWZmKi0tTZJ1A4NozgUAABKM22v9Y3nj50m3J9YV2RJBpz0S9OLMyMiQJOXl5Wnjxo1tOqZXr1669957de+992rHjh0KBoP63e9+pwcffFAHDx7Uo48+2pklh2ms/9NPP23xs6NHj6q2trZNfXoaz1NTUxPx59XV1S3Gfvvb3+rzzz/XU089pZ/85CdhP5s2bZpWr1593NdtVFNTo0ceeUTnn3++3njjjbCwuHfv3mOGUAAAYANZPmtFUHW59TkyAf7BPBHxHZ32aLw4z5yeMMvWJGsmZujQoXr//ffDloS1VW5urm644QatXr1avXv3lmE0rydt/A7PN2dgOtrw4cMlSRs2bGjxs7feektHjhxp03kyMjKUm5urjz76SHv37m3x87Vr17YY27ZtmyTJ960WxEePHtX69etb7H+sP4/t27fLNE2NHz++xYxYpNcGAAA2lOWT8uYnzOfIRETQaa8EvTinT5+uAwcO6KabbgpbotZox44dTb1ePv30U7311lst9vn888/V0NCgHj16NI3169dPkrRr167OKVyS3+9X79699fjjj2vHjh1N40eOHNFdd90V1bmmTJmiQ4cO6e677w4bf/XVVyN+P6fxuzfr1q0LG7/vvvv03nvvtdj/WH8ejefasGFD2Pdydu3apTvvvDOq9wEAAIDIWLqWZG6++Wa9+eab+sMf/qD169dr/PjxGjhwoKqrq/WPf/xD//u//6unn35agwcP1u7duzVq1Cide+65GjFihAYNGqR9+/YpEAjo8OHDuuOOO5rOO3r0aPXo0UMLFixQfX190/doOvKDe9++fTV//nz9+7//u0aMGKHCwsKmPjppaWkaOHCgunVrW3a/4447tHLlSv3+97/X5s2bddFFF2nnzp3605/+pMsvv1x//vOfw/afNm2annjiCV155ZUqLCzUSSedpDfffFN/+9vfIu5/9tlna+DAgXr22WfVs2dPZWVlyeFw6D/+4z+a7tS2YsUK5efn69JLL1V1dbVefvllXXLJJdq+fXuH/ZkBAAAkK4JOknE4HFq6dKkuu+wy/f73v9fLL7+sL7/8UgMGDNCQIUP0wAMPaPz48ZKk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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plot_predictions()" ] }, { "cell_type": "markdown", "id": "91695133", "metadata": {}, "source": [ "## Creating the Model\n", "\n", "The next step is to define the model. As this is mostly linear data, the neural network for this simple; there isn't any complex architecture with many hidden layers. \n", "\n", "Instead, the model's weights and biases replicate the standard linear regression model. \n", "\n", "We also define a forward function for making a forward pass through the model. In more complex ML models this would be a function to let data go through every layer in the model to generate an output. Since this is a simple linear case, the forward function just plugs in an input x into weight and bias parameters." ] }, { "cell_type": "code", "execution_count": 6, "id": "cf5a7f4d-1e8d-4484-87d5-53b0461595ea", "metadata": {}, "outputs": [], "source": [ "# Create a Linear Regression model class\n", "class LinearRegressionModel(nn.Module): # <- almost everything in PyTorch is a nn.Module (think of this as neural network lego blocks)\n", " def __init__(self):\n", " super().__init__() \n", " self.weights = nn.Parameter(torch.randn(1, # <- start with random weights (this will get adjusted as the model learns)\n", " dtype=torch.float), # <- PyTorch loves float32 by default\n", " requires_grad=True) # <- can we update this value with gradient descent?)\n", "\n", " self.bias = nn.Parameter(torch.randn(1, # <- start with random bias (this will get adjusted as the model learns)\n", " dtype=torch.float), # <- PyTorch loves float32 by default\n", " requires_grad=True) # <- can we update this value with gradient descent?))\n", "\n", " # Forward defines the computation in the model\n", " def forward(self, x: torch.Tensor) -> torch.Tensor: # <- \"x\" is the input data (e.g. training/testing features)\n", " return self.weights * x + self.bias # <- this is the linear regression formula (y = m*x + b)" ] }, { "cell_type": "code", "execution_count": 7, "id": "f6691ccd-7fcd-4505-8ca5-1e8aa136e159", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[Parameter containing:\n", " tensor([0.3367], requires_grad=True),\n", " Parameter containing:\n", " tensor([0.1288], requires_grad=True)]" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Set manual seed since nn.Parameter are randomly initialzied\n", "torch.manual_seed(42)\n", "\n", "# Create an instance of the model (this is a subclass of nn.Module that contains nn.Parameter(s))\n", "model_0 = LinearRegressionModel()\n", "\n", "# Check the nn.Parameter(s) within the nn.Module subclass we created\n", "list(model_0.parameters())" ] }, { "cell_type": "markdown", "id": "581537ab", "metadata": {}, "source": [ "We can use the following syntax to make predictions with our model. Note that we haven't yet trained the model. Could you guess as to how well these predictions will perform? \n", "\n", "These will be terrible predictions because the model hasn't even seen the training data yet." ] }, { "cell_type": "code", "execution_count": 8, "id": "2f72d15d-a977-4215-8a2f-3bfa79ed660a", "metadata": {}, "outputs": [], "source": [ "# Make predictions with model\n", "with torch.inference_mode(): \n", " y_preds = model_0(X_test)" ] }, { "cell_type": "code", "execution_count": 9, "id": "c91ae8e5-c8b0-4c47-8e33-3ffe9f117f1a", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Number of testing samples: 10\n", "Number of predictions made: 10\n", "Predicted values:\n", "tensor([[0.3914],\n", " [0.4588],\n", " [0.2635],\n", " [0.1355],\n", " [0.4386],\n", " [0.2298],\n", " [0.1490],\n", " [0.3376],\n", " [0.4251],\n", " [0.1894]])\n" ] } ], "source": [ "print(f\"Number of testing samples: {len(X_test)}\") \n", "print(f\"Number of predictions made: {len(y_preds)}\")\n", "print(f\"Predicted values:\\n{y_preds}\")" ] }, { "cell_type": "markdown", "id": "3b286c67-7d69-488b-ae48-808631432c02", "metadata": {}, "source": [ "We can plot our predictions to see that our model is very bad without training:" ] }, { "cell_type": "code", "execution_count": 10, "id": "95197ded-d2d0-4065-a209-fb51da64859f", "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAzoAAAJGCAYAAACTJvC6AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABKc0lEQVR4nO3deXhU5f3+8XuYkIQtg2wxEAhRQFEUBYqCIBPEULBM1FpiaQUUrdQlJVQpFGVRMS5I0SBqVaC2gFFEMipFQBNW+SqIVgU3FiEsCaAkyBLIcH5/zC8D40wgE5JZTt6v68p1Os+cOfOZ9ARz5zzn+VgMwzAEAAAAACZSJ9QFAAAAAEB1I+gAAAAAMB2CDgAAAADTIegAAAAAMB2CDgAAAADTIegAAAAAMB2CDgAAAADTiQp1AZVx8uRJ7d69W40aNZLFYgl1OQAAAABCxDAMHTp0SC1btlSdOhVft4mIoLN79261bt061GUAAAAACBM7d+5UYmJihc9HRNBp1KiRJPeHiYuLC3E1AAAAAEKlpKRErVu39mSEikRE0CmfrhYXF0fQAQAAAHDWW1pYjAAAAACA6RB0AAAAAJgOQQcAAACA6RB0AAAAAJgOQQcAAACA6RB0AAAAAJhORCwvXRUul0snTpwIdRlASNStW1dWqzXUZQAAAISM6YKOYRjau3eviouLZRhGqMsBQsJischms+n8888/6xrzAAAAZmS6oFNcXKyDBw+qefPmatCgAb/kodYxDEOHDx/Wvn37VK9ePTVu3DjUJQEAAASdqYKOYRgqKipSXFycmjVrFupygJCpV6+eSktLVVRUJJvNRuAHAAC1TsCLEaxcuVKDBg1Sy5YtZbFYtGjRorO+ZsWKFeratatiY2N1wQUX6MUXX6xKrWflcrnkcrkUFxdXI8cHIklcXJznZwIAAKC2CTjoHD58WJ07d9aMGTMqtf+2bds0cOBA9e7dWxs3btTf//53ZWRk6K233gq42LMpKyuTJEVFmepCFVAl5T8H5T8XAAAAtUnAiWDAgAEaMGBApfd/8cUX1aZNG02fPl2S1LFjR61fv15Tp07Vb3/720DfvlKYpgPwcwAAAGq3Gu+j89FHHyk1NdVrrH///lq/fn2Fyz+XlpaqpKTE6wsAAAAAKqvGg87evXsVHx/vNRYfH6+ysjLt37/f72uysrJks9k8X61bt67pMgEAAACYSI0HHcl3Ck15f5uKptaMGzdOxcXFnq+dO3fWeI2oOovFIrvdfk7HyM/Pl8Vi0aRJk6qlpppWHZ8ZAAAANafG79o///zztXfvXq+xoqIiRUVFqWnTpn5fExMTo5iYmJouzVQCvR+DZqqh17ZtW0nS9u3bQ1oHAACAGdV40OnRo4feeecdr7GlS5eqW7duqlu3bk2/fa0xceJEn7HJkyfLZrNp1KhRNfremzdvVv369c/pGN27d9fmzZvpfwQAAIBqEXDQ+fnnn/X99997Hm/btk2fffaZmjRpojZt2mjcuHHatWuXXnvtNUnSyJEjNWPGDI0ePVp33XWXPvroI7366quaP39+9X0K+J3yNXnyZDVu3LjGp4NdfPHF53yM+vXrV8txAAAAAKkK9+isX79eV155pa688kpJ0ujRo3XllVdqwoQJkqQ9e/Zox44dnv2Tk5O1ePFi5efn64orrtCjjz6q5557rsaWlsaZbd++XRaLRcOHD9fXX3+tm2++Wc2aNZPFYvFMoXr77bf1+9//Xu3atVP9+vVls9nUu3fvCnsf+btfZfjw4Z5jzpw5Ux07dlRsbKySkpI0efJknTx50mv/iu7Radu2rdq2bavDhw9r9OjRatWqlWJiYnT55ZdrwYIFFX7G9PR0NWnSRA0bNlSfPn20cuVKTZo0SRaLRfn5+ZX+fr3yyivq1KmTYmNj1bp1a40ZM0bHjh3zu++GDRt03333qVOnTrLZbKpXr54uu+wyPfHEE14rDJb/f/DDDz/ohx9+kMVi8XyVf/7jx48rOztb/fv3V+vWrRUTE6MWLVro5ptv1saNGytdPwAAQG0V8BUdu91+xvs75syZ4zPWp08fffrpp4G+FWrQ999/r6uvvlqXXnqphg0bph9//FHR0dGS3ItBREdHq1evXkpISNC+ffvkdDp1yy236LnnntP9999f6fd58MEHlZ+fr9/85jdKTU3VokWLNGnSJB0/flxTpkyp1DFOnDih1NRU/fjjj7r55pt15MgRvf766xo8eLCWLFnitXz5rl271LNnT+3Zs0cDBw5U586d9c033yg1NVUpKSkBfY8effRRTZgwQfHx8brrrrtUt25d5eTkaPPmzX73f/nll/XOO+/o2muv1cCBA3XkyBHl5+dr3Lhx+uSTTzxBsXHjxpo4caKnt9TpUwvLA+OPP/6oUaNGqXfv3ho4cKDOO+88bd26VU6nU//973+1cuVK/epXvwro8wAAAFRZgVMqzJPiU6RER6irqRwjAhQXFxuSjOLi4jPud/ToUWPTpk3G0aNHg1RZeJNkJCUleY1t27bNkGRIMh5++GG/r9uyZYvP2KFDh4zLLrvMsNlsxuHDh33ep0+fPl5jw4YNMyQZycnJxu7duz3j+/btMxo3bmw0atTIKC0t9Yzn5eUZkoyJEyd6HScpKcmQZKSlpXntv3z5ckOS0b9/f6/9//jHPxqSjKefftprfPbs2Z7PnZeX5/dzn+67774zoqKijFatWhmFhYWe8eLiYuOiiy7y+5m3b99ulJWVeY2dPHnSuOOOOwxJxurVq30+2y///yl37Ngxo6CgwGf8yy+/NBo2bGj069fvrJ+BnwcAAFAtduYaxlwZxjyre7szN6TlVDYbBGV5aYSf888/Xw899JDf5y644AKfsYYNG2r48OEqLi7WJ598Uun3efjhh5WQkOB53KxZM6WlpenQoUP65ptvKn2cf/zjH54rTpJ03XXXKSkpyauW0tJSvfnmm4qPj1dGRobX64cNGxbQPUDz5s1TWVmZRo8erRYtWnjG4+LiKvy+JSUlyWq1eo1ZLBbde++9kqTly5dX+v1jYmLUqlUrn/FLL71UKSkpWrlyZYUNdwEAAKpVYZ5ksUqGy70tzA91RZVC0Kkip1PKzHRvI1Hnzp29gsPpioqKNHr0aHXs2FH169f33D/y17/+VZK0e/fuSr9Ply5dfMYSExMlSQcPHqzUMRo3bqzk5GS/xzn9GN98841KS0vVrVs3n89msVjUo0ePStf9+eefS5J69+7t85y/Mcl9X820adPUvXt3xcXFqU6dOrJYLOrataukwL5vkvTZZ59pyJAhatOmjaKjoz3/P7zzzjs6fvx4hQ13AQAAqlV8yqmQY7ikeHuoK6qUGl9e2oycTiktTbJapenTpdxcyREhUxXLxcfH+x3/8ccf9atf/Uo7duzQNddco379+qlx48ayWq367LPPlJubq9LS0kq/j81m8xmLinKfdi6Xq8rHKD/O6YsalJSUSJKaN2/ud/+KPrM/xcXFkuR1Nedsx7nlllv0zjvvqEOHDkpPT1eLFi1Ut25dHTx4UM8++2xA37e1a9eqb9++kqTU1FS1b99eDRs2lMVi0aJFi/T5558HdDwAAIAqS3RI1+a6r+TE2yPmHh2CThXk5blDjsvl3ubnR17QqajB6KuvvqodO3boscce0/jx472ee+KJJ5SbmxuM8qokLi5OkrRv3z6/zxcWFlb6WOXhqqioSElJSWc9zieffKJ33nlH/fv313vvvec1hW3dunV69tlnK/3ekjRlyhSVlpZq9erVuuaaa7yeW7duneeKEwAAQFAkOiIm4JRj6loVpKScCjkul/SLlZUj2pYtWyRJDj/JbdWqVcEuJyAXXXSRYmJitGHDBh0/ftzrOcMwtG7dukofq3PnzpL8f2Z/Y+XftxtuuMHnPp2Kvm9Wq7XCq1pbtmxRkyZNfELOkSNHWMEQAACgEgg6VeBwuKerZWRE5rS1Mym/erF69Wqv8Xnz5mnx4sWhKKnSYmJidMstt2jv3r167rnnvJ577bXXKlwW2p8hQ4bIarVq2rRpKioq8oyXlJToscce89m/ou/bV199paysLL/v0aRJE+3fv99vX56kpCT99NNP+uqrrzxjLpdLDzzwQIVXrAAAAHAKU9eqyOEwV8Apd9ttt+nJJ5/U/fffr7y8PCUlJel///ufli9frptvvlkLFy4MdYlnlJWVpeXLl+vBBx9UXl6errjiCn3zzTd699139etf/1pLlixRnTpnz/ft2rXThAkTNHHiRF1++eUaPHiwoqKi9NZbb+myyy7zWTGue/fu6t69u9544w3t2bNHV199tXbs2CGn06kbbrjBb3PTvn37av369Ro0aJB69+7t6V3Uq1cv3X///Vq6dKl69eqlwYMHKzY2Vvn5+dq1a5fsdntATU8BAAAk933meXnu2Ulm/D32l7iiAy+JiYlasWKFrrvuOi1fvlwvvfSSSktLtXTpUg0aNCjU5Z1V69at9dFHH+l3v/ud1qxZo+nTp6uoqEhLly5Vu3btJJ26l+dsJkyYoJdffllNmzbVSy+9pDfffFODBw/Wm2++6bOv1WrVu+++qzvuuENbtmxRdna2Nm3apKlTp+qpp57ye/yHH35Yd911l7766itNnjxZ48aN8yxB/Zvf/EYLFizQBRdcoP/85z+aN2+eLr74Yn388cc+9wwBAACcTfliWtnZ7m2krhwcCIthGEaoizibkpIS2Ww2FRcXn/GX1GPHjmnbtm1KTk5WbGxsECtEJOjVq5c++ugjFRcXq2HDhqEup8bx8wAAAMplZrpDTvl95hkZ0rRpoa6qaiqbDbiiA9PZs2ePz9jcuXO1Zs0a9evXr1aEHAAAgNOZeTGtinCPDkynU6dOuvLKK3XJJZd4+v/k5+erUaNGmjp1aqjLAwAACLryxbTy890hpzbco0PQgemMHDlS77zzjtavX6/Dhw+refPmGjJkiB5++GFdfPHFoS4PAAAgJMy6mFZFCDownSlTpmjKlCmhLgMAAAAhxD06AAAAAEyHoAMAAABEEKfTvYpabVgi+lwQdAAAAIAIURv74VQVQQcAAACIEHl5p5aItlrdq6jBP4IOAAAAECFqYz+cqmLVNQAAACBC1MZ+OFVF0AEAAAAiSG3rh1NVTF0DAAAAYDoEHQAAAACmQ9BBUAwfPlwWi0Xbt28PdSlnNWfOHFksFs2ZMyfUpQAAALMqcEobMt1b1AiCjklYLJaAvqob4cBbfn6+LBaLJk2aFOpSAABAuClwSivTpG+z3VvCTo1gMQKTmDhxos/Y5MmTZbPZNGrUqOAX9AtZWVkaO3asWrVqFepSAAAAQqswT7JYJcPl3hbmS4msLlDdCDom4e/KweTJk9W4ceOwuKqQkJCghISEUJcBAAAQevEp0jfTT4WdeHuoKzIlpq7VQoZhaNasWbrmmmsUFxen+vXrq1u3bpo1a5bPvseOHdMzzzyjzp07y2azqWHDhrrwwgv1+9//Xl988YUk9/03t99+uyTp9ttv9ztFzt89OqdP7/r000/Vv39/NWrUSDabTTfddFOF9/MsXLhQ3bp1U7169RQfH6+77rpLP/30k9q2bau2bdtW+vvw448/auTIkYqPj1f9+vX1q1/9Sm+//XaF+8+aNUtpaWlq27atYmNj1aRJE/Xv3195eXle+02aNEkpKSmS3GHz9O9H+Wf69ttvNWbMGHXp0kVNmzZVbGysOnTooLFjx+rnn3+u9GcAAAARKNEhXZsrdchwb7maUyO4olPLGIahP/7xj5o3b546dOigIUOGKDo6WsuWLdOIESO0adMmTZ061bP/sGHD9MYbb+jyyy/X7bffrpiYGO3YsUN5eXnq37+/LrvsMt144406ePCgcnNzlZaWpiuuuCKgmtavX6+nn35adrtdd999tzZu3KhFixbpiy++0JdffqnY2FjPvrNmzdKIESPUuHFjDR06VDabTYsXL9b111+vEydOqG7dupV6zyNHjshut+uLL75Qjx491KdPH+3cuVPp6elKTU31+5p7771XnTt3Vr9+/dS8eXPt2rVLixYtUr9+/bRw4UKlpaVJkux2u7Zv365//etf6tOnj+yntSxu3LixJHdYe/XVV5WSkiK73a6TJ09q3bp1evLJJ7VixQqtXLmy0p8FAABEoEQHAaemGRGguLjYkGQUFxefcb+jR48amzZtMo4ePRqkysKbJCMpKclr7J///KchyRgxYoRx4sQJz3hpaakxaNAgQ5Kxfv16wzAM4+DBg4bFYjG6detmlJWVeR2nrKzM+OmnnzyPZ8+ebUgyZs+e7beWYcOGGZKMbdu2ecby8vIMSYYk4/XXX/fa/7bbbjMkGfPnz/eM/fTTT0bDhg2NRo0aGVu2bPGMnzhxwujXr5/fz1uRiRMnGpKMu+66y2v8/fff99T0y8+ydetWn+Ps3r3baNmypdG+fXuv8fLPNnHiRL/vX1BQYJSWlvqMT5482ZBk/Oc//6nU5zgTfh4AAIAZVTYbMHWtqiJ0ScAZM2aoQYMGmjFjhqKiTl3Qi46O1pQpUyRJ8+fPl+Reyc0wDMXExMhqtXodx2q1eq5OnKtrr71W6enpXmN33HGHJOmTTz7xjOXm5urnn3/WnXfeqQsuuMAzHhUVpUcffTSg93zttdcUHR2tRx55xGs8NTVV1113nd/XJCcn+4wlJCTot7/9rb777jv98MMPlX7/Vq1aKTo62mf8vvvukyQtX7680scCAACAL6auVUX5koAWq/tGsgiZW3nkyBF98cUXatmypZ544gmf50+cOCFJ+vrrryVJcXFx+vWvf60lS5aoS5cuuuWWW9S7d29dddVVfn9Jr6ouXbr4jCUmJkqSDh486Bn7/PPPJUk9e/b02b979+5ewe1MDh06pG3btumSSy7R+eef7/N879699cEHH/iMb926VVlZWfrwww+1a9culZaWej2/e/duJSUlVaoGwzA0e/ZszZkzR19++aWKi4t18uRJr2MBAIDw53RKeXlSSorkCP9fB2sVgk5VROiSgD/99JMMw9CuXbs0efLkCvc7fPiw538vWLBAjz/+uObPn6/x48dLkho1aqQ77rhDjz/+uOrXr3/OddlsNp+x8tDicrk8YyUlJZKk5s2b++xfp04dNWvWrFLvV1xcLElq0aKF3+fj4+N9xr7//nt1795dJSUlSklJ0aBBgxQXF6c6deooPz9fK1as8Ak+Z5KRkaEZM2aodevWcjgcSkhIUExMjCT3AgaBHAsAAISG0ymlpUlWqzR9upSbS9gJJwSdqojQJQHj4uIkSV27dtX69esr9ZoGDRpoypQpmjJlirZt26a8vDy9+OKLevbZZ3X06FG99NJLNVmyl/L69+3b5/PcyZMntX///kr16Sk/TlFRkd/nCwsLfcb+8Y9/6KefftJ//vMf/eEPf/B6buTIkVqxYsVZ37dcUVGRnn/+eV1++eX66KOPvMLi3r17zxhCAQBA+MjLc4ccl8u9zc8n6IQT7tGpighdErBRo0bq2LGjNm/e7DUlrLKSk5N1xx13aMWKFWrYsKGczlP3J5Xfw3P6FZjq1rlzZ0nS2rVrfZ77+OOPVVZWVqnjxMXFKTk5Wd9//7327t3r8/yqVat8xrZs2SJJcvziX6+TJ09qzZo1Pvuf6fuxdetWGYahfv36+VwR8/feAAAgPKWknAo5Lpd02kKrCAMEnapKdEhdp0VMyCmXkZGhI0eO6K677vKaolZu27Ztnl4v+/bt08cff+yzz08//aTS0lLVq1fPM9akSRNJUkFBQc0ULiktLU0NGzbUK6+8om3btnnGy8rK9PDDDwd0rNtuu03Hjx/XhAkTvMaXLl3q9/6c8ntvVq9e7TX+5JNP6ssvv/TZ/0zfj/JjrV271uu+nIKCAo0dOzagzwEAAELH4XBPV8vIYNpaOGLqWi1z9913a926dfrXv/6lNWvWqF+/fmrZsqUKCwv19ddf6//+7/80b948tW3bVrt27dJVV12lSy+9VF26dFGrVq104MAB5ebm6sSJExozZoznuD169FC9evU0ffp0lZSUeO6jqc5f3Bs3bqxp06bpT3/6k7p06aL09HRPH52YmBi1bNlSdepULruPGTNGCxcu1Msvv6yvvvpK1157rXbu3Kk33nhDN9xwg9577z2v/UeOHKnZs2fr5ptvVnp6upo2bap169bp008/9bv/xRdfrJYtW+r1119X/fr1lZiYKIvFoj//+c+eldreeustdevWTdddd50KCwv17rvvqm/fvtq6dWu1fc8AAEDNcjgIOOGKoFPLWCwWzZkzRwMHDtTLL7+sd999Vz///LNatGih9u3ba+rUqerXr58kqW3btpo0aZI+/PBDLV++XAcOHFCzZs3UpUsXZWZmejXWbNKkiRYsWKBJkybphRde0NGjRyVVb9CRpLvuukvnnXeeHn/8cc2ZM0c2m00Oh0NPPvmkkpKSdOGFF1bqOA0aNNCKFSs0btw4vf322/r000916aWXKicnR8XFxT7B5corr9TSpUv10EMPaeHChbJarerZs6fWrFkjp9Pps7/VatXChQv1t7/9Tf/+97916NAhSdKtt94qm82mOXPmqG3btnrrrbeUnZ2tNm3aaPTo0frb3/5WrSvaAQAA1FYWwzCMUBdxNiUlJbLZbCouLvbcSO7PsWPHtG3bNiUnJys2NjaIFSLUvv/+e7Vv316DBw9WTk5OqMsJC/w8AAAAM6psNuAeHUSU8vuDTnf06FFlZmZKkm688cYQVAUAACJehDaDR8WYuoaIsmLFCo0YMUKpqalq06aN9u/frw8//FDbt29X3759lZ6eHuoSAQBApInQZvA4M4IOIsqll16q66+/XmvWrNGiRYskSe3atdOjjz6qBx54oNKLEQAAAHhEaDN4nBlBBxGlffv2ev3110NdBgAAMJMIbQaPMyPoAAAAoHYrbwZfmO8OOVzNMQWCDgAAAJDoIOCYDDc0AAAAADAdgg4AAAAA0yHoAAAAwBScTikz070FCDoAAACIeE6nlJYmZWe7t4QdEHQAAAAQ8fLyJKtVcrnc2/z8UFeEUCPoAAAAIOKlpJwKOS6XZLeHuiKEGstLAwAAIOI5HFJurvtKjt3ufozajSs6qHHbt2+XxWLR8OHDvcbtdrssFkuNvW/btm3Vtm3bGjs+AAAILw6HNG0aIQduBB2TKQ8Vp39FR0erdevWGjJkiP73v/+FusRqM3z4cFksFm3fvj3UpQAAACDMMHXNpC688EL98Y9/lCT9/PPPWrdunebPn6+FCxfqww8/VM+ePUNcofTaa6/pyJEjNXb8Dz74oMaODQAAgPBG0DGpdu3aadKkSV5jDz30kKZMmaLx48crLy8vNIWdpk2bNjV6/AsvvLBGjw8AAGqG0+leRS0lhWloqDqmrtUi999/vyTpk08+kSRZLBbZ7Xbt2rVLw4cP1/nnn686deoo/7T1GFeuXKlBgwapWbNmiomJUfv27fXQQw/5vRLjcrn05JNPql27doqNjVW7du2UlZWlkydP+q3nTPfoOJ1O9e/fX02bNlVsbKzatm2r2267TV9++aUk9/03//rXvyRJycnJnml69tOWWKnoHp0jR45o0qRJuvjiixUbG6smTZrohhtu0Nq1a332nTRpkiwWi/Lz8/XGG2+oS5cuqlevnhISEpSRkaGjR4/6vOatt95Snz591KJFC8XGxqp169b69a9/rUWLFvn9rAAA4BT64aC6cEWnFvEXKg4cOKAePXqoSZMmSk9P1/HjxxUXFydJevHFF3XPPffovPPO06BBg9S8eXN98sknmjJlivLy8pSXl6fo6GjPsf70pz9p1qxZSk5O1r333qtjx45p2rRpfgPEmYwZM0ZPP/20mjRpohtvvFEtWrTQzp07tXz5cnXt2lWdOnXSqFGjNGfOHH3++ef6y1/+osaNG0vSWRcfKC0t1XXXXad169apS5cuGjVqlIqKipSTk6OlS5cqJydHN998s8/rnn/+ef33v/9VWlqa7Ha7lixZouzsbB04cEBz58717PfCCy/onnvuUUJCgm666SY1bdpUe/bs0ccff6xFixbpxhtvDOh7AQBAbeOvHw5XdVAlRgQoLi42JBnFxcVn3O/o0aPGpk2bjKNHjwapsvCzbds2Q5LRv39/n+fGjx9vSDLsdrthGIYhyZBk3H777UZZWZnXvl999ZURFRVlXHnllcaBAwe8nsvKyjIkGVOnTvWM5eXlGZKMzp07Gz///LNnvKCgwGjWrJkhyRg2bJjXcfr06WP88hR87733DEnGZZddZuzfv9/ruRMnThh79+71PB42bJghydi2bZvf70VSUpKRlJTkNfbII48Ykow//OEPxsmTJz3jn3/+uRETE2Ocd955RklJiWd84sSJhiTDZrMZX3/9tWf8yJEjRocOHQyLxWLs2rXLM96lSxcjOjraKCoq8qnnl5+npvHzAACIRLm5hiEZhtXq3ubmhroihJvKZgOmrlWV0yllZobt9dTvv/9ekyZN0qRJk/TAAw+oV69emjJlimJjY/X444979ouOjtZTTz0lq9Xq9fqXXnpJZWVleu6559SkSROv58aMGaPmzZtr/vz5nrHXXntNkjRhwgQ1aNDAM96qVSv95S9/qXTdzz//vCTp2WefVdOmTb2ei4qKUnx8fKWP5c+cOXNUt25dPfHEE15XuC6//HINHz5cP/30k3Jzc31e95e//EUXXXSR53G9evX0+9//XoZhaMOGDV771q1bV3Xr1vU5xi8/DwAA8FXeDycjw73lag6qiqlrVVE+edRqlaZPD8ufwi1btmjy5MmS3L94x8fHa8iQIRo7dqwuu+wyz37Jyclq1qyZz+vXrVsnSVqyZImWL1/u83zdunX19ddfex5//vnnkqTevXv77OtvrCIff/yxYmJi1KdPn0q/prJKSkq0detWdezYUYmJiT7P2+12vfTSS/rss888K9aV69Kli8/+5cc4ePCgZ2zw4MEaO3asOnXqpFtvvVV2u129evXyTK0DAABn53CE3a9WiEAEnaqIgMmj/fv315IlS866X0VXSH788UdJ0pQpUyr1fsXFxapTp47f0BTIVZiDBw+qVatWqlOn+i82lpSUnLGe888/X5L7s/ySzWbzGYuKcv/4uFwuz9iYMWPUtGlTvfjii5o2bZqeeeYZRUVFaeDAgZo+fbqSk5PP+XMAAADg7Ji6VhUpKadCjsslnbbSV6SpaNWz8gUJSkpKZBhGhV/lbDabTp48qf379/scq7CwsNL1NG7cWHv37q1wpbZzUf6ZKqqnfLx8v6qwWCy68847tX79eu3bt09vv/22br75ZjmdTt1www1eoQgAAAA1h6BTFbVg8uhVV10l6dQUtrPp3LmzJGnVqlU+z/kbq0j37t1VWlqqFStWnHXf8vuKKhse4uLidMEFF+j777/Xrl27fJ4vf88rrrii0vWeSdOmTXXjjTcqJydHffv21ebNm/X9999Xy7EBAIgEYX5LM0yOoFNVDoc0bZopQ44k3XPPPYqKitL999+vnTt3+jx/8OBBbdy40fN46NChkqRHHnlEhw8f9ozv2rVLzz77bKXf995775Xkvvm/fPpcubKyMq+rMeWLJBQUFFT6+MOGDdOJEyc0btw4rytSX375pWbPni2bzXZOS0C///77Kisr8xo7ceKE57PUq1evyscGACCS0A8HocY9OvCrU6dOmjlzpv785z/roosu0sCBA3XhhRd6buhfsWKFhg8frhdffFGS+0b+22+/XbNnz9Zll12mm266SaWlpcrJydHVV1+td999t1LvO3DgQD3wwAOaOnWq2rdvr5tuukktWrTQrl279MEHH+iBBx7QqFGjJEl9+/bV1KlTdffdd+t3v/udGjRooDZt2mjIkCEVHn/MmDF677339O9//1ubN2/Wddddp3379iknJ0cnTpzQa6+9pkaNGlX5+5aenq769eurV69eSkpK0okT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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plot_predictions(predictions=y_preds)" ] }, { "cell_type": "markdown", "id": "abe9e56b", "metadata": {}, "source": [ "## Training the Model\n", "\n", "To prepare for the model training process, we additionally have to define a loss function and an optimizer. In this case we use the Mean Absolute Error (MAE) as our loss function.\n", "\n", "$$MAE = \\frac{\\sum_{i=1}^{n}|y_{i}-x_{i}|}{n} = \\frac{\\sum_{i=1}^{n} |e_{i}|}{n}$$\n", "\n", "where $y_{i}$ are the predictions, $x_{i}$ are the true values and $e_{i}$ is the error ($y_{i}-x_{i}$).\n", "\n", "\n", "We will optimize with the [Stochastic Gradient Descent algorithm](https://en.wikipedia.org/wiki/Stochastic_gradient_descent)." ] }, { "cell_type": "code", "execution_count": 11, "id": "d6bda52d-d676-4212-b994-8410934bd6cb", "metadata": {}, "outputs": [], "source": [ "# Create the loss function\n", "loss_fn = nn.L1Loss() # MAE loss is same as L1Loss\n", "\n", "# Create the optimizer\n", "optimizer = torch.optim.SGD(params=model_0.parameters(), # parameters of target model to optimize\n", " lr=0.01) # learning rate (how much the optimizer should change parameters at each step, higher=more (less stable), lower=less (might take a long time))" ] }, { "cell_type": "markdown", "id": "d15cdb75", "metadata": {}, "source": [ "It's also good to check whether we are currently using CPU or GPU resources. Many ML tasks execute more efficiently on GPUs, and so it is worthwhile to execute this step. The following lines of code check if the current device PyTorch is running on is CPU or CUDA, along with more information. Depending on your system environment, this may change." ] }, { "cell_type": "code", "execution_count": 12, "id": "9ecb3850-501e-4656-9cf5-84e31a5c9ae7", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Using device: cpu\n", "\n" ] } ], "source": [ "# train on the GPU or on the CPU, if a GPU is not available\n", "device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')\n", "\n", "print('Using device:', device)\n", "print()\n", "\n", "#Additional Info when using cuda\n", "if device.type == 'cuda':\n", " print(torch.cuda.get_device_name(0))\n", " print('Memory Usage:')\n", " print('Allocated:', round(torch.cuda.memory_allocated(0)/1024**3,1), 'GB')\n", " print('Cached: ', round(torch.cuda.memory_reserved(0)/1024**3,1), 'GB')" ] }, { "cell_type": "markdown", "id": "591f3874", "metadata": {}, "source": [ "Now begins the long awaited training step. We put together the functions we've defined previously iteratively feed the dataset through the model (each iteration is called an \"epoch\"). Over multiple iterations, the model parameters will be optimized. It is also worthwhile to see the time it takes for the model training step. As this is a simple linear model, training should be quick." ] }, { "cell_type": "code", "execution_count": 13, "id": "a34c2021-e94c-42e4-89ae-0690d730e8d1", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Epoch: 0 | MAE Train Loss: 0.34703248739242554 | MAE Test Loss: 0.345443993806839 \n", "Epoch: 10 | MAE Train Loss: 0.2236068695783615 | MAE Test Loss: 0.22056642174720764 \n", "Epoch: 20 | MAE Train Loss: 0.10422110557556152 | MAE Test Loss: 0.10919070243835449 \n", "Epoch: 30 | MAE Train Loss: 0.056145280599594116 | MAE Test Loss: 0.07201977074146271 \n", "Epoch: 40 | MAE Train Loss: 0.04523301124572754 | MAE Test Loss: 0.06203325837850571 \n", "Epoch: 50 | MAE Train Loss: 0.0405350998044014 | MAE Test Loss: 0.05537428334355354 \n", "Epoch: 60 | MAE Train Loss: 0.03626192361116409 | MAE Test Loss: 0.04946230724453926 \n", "Epoch: 70 | MAE Train Loss: 0.03198875114321709 | MAE Test Loss: 0.04355033114552498 \n", "Epoch: 80 | MAE Train Loss: 0.02771509811282158 | MAE Test Loss: 0.037638384848833084 \n", "Epoch: 90 | MAE Train Loss: 0.023439554497599602 | MAE Test Loss: 0.0317264162003994 \n", "Training took 0.2305295467376709 seconds\n" ] } ], "source": [ "start_time = time.time()\n", "torch.manual_seed(42)\n", "\n", "# Set the number of epochs (how many times the model will pass over the training data)\n", "epochs = 100\n", "\n", "# Create empty loss lists to track values\n", "train_loss_values = []\n", "test_loss_values = []\n", "epoch_count = []\n", "\n", "for epoch in range(epochs):\n", " ### Training\n", " # Put model in training mode (this is the default state of a model)\n", " model_0.train()\n", " # 1. Forward pass on train data using the forward() method inside \n", " y_pred = model_0(X_train)\n", " # print(y_pred)\n", " # 2. Calculate the loss (how different are our models predictions to the ground truth)\n", " loss = loss_fn(y_pred, y_train)\n", " # 3. Zero grad of the optimizer\n", " optimizer.zero_grad()\n", " # 4. Loss backwards\n", " loss.backward()\n", " # 5. Progress the optimizer\n", " optimizer.step()\n", " ### Testing\n", " # Put the model in evaluation mode\n", " model_0.eval()\n", " with torch.inference_mode():\n", " # 1. Forward pass on test data\n", " test_pred = model_0(X_test)\n", "\n", " # 2. Caculate loss on test data\n", " test_loss = loss_fn(test_pred, y_test.type(torch.float)) # predictions come in torch.float datatype, so comparisons need to be done with tensors of the same type\n", "\n", " # Print out what's happening\n", " if epoch % 10 == 0:\n", " epoch_count.append(epoch)\n", " train_loss_values.append(loss.detach().numpy())\n", " test_loss_values.append(test_loss.detach().numpy())\n", " print(f\"Epoch: {epoch} | MAE Train Loss: {loss} | MAE Test Loss: {test_loss} \")\n", "curr_time = time.time()\n", "print(f\"Training took {curr_time - start_time} seconds\")" ] }, { "cell_type": "markdown", "id": "1c6d85dd", "metadata": {}, "source": [ "Plotting the loss curves over epochs shows how loss decreases through each iteration, showing the model improving incrementally." ] }, { "cell_type": "code", "execution_count": 14, "id": "8c9b8154-7d2d-42d8-bd6e-d9d3db8156ce", "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkAAAAHFCAYAAAAaD0bAAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABpTElEQVR4nO3deVhU9f4H8PeZgZlhHZEdWcQV3AEV1EzNxLUyLcndyq3FQm+/W17Nrbpmm14rNSv1divEyspKU6xccsMNc9dSQQVCUXYZYOb7+2NgZASU/QzM+/U857nDmTNnPodTl3ff7UhCCAEiIiIiK6KQuwAiIiKi+sYARERERFaHAYiIiIisDgMQERERWR0GICIiIrI6DEBERERkdRiAiIiIyOowABEREZHVYQAiIiIiq8MARFQBSZIqte3YsaNG37NgwQJIklStz+7YsaNWarB0kyZNQvPmze953IoVK7Bu3bo6rSU5ORkLFixAQkJCpY63lntE1NDYyF0AkaXat2+f2c+vvfYafvvtN/z6669m+9u1a1ej75k8eTIGDRpUrc+GhoZi3759Na6hsVixYgXc3NwwadKkOvuO5ORkLFy4EM2bN0eXLl3q7HuIqG4xABFVICIiwuxnd3d3KBSKMvvvlJeXB3t7+0p/j6+vL3x9fatVo7Oz8z3rIZKDXq9HUVER1Gq13KUQlYtdYEQ10LdvX3To0AG7du1Cz549YW9vj6eeegoAEBsbi8jISHh7e8POzg7BwcF45ZVXkJuba3aO8rrAmjdvjmHDhuHnn39GaGgo7OzsEBQUhDVr1pgdV173yqRJk+Do6Ig///wTQ4YMgaOjI/z8/PCPf/wDOp3O7PNXrlzBY489BicnJzRp0gRjx47FwYMHIUnSPbuSrl27hmeffRbt2rWDo6MjPDw88MADD2D37t1mx126dAmSJOGdd97Be++9h8DAQDg6OqJHjx7Yv39/mfOuW7cObdu2hVqtRnBwMD777LO71lH6d3by5Ens3LnT1D1ZutssKysLL730EgIDA6FSqdCsWTNER0eXuR9fffUVwsPDodVqYW9vjxYtWpju6Y4dO9CtWzcAwJNPPmn6ngULFlSqxtI2bdqEHj16wN7eHk5OThgwYECZVsdr165h6tSp8PPzg1qthru7O3r16oXt27ebjjl69CiGDRsGDw8PqNVq+Pj4YOjQobhy5co9a/j555/Rv39/07UGBwdj8eLFpvf79u2Lvn37lvncnV2SJff4rbfewuuvv47AwECo1Wps2LABKpUKr776aplznDlzBpIkYfny5aZ9qampmDZtGnx9faFSqRAYGIiFCxeiqKjI7LMrV65E586d4ejoCCcnJwQFBeFf//rXPa+XqDS2ABHVUEpKCsaNG4d//vOf+Pe//w2FwvjfFefPn8eQIUMQHR0NBwcHnDlzBkuWLEF8fHyZbrTyHDt2DP/4xz/wyiuvwNPTE5988gmefvpptGrVCvfff/9dP1tYWIiHH34YTz/9NP7xj39g165deO2116DVajFv3jwAQG5uLvr164cbN25gyZIlaNWqFX7++WdERUVV6rpv3LgBAJg/fz68vLyQk5ODb7/9Fn379sUvv/xS5g/nhx9+iKCgICxbtgwA8Oqrr2LIkCG4ePEitFotAGP4efLJJ/HII4/g3XffRWZmJhYsWACdTmf6vVbk22+/xWOPPQatVosVK1YAgKn1IS8vD3369MGVK1fwr3/9C506dcLJkycxb948HD9+HNu3b4ckSdi3bx+ioqIQFRWFBQsWQKPRIDEx0XS/QkNDsXbtWjz55JOYO3cuhg4dCgBVbsH78ssvMXbsWERGRiImJgY6nQ5vvfWW6Xd33333AQDGjx+PI0eO4I033kCbNm2QkZGBI0eOID09HYDxHg4YMACBgYH48MMP4enpidTUVPz222/Izs6+aw2ffvoppkyZgj59+mDVqlXw8PDAuXPncOLEiSpdS2nLly9HmzZt8M4778DZ2RmtW7fGsGHD8N///hcLFy40u4dr166FSqXC2LFjARjDT/fu3aFQKDBv3jy0bNkS+/btw+uvv45Lly5h7dq1AID169fj2WefxYwZM/DOO+9AoVDgzz//xKlTp6pdN1kpQUSVMnHiROHg4GC2r0+fPgKA+OWXX+76WYPBIAoLC8XOnTsFAHHs2DHTe/Pnzxd3/qsYEBAgNBqNSExMNO27deuWaNq0qZg2bZpp32+//SYAiN9++82sTgBiw4YNZuccMmSIaNu2rennDz/8UAAQW7ZsMTtu2rRpAoBYu3btXa/pTkVFRaKwsFD0799fPProo6b9Fy9eFABEx44dRVFRkWl/fHy8ACBiYmKEEELo9Xrh4+MjQkNDhcFgMB136dIlYWtrKwICAu5ZQ/v27UWfPn3K7F+8eLFQKBTi4MGDZvu//vprAUBs3rxZCCHEO++8IwCIjIyMCr/j4MGDVfr93HmPSq6zY8eOQq/Xm47Lzs4WHh4eomfPnqZ9jo6OIjo6usJzHzp0SAAQ3333XaVqKf1dzs7O4r777jP7Xd+pT58+5f4+J06caHY/Su5xy5YtRUFBgdmxmzZtEgDEtm3bTPuKioqEj4+PGDlypGnftGnThKOjo9k/80LcvicnT54UQgjx/PPPiyZNmlTlconKxS4wohpycXHBAw88UGb/hQsXMGbMGHh5eUGpVMLW1hZ9+vQBAJw+ffqe5+3SpQv8/f1NP2s0GrRp0waJiYn3/KwkSXjooYfM9nXq1Mnsszt37oSTk1OZAdijR4++5/lLrFq1CqGhodBoNLCxsYGtrS1++eWXcq9v6NChUCqVZvUAMNV09uxZJCcnY8yYMWZdggEBAejZs2elayrPjz/+iA4dOqBLly4oKioybQMHDjTrQizp3ho1ahQ2bNiAq1ev1uh7y1NynePHjzdrEXF0dMTIkSOxf/9+5OXlAQC6d++OdevW4fXXX8f+/ftRWFhodq5WrVrBxcUFL7/8MlatWlXpVpC9e/ciKysLzz77bLVnIJbn4Ycfhq2trdm+wYMHw8vLy9SCAwBbt25FcnKyqWsRMN6jfv36wcfHx+weDR48GIDxn1fA+DvJyMjA6NGj8f333+P69eu1Vj9ZFwYgohry9vYusy8nJwe9e/fGgQMH8Prrr2PHjh04ePAgNm7cCAC4devWPc/r6upaZp9ara7UZ+3t7aHRaMp8Nj8/3/Rzeno6PD09y3y2vH3lee+99/DMM88gPDwc33zzDfbv34+DBw9i0KBB5dZ45/WUdE+VHFvSrePl5VXms+Xtq4q///4bf/zxB2xtbc02JycnCCFMf0Tvv/9+fPfddygqKsKECRPg6+uLDh06ICYmpkbfX1rJdZb3z42Pjw8MBgNu3rwJwDiObOLEifjkk0/Qo0cPNG3aFBMmTEBqaioAQKvVYufOnejSpQv+9a9/oX379vDx8cH8+fPLhKXSrl27BqDqXXf3Ut412djYYPz48fj222+RkZEBwNjV6e3tjYEDB5qO+/vvv/HDDz+UuUft27cHANM9Gj9+PNasWYPExESMHDkSHh4eCA8PR1xcXK1eCzV+HANEVEPl/Rf0r7/+iuTkZOzYscPU6gPA9AfAEri6uiI+Pr7M/pI/rvfy+eefo2/fvli5cqXZ/nuNPblbPRV9f2Vrqoibmxvs7OzKDCIv/X6JRx55BI888gh0Oh3279+PxYsXY8yYMWjevDl69OhRozqA29eZkpJS5r3k5GQoFAq4uLiY6lq2bBmWLVuGpKQkbNq0Ca+88grS0tLw888/AwA6duyI9evXQwiBP/74A+vWrcOiRYtgZ2eHV155pdwa3N3dAeCeA6U1Gg0yMzPL7K+o1aWi1qQnn3wSb7/9NtavX4+oqChs2rQJ0dHRZi2Cbm5u6NSpE954441yz+Hj42N2vieffBK5ubnYtWsX5s+fj2HDhuHcuXMICAi46zURlWALEFEdKPlDcOcU4I8++kiOcsrVp08fZGdnY8uWLWb7169fX6nPS5JU5vr++OOPMjOZKqtt27bw9vZGTEwMhBCm/YmJidi7d2+lzlFRC9mwYcPw119/wdXVFV27di2zlbfIolqtRp8+fbBkyRIAxtlWJfuByrXiladt27Zo1qwZvvzyS7PrzM3NxTfffGOaGXYnf39/PP/88xgwYACOHDlS5n1JktC5c2csXboUTZo0KfeYEj179oRWq8WqVavMarhT8+bNce7cObPZg+np6ZW+HyWCg4MRHh6OtWvX4ssvv4ROp8OTTz5pdsywYcNw4sQJtGzZstx7VDoAlXBwcMDgwYMxZ84cFBQU4OTJk1Wqi6wbW4CI6kDPnj3h4uKC6dOnY/78+bC1tcUXX3yBY8eOyV2aycSJE7F06VKMGzcOr7/+Olq1aoUtW7Zg69atAHDPWVfDhg3Da6+9hvnz56NPnz44e/YsFi1ahMDAwDLTlitDoVDgtddew+TJk/Hoo49iypQpyMjIwIIFCyrdBVbSGhIbG4sWLVpAo9GgY8eOiI6OxjfffIP7778fM2fORKdOnWAwGJCUlIRt27bhH//4B8LDwzFv3jxcuXIF/fv3h6+vLzIyMvCf//zHbPxWy5YtYWdnhy+++ALBwcFwdHSEj49PuX+gK7rOt956C2PHjsWwYcMwbdo06HQ6vP3228jIyMCbb74JAMjMzES/fv0wZswYBAUFwcnJCQcPHsTPP/+MESNGADCOm1mxYgWGDx+OFi1aQAiBjRs3IiMjAwMGDKiwBkdHR7z77ruYPHkyHnzwQUyZMgWenp74888/cezYMXzwwQcAjN1NH330EcaNG4cpU6YgPT0db731FpydnSt1raU99dRTmDZtGpKTk9GzZ0+0bdvW7P1FixYhLi4OPXv2xAsvvIC2bdsiPz8fly5dwubNm7Fq1Sr4+vpiypQpsLOzQ69eveDt7Y3U1FQsXrwYWq3WNIaLqFLkHIFN1JBUNAusffv25R6/d+9e0aNHD2Fvby/c3d3F5MmTxZEjR8rMIKpoFtjQoUPLnPPOWTkVzQK7s86KvicpKUmMGDFCODo6CicnJzFy5EixefNmAUB8//33Ff0qhBBC6HQ68dJLL4lmzZoJjUYjQkNDxXfffVfhDKG33367zDkAiPnz55vt++STT0Tr1q2FSqUSbdq0EWvWrClzzopcunRJREZGCicnJwHA7DM5OTli7ty5om3btkKlUgmtVis6duwoZs6cKVJTU4UQQvz4449i8ODBolmzZkKlUgkPDw8xZMgQsXv3brPviYmJEUFBQcLW1rbcayitvHskhBDfffedCA8PFxqNRjg4OIj+/fuLPXv2mN7Pz88X06dPF506dRLOzs7Czs5OtG3bVsyfP1/k5uYKIYQ4c+aMGD16tGjZsqWws7MTWq1WdO/eXaxbt+6evyshhNi8ebPo06ePcHBwEPb29qJdu3ZiyZIlZsf897//FcHBwUKj0Yh27dqJ2NjYKt3jEpmZmcLOzk4AEB9//HG5x1y7dk288MILIjAwUNja2oqmTZuKsLAwMWfOHJGTk2Oqp1+/fsLT01OoVCrh4+MjRo0aJf74449KXTNRCUmIu7R/EpHV+fe//425c+ciKSmp1gfJEhFZCnaBEVmxkq6OoKAgFBYW4tdff8Xy5csxbtw4hh8iatQYgIismL29PZYuXYpLly5Bp9PB398fL7/8MubOnSt3aUREdYpdYERERGR1OA2eiIiIrA4DEBEREVkdBiAiIiKyOhwEXQ6DwYDk5GQ4OTnV6oMCiYiIqO4IIZCdnQ0fH597LubKAFSO5ORk+Pn5yV0GERERVcPly5fvuZQHA1A5nJycABh/gdVZ8p2IiIjqX1ZWFvz8/Ex/x++GAagcJd1ezs7ODEBEREQNTGWGr3AQNBEREVkdBiAiIiKyOgxAREREZHU4BoiIiKyKwWBAQUGB3GVQNalUqntOca8MBiAiIrIaBQUFuHjxIgwGg9ylUDUpFAoEBgZCpVLV6DwMQEREZBWEEEhJSYFSqYSfn1+ttCJQ/SpZqDglJQX+/v41WqyYAYiIiKxCUVER8vLy4OPjA3t7e7nLoWpyd3dHcnIyioqKYGtrW+3zyB5/V6xYgcDAQGg0GoSFhWH37t0VHvv777+jV69ecHV1hZ2dHYKCgrB06VKzY9atWwdJksps+fn5dX0pRERkwfR6PQDUuOuE5FVy/0ruZ3XJ2gIUGxuL6OhorFixAr169cJHH32EwYMH49SpU/D39y9zvIODA55//nl06tQJDg4O+P333zFt2jQ4ODhg6tSppuOcnZ1x9uxZs89qNJo6vx4iIrJ8fMZjw1Zb90/WAPTee+/h6aefxuTJkwEAy5Ytw9atW7Fy5UosXry4zPEhISEICQkx/dy8eXNs3LgRu3fvNgtAkiTBy8ur7i+AiIiIGiTZusAKCgpw+PBhREZGmu2PjIzE3r17K3WOo0ePYu/evejTp4/Z/pycHAQEBMDX1xfDhg3D0aNH73oenU6HrKwss42IiKix6tu3L6Kjo2U/h5xkC0DXr1+HXq+Hp6en2X5PT0+kpqbe9bO+vr5Qq9Xo2rUrnnvuOVMLEgAEBQVh3bp12LRpE2JiYqDRaNCrVy+cP3++wvMtXrwYWq3WtPFJ8EREZAnKG9Naeps0aVK1zrtx40a89tprtVtsAyP7LLA7+/KEEPfs39u9ezdycnKwf/9+vPLKK2jVqhVGjx4NAIiIiEBERITp2F69eiE0NBTvv/8+li9fXu75Zs+ejVmzZpl+LnmabF1Iy85Hek4Bgr35kFUiIrq7lJQU0+vY2FjMmzfPbIyrnZ2d2fGFhYWVmhnVtGnT2iuygZKtBcjNzQ1KpbJMa09aWlqZVqE7BQYGomPHjpgyZQpmzpyJBQsWVHisQqFAt27d7toCpFarTU9+r8snwG85noKei3/FnG+P18n5iYiocfHy8jJtWq3WNMbVy8sL+fn5aNKkCTZs2IC+fftCo9Hg888/R3p6OkaPHg1fX1/Y29ujY8eOiImJMTvvnd1XzZs3x7///W889dRTcHJygr+/P1avXl2lWm/evIkJEybAxcUF9vb2GDx4sNnf3sTERDz00ENwcXGBg4MD2rdvj82bN5s+O3bsWLi7u8POzg6tW7fG2rVrq/+LqwTZApBKpUJYWBji4uLM9sfFxaFnz56VPo8QAjqd7q7vJyQkwNvbu9q11pauXhLGK35Gu6tf4dzf2XKXQ0Rk1YQQyCsokmUTQtTadbz88st44YUXcPr0aQwcOBD5+fkICwvDjz/+iBMnTmDq1KkYP348Dhw4cNfzvPvuu+jatSuOHj2KZ599Fs888wzOnDlT6TomTZqEQ4cOYdOmTdi3bx+EEBgyZAgKCwsBAM899xx0Oh127dqF48ePY8mSJXB0dAQAvPrqqzh16hS2bNmC06dPY+XKlXBzc6v+L6USZO0CmzVrFsaPH4+uXbuiR48eWL16NZKSkjB9+nQAxq6pq1ev4rPPPgMAfPjhh/D390dQUBAA47pA77zzDmbMmGE658KFCxEREYHWrVsjKysLy5cvR0JCAj788MP6v8A7uF87gPk2/8Xfogk+jn8Kcx/qJHdJRERW61ahHu3mbZXlu08tGgh7Ve38CY6OjsaIESPM9r300kum1zNmzMDPP/+Mr776CuHh4RWeZ8iQIXj22WcBGEPV0qVLsWPHDtPf3Ls5f/48Nm3ahD179pgaMb744gv4+fnhu+++w+OPP46kpCSMHDkSHTt2BAC0aNHC9PmkpCSEhISga9euAIwtUnVN1gAUFRWF9PR0LFq0CCkpKejQoQM2b96MgIAAAMa+z6SkJNPxBoMBs2fPxsWLF2FjY4OWLVvizTffxLRp00zHZGRkYOrUqUhNTYVWq0VISAh27dqF7t271/v1ldFmMArUTeGpu4G0Iz9BN7g91DZKuasiIqIGrCQ0lNDr9XjzzTcRGxuLq1evQqfTQafTwcHB4a7n6dTp9n+Ul3S1paWlVaqG06dPw8bGxixgubq6om3btjh9+jQA4IUXXsAzzzyDbdu24cEHH8TIkSNN3/nMM89g5MiROHLkCCIjIzF8+PAq9QZVh+yDoJ999llT4rzTunXrzH6eMWOGWWtPeZYuXVpmdWiLYaOCTchoYP+HGFq0HXGnJmJYJx+5qyIiskp2tkqcWjRQtu+uLXcGm3fffRdLly7FsmXL0LFjRzg4OCA6OhoFBQV3Pc+dg6clSar0Q2Mr6tIrPbFp8uTJGDhwIH766Sds27YNixcvxrvvvosZM2Zg8ODBSExMxE8//YTt27ejf//+eO655/DOO+9U6vurQ/ZHYVgbReh4AMADiqPYvO8PmashIrJekiTBXmUjy1aXq1Hv3r0bjzzyCMaNG4fOnTujRYsWd50IVBvatWuHoqIis3FG6enpOHfuHIKDg037/Pz8MH36dGzcuBH/+Mc/8PHHH5vec3d3x6RJk/D5559j2bJlVR6EXVUMQPXNIxg6z1DYSnr4Jn2Hyzfy5K6IiIgakVatWiEuLg579+7F6dOnMW3atHuur1dTrVu3xiOPPIIpU6bg999/x7FjxzBu3Dg0a9YMjzzyCADjWKWtW7fi4sWLOHLkCH799VdTOJo3bx6+//57/Pnnnzh58iR+/PFHs+BUFxiAZKDuPhEAEKXcgQ0Hk+5+MBERURW8+uqrCA0NxcCBA9G3b194eXlh+PDhdf69a9euRVhYGIYNG4YePXpACIHNmzebutb0ej2ee+45BAcHY9CgQWjbti1WrFgBwDgzfPbs2ejUqRPuv/9+KJVKrF+/vk7rlURtzsVrJLKysqDVapGZmVk3awLlZ6Ho7Taw0d/CVJs3sGL2s7BRMosSEdWl/Px8XLx4EYGBgXxAdgN2t/tYlb/f/KsrB40zpPbDAQAP5m/DrvPX5K2HiIjIyjAAyUQZZuwGG6rcj2/3n73H0URERFSbGIDk4h+BgiYt4SDp4PjnJqRl58tdERERkdVgAJKLJEHVdQIA4DHFDnxz+KrMBREREVkPBiA5dR4Ng6REmOI89h3YU6vPhiEiIqKKMQDJyckThlaRAID7sn/GgYs3ZC6IiIjIOjAAycymq3Ew9Ajlbnwdf0HmaoiIiKwDA5DcWg1Aob0H3KQs5J/cjMy8QrkrIiIiavQYgOSmtIFNyFgAwAj8iu+PcTA0ERFRXWMAsgBSyDgAQB/FMWzbf5SDoYmIyGJIkoTvvvtO7jJqHQOQJXBrhSLfCCglgc7XN+P41Uy5KyIiIgsgSdJdt0mTJlX73M2bN8eyZctqrdaGxkbuAsjIputE4Mp+jFLuwOr4RHTybSJ3SUREJLOUlBTT69jYWMybNw9nz95+eoCdnZ0cZTUKbAGyFO0eQZGtIwIUaUg+th15BUVyV0RERDLz8vIybVqtFpIkme3btWsXwsLCoNFo0KJFCyxcuBBFRbf/fixYsAD+/v5Qq9Xw8fHBCy+8AADo27cvEhMTMXPmTFNrUmUdP34cDzzwAOzs7ODq6oqpU6ciJyfH9P6OHTvQvXt3ODg4oEmTJujVqxcSExMBAMeOHUO/fv3g5OQEZ2dnhIWF4dChQ7X026oatgBZCpUDlB0fA46sw8OGX/DTH6PweFc/uasiImq8hAAK8+T5blt7oAqhozxbt27FuHHjsHz5cvTu3Rt//fUXpk6dCgCYP38+vv76ayxduhTr169H+/btkZqaimPHjgEANm7ciM6dO2Pq1KmYMmVKpb8zLy8PgwYNQkREBA4ePIi0tDRMnjwZzz//PNatW4eioiIMHz4cU6ZMQUxMDAoKChAfH28KWGPHjkVISAhWrlwJpVKJhIQE2Nra1uj3UF0MQBZECp0AHFmHwYp4TD1wmgGIiKguFeYB//aR57v/lQyoHGp0ijfeeAOvvPIKJk40rifXokULvPbaa/jnP/+J+fPnIykpCV5eXnjwwQdha2sLf39/dO/eHQDQtGlTKJVKODk5wcvLq9Lf+cUXX+DWrVv47LPP4OBgrP+DDz7AQw89hCVLlsDW1haZmZkYNmwYWrZsCQAIDg42fT4pKQn/93//h6CgIABA69ata/Q7qAl2gVmSZqEodA2CRiqEf/Jm/JmWLXdFRERkoQ4fPoxFixbB0dHRtE2ZMgUpKSnIy8vD448/jlu3bqFFixaYMmUKvv32W7Puseo4ffo0OnfubAo/ANCrVy8YDAacPXsWTZs2xaRJkzBw4EA89NBD+M9//mM2jmnWrFmYPHkyHnzwQbz55pv466+/alRPTbAFyJJIEmy7TgS2zsYo5Q7EHryMOUPbyV0VEVHjZGtvbImR67tryGAwYOHChRgxYkSZ9zQaDfz8/HD27FnExcVh+/btePbZZ/H2229j586d1e52EkJUOF6oZP/atWvxwgsv4Oeff0ZsbCzmzp2LuLg4REREYMGCBRgzZgx++uknbNmyBfPnz8f69evx6KOPVquemmALkKXpFAWDwhadFBfxx+E9KCgyyF0REVHjJEnGbig5thqO/wGA0NBQnD17Fq1atSqzKRTGP+92dnZ4+OGHsXz5cuzYsQP79u3D8ePHAQAqlQp6vb5K39muXTskJCQgNzfXtG/Pnj1QKBRo06aNaV9ISAhmz56NvXv3okOHDvjyyy9N77Vp0wYzZ87Etm3bMGLECKxdu7Ymv4ZqYwCyNA6uQNuhAIBBBXHYfvpvmQsiIiJLNG/ePHz22WdYsGABTp48idOnT5taXABg3bp1+PTTT3HixAlcuHAB//vf/2BnZ4eAgAAAxnWAdu3ahatXr+L69euV+s6xY8dCo9Fg4sSJOHHiBH777TfMmDED48ePh6enJy5evIjZs2dj3759SExMxLZt23Du3DkEBwfj1q1beP7557Fjxw4kJiZiz549OHjwoNkYofrEAGSBFGHjAQCPKn/HN/Hy9Y8SEZHlGjhwIH788UfExcWhW7duiIiIwHvvvWcKOE2aNMHHH3+MXr16oVOnTvjll1/www8/wNXVFQCwaNEiXLp0CS1btoS7u3ulvtPe3h5bt27FjRs30K1bNzz22GPo378/PvjgA9P7Z86cwciRI9GmTRtMnToVzz//PKZNmwalUon09HRMmDABbdq0wahRozB48GAsXLiwbn5B9yAJPnehjKysLGi1WmRmZsLZ2bn+CzDoUfReB9jkJGNG4fN4+aU58HWpeX8xEZE1y8/Px8WLFxEYGAiNRiN3OVRNd7uPVfn7zRYgS6RQwibU+HywUYod+OrQFZkLIiIialwYgCxV8RPieytPYPfBw9Ab2FBHRERUWxiALJVLc+ib9wEA9Mnbhl3nr8lcEBERUePBAGTBlGETAACPKXdiw4FL8hZDRETUiDAAWbKgYdCrtWgmpePW2V9xLVsnd0VERA0e5/40bLV1/xiALJmtBsrOUQCAxxS/YeMRDoYmIqoupVIJACgoKJC5EqqJkvtXcj+ri4/CsHQh44H41RigOISo+JOYen+LCpchJyKiitnY2MDe3h7Xrl2Dra2tabVkajgMBgOuXbsGe3t72NjULMIwAFk6707Qe3WGOvUYQjK24eCl+9A9sKncVRERNTiSJMHb2xsXL15EYmKi3OVQNSkUCvj7+9e4MYABqAFQho4HNh/DKOUOfByfyABERFRNKpUKrVu3ZjdYA6ZSqWql9Y4BqCHo+DgMW+cgGJeRdGIPMh/uAK1d9Z7kS0Rk7RQKBVeCJg6CbhDsmkBq9wgA4FHxKzYdS5a5ICIiooaNAaiBkEKND0h9SLkX38Wfk7kaIiKiho0BqKEIuA96bQCcpVsISN2OE1cz5a6IiIiowWIAaigUCuNgaABRNjsQe/CyzAURERE1XAxADUmXMRCSAuGKMziScAi3CvRyV0RERNQgyR6AVqxYgcDAQGg0GoSFhWH37t0VHvv777+jV69ecHV1hZ2dHYKCgrB06dIyx33zzTdo164d1Go12rVrh2+//bYuL6H+aJsBLfsDAIYW/YLNx1NkLoiIiKhhkjUAxcbGIjo6GnPmzMHRo0fRu3dvDB48GElJSeUe7+DggOeffx67du3C6dOnMXfuXMydOxerV682HbNv3z5ERUVh/PjxOHbsGMaPH49Ro0bhwIED9XVZdapkMPRI5S58FX9J3mKIiIgaKEnI+FS48PBwhIaGYuXKlaZ9wcHBGD58OBYvXlypc4wYMQIODg743//+BwCIiopCVlYWtmzZYjpm0KBBcHFxQUxMTKXOmZWVBa1Wi8zMTDg7O1fhiupBUQH07wZBeSsdTxW8hDkzZ6Klu6PcVREREcmuKn+/ZWsBKigowOHDhxEZGWm2PzIyEnv37q3UOY4ePYq9e/eiT58+pn379u0rc86BAwdW+pwWz0YFZZfRAIAo5Q5s4GBoIiKiKpMtAF2/fh16vR6enp5m+z09PZGamnrXz/r6+kKtVqNr16547rnnMHnyZNN7qampVT6nTqdDVlaW2WbRQozdYA8ojuK3wydQUGSQuSAiIqKGRfZB0Hc+zEwIcc8HnO3evRuHDh3CqlWrsGzZsjJdW1U95+LFi6HVak2bn59fFa+innkEwdCsG2wlPfrm/4Jfz/wtd0VEREQNimwByM3NDUqlskzLTFpaWpkWnDsFBgaiY8eOmDJlCmbOnIkFCxaY3vPy8qryOWfPno3MzEzTdvmy5XcrKUrWBFLuwPr48geNExERUflkC0AqlQphYWGIi4sz2x8XF4eePXtW+jxCCOh0OtPPPXr0KHPObdu23fWcarUazs7OZpvF6zACBlt7tFSkIOfPPUjOuCV3RURERA2GrE+DnzVrFsaPH4+uXbuiR48eWL16NZKSkjB9+nQAxpaZq1ev4rPPPgMAfPjhh/D390dQUBAA47pA77zzDmbMmGE654svvoj7778fS5YswSOPPILvv/8e27dvx++//17/F1iX1E5QtB8BJHyOUYod+OrQQ3jxwdZyV0VERNQgyBqAoqKikJ6ejkWLFiElJQUdOnTA5s2bERAQAABISUkxWxPIYDBg9uzZuHjxImxsbNCyZUu8+eabmDZtmumYnj17Yv369Zg7dy5effVVtGzZErGxsQgPD6/366tzIeOAhM8xVLkfww+ew/MPtIJScffxU0RERCTzOkCWyqLXASpNCBg+6AZF+nm8XDgFQye+jPvbuMtdFRERkSwaxDpAVAskCYqQcQCAKOVvfEAqERFRJTEANXSdR0NISoQq/sSFU4eQnqO792eIiIisHANQQ+fkCanNIADAo9IObDxyVeaCiIiILB8DUGNQvCbQCOVufB3/Fzisi4iI6O4YgBqDVgNgcPSEm5SF5jd+x+HEm3JXREREZNEYgBoDpQ0UXcYAKF4ZmoOhiYiI7ooBqLEofkBqH8UxHPzjJLLyC2UuiIiIyHIxADUWri0hAnpCKQkMM/yGH44ly10RERGRxWIAakSkkAkAgFHKHdgQnyhvMURERBaMAagxafcIhMoRAYo02Kfsx8nkTLkrIiIiskgMQI2Jyh5Sx8cAFLcCcTA0ERFRuRiAGpvibrDBinhsP3oO+YV6mQsiIiKyPAxAjU2zUAiPdtBIhehXuAs/n0iVuyIiIiKLwwDU2EgSpOIp8aOUO7D+YJK89RAREVkgBqDGqFMUhMIWnRQXkXnxKC5ez5W7IiIiIovCANQYObhCChoKwNgKFMvB0ERERGYYgBqr4gekPqr8HZsOXUCh3iBzQURERJaDAaixatEPwrkZmki5CLu1B7+eSZO7IiIiIovBANRYKZSQQsYBYDcYERHRnRiAGrMuYyEgobfyBM6fPYmUzFtyV0RERGQRGIAaM5cASC36AAAeU+7E14euyFwQERGRZWAAauyK1wR6TLkTXx28BINByFwQERGR/BiAGrugYRCaJmgmpaN51kHs/Std7oqIiIhkxwDU2NlqIHUaBYArQxMREZVgALIGxd1gkYpDOHjyPG7kFshcEBERkbwYgKyBdyfAuzNUkh5DsBvfHr0qd0VERESyYgCyFqUekBobnwghOBiaiIisFwOQtej4OISNBsGKy9Bc+wNHkjLkroiIiEg2DEDWwq4JpOCHAQBRyh2I5WBoIiKyYgxA1qT4AakPKfci7tglZOcXylwQERGRPBiArEnAfRAuzeEs3UI//V78+EeK3BURERHJggHImigUpgekRtnswHo+IJWIiKwUA5C16TIWQlIgXHEGmVdO43RKltwVERER1TsGIGvj7AOp1YMAgFHKnYhlKxAREVkhBiBrVNwNNlK5C5uOJCG/UC9zQURERPWLAcgatRkMYe8GTykDXQoOYevJVLkrIiIiqlcMQNbIRgWp8xMAStYEYjcYERFZFwYga1X8aIwHFEdx7q8LSEzPlbkgIiKi+sMAZK08ggDfbrCV9Bih3IUNh9gKRERE1oMByJoVtwJFKXfgq4OXUaQ3yFsPERFRPWEAsmYdRkDYOqClIgV+ucfx29lrcldERERUL2QPQCtWrEBgYCA0Gg3CwsKwe/fuCo/duHEjBgwYAHd3dzg7O6NHjx7YunWr2THr1q2DJElltvz8/Lq+lIZH7QSp/aMA+IBUIiKyLrIGoNjYWERHR2POnDk4evQoevfujcGDByMpqfw/xLt27cKAAQOwefNmHD58GP369cNDDz2Eo0ePmh3n7OyMlJQUs02j0dTHJTU8xQ9IHarcjwNnEpGayaBIRESNnySEEHJ9eXh4OEJDQ7Fy5UrTvuDgYAwfPhyLFy+u1Dnat2+PqKgozJs3D4CxBSg6OhoZGRnVrisrKwtarRaZmZlwdnau9nkaBCGAD7oB6efxcuEU+D84Hc/1ayV3VURERFVWlb/fsrUAFRQU4PDhw4iMjDTbHxkZib1791bqHAaDAdnZ2WjatKnZ/pycHAQEBMDX1xfDhg0r00JEpUiSqRUoSvkbYg9ehsEgWyYmIiKqF7IFoOvXr0Ov18PT09Nsv6enJ1JTK7cy8bvvvovc3FyMGjXKtC8oKAjr1q3Dpk2bEBMTA41Gg169euH8+fMVnken0yErK8tssyqdR0NISoQq/oTq5jnsv5Aud0VERER1SvZB0JIkmf0shCizrzwxMTFYsGABYmNj4eHhYdofERGBcePGoXPnzujduzc2bNiANm3a4P3336/wXIsXL4ZWqzVtfn5+1b+ghsjRA1KbQQCMg6HXc2VoIiJq5GQLQG5ublAqlWVae9LS0sq0Ct0pNjYWTz/9NDZs2IAHH3zwrscqFAp069btri1As2fPRmZmpmm7fNkKA0BxN9ijyt/xy4kruJlbIHNBREREdUe2AKRSqRAWFoa4uDiz/XFxcejZs2eFn4uJicGkSZPw5ZdfYujQoff8HiEEEhIS4O3tXeExarUazs7OZpvVaTUAcPSCm5SF+8QhfJdwVe6KiIiI6oysXWCzZs3CJ598gjVr1uD06dOYOXMmkpKSMH36dADGlpkJEyaYjo+JicGECRPw7rvvIiIiAqmpqUhNTUVmZqbpmIULF2Lr1q24cOECEhIS8PTTTyMhIcF0TqqA0gboMhpAcTdY/GXIOEGQiIioTskagKKiorBs2TIsWrQIXbp0wa5du7B582YEBAQAAFJSUszWBProo49QVFSE5557Dt7e3qbtxRdfNB2TkZGBqVOnIjg4GJGRkbh69Sp27dqF7t271/v1NTjFj8booziGjL8TcexK5j0+QERE1DDJug6QpbKqdYDutHYIkLgHbxeOwo2wGVg8opPcFREREVVKg1gHiCxUcSvQKOUO/JBwBbm6InnrISIiqgMMQGSu3SMQamcEKNLQsegEfvwjWe6KiIiIah0DEJlT2UPqMBKAsRWIawIREVFjxABEZRWvCTRYEY+/kq7ibGq2zAURERHVLgYgKssnFPBoD41UiIeVexHLViAiImpkGICoLEkCQsYBMD4gdePRK9AV6WUuioiIqPYwAFH5OkVBKGzRUXEJPrfOY9vJv+WuiIiIqNYwAFH5HFwhBRkfNfK4cie7wYiIqFFhAKKKlXpA6sE/k3H5Rp7MBREREdUOBiCqWIt+gLMvmki5iFQcwoZDbAUiIqLGgQGIKqZQAiFjARjXBPrq0BUU6Q3y1kRERFQLGIDo7rqMhYCE3soTsMm+jF3nr8ldERERUY0xANHduQRAatEHgHEw9Pp4doMREVHDxwBE91b8gNTHlDvx25lUpGXny1wQERFRzTAA0b0FDQM0TdBMSkcP/IGvD1+RuyIiIqIaYQCie7PVAJ2iABgHQ8cevAwhhLw1ERER1QADEFVO8ZpAAxWHkJWeiv0XbshcEBERUfUxAFHleHUEvDvDVtJjuHIPYg8myV0RERFRtTEAUeUVD4YepdyBzSdSkJlXKG89RERE1cQARJXX8XEIGw2CFZcRpP8T3yVclbsiIiKiamEAosqzawIp+GEAQJRyB2LikzgYmoiIGiQGIKqa4sHQDyv34lLqdSRczpC3HiIiompgAKKqCbgPcGkOJ+kWhigO4MsDHAxNREQNDwMQVY1CAYSMAwBE2ezAD38kI/MWB0MTEVHDwgBEVddlLISkRLjiDAKKLuHbI1wZmoiIGhYGIKo6Zx9IwcMAAJOUW/HFAQ6GJiKihoUBiKon/BkAwKPK33E9LRmHEm/KXBAREVHlMQBR9fhHAN6doZEK8YRyB77Ynyh3RURERJXGAETVI0mmVqDxNtuw7cQV3MgtkLkoIiKiymEAourrMAJw8ICPdAP9DPH45jAHQxMRUcPAAETVZ6MGuj4FAHjS5md8yZWhiYiogWAAoprp+hSEwhZdFefgmH4c+/5Kl7siIiKie2IAoppx8oTUYSQAYyvQF/FcGZqIiCwfAxDVXPg0AMAwxT4cOXEa17J1MhdERER0dwxAVHPNQgG/cKgkPZ5QbMdXhy/LXREREdFdMQBR7QifDgAYo9yOrw/8BYOBg6GJiMhyMQBR7Qh+CAYnH7hLWQjJ/BW7/7wud0VEREQVYgCi2qG0haL7FADFU+L3X5K3HiIiortgAKLaEzYJBhsNOiguIePsbvydlS93RUREROViAKLaY98Uik5RAIAJii2IPcjB0EREZJkYgKh2FQ+GHqg4hN8OHIaeg6GJiMgCyR6AVqxYgcDAQGg0GoSFhWH37t0VHrtx40YMGDAA7u7ucHZ2Ro8ePbB169Yyx33zzTdo164d1Go12rVrh2+//bYuL4FK82wHQ/M+sJEMGJj3I3acTZO7IiIiojJkDUCxsbGIjo7GnDlzcPToUfTu3RuDBw9GUlL5qwnv2rULAwYMwObNm3H48GH069cPDz30EI4ePWo6Zt++fYiKisL48eNx7NgxjB8/HqNGjcKBAwfq67KsnqKH8SnxTyh/xVf7zspcDRERUVmSkPHpleHh4QgNDcXKlStN+4KDgzF8+HAsXry4Uudo3749oqKiMG/ePABAVFQUsrKysGXLFtMxgwYNgouLC2JiYip1zqysLGi1WmRmZsLZ2bkKV0QAAIMBhf8JgW3mJfyr8Gk8+9Lr8HWxl7sqIiJq5Kry91u2FqCCggIcPnwYkZGRZvsjIyOxd+/eSp3DYDAgOzsbTZs2Ne3bt29fmXMOHDiw0uekWqBQwDbC+HiMScqfEcvngxERkYWRLQBdv34der0enp6eZvs9PT2RmppaqXO8++67yM3NxahRo0z7UlNTq3xOnU6HrKwss41qKGQsimzs0UZxFRfjf0Kh3iB3RURERCayD4KWJMnsZyFEmX3liYmJwYIFCxAbGwsPD48anXPx4sXQarWmzc/PrwpXQOXSaCGFjAMAPFrwA345/bfMBREREd0mWwByc3ODUqks0zKTlpZWpgXnTrGxsXj66aexYcMGPPjgg2bveXl5Vfmcs2fPRmZmpmm7fJnr19QGZcR0CEjorzyK7b/vk7scIiIiE9kCkEqlQlhYGOLi4sz2x8XFoWfPnhV+LiYmBpMmTcKXX36JoUOHlnm/R48eZc65bdu2u55TrVbD2dnZbKNa4NoS+c37AwDaX1mPxPRcmQsiIiIyqlYAunz5Mq5cuWL6OT4+HtHR0Vi9enWVzjNr1ix88sknWLNmDU6fPo2ZM2ciKSkJ06cbF9ObPXs2JkyYYDo+JiYGEyZMwLvvvouIiAikpqYiNTUVmZmZpmNefPFFbNu2DUuWLMGZM2ewZMkSbN++HdHR0dW5VKohu97PAQAeV+7Exr2nZa6GiIjIqFoBaMyYMfjtt98AGAcdDxgwAPHx8fjXv/6FRYsWVfo8UVFRWLZsGRYtWoQuXbpg165d2Lx5MwICAgAAKSkpZmsCffTRRygqKsJzzz0Hb29v0/biiy+ajunZsyfWr1+PtWvXolOnTli3bh1iY2MRHh5enUulmmrRDznOreAo5UN/5HMUFHEwNBERya9a6wC5uLhg//79aNu2LZYvX47Y2Fjs2bMH27Ztw/Tp03HhwoW6qLXecB2g2qWP/xTKzbNwyeCJ4yN+wUNdOMiciIhqX52vA1RYWAi1Wg0A2L59Ox5++GEAQFBQEFJSUqpzSmrElF1GI9/GGc0Vf+PMrm/kLoeIiKh6Aah9+/ZYtWoVdu/ejbi4OAwaNAgAkJycDFdX11otkBoBlT0KO48HAPS4tgF/XcuRuSAiIrJ21QpAS5YswUcffYS+ffti9OjR6Ny5MwBg06ZN6N69e60WSI2DU+9nYIAC9ylPYvuO3+Quh4iIrJxNdT7Ut29fXL9+HVlZWXBxcTHtnzp1Kuzt+cwnKkcTP1z3HQCPK1vhdnIt8ocPgcZWKXdVRERkparVAnTr1i3odDpT+ElMTMSyZctw9uzZMqsyE5Vw7W+crTdU7MIvRzglnoiI5FOtAPTII4/gs88+AwBkZGQgPDwc7777LoYPH272ZHei0pTNeyLNoS00UiFu7v5E7nKIiMiKVSsAHTlyBL179wYAfP311/D09ERiYiI+++wzLF++vFYLpEZEkqC5z7gw4gPZ3+Ps1RsyF0RERNaqWgEoLy8PTk5OAIyPmRgxYgQUCgUiIiKQmJhYqwVS4+Lc7QlkKV3gI93Asbj/yV0OERFZqWoFoFatWuG7777D5cuXsXXrVkRGRgIwPnSUCwfSXdmocbPdWABA60tfIK+gSOaCiIjIGlUrAM2bNw8vvfQSmjdvju7du6NHjx4AjK1BISEhtVogNT5+A2agEDYIwVns2Rl37w8QERHVsmoFoMceewxJSUk4dOgQtm7datrfv39/LF26tNaKo8ZJ4eyFi57GVkObQ1V7gC4REVFtqFYAAgAvLy+EhIQgOTkZV69eBQB0794dQUFBtVYcNV4eA6IBAL3yd+LM+fPyFkNERFanWgHIYDBg0aJF0Gq1CAgIgL+/P5o0aYLXXnsNBgOf9k331qRVOC5oOkAl6XF1+4dyl0NERFamWgFozpw5+OCDD/Dmm2/i6NGjOHLkCP7973/j/fffx6uvvlrbNVIjVdRtGgCgc+pG5OTmylwNERFZE0kIIar6IR8fH6xatcr0FPgS33//PZ599llTl1hDlZWVBa1Wi8zMTM5qq0OiqADX3wiCu0jH3k6vo+eIGXKXREREDVhV/n5XqwXoxo0b5Y71CQoKwo0bXNyOKkeyUeFSi9EAAI+TayHYfUpERPWkWgGoc+fO+OCDD8rs/+CDD9CpU6caF0XWo82QGcgXtmil/wt/Hv5F7nKIiMhKVOtp8G+99RaGDh2K7du3o0ePHpAkCXv37sXly5exefPm2q6RGjGtqxf2u0QiIuMn3Nr9AdBtgNwlERGRFahWC1CfPn1w7tw5PProo8jIyMCNGzcwYsQInDx5EmvXrq3tGqmRc+rzPACgXeYuZP19UeZqiIjIGlRrEHRFjh07htDQUOj1+to6pSw4CLp+CSGQ8Pr9CNH/gePNJ6HjpP/IXRIRETVAdT4Imqg2SZKEmx2fBgAEJH4NocuRuSIiImrsGIDIInSNfAJJwhPOIgeJO9bJXQ4RETVyDEBkEZztNUjwfhwAoD7yCVB7PbNERERlVGkW2IgRI+76fkZGRk1qISsXOGAacj77BN66i8g+tR1O7TkjjIiI6kaVApBWq73n+xMmTKhRQWS9OrTwww+aAXhY9wNu/racAYiIiOpMlQIQp7hTXZIkCVL4VGDXD/C9vhsi/S9Iri3lLouIiBohjgEii9KvV0/sFCFQQCAljtPhiYiobjAAkUVxVNvgQsvxAACXc18B+VkyV0RERI0RAxBZnO79R+K8oRnsDHnIOfBfucshIqJGiAGILE77Zk2w3Xk4AEC/bxVgaNgrixMRkeVhACKL5HHfRGQKe2jzr8Bwdqvc5RARUSPDAEQWaUhoK3wjPQgAyNzxvszVEBFRY8MARBbJTqVEZvuJ0AsJLn/vBf4+JXdJRETUiDAAkcUaen84thq6AQDyfl8hczVERNSYMACRxWrj6YR97sbng9me3ADk3ZC5IiIiaiwYgMiihd43GCcNAbA16GA4zCnxRERUOxiAyKIN7uiDWOVQAEDBvo8AfZHMFRERUWPAAEQWTWOrhF3IKFwXztDkpQBnfpC7JCIiagQYgMjijerRGl/o+wMAdHs4GJqIiGqOAYgsXkt3R5xp9jgKhBLq5Hgg+ajcJRERUQPHAEQNwtBeIfjJEAEAMOxbKXM1RETU0MkegFasWIHAwEBoNBqEhYVh9+7dFR6bkpKCMWPGoG3btlAoFIiOji5zzLp16yBJUpktPz+/Dq+C6lpkOy98q3rI+MOJjUD23/IWREREDZqsASg2NhbR0dGYM2cOjh49it69e2Pw4MFISkoq93idTgd3d3fMmTMHnTt3rvC8zs7OSElJMds0Gk1dXQbVA5WNAu279cNhQ2soRCFwaI3cJRERUQMmawB677338PTTT2Py5MkIDg7GsmXL4Ofnh5Ury+/iaN68Of7zn/9gwoQJ0Gq1FZ5XkiR4eXmZbdTwje7mj7VFgwAA+vhPgCKdzBUREVFDJVsAKigowOHDhxEZGWm2PzIyEnv37q3RuXNychAQEABfX18MGzYMR49y0Gxj4O9qj5wWg5EimkJ56zpw8lu5SyIiogZKtgB0/fp16PV6eHp6mu339PREampqtc8bFBSEdevWYdOmTYiJiYFGo0GvXr1w/vz5Cj+j0+mQlZVltpFleiKiJf5XNAAAYNi/EhBC5oqIiKghkn0QtCRJZj8LIcrsq4qIiAiMGzcOnTt3Ru/evbFhwwa0adMG77//foWfWbx4MbRarWnz8/Or9vdT3eof7IE4u0HIF7ZQpCQAlw/IXRIRETVAsgUgNzc3KJXKMq09aWlpZVqFakKhUKBbt253bQGaPXs2MjMzTdvly5dr7fupdtkqFRjcvT2+0/cy7tjPKfFERFR1sgUglUqFsLAwxMXFme2Pi4tDz549a+17hBBISEiAt7d3hceo1Wo4OzubbWS5orr7478G42BocfoHIPOKzBUREVFDI2sX2KxZs/DJJ59gzZo1OH36NGbOnImkpCRMnz4dgLFlZsKECWafSUhIQEJCAnJycnDt2jUkJCTg1KlTpvcXLlyIrVu34sKFC0hISMDTTz+NhIQE0zmp4WvWxA4+bbpir74dJKEH4j+WuyQiImpgbOT88qioKKSnp2PRokVISUlBhw4dsHnzZgQEBAAwLnx455pAISEhpteHDx/Gl19+iYCAAFy6dAkAkJGRgalTpyI1NRVarRYhISHYtWsXunfvXm/XRXVvTLg/1p4bhJ7KUxCH10Hq8zKgspe7LCIiaiAkITiN5k5ZWVnQarXIzMxkd5iF0hsE+rwZhy/zn4W/4howbBnQ9Um5yyIiIhlV5e+37LPAiKpDqZAwKjwQ/9UPNO448BGnxBMRUaUxAFGDFdXND1+LfsgRGuDaaeDCDrlLIiKiBoIBiBosT2cNIoKb42v9/cYdB1bJWxARETUYDEDUoI0NDzB1g4lzW4H0v2SuiIiIGgIGIGrQ7mvlBr1LS/yq7wIJglPiiYioUhiAqEFTKCQ80d0P60oGQx/9HMjns9yIiOjuGICowXs8zA/7pM740+ADFGQDCV/KXRIREVk4BiBq8Nyd1Ihs7327FSj+I8BgkLcoIiKyaAxA1CiMDffHN/reyBQOwI0LwPltcpdEREQWjAGIGoUeLVzh7eaK9fq+xh0H+JR4IiKqGAMQNQqSJGFMuD8+K4qEHgrjoohpp+Uui4iILBQDEDUaI0N9cc3GE9v0YcYdXBiRiIgqwABEjYaLgwpDO3pjbdEg445jsUDeDXmLIiIii8QARI3KmHB/xIsgnBLNgaJbwJH/yl0SERFZIAYgalS6BrigjacT1hSVTIn/BNAXyVsUERFZHAYgalQkScKY7v74Qd8DGZIWyLoCnPlR7rKIiMjCMABRo/NoqC8kWw0+K+xn3MHB0EREdAcGIGp0tHa2eKiTDz4vGgA9lEDSPiA5Qe6yiIjIgjAAUaM0JtwfaXDBT4YI4w62AhERUSkMQNQodfFrgnbezvi0sHgw9IlvgJw0eYsiIiKLwQBEjVLJytDHRCucVLQF9AXAoTVyl0VERBaCAYgareEhzeCgUmJV/gDjjoOfAkU6eYsiIiKLwABEjZaj2gYPd2mGLYbuuGnjBuSmASe/lbssIiKyAAxA1KiNDfdHEWywRtffuGP/SkAIeYsiIiLZMQBRo9ahmRadfbX4vLAfihRqICUBuHxA7rKIiEhmDEDU6I0ND8BNOONnRW/jjv0r5S2IiIhkxwBEjd6wzt5wUtvgg9wHjTtO/wBkXpG3KCIikhUDEDV69iobjAhthjPCH2ftugBCDxz8RO6yiIhIRgxAZBXGhAcAAJZmPWDccXgdUJAnX0FERCQrBiCyCm29nNA1wAXb9KHI1DQDbt0Ejm+QuywiIpIJAxBZjTHh/jBAgf8WFS+MuH8Vp8QTEVkpBiCyGkM6ekNrZ4tPcnqhyMYeuHYauLhT7rKIiEgGDEBkNTS2SjwW5ossOGCXXalWICIisjoMQGRVRnf3BwC8kV68JtC5n4EbF2SsiIiI5MAARFallYcjIlo0xV8GH1x06QlAAAdWy10WERHVMwYgsjqmKfHZxVPij/wXOLNZxoqIiKi+MQCR1RnY3hOuDipsyglGukdPoDAPWD8a2L4A0BfJXR4REdUDBiCyOmobJR7r6gtAwv+p5wLhzxjf+H0p8L/hQE6anOUREVE9YAAiqzSmeDD0b39m4HL4POCxtYDKEbi0G1jVG0jcJ3OFRERUlxiAyCoFuDqgd2s3CAHExCcBHUYAU34D3IOAnFRg3VBg7wdcKJGIqJFiACKrNTbc2AoUe/AyUjPzAfc2wORfgI6PGx+Yum0OsGECkJ8lc6VERFTbZA9AK1asQGBgIDQaDcLCwrB79+4Kj01JScGYMWPQtm1bKBQKREdHl3vcN998g3bt2kGtVqNdu3b49ttv66h6asj6B3si0M0B6bkFGP3xfmMIUjsCIz4GhrwDKGyB05uA1X2Bv0/KXS4REdUiWQNQbGwsoqOjMWfOHBw9ehS9e/fG4MGDkZSUVO7xOp0O7u7umDNnDjp37lzuMfv27UNUVBTGjx+PY8eOYfz48Rg1ahQOHDhQl5dCDZCtUoH/Pd0dvi52uHg9F0+s3oeUzFuAJAHdpwBP/Qw4+wI3/gI+7g8cWy93yUREVEskIeQb5BAeHo7Q0FCsXLnStC84OBjDhw/H4sWL7/rZvn37okuXLli2bJnZ/qioKGRlZWHLli2mfYMGDYKLiwtiYmIqVVdWVha0Wi0yMzPh7Oxc+QuiBunKzTyM/ng/Lt+4hQBXe6yfGgFvrZ3xzdx0YOMU4K9fjD+HPQkMehOw1chXMBERlasqf79lawEqKCjA4cOHERkZabY/MjISe/furfZ59+3bV+acAwcOvOs5dTodsrKyzDayHr4u9lg/tQf8mtohMT0PT6zej+SMW8Y3HVyBsV8BfWcDkIDDa4E1A4GbibLWTERENSNbALp+/Tr0ej08PT3N9nt6eiI1NbXa501NTa3yORcvXgytVmva/Pz8qv391DA1a2JXcQhSKIG+rwDjvgbsmgIpCcBH9wPntslaMxERVZ/sg6AlSTL7WQhRZl9dn3P27NnIzMw0bZcvX67R91PDVBKC/JvaI+mGMQRdLQlBANDqQWDaLqBZGJCfAXz5OPDr64BBL1vNRERUPbIFIDc3NyiVyjItM2lpaWVacKrCy8uryudUq9VwdnY228g6GUNQRKkQtM88BDXxA57cAnSbYvx519vA5yOA3OvyFExERNUiWwBSqVQICwtDXFyc2f64uDj07Nmz2uft0aNHmXNu27atRuck6+JTHIICXO1x+cYtPLF6H67czLt9gI0aGPoOMOITwNYeuLDDuHr05XjZaiYioqqRtQts1qxZ+OSTT7BmzRqcPn0aM2fORFJSEqZPnw7A2DU1YcIEs88kJCQgISEBOTk5uHbtGhISEnDq1CnT+y+++CK2bduGJUuW4MyZM1iyZAm2b99e4ZpBROUpG4L2m4cgAOj0ODDlV8C1NZCdDKwdDOxfxdWjiYgaAFmnwQPGhRDfeustpKSkoEOHDli6dCnuv/9+AMCkSZNw6dIl7Nixw3R8eWN5AgICcOnSJdPPX3/9NebOnYsLFy6gZcuWeOONNzBixIhK18Rp8FQiJfMWRq/ej0vpefB1MYYiXxd784N02cCmGcDJ4gU32z8KPPw+oHaq/4KJiKxYVf5+yx6ALBEDEJWWmpmPJ1bvM4WgmCkR8Gt6RwgSAjjwkfHxGYYiwK0NMOozwCNYnqKJiKxQg1gHiKih8NJqsH5qDwS6OeDKTWN32OUbd3SHSRIQMd04QNrJB7h+Dvj4AeCPr+QpmoiI7ooBiKgSvLQaxEyJQKCbA65mVBCCAMCvOzB9N9CiL1CYB2ycDPz0ElCkq/eaiYioYgxARJVkbAmKQIt7hSAHN2DcRuD+/zP+fPBj4wDpDK4vRURkKRiAiKrA01mDmDtCUFJ6OSFIoQQemAuM+QrQNAGuHjauHv3n9nqvmYiIymIAIqoiT+filiD3khC0r/wQBABtIo2rR3t3AW7dAD5/DNjxJmAw1GvNRERkjgGIqBo8nDVYPyUCLd0dkFw8SywxPbf8g10CgKe2Gp8kDwHsWAx88ZjxSfNERCQLBiCiavIo7g67HYL2VxyCbDXAQ8uA4asAGzvgr1+MXWJXDtdrzUREZMQARFQDHk7GENTKwxEpxSHo0vUKQhAAdBkNTPkFaNoSyLoCrBkIxH/M1aOJiOoZAxBRDXk4GafIVzoEebYHpu4Agh8CDIXA5peAjVOAgrt8hoiIahUDEFEtcHdSI2ZKBFp7OCI1yxiCLt4tBGmcgVH/AyLfACQlcPwr48KJ187VX9FERFaMAYiolrg7qfGlWQjad/cQJElAz+eBST8Bjl7AtTPAx/2AExvrr2giIivFAERUi0qHoL+zdHhi9T5cuJZz9w8F9DCuHt28N1CQA3z9JLDlFaCooH6KJiKyQgxARLXM3UmNmKkRaONZEoL23zsEOXoA478D7ptp/PnASmDdUCDzap3XS0RkjRiAiOqAm6OxJaitpxPSso0h6K97hSClDfDgAuCJGECtBa7EG6fK//VbvdRMRGRNGICI6ogxBIWbQtDoyoQgAAgaAkzbCXh1AvKuA/97FNj1NlePJiKqRQxARHXItTgEBXndbgn6M60SIahpIPD0NiBkPAAB/Po6EPMEkHejzmsmIrIGDEBEdczVUY0vJhtD0LVsHUZ/XMkQZGsHPPIB8MiHgI0GOL8VWN0HuHqk7osmImrkGICI6oFr8ZigkhBkbAnKrtyHQ8YBT8cBLoFARpJx9ehDa7h6NBFRDTAAEdWTpg4qfDklAsHezrieo8MTqw9UPgR5dzKuHt12KKAvAH6cCXz3DFBQwVPoiYjorhiAiOpRUwcVvpwcbhaCzv9dyRBk1wR44gvgwYWApACOxQCfPAik/1WnNRMRNUYMQET1zKU4BLUrDkGjP95f+RAkScB90cDEHwAHDyDtJPBRH+DUpjqtmYiosWEAIpKBi4MKX0wOR3sfZ1zPKcDoj/fjXGVDEAA0v8+4erR/T6AgG9gwHtj0AnBmM5CdWneFExE1EpIQHEl5p6ysLGi1WmRmZsLZ2VnucqgRy8grwNhPDuBkchZcHVTFK0g7Vf4E+kLgl4XA3vfN9zv5AM1CAZ+Q2/9r51K7xRMRWZiq/P1mACoHAxDVp4y8Aoz79ABOXDWGoC+nRKCtVxVCEAD8ud34ENWrR4wPVUU5/1o3bQH4hBYHolDjwGqVQ61cAxGRJWAAqiEGIKpvtRKCSuhygJRjQPIRYyBKPgLcvFT2OEkBuAcDzUJuByOP9oCNqkbXQkQkFwagGmIAIjlk5hVi3KcHcPxqZvGU+XAEedXSP395N4oD0dHbwSinnLFCSjXg1cG8pcitNaBQ1k4dRER1iAGohhiASC6ZeYUYv+YA/rhiDEFfFE+ZrxNZybdbiK4eAZKPAvkZZY9TOQLeXcxbipoEGGekERFZEAagGmIAIjmVDkEu9ramxRPrnBDAjQvGIFQSjFKOAYXlLLZo1/R2C1HJ/zp51n2NRER3wQBUQwxAJLfMW4UY/+ntEPTF5Ai085Hhn0V9EXD97O1AlHwUSD0BGArLHuvcrNSss5KZZ03qvWQisl4MQDXEAESWIPNWISZ8egDH5A5BdyrSAX+fuN1tdteZZy3NQ5F3Z0BlX+8lE5F1YACqIQYgshSZtwoxYU08jl3OQBN72+LFE7Vyl1UWZ54RkQVgAKohBiCyJFn5hRj/6e0Q9PnT4ejQzAJD0J2qO/PMu7NxzSJbu/qvmYgaNAagGmIAIkuTlV+ICZ/GI+FyBrR2xpagBhGC7lTZmWcA4ORtDEIugUDT5qVeB3JVayIqFwNQDTEAkSXKyi/ExDXxOJrUwENQaeXNPPv7FKDLvPvn7Fxuh6HSwahpC8DRk1P0iawUA1ANMQCRpcrON44JalQh6E5CALduAjcuGsPRzYvmr3P+vvvnbe0Bl+bFwai5eUjS+gFKm/q4CiKSAQNQDTEAkSXLLm4JOpKUAWeNDb6YHIGOvo0sBN2NLsc4wPpmcSi6cfH268wrgDBU/FmFDdDEv/zWI5fmHHdE1MAxANUQAxBZuuz8QkxaexCHE2/CWWODzyeHo5NvE7nLkl9RAZB5uWwwunHRGJr0urt/3snHGIqaNi8ORi2Kw1Eg1zQiagAYgGqIAYgaghxdESauiWcIqiyDAchOLicYFXex6bLu/nm7prfDUOlg1LQF4OjBcUdEFoABqIYYgKihyNEVYdKaeBxKvAmlQkI7b2eEBbggNMAFYQEu8NFqIPEP870JYZy2X1632o2LQG7a3T9v61BqvFHg7W61JgGA1hewUdfLZRBZOwagGmIAooYkR1eEZz4/jN3nr5d5z9NZbQxE/sZA1N5HC5WNQoYqGzhdzu2WojtD0r3GHQGAoxfQxM84CLuJf/Fr/9uvVQ71cx1EjRwDUA0xAFFDlJxxC0eSbuJw4k0cSbyJk8lZKDKY/+uttlGgk6/W2ELkb2wpcnNk60SNFBUAGUnld6tlXi7/YbJ3smt6Oww1CSgOSsVhSevH8UdEldSgAtCKFSvw9ttvIyUlBe3bt8eyZcvQu3fvCo/fuXMnZs2ahZMnT8LHxwf//Oc/MX36dNP769atw5NPPlnmc7du3YJGo6lUTQxA1BjcKtDjjysZOJxkDESHE2/iZl7Zh5g2d7VHqP/tbrM2nk5QKthtVitKutYyEo1hKOOyMSyVfn2vNY8AQO18OwyVDkYlgcnelWOQiFC1v9+yLogRGxuL6OhorFixAr169cJHH32EwYMH49SpU/D39y9z/MWLFzFkyBBMmTIFn3/+Ofbs2YNnn30W7u7uGDlypOk4Z2dnnD171uyzlQ0/RI2FnUqJ8BauCG/hCgAQQuDi9VwcScowtRKdS8vGpfQ8XErPw8ajVwEAjmobhPg3MXWbdfFvAmeNrZyX0nBJEuDgatyahZZ/zK2M24EoszgUmUJSEpCXbhyg/fcJ41YeW/vbgcjUzeZ/+7WjJ6Bg1ydRabK2AIWHhyM0NBQrV6407QsODsbw4cOxePHiMse//PLL2LRpE06fPm3aN336dBw7dgz79u0DYGwBio6ORkZGRrXrYgsQWYvMW4VIuHw7EB1NuoncAr3ZMZIEtPV0QkhxIAoLcEFzV3sOrq4vBbnGcUYlwejOFqTynq92J6UKcG5WcTebkw8XiKRGoUG0ABUUFODw4cN45ZVXzPZHRkZi79695X5m3759iIyMNNs3cOBAfPrppygsLIStrfG/UnNychAQEAC9Xo8uXbrgtddeQ0hISIW16HQ66HS31wfJyrrHdFiiRkJrZ4s+bdzRp407AEBvEDibmm3WbZZ0Iw9nUrNxJjUbMfFJAICmDipTC1FYgAs6+WqhsVXKeSmNl8oBcG9r3MpTmA9kXTVvNSrdmpR1FdAXGMcl3bxY/jkkJeDsU0E3mz9nslGjJFsAun79OvR6PTw9Pc32e3p6IjW1/P+iSU1NLff4oqIiXL9+Hd7e3ggKCsK6devQsWNHZGVl4T//+Q969eqFY8eOoXXr1uWed/HixVi4cGHtXBhRA6ZUSGjn44x2Ps4YHxEAALiWrcORUoHoj6uZuJFbgO2n/8b208bHUtgoJLRvpi0eWN0EYQEu8NZyVeV6YasBXFsat/LoC40PoTUbg5RU6vUVwFBofD/zcsXf4+hVagZbqW62kqCksq+b6yOqI7K3ed7ZjC6EuGvTennHl94fERGBiIgI0/u9evVCaGgo3n//fSxfvrzcc86ePRuzZs0y/ZyVlQU/P7+qXQhRI+XupMbA9l4Y2N4LAKAr0uNkcpYpEB1KvIlr2Tocu5yBY5czsGaP8XM+Wo1pYHVYgAuCvZ1hq+Q4lHqntAVcAoxbeQwGYzeaqdUo8Y7xSJeBolvGY3JSgSvx5Z/H3tW81cjstR+gsaLHtVCDIFsAcnNzg1KpLNPak5aWVqaVp4SXl1e5x9vY2MDV1bXczygUCnTr1g3nz5+vsBa1Wg21ms27RJWhtlEaZ435u2Byb+N/hFy5eet2K1HSTZxOyUZyZj6S/0jBj3+kAAA0tgp09m1iWpcoNMAFTR1UMl8NQaEwdn85+wAIL/u+EEDu9Ttaje6Y0abLMg7WzksHko+W/z1qbTktSCVdbP6AfVPOZKN6JVsAUqlUCAsLQ1xcHB599FHT/ri4ODzyyCPlfqZHjx744YcfzPZt27YNXbt2NY3/uZMQAgkJCejYsWPtFU9EJpIkwa+pPfya2uORLs0AALm6Ihy7kmFqJTqSlIHMW4U4cPEGDly8YfpsCzcHs1aiVu6OUHAKvmWRJMDR3bg1Cyv/mFsZ5QSjUoHp1g3jdP+/jxu38tjaVzAGKcD4s4MHZ7JRrZJ1FlhsbCzGjx+PVatWoUePHli9ejU+/vhjnDx5EgEBAZg9ezauXr2Kzz77DIBxGnyHDh0wbdo0TJkyBfv27cP06dMRExNjmga/cOFCREREoHXr1sjKysLy5cvxv//9D3v27EH37t0rVRdngRHVLoNB4ML1HBwuFYj+TMspc5yTxgYdm2nh5ayBu7Ma7o5qeDhr4OGkNm7OGjiqZe+5p6rS5ZSa6p9UdqB2zt/3PodSdcdU/wDzoOTkzZls1DBmgQFAVFQU0tPTsWjRIqSkpKBDhw7YvHkzAgKMfdUpKSlISkoyHR8YGIjNmzdj5syZ+PDDD+Hj44Ply5ebrQGUkZGBqVOnIjU1FVqtFiEhIdi1a1elww8R1T6FQkIrDye08nBCVDfjGl8ZeQU4Wrwm0eHEm0i4nIHs/CLs/Sv9rueyVymLA5ExJJW8Ngak4v1OarjY23KqvqVQOwIewcatPKaZbOWMP8pIMj7EVl8A3PjLuJVHUgLaZuaPGCnd1ebsC9iwy5Vuk30laEvEFiCi+lekN+B0SjbOp2UjLVuHtCwd0rLzkZatw7VsHdKy8susUXQ3tkoJ7o5quJduQXLSFIek269dHVSw4eBsy1Yyk62ibraSmWx3JRlbiSp6JpvWlzPZGoEG9SgMS8QARGSZcnVFxeHIGIxM4Sg7vzgkGV+X98iPikgS4OqggrtT6a628luVuNaRhTLojd1oZsHojm62ovx7n8fB/Y4xSP7m3Wwa/j2wdAxANcQARNSw6Yr0uJ5TYB6USr0uCUzXcwqgN1T+/wKdNTZmY5LcS7UklX7tpLZh95slMZvJllR+N1tB9r3Po9GWCkblrIlk58KZbDJjAKohBiAi66A3CNzILbjd1Vaq2610F1xatg4FRYZKn1djq4CHkwZujiq4Oqrh5qiGe6nXJfvdHdVwtmNYkp0QQH5GOdP8E28HpVs3730eW4fyxx+VBCZHDwakOsYAVEMMQERUmhACWbeKbne1FbciGUOSzixAZeuKqnRuW6UEVwc13JxUcHNUm167O6rh6qgqDkzG103tOV5JNqaZbHc8rLYkNOWm3fscSrVxrNGdayCZnsnmDSjYzVoTDEA1xABERNV1q0BfqovN2M1m/F8d0k2vjf+bnV+1sCRJQFN7VZlg5FbcmuTmpCoOUMbB3RyzVI8K84sfWptYdqHIjCQgOwUQ92hFVNgUP5MtoJz1kDiTrTIYgGqIAYiI6kN+oR7puQVILw5I17MLcD23+H9zdEgv9fpGXgGq+v/WTmobuDkVd7mVbmUq7pIree3mqIIjxy3VLX3h7YfW3hmOSh5aa7hXIC41k+3OR42UtCTZWvcz+BiAaogBiIgsTcl4JfOWpIpamHQo1Fft/9rVNgrT+CS3crrfjC1MxpYlF3sVV+yubQY9kJ1aNhiVvM68UsWZbCVdawHmC0g28plsDEA1xABERA2ZEAJZ+UXFrUrGkGRsTdLhWk6pFqfi11VZXwkAlAoJTR1UZoHJ7Y5B3qXDEx+CWwuEAHKvlT8GqeR1QdnV1cvQNCkbjEq3JjXwmWwMQDXEAERE1uRWgb5Mi1J68etrpV5fz9EhowprLJXQ2tmahSK3O7rf3JzUcCvuorNX8XEW1SKEcaZaeQ+rLQlN+Rn3Po/K8Y6utVLT/Jv4G1uYLDggMQDVEAMQEVH5CvUG3MgtwLVsHdJzC4pbmG6/vlaqKy49t2rrLAHGR524lhOW7uyWc3NUQWvHx51UiS67/GBUEpgqM5PNRnN7JpupBalUa5LMM9kYgGqIAYiIqOYMBoHMW4W4nmMejEqPVyrdJZdfWPm1loDbSwiUG5hKZsQVv+YSApVQeKt4JltS+S1JWckA7hEZFDaAc7PbLUZ3tiZpfQGlbZ1dAgNQDTEAERHVLyEEcgv0pjB0LbvAbBaceWiq3hICLvaqUjPizMcv3dnKxCUEylFUYJytVt74o8rOZJMUxlYirR/QLBQYtLhWS2wwT4MnIiICAEmS4Ki2gaPaBgGuDvc8Xlekv93VVjxW6c6ZcCWvb+QWwCCAG7kFuJFbAODeg4Wd1DblrrdkHK9UPG6peL/VPPrERgU0DTRu5THojesdmYJRYtnHjuh1xqCUddUYhmTEAERERA2O2kYJnyZ28Gly73VvSpYQKGlRSs/VmZ4Fd+eMuOs5BSjQG5CtK0K2rgiX0vPueX6VjeKOlbvLnxHn5qhCE3sVlI11CQGF0tjFpfUF0KPs+3fOZFPdO+jWJXaBlYNdYERE1qlkCYH0O2bEXbtjdlxJC1NOFR99opCApg5lu9/KmxHn6qCGyobjlqqCXWBERETVIEkStHa20NrZooX7vY8vWUKg9Iy4ihaovJlXCIOAaT9w7yfQO2tsTN1tFc2IK2l9clDzT3pV8LdFRERUTXYqJfya2sOvqf09jy3UG3Azt2S8knn3m+l/s42PQEnPKUCRwdgalZVfhAvXcu9di63SbPabu+m1qngVb+M+N0c1lxAAAxAREVG9sFUq4OGsgYez5p7HliwhYByvVLb77brZ41CMSwjcKtTj8o1buHzj1j3Pb6OQyn/cSTnrLTV1aJxLCDAAERERWRiFQoKLgwouDiq08rj38bm6ors+G+72g3Z1yMovQpFB4O8sHf7O0t3z3CVLCLg63J4J5+qggrvZg3Zvd9E1lCUEGICIiIgaOAe1DRyqsITAjdwCszWW7nwESsm+G7k6syUEzqfdewkBR7VNqZlw5S1SeTtAOWnqblHEe2EAIiIisiJqGyW8tXbw1lZuCYGbeQVmrUkVPQalZAmBHF0RciqxhECQlxN+jr6/ti6ryhiAiIiIqFxKhWRqwWkLp7seK4RAtq7IFIZMq3pXsN6Su5O6nq6ifAxAREREVGOSJMFZYwtnTeWWECjSV+3Zb7Wt8Q3rJiIiIosn98wyBiAiIiKyOgxAREREZHUYgIiIiMjqMAARERGR1WEAIiIiIqvDAERERERWhwGIiIiIrA4DEBEREVkdBiAiIiKyOgxAREREZHUYgIiIiMjqMAARERGR1WEAIiIiIqtjI3cBlkgIAQDIysqSuRIiIiKqrJK/2yV/x++GAagc2dnZAAA/Pz+ZKyEiIqKqys7OhlarvesxkqhMTLIyBoMBycnJcHJygiRJtXrurKws+Pn54fLly3B2dq7Vc1PV8X5YFt4Py8L7YXl4T+5OCIHs7Gz4+PhAobj7KB+2AJVDoVDA19e3Tr/D2dmZ//BaEN4Py8L7YVl4PywP70nF7tXyU4KDoImIiMjqMAARERGR1WEAqmdqtRrz58+HWq2WuxQC74el4f2wLLwflof3pPZwEDQRERFZHbYAERERkdVhACIiIiKrwwBEREREVocBiIiIiKwOA1A9WrFiBQIDA6HRaBAWFobdu3fLXZJVWLx4Mbp16wYnJyd4eHhg+PDhOHv2rNkxQggsWLAAPj4+sLOzQ9++fXHy5EmZKrYuixcvhiRJiI6ONu3j/ah/V69exbhx4+Dq6gp7e3t06dIFhw8fNr3Pe1J/ioqKMHfuXAQGBsLOzg4tWrTAokWLYDAYTMfwftQCQfVi/fr1wtbWVnz88cfi1KlT4sUXXxQODg4iMTFR7tIavYEDB4q1a9eKEydOiISEBDF06FDh7+8vcnJyTMe8+eabwsnJSXzzzTfi+PHjIioqSnh7e4usrCwZK2/84uPjRfPmzUWnTp3Eiy++aNrP+1G/bty4IQICAsSkSZPEgQMHxMWLF8X27dvFn3/+aTqG96T+vP7668LV1VX8+OOP4uLFi+Krr74Sjo6OYtmyZaZjeD9qjgGonnTv3l1Mnz7dbF9QUJB45ZVXZKrIeqWlpQkAYufOnUIIIQwGg/Dy8hJvvvmm6Zj8/Hyh1WrFqlWr5Cqz0cvOzhatW7cWcXFxok+fPqYAxPtR/15++WVx3333Vfg+70n9Gjp0qHjqqafM9o0YMUKMGzdOCMH7UVvYBVYPCgoKcPjwYURGRprtj4yMxN69e2WqynplZmYCAJo2bQoAuHjxIlJTU83uj1qtRp8+fXh/6tBzzz2HoUOH4sEHHzTbz/tR/zZt2oSuXbvi8ccfh4eHB0JCQvDxxx+b3uc9qV/33XcffvnlF5w7dw4AcOzYMfz+++8YMmQIAN6P2sKHodaD69evQ6/Xw9PT02y/p6cnUlNTZarKOgkhMGvWLNx3333o0KEDAJjuQXn3JzExsd5rtAbr16/HkSNHcPDgwTLv8X7UvwsXLmDlypWYNWsW/vWvfyE+Ph4vvPAC1Go1JkyYwHtSz15++WVkZmYiKCgISqUSer0eb7zxBkaPHg2A/47UFgageiRJktnPQogy+6huPf/88/jjjz/w+++/l3mP96d+XL58GS+++CK2bdsGjUZT4XG8H/XHYDCga9eu+Pe//w0ACAkJwcmTJ7Fy5UpMmDDBdBzvSf2IjY3F559/ji+//BLt27dHQkICoqOj4ePjg4kTJ5qO4/2oGXaB1QM3NzcolcoyrT1paWllEjzVnRkzZmDTpk347bff4Ovra9rv5eUFALw/9eTw4cNIS0tDWFgYbGxsYGNjg507d2L58uWwsbEx/c55P+qPt7c32rVrZ7YvODgYSUlJAPjvSH37v//7P7zyyit44okn0LFjR4wfPx4zZ87E4sWLAfB+1BYGoHqgUqkQFhaGuLg4s/1xcXHo2bOnTFVZDyEEnn/+eWzcuBG//vorAgMDzd4PDAyEl5eX2f0pKCjAzp07eX/qQP/+/XH8+HEkJCSYtq5du2Ls2LFISEhAixYteD/qWa9evcosDXHu3DkEBAQA4L8j9S0vLw8KhfmfZ6VSaZoGz/tRS2QcgG1VSqbBf/rpp+LUqVMiOjpaODg4iEuXLsldWqP3zDPPCK1WK3bs2CFSUlJMW15enumYN998U2i1WrFx40Zx/PhxMXr0aE4prUelZ4EJwftR3+Lj44WNjY144403xPnz58UXX3wh7O3txeeff246hvek/kycOFE0a9bMNA1+48aNws3NTfzzn/80HcP7UXMMQPXoww8/FAEBAUKlUonQ0FDTNGyqWwDK3dauXWs6xmAwiPnz5wsvLy+hVqvF/fffL44fPy5f0VbmzgDE+1H/fvjhB9GhQwehVqtFUFCQWL16tdn7vCf1JysrS7z44ovC399faDQa0aJFCzFnzhyh0+lMx/B+1JwkhBBytkARERER1TeOASIiIiKrwwBEREREVocBiIiIiKwOAxARERFZHQYgIiIisjoMQERERGR1GICIiIjI6jAAERFVQJIkfPfdd3KXQUR1gAGIiCzSpEmTIElSmW3QoEFyl0ZEjYCN3AUQEVVk0KBBWLt2rdk+tVotUzVE1JiwBYiILJZarYaXl5fZ5uLiAsDYPbVy5UoMHjwYdnZ2CAwMxFdffWX2+ePHj+OBBx6AnZ0dXF1dMXXqVOTk5Jgds2bNGrRv3x5qtRre3t54/vnnzd6/fv06Hn30Udjb26N169bYtGmT6b2bN29i7NixcHd3h52dHVq3bl0msBGRZWIAIqIG69VXX8XIkSNx7NgxjBs3DqNHj8bp06cBAHl5eRg0aBBcXFxw8OBBfPXVV9i+fbtZwFm5ciWee+45TJ06FcePH8emTZvQqlUrs+9YuHAhRo0ahT/++ANDhgzB2LFjcePGDdP3nzp1Clu2bMHp06excuVKuLm51d8vgIiqT+6nsRIRlWfixIlCqVQKBwcHs23RokVCCCEAiOnTp5t9Jjw8XDzzzDNCCCFWr14tXFxcRE5Ojun9n376SSgUCpGamiqEEMLHx0fMmTOnwhoAiLlz55p+zsnJEZIkiS1btgghhHjooYfEk08+WTsXTET1imOAiMhi9evXDytXrjTb17RpU9PrHj16mL3Xo0cPJCQkAABOnz6Nzp07w8HBwfR+r169YDAYcPbsWUiShOTkZPTv3/+uNXTq1Mn02sHBAU5OTkhLSwMAPPPMMxg5ciSOHDmCyMhIDB8+HD179qzWtRJR/WIAIiKL5eDgUKZL6l4kSQIACCFMr8s7xs7OrlLns7W1LfNZg8EAABg8eDASExPx008/Yfv27ejfvz+ee+45vPPOO1WqmYjqH8cAEVGDtX///jI/BwUFAQDatWuHhIQE5Obmmt7fs2cPFAoF2rRpAycnJzRv3hy//PJLjWpwd3fHpEmT8Pnnn2PZsmVYvXp1jc5HRPWDLUBEZLF0Oh1SU1PN9tnY2JgGGn/11Vfo2rUr7rvvPnzxxReIj4/Hp59+CgAYO3Ys5s+fj4kTJ2LBggW4du0aZsyYgfHjx8PT0xMAsGDBAkyfPh0eHh4YPHgwsrOzsWfPHsyYMaNS9c2bNw9hYWFo3749dDodfvzxRwQHB9fib4CI6goDEBFZrJ9//hne3t5m+9q2bYszZ84AMM7QWr9+PZ599ll4eXnhiy++QLt27QAA9vb22Lp1K1588UV069YN9vb2GDlyJN577z3TuSZOnIj8/HwsXboUL730Etzc3PDYY49Vuj6VSoXZs2fj0qVLsLOzQ+/evbF+/fpauHIiqmuSEELIXQQRUVVJkoRvv/0Ww4cPl7sUImqAOAaIiIiIrA4DEBEREVkdjgEiogaJvfdEVBNsASIiIiKrwwBEREREVocBiIiIiKwOAxARERFZHQYgIiIisjoMQERERGR1GICIiIjI6jAAERERkdVhACIiIiKr8/+cS/TzWNxqxQAAAABJRU5ErkJggg==\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Plot the loss curves\n", "plt.plot(epoch_count, train_loss_values, label=\"Train loss\")\n", "plt.plot(epoch_count, test_loss_values, label=\"Test loss\")\n", "plt.title(\"Training and test loss curves\")\n", "plt.ylabel(\"Loss\")\n", "plt.xlabel(\"Epochs\")\n", "plt.legend();" ] }, { "cell_type": "code", "execution_count": 15, "id": "9dd7076e-6115-4de0-9cc3-0a2c9cc076f6", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The model learned the following values for weights and bias:\n", "OrderedDict([('weights', tensor([0.6178])), ('bias', tensor([0.3428]))])\n", "\n", "And the original values for weights and bias are:\n", "weights: 0.7, bias: 0.3\n" ] } ], "source": [ "# Find our model's learned parameters\n", "print(\"The model learned the following values for weights and bias:\")\n", "print(model_0.state_dict())\n", "print(\"\\nAnd the original values for weights and bias are:\")\n", "print(f\"weights: {weight}, bias: {bias}\")" ] }, { "cell_type": "markdown", "id": "7bd562fd", "metadata": {}, "source": [ "## Testing the Model\n", "\n", "We can now evaluate the trained model. We see that it very nearly approximates the values in the testing set." ] }, { "cell_type": "code", "execution_count": 16, "id": "b965b5a3-4aed-4fd6-ad74-038113c05623", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "tensor([[0.8247],\n", " [0.9482],\n", " [0.5899],\n", " [0.3552],\n", " [0.9112],\n", " [0.5281],\n", " [0.3799],\n", " [0.7258],\n", " [0.8864],\n", " [0.4540]])" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 1. Set the model in evaluation mode\n", "model_0.eval()\n", "\n", "# 2. Setup the inference mode context manager\n", "with torch.inference_mode():\n", " # 3. Make sure the calculations are done with the model and data on the same device\n", " # in our case, we haven't setup device-agnostic code yet so our data and model are\n", " # on the CPU by default.\n", " # model_0.to(device)\n", " # X_test = X_test.to(device)\n", " y_preds = model_0(X_test)\n", "y_preds" ] }, { "cell_type": "code", "execution_count": 17, "id": "c24e631f-b161-44fd-94ef-758c315bfc24", "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAzoAAAJGCAYAAACTJvC6AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABUXUlEQVR4nO3de3hTVb7/8U9IacutYQCphZZSFYQRRSkDAiKJYBlwSNHj0BlmEBQcOV4YylEOHFQuo1NRBtEqeAWG8cYoSKMyjHVMucpPYdCjgDcuFrBQQUlRoEDYvz/2aWpsC01pm2T3/XqePNus7L3zTd3lyadr7bVshmEYAgAAAAALaRTuAgAAAACgthF0AAAAAFgOQQcAAACA5RB0AAAAAFgOQQcAAACA5RB0AAAAAFgOQQcAAACA5cSEu4DqOH36tL7++mu1aNFCNpst3OUAAAAACBPDMHTkyBG1a9dOjRpV3W8TFUHn66+/VkpKSrjLAAAAABAh9uzZo+Tk5Cpfj4qg06JFC0nmh0lISAhzNQAAAADCpaSkRCkpKYGMUJWoCDplw9USEhIIOgAAAADOeksLkxEAAAAAsByCDgAAAADLIegAAAAAsByCDgAAAADLIegAAAAAsByCDgAAAADLiYrppWvC7/fr5MmT4S4DCIvGjRvLbreHuwwAAICwsVzQMQxD+/fvl8/nk2EY4S4HCAubzSaHw6Hzzz//rHPMAwAAWFHIQWfNmjV65JFHtHnzZhUVFen111/X8OHDz3jM6tWrNWnSJG3dulXt2rXT5MmTNX78+JrWfEY+n0+HDx/Weeedp2bNmvElDw2OYRj64Ycf9M0336hJkyZq2bJluEsCAACodyEHnR9++EHdu3fXzTffrP/4j/846/67du3S0KFDdeutt+qFF17Q+vXrdfvtt+u8886r1vGhMAxDxcXFSkhIUJs2bWr13EA0adKkiUpLS1VcXCyHw0HgBwAADU7IQWfIkCEaMmRItfd/6qmn1KFDB82bN0+S1LVrV23atElz5syp9aDj9/vl9/uVkJBQq+cFolFCQoJKSkrk9/sVE2O5UaoAAABnVOezrr333nvKyMgIahs8eLA2bdpU5WQBpaWlKikpCXpUx6lTpySJL3WAyn8Pyn4vAAAAGpI6Dzr79+9XYmJiUFtiYqJOnTqlgwcPVnpMTk6OHA5H4JGSkhLSezJMB+D3AAAANGz1so7OT79wlc2GVtUXsalTp8rn8wUee/bsqfMaAQAAAFhHnY/xOv/887V///6gtuLiYsXExKh169aVHhMXF6e4uLi6Lg0AAACARdV5j06fPn2Un58f1Pb222+rZ8+eaty4cV2/PeqBzWaT0+k8p3MUFBTIZrNpxowZtVJTXauNzwwAAIC6E3LQ+f777/Xhhx/qww8/lGROH/3hhx+qsLBQkjns7KabbgrsP378eH311VeaNGmStm/froULF+r555/X3XffXTufAJLML96hPBB+HTt2VMeOHcNdBgAAgCWFPHRt06ZNcrlcgeeTJk2SJI0ePVqLFy9WUVFRIPRIUlpamlauXKns7Gw9+eSTateunR5//PFan1q6oZs+fXqFtpkzZ8rhcGjixIl1+t7bt29X06ZNz+kcvXr10vbt21n/CAAAALXCZpTNDBDBSkpK5HA45PP5zrhGzvHjx7Vr1y6lpaUpPj6+HiuMTDabTampqdq9e3e4S7Ecm82mAQMGqKCgoMbnKOvNqav/P/w+AAAAK6puNqiXWdcQOXbv3i2bzaYxY8bo008/1Q033KA2bdrIZrMFvnC//vrr+u1vf6uLLrpITZs2lcPhUP/+/bVs2bJKz1nZ/SpjxowJnHP+/Pnq2rWr4uPjlZqaqpkzZ+r06dNB+1d1j07Z8K4ffvhBkyZNUvv27RUXF6fLLrtMr732WpWfMSsrS61atVLz5s01YMAArVmzRjNmzJDNZgspnDz33HPq1q2b4uPjlZKSosmTJ+v48eOV7rt582bdeeed6tatmxwOh5o0aaJLL71UDz30UNCaUWX/D7766it99dVXQUMKyz7/iRMnlJubq8GDByslJUVxcXFq27atbrjhBm3ZsqXa9QMAADRUrKzZQH355Ze68sordckll2j06NH69ttvFRsbK8m8zyo2NlZXXXWVkpKS9M0338jj8ejGG2/U448/rrvuuqva73PPPfeooKBAv/rVr5SRkaEVK1ZoxowZOnHihB588MFqnePkyZPKyMjQt99+qxtuuEFHjx7VK6+8ohEjRmjVqlVBC9Lu27dPffv2VVFRkYYOHaru3bvrs88+U0ZGRtCQy+r405/+pPvvv1+JiYm69dZb1bhxYy1dulTbt2+vdP9nn31Wb7zxhq6++moNHTpUR48eVUFBgaZOnaoPPvggEBRbtmyp6dOna968eZIUNLSwLDB+++23mjhxovr376+hQ4fqZz/7mXbu3CmPx6N//OMfWrNmjX7xi1+E9HkAAABqbK9HOuCVEl1Ssjvc1VSPEQV8Pp8hyfD5fGfc79ixY8a2bduMY8eO1VNlkU2SkZqaGtS2a9cuQ5IhybjvvvsqPW7Hjh0V2o4cOWJceumlhsPhMH744YcK7zNgwICgttGjRxuSjLS0NOPrr78OtH/zzTdGy5YtjRYtWhilpaWBdq/Xa0gypk+fHnSe1NRUQ5KRmZkZtP8777xjSDIGDx4ctP/vf/97Q5LxyCOPBLUvWrQo8Lm9Xm+ln/vHvvjiCyMmJsZo3769ceDAgUC7z+czLr744ko/8+7du41Tp04FtZ0+fdq45ZZbDEnGunXrKny2n/7/KXP8+HFj7969Fdo/+eQTo3nz5sagQYPO+hn4fQAAALViT55hvCjDeMlubvfkhbWc6mYDhq41UOeff77uvffeSl+74IILKrQ1b95cY8aMkc/n0wcffFDt97nvvvuUlJQUeN6mTRtlZmbqyJEj+uyzz6p9nkcffTTQ4yRJAwcOVGpqalAtpaWlevXVV5WYmKgJEyYEHT969Gh16dKl2u/30ksv6dSpU5o0aZLatm0baE9ISKjy55aamiq73R7UZrPZdMcdd0iS3nnnnWq/f1xcnNq3b1+h/ZJLLpHL5dKaNWuChsMBAADUmQNeyWaXDL+5PVAQ7oqqhaBTQx6PlJ1tbqNR9+7dg4LDjxUXF2vSpEnq2rWrmjZtGrh/5L/+678kSV9//XW136dHjx4V2pKTkyVJhw8frtY5WrZsqbS0tErP8+NzfPbZZyotLVXPnj0rfDabzaY+ffpUu+6PPvpIktS/f/8Kr1XWJpn31cydO1e9evVSQkKCGjVqJJvNpvT0dEmh/dwk6cMPP9TIkSPVoUMHxcbGBv4/vPHGGzpx4oQOHjwY0vkAAABqJNFVHnIMv5ToDHdF1cI9OjXg8UiZmZLdLs2bJ+XlSe4oGapYJjExsdL2b7/9Vr/4xS9UWFiofv36adCgQWrZsqXsdrs+/PBD5eXlqbS0tNrv43A4KrTFxJiXnd/vr/E5ys7z40kNSkpKJEnnnXdepftX9Zkr4/P5JCmoN+ds57nxxhv1xhtvqHPnzsrKylLbtm3VuHFjHT58WI899lhIP7cNGzbommuukSRlZGSoU6dOat68uWw2m1asWKGPPvoopPMBAADUWLJbujrP7MlJdEbNPToEnRrwes2Q4/eb24KC6As6VS0a+vzzz6uwsFAPPPCApk2bFvTaQw89pLy8vPoor0bKphf85ptvKn39wIED1T5XWbgqLi5WamrqWc/zwQcf6I033tDgwYP11ltvBQ1h27hxox577LFqv7ckPfjggyotLdW6devUr1+/oNc2btwY6HECAACoF8nuqAk4ZRi6VgMuV3nI8fuln8ysHNV27NghSXJXktzWrl1b3+WE5OKLL1ZcXJw2b96sEydOBL1mGIY2btxY7XN1795dUuWfubK2sp/bddddV+E+nap+bna7vcperR07dqhVq1YVQs7Ro0f173//++wfAAAAoIEj6NSA220OV5swITqHrZ1JWe/FunXrgtpfeuklrVy5MhwlVVtcXJxuvPFG7d+/X48//njQa0uWLKlyWujKjBw5Una7XXPnzlVxcXGgvaSkRA888ECF/av6uW3dulU5OTmVvkerVq108ODBStflSU1N1XfffaetW7cG2vx+v+6+++4qe6wAAABQjqFrNeR2WyvglBk1apRmz56tu+66S16vV6mpqfrf//1fvfPOO7rhhhu0fPnycJd4Rjk5OXrnnXd0zz33yOv16vLLL9dnn32mN998U7/85S+1atUqNWp09nx/0UUX6f7779f06dN12WWXacSIEYqJidGyZct06aWXVpgxrlevXurVq5f+/ve/q6ioSFdeeaUKCwvl8Xh03XXXVbq46TXXXKNNmzZp2LBh6t+/f2Dtoquuukp33XWX3n77bV111VUaMWKE4uPjVVBQoH379snpdIa06CkAAEBDRI8OgiQnJ2v16tUaOHCg3nnnHT399NMqLS3V22+/rWHDhoW7vLNKSUnRe++9p1//+tdav3695s2bp+LiYr399tu66KKLJJXfy3M2999/v5599lm1bt1aTz/9tF599VWNGDFCr776aoV97Xa73nzzTd1yyy3asWOHcnNztW3bNs2ZM0cPP/xwpee/7777dOutt2rr1q2aOXOmpk6dGpiC+le/+pVee+01XXDBBXrhhRf00ksvqUuXLnr//fcr3DMEAACAimyGYRjhLuJsSkpK5HA45PP5zvgl9fjx49q1a5fS0tIUHx9fjxUiGlx11VV677335PP51Lx5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JZKk8847r8L+jRo1Ups2bar1fj6fT5LUtm3bSl9PTEys0Pbll1+qV69eKikpkcvl0rBhw5SQkKBGjRqpoKBAq1evrhB8zmTChAl64oknlJKSIrfbraSkJMXFxUkyJzAI5VwAACDKJLrMP5aXfZ9MdIa7Iksi6NRElF6cCQkJkqT09HRt2rSpWsc0a9ZMDz74oB588EHt2rVLXq9XTz31lB577DEdO3ZMTz/9dF2WHKSs/m+++abCa6dPn9bBgwertU5P2XmKi4srff3AgQMV2h599FF99913euGFF/S73/0u6LXx48dr9erVZ33fMsXFxXryySd12WWX6b333gsKi/v37z9jCAUAABaQ7DZHBB0oML9HRsEfzKMR9+jURNnF2XlC1Axbk8yemK5du2r79u1BQ8KqKy0tTbfccotWr16t5s2by/OjqQXL7uH5cQ9MbevevbskacOGDRVee//993Xq1KlqnSchIUFpaWn68ssvtX///gqvr127tkLbjh07JEnun3TZnj59WuvXr6+w/5l+Hjt37pRhGBo0aFCFHrHK3hsAAFhQsltKnxs13yOjEUGnpqL04pwwYYKOHj2qW2+9NWiIWpldu3YF1nr55ptv9P7771fY57vvvlNpaamaNGkSaGvVqpUkae/evXVTuKTMzEw1b95czz33nHbt2hVoP3XqlO67776QzjVq1CidOHFC999/f1D722+/Xen9OWX33qxbty6offbs2frkk08q7H+mn0fZuTZs2BB0X87evXs1ZcqUkD4HAAAAKsfQtQbmtttu08aNG/XXv/5V69ev16BBg9SuXTsdOHBAn376qf7f//t/eumll9SxY0ft27dPvXv31iWXXKIePXqoffv2OnTokPLy8nTy5ElNnjw5cN4+ffqoSZMmmjdvnkpKSgL30dTmF/eWLVtq7ty5+sMf/qAePXooKysrsI5OXFyc2rVrp0aNqpfdJ0+erOXLl+vZZ5/V1q1bdfXVV2vPnj36+9//ruuuu05vvfVW0P7jx4/XokWLdMMNNygrK0utW7fWxo0b9e9//7vS/bt06aJ27drplVdeUdOmTZWcnCybzab//M//DMzUtmzZMvXs2VMDBw7UgQMH9Oabb+qaa67Rzp07a+1nBgAA0FARdBoYm82mxYsXa+jQoXr22Wf15ptv6vvvv1fbtm3VqVMnzZkzR4MG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VenVq5dKS0u1evXqs+5bdv1UNzwkJCToggsu0Jdffql9+/ZVeL3sPS+//PJq13smrVu31vDhw7V06VJdc8012r59u7788staOTcAAAjWAL6eIUQhBZ02bdrIbrdX6L0pLi6ucjhQkyZNtHDhQh09elS7d+9WYWGhOnbsqBYtWlQ6zEmS4uLilJCQEPSIOG63NHeuZX+Lbr/9dsXExOiuu+6qNGgePnxYW7ZsCTy/6aabJEmzZs3SDz/8EGjft2+fHnvssWq/7x133CHJvPm/bPhcmVOnTgX1xpRNkrB3795qn3/06NE6efKkpk6dGtQj9cknn2jRokVyOBznNAX0P//5T506dSqo7eTJk4HP0qRJkxqfGwAAnJnFv54hRCHdoxMbG6v09HTl5+fr+uuvD7Tn5+crMzPzjMc2btw4cPP2K6+8ol/96ld1ch8Gake3bt00f/58/ed//qcuvvhiDR06VBdeeGHghv7Vq1drzJgxeuqppySZN/LffPPNWrRokS699FJdf/31Ki0t1dKlS3XllVfqzTffrNb7Dh06VHfffbfmzJmjTp066frrr1fbtm21b98+/etf/9Ldd9+tiRMnSpKuueYazZkzR7fddpt+/etfq1mzZurQoYNGjhxZ5fknT56st956S3/729+0fft2DRw4UN98842WLl2qkydPasmSJWrRokWNf25ZWVlq2rSprrrqKqWmpurkyZPKz8/Xtm3blJWVpQ4dOtT43AAAAKi+kGddmzRpkkaNGqWePXuqT58+euaZZ1RYWKjx48dLMoed7du3LzDd8Oeff673339fvXv31nfffae5c+fqk08+Caxqj8h166236vLLL9fcuXO1Zs0aeTweORwOdejQQdnZ2Ro9enTQ/s8++6w6d+6sZ599Vk888YSSk5M1adIkjRgxotpBR5IeeeQR9enTR0888YRee+01HT9+XElJSbrmmmt07bXXBvYbMmSIHn74YT377LOaPXu2Tp48qQEDBpwx6MTHx+vdd9/V7NmztXTpUj366KNq2rSprr76av3P//yPrrrqqtB/UD+Sk5OjVatW6f3339cbb7yhZs2a6aKLLtLTTz+tW2655ZzODQAAgOqzGT8ev1NN8+fP18MPP6yioiJ169ZNjz76qK6++mpJ0pgxY7R7924VFBRIkrZv366RI0fqs88+U+PGjeVyuTR79uygNUnOpqSkRA6HQz6f74zD2I4fP65du3YpLS2twkxvQEPD7wMAALCi6maDGgWd+kbQAULH7wMAALCi6mYDbpIBAABARPF4pOxscwvUFEEHAAAAEcPjkTIzpdxcc1tvYYd0ZTkEHQAAAEQMr7d80U+7Xfq/277rVtjSFeoSQQcAAAARw+UqDzl+v+R01sObhiVdoa4RdAAAABAx3G4pL0+aMMHc1svin2FJV6hrIa+jEw2iYCI5oM7xewAAiFZudz0FnB+/YV6e2ZPjdNbzm6OuWCroxMSYH+fUqVNhrgQIv7Lfg7LfCwAAcAb1nq5Q1yw1dM1ut8tut6ukpCTcpQBhV1JSEvidAAAAaGgs9adem82mtm3bqqioSHFxcWrWrJlsNlu4ywLqlWEY+uGHH1RSUqKkpCR+BwAAQINkqaAjSQ6HQ8eOHdPBgwf1zTffhLscICxsNptatmwph8MR7lIAAADCwnJBx2azKSkpSW3bttXJkyfDXQ4QFo0bN2bIGgAg7Dwec+Zml4vbX1D/LBd0ynBvAgAAQPiUrcFpt0vz5tXjVNHA/7HUZAQAAACIDKzBiXAj6AAAAKDWsQYnws2yQ9cAAAAQPqzBiXAj6AAAAKBOsAYnwomhawAAAAAsh6ADAAAAwHIIOgAAAAAsh6ADAAAAwHIIOgAAAKiSxyNlZ5tbIJoQdAAAAFApj0fKzJRyc80tYQfRhKADAACASnm95Qt+2u3mmjhAtCDoAAAAoFIuV3nI8fvNhT+BaMGCoQAAAKiU2y3l5Zk9OU4ni38iuhB0AAAAUCW3m4CD6MTQNQAAAACWQ9ABAAAAYDkEHQAAAACWQ9ABAAAAYDkEHQAAgIZgr0fanG1ugQaAoAMAAGB1ez3Smkzp81xzS9hBA0DQAQAAsLoDXslmlwy/uT1QEO6KgDpH0AEAALC6RFd5yDH8UqIz3BUBdY4FQwEAAKwu2S1dnWf25CQ6zeeAxRF0AAAAGoJkNwEHDQpD1wAAAABYDkEHAAAAgOUQdAAAAABYDkEHAAAAgOUQdAAAAKKExyNlZ5tbAGdG0AEAAIgCHo+UmSnl5ppbwg5wZgQdAACAKOD1Sna75Peb24KCcFcERDaCDgAAQBRwucpDjt8vOZ3hrgiIbCwYCgAAEAXcbikvz+zJcTrN5wCqRtABAACIEm73OQQcj8cc/+ZykZLQIDB0DQAAwOqYyQANEEEHAADA6pjJAA0QQQcAAMDqmMkADRD36AAAAFgdMxmgASLoAAAA1LOwzAtwTjMZANGHoWsAAAD1iHkBgPpB0AEAAKhHzAsA1A+CDgAAQD1iXgCgfnCPDgAAQD1iXgCgfhB0AAAA6hnzAgB1j6FrAAAAACyHoAMAAADAcgg6AAAAACyHoAMAAADAcgg6AAAANeTxSNnZLPoJRKIaBZ358+crLS1N8fHxSk9P19q1a8+4/4svvqju3buradOmSkpK0s0336xDhw7VqGAAAIBI4PFImZlSbq65JewAkSXkoLN06VJNnDhR06ZN05YtW9S/f38NGTJEhYWFle6/bt063XTTTRo7dqy2bt2qV199VR988IHGjRt3zsUDAACEi9dbvuin3W6uiwMgcoQcdObOnauxY8dq3Lhx6tq1q+bNm6eUlBQtWLCg0v03btyojh07asKECUpLS9NVV12l2267TZs2bTrn4gEAAMLF5SoPOX6/ufgngMgRUtA5ceKENm/erIyMjKD2jIwMbdiwodJj+vbtq71792rlypUyDEMHDhzQa6+9puuuu67K9yktLVVJSUnQAwAAIJK43VJenjRhgrllAVAgsoQUdA4ePCi/36/ExMSg9sTERO3fv7/SY/r27asXX3xRWVlZio2N1fnnn6+WLVsqNze3yvfJycmRw+EIPFJSUkIpEwAAoF643dLcuYQcIBLVaDICm80W9NwwjAptZbZt26YJEybo/vvv1+bNm7Vq1Srt2rVL48ePr/L8U6dOlc/nCzz27NlTkzIBAAAANFAxoezcpk0b2e32Cr03xcXFFXp5yuTk5Khfv3665557JEmXXXaZmjVrpv79++uBBx5QUlJShWPi4uIUFxcXSmkAAAAAEBBSj05sbKzS09OVn58f1J6fn6++fftWeszRo0fVqFHw29jtdklmTxAAAAAA1LaQh65NmjRJzz33nBYuXKjt27crOztbhYWFgaFoU6dO1U033RTYf9iwYVq+fLkWLFignTt3av369ZowYYJ69eqldu3a1d4nAQAAAID/E9LQNUnKysrSoUOHNGvWLBUVFalbt25auXKlUlNTJUlFRUVBa+qMGTNGR44c0RNPPKH/+q//UsuWLXXNNddo9uzZtfcpAAAAasjjMdfEcbmYVACwEpsRBePHSkpK5HA45PP5lJCQEO5yAACARXg8UmZm+Vo4TBMNRL7qZoMazboGAABgBV5vecix26WCgnBXBKC2EHQAAECD5XKVhxy/X3I6w10RgNoS8j06AAAAVuF2m8PVCgrMkMOwNcA6CDoAAKBBc7sJOIAVMXQNAAAAgOUQdAAAAABYDkEHAAAAgOUQdAAAAABYDkEHAABYgscjZWebWwAg6AAAgKjn8UiZmVJurrkl7AAg6AAAgKjn9ZYv+mm3m+viAGjYCDoAACDquVzlIcfvNxf/BNCwsWAoAACIem63lJdn9uQ4nSwACoCgAwAALMLtJuAAKMfQNQAAAACWQ9ABAAAAYDkEHQAAAACWQ9ABAAAAYDkEHQAAEFE8Hik7m0U/AZwbgg4AAIgYHo+UmSnl5ppbwg6AmiLoAACAiOH1li/6abeb6+IAQE0QdAAAQMRwucpDjt9vLv4JADXBgqEAACBiuN1SXp7Zk+N0sgAogJoj6AAAgIjidhNwAJw7hq4BAAAAsByCDgAAAADLIegAAAAAsByCDgAAAADLIegAAIBa5/FI2dks+AkgfAg6AACgVnk8UmamlJtrbgk7AMKBoAMAAGqV11u+4Kfdbq6JAwD1jaADAABqlctVHnL8fnPhTwCobywYCgAAapXbLeXlmT05TieLfwIID4IOAACodW43AQdAeDF0DQAAAIDlEHQAAAAAWA5BBwAAAIDlEHQAAAAAWA5BBwAAVG2vR9qcbW4BIIoQdAAAQOX2eqQ1mdLnueaWsAMgihB0AABA5Q54JZtdMvzm9kBBuCsCgGoj6AAAgMoluspDjuGXEp3hrggAqo0FQwEAQOWS3dLVeWZPTqLTfA4AUYKgAwAAqpbsJuAAiEoMXQMAAFXzeKTsbHMLAFGEoAMAACrn8UiZmVJurrkl7ACIIgQdAABQOa9Xstslv9/cFhSEuyIAqDaCDgAAqJzLVR5y/H7J6Qx3RQBQbUxGAACAxXk8ZueMyyW5Q5lXwO2W8vLMnhynM8SDASC8bIZhGOEu4mxKSkrkcDjk8/mUkJAQ7nIAAIgaZbfZlHXK5OWRVwBEt+pmA4auAQBgYdxmA6ChIugAAGBh3GYDoKHiHh0AACyM22wANFQEHQAALM7tJuAAaHgYugYAAADAcgg6AAAAACyHoAMAAADAcgg6AAAAACyHoAMAQJTweKTsbHMLADgzgg4AAFHA45EyM6XcXHNL2AGAM6tR0Jk/f77S0tIUHx+v9PR0rV27tsp9x4wZI5vNVuFxySWX1LhoAAAaGq+3fNFPu91cFwcAULWQg87SpUs1ceJETZs2TVu2bFH//v01ZMgQFRYWVrr/Y489pqKiosBjz549atWqlX7961+fc/EAADQULld5yPH7zcU/AQBVsxmGYYRyQO/evdWjRw8tWLAg0Na1a1cNHz5cOTk5Zz1+xYoVuuGGG7Rr1y6lpqZW6z1LSkrkcDjk8/mUkJAQSrkAAFiGx2P25DidLAAKoOGqbjaICeWkJ06c0ObNmzVlypSg9oyMDG3YsKFa53j++ec1aNCgM4ac0tJSlZaWBp6XlJSEUiYAAJbkdhNwAKC6Qhq6dvDgQfn9fiUmJga1JyYmav/+/Wc9vqioSP/4xz80bty4M+6Xk5Mjh8MReKSkpIRSJgAAAIAGrkaTEdhstqDnhmFUaKvM4sWL1bJlSw0fPvyM+02dOlU+ny/w2LNnT03KBAAAANBAhTR0rU2bNrLb7RV6b4qLiyv08vyUYRhauHChRo0apdjY2DPuGxcXp7i4uFBKAwAAAICAkHp0YmNjlZ6ervz8/KD2/Px89e3b94zHrl69Wl9++aXGjh0bepUAAAAAEIKQenQkadKkSRo1apR69uypPn366JlnnlFhYaHGjx8vyRx2tm/fPi1ZsiTouOeff169e/dWt27daqdyAACilMdjrovjcjG5AADUlZCDTlZWlg4dOqRZs2apqKhI3bp108qVKwOzqBUVFVVYU8fn82nZsmV67LHHaqdqAACilMcjZWaa6+HMmyfl5RF2AKAuhLyOTjiwjg4AwCqys6Xc3PLFPydMkObODXdVABA9qpsNajTrGgAAqBmXqzzk+P3m4p8AgNoX8tA1AABQc263OVytoMAMOQxbA4C6QdABAKCeud0EHACoawxdAwAAAGA5BB0AAAAAlkPQAQAAAGA5BB0AAAAAlkPQAQCgBjwec00cjyfclQAAKkPQAQAgRB6PlJlpLvyZmUnYAYBIRNABACBEXm/5gp92u7kmDgAgshB0AAAIkctVHnL8fnPhTwBAZGHBUAAAQuR2S3l5Zk+O08ninwAQiQg6AADUgNtNwAGASMbQNQAAAACWQ9ABAAAAYDkEHQAAAACWQ9ABAAAAYDkEHQBAg+bxSNnZLPoJAFZD0AEANFgej5SZKeXmmlvCDgBYB0EHANBgeb3li37a7ea6OAAAayDoAAAaLJerPOT4/ebinwAAa2DBUABAg+V2S3l5Zk+O08kCoABgJQQdAECD5nYTcADAihi6BgAAAMByCDoAAAAALIegAwAAAMByCDoAAAAALIegAwCwBI9Hys5m0U8AgImgAwCIeh6PlJkp5eaaW8IOAICgAwCIel5v+aKfdru5Lg4AoGEj6AAAop7LVR5y/H5z8U8AQMPGgqEAgKjndkt5eWZPjtPJAqAAAIIOAMAi3G4CDgCgHEPXAAAAAFgOQQcAAACA5RB0AAAAAFgOQQcAAACA5RB0AAARw+ORsrNZ8BMAcO4IOgCAiODxSJmZUm6uuSXsAADOBUEHABARvN7yBT/tdnNNHAAAaoqgAwCICC5Xecjx+82FPwEAqCkWDAUARAS3W8rLM3tynE4W/wQAnBuCDgAgYrjdBBwAQO1g6BoAAAAAyyHoAAAAALAcgg4AAAAAyyHoAAAAALAcgg4AoNZ5PFJ2Not+AgDCh6ADAKhVHo+UmSnl5ppbwg4AIBwIOgCAWuX1li/6abeb6+IAAFDfCDoAgFrlcpWHHL/fXPwTAID6xoKhAIBa5XZLeXlmT47TyQKgAIDwIOgAAGqd203AAQCEF0PXAAAAAFgOQQcAAACA5RB0AAAAAFgOQQcAAACA5RB0AACV8nik7GwW/AQARCeCDgCgAo9HysyUcnPNLWEHABBtCDoAgAq83vIFP+12c00cAACiCUEHAFCBy1Uecvx+c+FPAACiSY2Czvz585WWlqb4+Hilp6dr7dq1Z9y/tLRU06ZNU2pqquLi4nThhRdq4cKFNSoYAFD33G4pL0+aMMHcsvgnACDaxIR6wNKlSzVx4kTNnz9f/fr109NPP60hQ4Zo27Zt6tChQ6XHjBgxQgcOHNDzzz+viy66SMXFxTp16tQ5Fw8AqDtuNwEHABC9bIZhGKEc0Lt3b/Xo0UMLFiwItHXt2lXDhw9XTk5Ohf1XrVql3/zmN9q5c6datWpVrfcoLS1VaWlp4HlJSYlSUlLk8/mUkJAQSrkAAAAALKSkpEQOh+Os2SCkoWsnTpzQ5s2blZGREdSekZGhDRs2VHqMx+NRz5499fDDD6t9+/bq3Lmz7r77bh07dqzK98nJyZHD4Qg8UlJSQikTAAAAQAMX0tC1gwcPyu/3KzExMag9MTFR+/fvr/SYnTt3at26dYqPj9frr7+ugwcP6vbbb9e3335b5X06U6dO1aRJkwLPy3p0AAAAAKA6Qr5HR5JsNlvQc8MwKrSVOX36tGw2m1588UU5HA5J0ty5c3XjjTfqySefVJMmTSocExcXp7i4uJqUBgAAAAChDV1r06aN7HZ7hd6b4uLiCr08ZZKSktS+fftAyJHMe3oMw9DevXtrUDIAIBQej5SdzaKfAICGJaSgExsbq/T0dOXn5we15+fnq2/fvpUe069fP3399df6/vvvA22ff/65GjVqpOTk5BqUDACoLo9HysyUcnPNLWEHANBQhLyOzqRJk/Tcc89p4cKF2r59u7Kzs1VYWKjx48dLMu+vuemmmwL7jxw5Uq1bt9bNN9+sbdu2ac2aNbrnnnt0yy23VDpsDQBQe7ze8kU/7XapoCDcFQEAUD9CvkcnKytLhw4d0qxZs1RUVKRu3bpp5cqVSk1NlSQVFRWpsLAwsH/z5s2Vn5+vu+66Sz179lTr1q01YsQIPfDAA7X3KQCgIfB4zOTiclV7gRuXS5o3rzzsOJ11WiEAABEj5HV0wqG6c2UDgGWVjUErSyx5edUOOx6P2ZPjdLIAKAAg+lU3G9Ro1jUAQD2rbAxaNVOL203AAQA0PCHfowMACAOXqzzkMAYNAICzokcHAKKB220OV2MMGgAA1ULQAYBowRg0AACqjaFrAAAAACyHoAMA0WKvR9qcbW4BAMAZEXQAIBrs9UhrMqXPc80tYQcAgDMi6ABANDjglWx2yfCb2wMF4a4IAICIRtABgGiQ6CoPOYZfSnSGuyIAACIas64BQDRIdktX55k9OYlO8zkAAKgSQQcAokWym4ADAEA1MXQNAAAAgOUQdAAAAABYDkEHAAAAgOUQdAAAAABYDkEHAOqRxyNlZ5tbAABQdwg6AFBPPB4pM1PKzTW3hB0AAOoOQQcA6onXK9ntkt9vbgsKwl0RAADWRdABgHricpWHHL9fcjrDXREAANbFgqEAUE/cbikvz+zJcTrN5wAAoG4QdACgHrndBBwAAOoDQ9cAAAAAWA5BBwAAAIDlEHQAAAAAWA5BBwAAAIDlEHQAoAY8Hik7m0U/AQCIVAQdAAiRxyNlZkq5ueaWsAMAQOQh6ABAiLze8kU/7XZzXRwAABBZCDoAECKXqzzk+P3m4p8AACCysGAoAITI7Zby8syeHKeTBUABAIhEBB0AqAG3m4ADAEAkY+gaAAAAAMsh6AAAAACwHIIOAAAAAMsh6AAAAACwHIIOgAbN45Gys1n0EwAAqyHoAGiwPB4pM1PKzTW3hB0AAKyDoAOgwfJ6yxf9tNvNdXEAAIA1EHQANFguV3nI8fvNxT8BAIA1sGAogAbL7Zby8syeHKeTBUABALASgg6ABs3tJuAAAGBFDF0DAAAAYDkEHQCRg7meAQBALSHoAIgMzPUMAABqEUEHQGRgrmcAAFCLCDoAIsM5zPXMiDcAAPBTNsMwjHAXcTYlJSVyOBzy+XxKSEgIdzkA6orHE/Jcz2Uj3sryUV4es6gBAGBl1c0GTC8NIHLUYK7nyka8EXQAAABD1wBEtXMY8QYAACyMHh0AUc3tNoerhTjiDQAAWBxBB0DUq8GINwAAYHEMXQMAAABgOQQdAAAAAJZD0AEAAABgOQQdAAAAAJZD0AEQOfZ6pM3Z5hYAAOAcEHQARIa9HmlNpvR5rrkl7AAAgHNA0AEQGQ54JZtdMvzm9kBBuCsCAABRjKADIDIkuspDjuGXEp3hrggAAEQxFgwFEBmS3dLVeWZPTqLTfA4AAFBDNerRmT9/vtLS0hQfH6/09HStXbu2yn0LCgpks9kqPD799NMaFw3AopLdUvpcQg4AADhnIQedpUuXauLEiZo2bZq2bNmi/v37a8iQISosLDzjcZ999pmKiooCj06dOtW4aAAAAAA4k5CDzty5czV27FiNGzdOXbt21bx585SSkqIFCxac8bi2bdvq/PPPDzzsdnuNiwYAAACAMwkp6Jw4cUKbN29WRkZGUHtGRoY2bNhwxmOvuOIKJSUlaeDAgfJ6vWfct7S0VCUlJUEPAAAAAKiukILOwYMH5ff7lZiYGNSemJio/fv3V3pMUlKSnnnmGS1btkzLly/XxRdfrIEDB2rNmjVVvk9OTo4cDkfgkZKSEkqZAAAAABq4Gs26ZrPZgp4bhlGhrczFF1+siy++OPC8T58+2rNnj+bMmaOrr7660mOmTp2qSZMmBZ6XlJQQdoAo4fFIXq/kcklu5hQAAABhElKPTps2bWS32yv03hQXF1fo5TmTK6+8Ul988UWVr8fFxSkhISHoASDyeTxSZqaUm2tuPZ5wVwQAABqqkIJObGys0tPTlZ+fH9Sen5+vvn37Vvs8W7ZsUVJSUihvDSAKeL2S3S75/ea2oCDcFQEAgIYq5KFrkyZN0qhRo9SzZ0/16dNHzzzzjAoLCzV+/HhJ5rCzffv2acmSJZKkefPmqWPHjrrkkkt04sQJvfDCC1q2bJmWLVtWu58EQNi5XNK8eeVhx+kMd0UAAKChCjnoZGVl6dChQ5o1a5aKiorUrVs3rVy5UqmpqZKkoqKioDV1Tpw4obvvvlv79u1TkyZNdMkll+itt97S0KFDa+9TAIgIbreUl2f25Did3KMDAADCx2YYhhHuIs6mpKREDodDPp+P+3UAAACABqy62SDkBUMBAAAAINIRdAAAAABYDkEHAAAAgOUQdAAAAABYDkEHQKU8Hik7m0U/AQBAdCLoAKjA45EyM6XcXHNL2AEAANGGoAOgAq+3fNFPu91cFwcAACCaEHQAVOBylYccv99c/BMAACCaxIS7AACRx+2W8vLMnhyn03wOAAAQTQg6ACrldhNwAABA9GLoGgAAAADLIegAAAAAsByCDgAAAADLIegAAAAAsByCDmBxHo+Unc2inwAAoGEh6AAW5vFImZlSbq65JewAAICGgqADWJjXW77op91urosDAADQEBB0AAtzucpDjt9vLv4JAADQELBgKGBhbreUl2f25DidLAAKAAAaDoIOYHFuNwEHAAA0PAxdAwAAAGA5BB0AAAAAlkPQAQAAAGA5BB0AAAAAlkPQAULl8UjZ2fW6+mYY3hIAACCq2QzDMMJdxNmUlJTI4XDI5/MpISEh3OWgIfN4pMzM8oVp8vLqfEqzMLwlAABAxKpuNqBHBwiF11ueOOx2c4Ea670lAABA1CPoAKFwucoTh99vrsJpvbcEAACIeiwYCoTC7TbHjhUUmImjHsaQheEtAQAAoh736AAAAACIGtyjAwAAAKDBIugAAAAAsByCDgAAAADLIegAAAAAsByCDlCPPB4pO9vcAgAAoO4QdIB64vFImZlSbq65JewAAADUHYIOUE+83vJFP+12c10cAAAA1A2CDlBPXK7ykOP3m4t/AgAAoG7EhLsAoKFwu6W8PLMnx+k0nwMAAKBuEHSAeuR2E3AAAADqA0PXAAAAAFgOQQcAAACA5RB0AAAAAFgOQQcAAACA5RB0gFDt9Uibs80tAAAAIhJBBwjFXo+0JlP6PNfcEnYAAAAiEkEHCMUBr2SzS4bf3B4oCHdFAAAAqARBBwhFoqs85Bh+KdEZ7ooAAABQCRYMBUKR7JauzjN7chKd5nMAAABEHIIOEKpkNwEHAAAgwjF0DQAAAIDlEHQAAAAAWA5BBwAAAIDlEHQAAAAAWA5BBw2WxyNlZ5tbAAAAWAtBBw2SxyNlZkq5ueaWsAMAAGAtBB00SF6vZLdLfr+5LSgId0UAAACoTQQdNEguV3nI8fslpzPcFQEAAKA2sWAoGiS3W8rLM3tynE7zOQAAAKyDoIMGy+0m4AAAAFgVQ9cAAAAAWE6Ngs78+fOVlpam+Ph4paena+3atdU6bv369YqJidHll19ek7cFAAAAgGoJOegsXbpUEydO1LRp07Rlyxb1799fQ4YMUWFh4RmP8/l8uummmzRw4MAaFwsAAAAA1WEzDMMI5YDevXurR48eWrBgQaCta9euGj58uHJycqo87je/+Y06deoku92uFStW6MMPP6xy39LSUpWWlgael5SUKCUlRT6fTwkJCaGUCwAAAMBCSkpK5HA4zpoNQurROXHihDZv3qyMjIyg9oyMDG3YsKHK4xYtWqQdO3Zo+vTp1XqfnJwcORyOwCMlJSWUMtHAeDxSdjaLfgIAAKBcSEHn4MGD8vv9SkxMDGpPTEzU/v37Kz3miy++0JQpU/Tiiy8qJqZ6k7xNnTpVPp8v8NizZ08oZaIB8XikzEwpN9fcEnYAAAAg1XAyApvNFvTcMIwKbZLk9/s1cuRIzZw5U507d672+ePi4pSQkBD0ACrj9ZYv+mm3m+viAAAAACEFnTZt2shut1fovSkuLq7QyyNJR44c0aZNm3TnnXcqJiZGMTExmjVrlj766CPFxMTo3XffPbfq0eC5XOUhx+83F/8EAAAAQlowNDY2Vunp6crPz9f1118faM/Pz1dmZmaF/RMSEvTxxx8Htc2fP1/vvvuuXnvtNaWlpdWwbMDkdkt5eWZPjtPJAqAAAAAwhRR0JGnSpEkaNWqUevbsqT59+uiZZ55RYWGhxo8fL8m8v2bfvn1asmSJGjVqpG7dugUd37ZtW8XHx1doB2rK7SbgAAAAIFjIQScrK0uHDh3SrFmzVFRUpG7dumnlypVKTU2VJBUVFZ11TR0AAAAAqEshr6MTDtWdKxsAAACAtdXJOjoAAAAAEA0IOgAAAAAsh6CDiODxSNnZLPgJAACA2kHQQdh5PFJmppSba24JOwAAADhXBB2EnddbvuCn3W6uiQMAAACcC4KOlUXJeDCXqzzk+P3mwp8AAADAuWB6aasqGw9Wlh7y8iJ6VU2Px+zJcTojukwAAACEWXWzQcgLhiJKVDYeLIIThNsd0eUBAAAgyjB0zaoYDwYAAIAGjB4dq3K7zeFqjAcDAABAA0TQsTLGgwEAAKCBYugaAAAAAMsh6KBWRcmM1gAAALA4gg5qTdmM1rm55pawAwAAgHAh6KDWVDajNQAAABAOBB3UGma0BgAAQKRg1jXUGma0BgAAQKQg6KBWMaM1AAAAIgFD1wAAAABYDkEHAAAAgOUQdAAAAABYDkEHAAAAgOUQdOqLxyNlZ0fNKppRVi4AAAAQxGYYhhHuIs6mpKREDodDPp9PCQkJ4S4ndB6PlJlZvsBMXl5ET00WZeUCAACgAaluNqBHpz54veWpwW43F5qJYFFWLgAAAFABQac+uFzlqcHvN1fTjGBRVi4AAABQAQuG1ge32xz/VVBgpoYIHwcWZeUCAAAAFXCPDgAAAICowT06AAAAABosgg4AAAAAyyHoAAAAALAcgg4AAAAAyyHoWNlej7Q529wCAAAADQhBx6r2eqQ1mdLnueaWsAMAAIAGhKBjVQe8ks0uGX5ze6Ag3BUBAAAA9YagY1WJrvKQY/ilRGe4KwIAAADqTUy4C0AdSXZLV+eZPTmJTvM5AAAA0EAQdKws2U3AAQAAQIPE0DUAAAAAlkPQAQAAAGA5BB0AAAAAlkPQAQAAAGA5BJ0o4PFI2dnmFgAAAMDZEXQinMcjZWZKubnmlrADAAAAnB1BJ8J5vZLdLvn95ragINwVAQAAAJGPoBPhXK7ykOP3S05nuCsCAAAAIh8LhkY4t1vKyzN7cpxO8zkAAACAMyPoRAG3m4ADAAAAhIKhawAAAAAsh6ADAAAAwHIIOgAAAAAsh6ADAAAAwHIIOvVlr0fanG1uAQAAANQpgk592OuR1mRKn+eaW8IOAAAAUKcIOvXhgFey2SXDb24PFIS7IgAAAMDSCDr1IdFVHnIMv5ToDHdFAAAAgKWxYGh9SHZLV+eZPTmJTvM5AAAAgDpD0KkvyW4CDgAAAFBPGLoGAAAAwHIIOgAAAAAsp0ZBZ/78+UpLS1N8fLzS09O1du3aKvddt26d+vXrp9atW6tJkybq0qWLHn300RoXDAAAAABnE/I9OkuXLtXEiRM1f/589evXT08//bSGDBmibdu2qUOHDhX2b9asme68805ddtllatasmdatW6fbbrtNzZo10x/+8Ida+RAAAAAA8GM2wzCMUA7o3bu3evTooQULFgTaunbtquHDhysnJ6da57jhhhvUrFkz/e1vf6vW/iUlJXI4HPL5fEpISAil3Frn8Uher+RySW7mFgAAAADqVXWzQUhD106cOKHNmzcrIyMjqD0jI0MbNmyo1jm2bNmiDRs2aMCAAVXuU1paqpKSkqBHJPB4pMxMKTfX3Ho84a4IAAAAQGVCCjoHDx6U3+9XYmJiUHtiYqL2799/xmOTk5MVFxennj176o477tC4ceOq3DcnJ0cOhyPwSElJCaXMOuP1Sna75Peb24KCcFcEAAAAoDI1mozAZrMFPTcMo0LbT61du1abNm3SU089pXnz5unll1+uct+pU6fK5/MFHnv27KlJmbXO5SoPOX6/5HSGuyIAAAAAlQlpMoI2bdrIbrdX6L0pLi6u0MvzU2lpaZKkSy+9VAcOHNCMGTP029/+ttJ94+LiFBcXF0pp9cLtlvLyzJ4cp5N7dAAAAIBIFVKPTmxsrNLT05Wfnx/Unp+fr759+1b7PIZhqLS0NJS3jhhutzR3LiEHAAAAiGQhTy89adIkjRo1Sj179lSfPn30zDPPqLCwUOPHj5dkDjvbt2+flixZIkl68skn1aFDB3Xp0kWSua7OnDlzdNddd9XixwAAAACAciEHnaysLB06dEizZs1SUVGRunXrppUrVyo1NVWSVFRUpMLCwsD+p0+f1tSpU7Vr1y7FxMTowgsv1EMPPaTbbrut9j4FAAAAAPxIyOvohEMkraMDAAAAIHzqZB0dAAAAAIgGBB0AAAAAlkPQAQAAAGA5BB0AAAAAlkPQAQAAAGA5BB0AAAAAlkPQAQAAAGA5BB0AAAAAlkPQAQAAAGA5BB0AAAAAlkPQAQAAAGA5BB0AAAAAlkPQAQAAAGA5BB0AAAAAlkPQAQAAAGA5BB0AAAAAlhMT7gKqwzAMSVJJSUmYKwEAAAAQTmWZoCwjVCUqgs6RI0ckSSkpKWGuBAAAAEAkOHLkiBwOR5Wv24yzRaEIcPr0aX399ddq0aKFbDZbWGspKSlRSkqK9uzZo4SEhLDWgujD9YNzwfWDmuLawbng+sG5qIvrxzAMHTlyRO3atVOjRlXfiRMVPTqNGjVScnJyuMsIkpCQwC87aozrB+eC6wc1xbWDc8H1g3NR29fPmXpyyjAZAQAAAADLIegAAAAAsByCToji4uI0ffp0xcXFhbsURCGuH5wLrh/UFNcOzgXXD85FOK+fqJiMAAAAAABCQY8OAAAAAMsh6AAAAACwHIIOAAAAAMsh6AAAAACwHIIOAAAAAMsh6FRi/vz5SktLU3x8vNLT07V27doz7r969Wqlp6crPj5eF1xwgZ566ql6qhSRKJTrZ/ny5br22mt13nnnKSEhQX369NE///nPeqwWkSTUf3vKrF+/XjExMbr88svrtkBEtFCvn9LSUk2bNk2pqamKi4vThRdeqIULF9ZTtYg0oV4/L774orp3766mTZsqKSlJN998sw4dOlRP1SJSrFmzRsOGDVO7du1ks9m0YsWKsx5Tn9+bCTo/sXTpUk2cOFHTpk3Tli1b1L9/fw0ZMkSFhYWV7r9r1y4NHTpU/fv315YtW/Q///M/mjBhgpYtW1bPlSMShHr9rFmzRtdee61WrlypzZs3y+VyadiwYdqyZUs9V45wC/XaKePz+XTTTTdp4MCB9VQpIlFNrp8RI0boX//6l55//nl99tlnevnll9WlS5d6rBqRItTrZ926dbrppps0duxYbd26Va+++qo++OADjRs3rp4rR7j98MMP6t69u5544olq7V/v35sNBOnVq5cxfvz4oLYuXboYU6ZMqXT/yZMnG126dAlqu+2224wrr7yyzmpE5Ar1+qnMz3/+c2PmzJm1XRoiXE2vnaysLOPee+81pk+fbnTv3r0OK0QkC/X6+cc//mE4HA7j0KFD9VEeIlyo188jjzxiXHDBBUFtjz/+uJGcnFxnNSLySTJef/31M+5T39+b6dH5kRMnTmjz5s3KyMgIas/IyNCGDRsqPea9996rsP/gwYO1adMmnTx5ss5qReSpyfXzU6dPn9aRI0fUqlWruigREaqm186iRYu0Y8cOTZ8+va5LRASryfXj8XjUs2dPPfzww2rfvr06d+6su+++W8eOHauPkhFBanL99O3bV3v37tXKlStlGIYOHDig1157Tdddd119lIwoVt/fm2Nq/YxR7ODBg/L7/UpMTAxqT0xM1P79+ys9Zv/+/ZXuf+rUKR08eFBJSUl1Vi8iS02un5/6y1/+oh9++EEjRoyoixIRoWpy7XzxxReaMmWK1q5dq5gY/ilvyGpy/ezcuVPr1q1TfHy8Xn/9dR08eFC33367vv32W+7TaWBqcv307dtXL774orKysnT8+HGdOnVKbrdbubm59VEyolh9f2+mR6cSNpst6LlhGBXazrZ/Ze1oGEK9fsq8/PLLmjFjhpYuXaq2bdvWVXmIYNW9dvx+v0aOHKmZM2eqc+fO9VUeIlwo//acPn1aNptNL774onr16qWhQ4dq7ty5Wrx4Mb06DVQo18+2bds0YcIE3X///dq8ebNWrVqlXbt2afz48fVRKqJcfX5v5s+AP9KmTRvZ7fYKf8EoLi6ukD7LnH/++ZXuHxMTo9atW9dZrYg8Nbl+yixdulRjx47Vq6++qkGDBtVlmYhAoV47R44c0aZNm7RlyxbdeeedkswvroZhKCYmRm+//bauueaaeqkd4VeTf3uSkpLUvn17ORyOQFvXrl1lGIb27t2rTp061WnNiBw1uX5ycnLUr18/3XPPPZKkyy67TM2aNVP//v31wAMPMJoFVarv78306PxIbGys0tPTlZ+fH9Sen5+vvn37VnpMnz59Kuz/9ttvq2fPnmrcuHGd1YrIU5PrRzJ7csaMGaOXXnqJ8c0NVKjXTkJCgj7++GN9+OGHgcf48eN18cUX68MPP1Tv3r3rq3REgJr829OvXz99/fXX+v777wNtn3/+uRo1aqTk5OQ6rReRpSbXz9GjR9WoUfBXSLvdLqn8r/NAZer9e3OdTHEQxV555RWjcePGxvPPP29s27bNmDhxotGsWTNj9+7dhmEYxpQpU4xRo0YF9t+5c6fRtGlTIzs729i2bZvx/PPPG40bNzZee+21cH0EhFGo189LL71kxMTEGE8++aRRVFQUeBw+fDhcHwFhEuq181PMutawhXr9HDlyxEhOTjZuvPFGY+vWrcbq1auNTp06GePGjQvXR0AYhXr9LFq0yIiJiTHmz59v7Nixw1i3bp3Rs2dPo1evXuH6CAiTI0eOGFu2bDG2bNliSDLmzp1rbNmyxfjqq68Mwwj/92aCTiWefPJJIzU11YiNjTV69OhhrF69OvDa6NGjjQEDBgTtX1BQYFxxxRVGbGys0bFjR2PBggX1XDEiSSjXz4ABAwxJFR6jR4+u/8IRdqH+2/NjBB2Eev1s377dGDRokNGkSRMjOTnZmDRpknH06NF6rhqRItTr5/HHHzd+/vOfG02aNDGSkpKM3/3ud8bevXvruWqEm9frPeP3mHB/b7YZBn2MAAAAAKyFe3QAAAAAWA5BBwAAAIDlEHQAAAAAWA5BBwAAAIDlEHQAAAAAWA5BBwAAAIDlEHQAAAAAWA5BBwAAAIDlEHQAAAAAWA5BBwAAAIDlEHQAAAAAWM7/Byz8Tre590ErAAAAAElFTkSuQmCC\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plot_predictions(predictions=y_preds)" ] }, { "cell_type": "markdown", "id": "7c048192", "metadata": {}, "source": [ "## Saving the Trained Model\n", "\n", "Lastly, we can save the trained model. We can either save the entire model or just its state_dict (its parameters). The latter is the safer option in most cases." ] }, { "cell_type": "code", "execution_count": 18, "id": "a8349e7e-7c9d-49dd-85e1-9c7ee2eabb2b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Saving model to: models/01_pytorch_workflow_model_0.pth\n" ] } ], "source": [ "# 1. Create models directory \n", "MODEL_PATH = Path(\"models\")\n", "MODEL_PATH.mkdir(parents=True, exist_ok=True)\n", "\n", "# 2. Create model save path \n", "MODEL_NAME = \"01_pytorch_workflow_model_0.pth\"\n", "MODEL_SAVE_PATH = MODEL_PATH / MODEL_NAME\n", "\n", "# 3. Save the model state dict \n", "print(f\"Saving model to: {MODEL_SAVE_PATH}\")\n", "torch.save(obj=model_0.state_dict(), # only saving the state_dict() only saves the models learned parameters\n", " f=MODEL_SAVE_PATH)" ] }, { "cell_type": "code", "execution_count": 19, "id": "ae1fb441-97d6-473a-9f63-646601cd508b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-rw-r--r-- 1 jovyan users 1680 Nov 7 20:37 models/01_pytorch_workflow_model_0.pth\n" ] } ], "source": [ "# Check the saved file path\n", "!ls -l models/01_pytorch_workflow_model_0.pth" ] }, { "cell_type": "code", "execution_count": 20, "id": "02d45a04-583e-434c-881a-cafb2ac4c924", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Instantiate a new instance of our model (this will be instantiated with random weights)\n", "loaded_model_0 = LinearRegressionModel()\n", "\n", "# Load the state_dict of our saved model (this will update the new instance of our model with trained weights)\n", "loaded_model_0.load_state_dict(torch.load(f=MODEL_SAVE_PATH))" ] }, { "cell_type": "code", "execution_count": 21, "id": "a302042f-1bfb-463d-abac-dd24f645ed91", "metadata": {}, "outputs": [], "source": [ "# 1. Put the loaded model into evaluation mode\n", "loaded_model_0.eval()\n", "\n", "# 2. Use the inference mode context manager to make predictions\n", "with torch.inference_mode():\n", " loaded_model_preds = loaded_model_0(X_test) # perform a forward pass on the test data with the loaded model" ] }, { "cell_type": "code", "execution_count": 22, "id": "9116eee9-abe7-4b26-9e80-cd7b9fa154bd", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "tensor([[True],\n", " [True],\n", " [True],\n", " [True],\n", " [True],\n", " [True],\n", " [True],\n", " [True],\n", " [True],\n", " [True]])" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Compare previous model predictions with loaded model predictions (these should be the same)\n", "y_preds == loaded_model_preds" ] }, { "cell_type": "code", "execution_count": null, "id": "ca43e7cd-e9af-4a1d-a99d-3e16ba6c9015", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3-0.9.4", "language": "python", "name": "python3-0.9.4" }, "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.8.12" } }, "nbformat": 4, "nbformat_minor": 5 }