Neural-Networks-From-Scratch/final_projects/Final_Neural_Network_Regularization.ipynb

711 lines
104 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

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

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-block alert-success\" style=\"font-size:20px;\">\n",
" NEURAL NETWORK FROM SCRATCH (TRAINING + REGULARIZATION + TESTING)\n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-block alert-danger\">\n",
"\n",
"LOADING THE DATASET</div>"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import nnfs\n",
"from nnfs.datasets import spiral_data\n",
"nnfs.init()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-block alert-danger\">\n",
"\n",
"PLOTTING THE DATASET</div>"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAjgAAAGdCAYAAAAfTAk2AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/H5lhTAAAACXBIWXMAAA9hAAAPYQGoP6dpAADWa0lEQVR4nOydZ5gTVReA30myhbZL70VAwEIHaZ8KKlJEAREbKk1RQFDBhgWwI0XBAqIUUVGqICIKCFIUERFQqoCC9F52aVuSOd+PS3Y3bNrupu1y3zzzJJncufdMMpk5c+4phogIGo1Go9FoNHkIS7gF0Gg0Go1Gowk0WsHRaDQajUaT59AKjkaj0Wg0mjyHVnA0Go1Go9HkObSCo9FoNBqNJs+hFRyNRqPRaDR5Dq3gaDQajUajyXNoBUej0Wg0Gk2ewxZuAcKBaZocPHiQQoUKYRhGuMXRaDQajUbjByLCmTNnKFu2LBaLdxvNZangHDx4kAoVKoRbDI1Go9FoNNlg3759lC9f3muboCo4K1euZOTIkaxbt45Dhw4xd+5cOnbs6HWb5cuXM3DgQLZs2UKFChV4+eWX6d69u0ubsWPHMnLkSA4fPkydOnX44IMPaNSokd9yFSpUCFBfUFxcXFZ3S6PRaDQaTRhITEykQoUKaddxbwRVwTl37hx16tShZ8+edOrUyWf73bt3065dO3r37s2XX37J0qVLeeSRRyhTpgytW7cGYMaMGQwcOJDx48fTuHFjxowZQ+vWrdm+fTslS5b0Sy7ntFRcXJxWcDQajUajyWX4415ihKrYpmEYPi04zz//PAsWLGDz5s1p6+677z5Onz7NwoULAWjcuDHXXXcdH374IaD8aSpUqED//v0ZNGiQX7IkJiYSHx9PQkKCVnA0Go1Go8klZOX6HVFRVKtXr6Zly5Yu61q3bs3q1asBSElJYd26dS5tLBYLLVu2TGvjjuTkZBITE10WjUaj0Wg0eZeIUnAOHz5MqVKlXNaVKlWKxMRELly4wPHjx3E4HG7bHD582GO/w4YNIz4+Pm3RDsYajUaj0eRtIkrBCRYvvPACCQkJacu+ffvCLZJGo9FoNJogElFh4qVLl+bIkSMu644cOUJcXBz58uXDarVitVrdtildurTHfmNiYoiJiQmKzBqNRqPRaCKPiLLgNG3alKVLl7qs+/HHH2natCkA0dHRNGjQwKWNaZosXbo0rY1Go9FoNBpNUBWcs2fP8ueff/Lnn38CKgz8zz//ZO/evYCaOuratWta+969e7Nr1y6ee+45/v77b8aNG8fMmTMZMGBAWpuBAwcyYcIEPvvsM7Zt20afPn04d+4cPXr0COauaDQajUajyUUEdYrqjz/+4Kabbkp7P3DgQAC6devGlClTOHToUJqyA1C5cmUWLFjAgAEDeO+99yhfvjwTJ05My4EDcO+993Ls2DGGDBnC4cOHqVu3LgsXLszkeKzRaDQajebyJWR5cCIJnQdHo8mdiAj88gvs2gVFi8Ktt2LExoZbLI1GEyKycv2OKCdjjUaj8YQsWwaP9oJ//01fGR+PvPIqPPGELpyr0Whc0AqORqOJeGTVKmjdCkzT9YOEBBjwFCQnw3PPhUU2jUYTmURUFJVGo9G4ZdDzSrm5VMFx8spQJCEhtDJpNJqIRis4Go0mopH//oNVqzwrN6AsOF9/HTKZNBpN5KMVHI1GE9l4KcOShtUKhw4FXxaNRpNr0AqORqOJbMqW9d3G4YBy5YIvi0ajyTVoBUej0UQ0RsWK0Ly5stJ4IjYW7rordEJpNJqIRys4Go0m8hkxEmw2sHg4Zb09HKNQodDKpNFoIhqt4Gg0mojHuO46WLYcatZ0/aBkSZgwEaN//7DIpdFoIhedB0ej0eQKjCZNkA1/wp9/pmcyvuEGDJs+jWk0mszoM4NGo8k1GIaB1K0Lp0/DihWwfDly441w8806k7FGo3FBKzgajSbXILt2QYf2sGWL8skBeP01uOoq5Jt5GNWrh1dAjUYTMWgfHI1GkyuQhARofiNs365W2O1qAdi5E1o0R06eDJ+AGo0motAKjkajyR18+ikcPJiu1GTE4YCjR2HixNDLpdFoIhKt4Gg0mtzBtK9AxPPnpglffRU6eTQaTUSjFRyNRpM7OHnKd5tTfrTRaDSXBVrB0Wg0EY8sXQpnEr03slrhqhqhEegyRVJSkAkTkAb1kbhCSMUKyAsvIAcPhls0jSYTWsHRaHI5Yrcjc+Ygd9yO1KmNtLsNmTkTSU0Nt2gBQd59F25tCcePe2/ocEDvPqER6jJELlyAVrdC78dULqKzZ2H/fhg1EmrVRDZtCreIGo0LWsHRaMKMJCQgo0cjDRsgla9AWrdCvv4acTh8b3vunLr4d74LFi6ETZtg8WK4714VVXTmTAj2IHjIhg3wzNPqjWl6bmgY0KkTdOgQGsEuR155BX75RflBZfSFcjggMRE63Yl4+400mhCjFRyNJozIf/9B7VrqIr5+PezZAz/9BHd3hrs6+bbCPPUk/Pyzeu1UiJzPv/8OfXoHTfaQMG5ser4bT8TEwGuvw/QZGJ5qVWlyhFy4AB+P96xkOhzw77+wZEloBdNovKDPBhpNmBAR6HQnHDqU+Y4YYP58eOMNz9sfOwaffeb9ojNjRu72j1i92n1YeEaKFcd46SVdsiGY7NyprDTesNngt99CI49G4wdawdFowsWvvypfBk8XcBH48AMkOdnz9r4u/g5HuoUnNxId47tNrB9tNDnDavXdRiTN2iZnziCTJiHPP4+89RayY0eQBdRoMqMVHI0mXKxY4fvCceoU/P23+8/89XfIzX4Rt9/u/Tuy2eCO9qGT53KlRg0oU8Z7G4cDbr0V+eorKFMaHu0FY0bD0CFwVQ3kwQeQpKTQyKvRoBUcjSZ85LQ4ZKNG4MvnxDCgSZOcjRNOHntM+di420/DUMrP44+HXq7LDMNmg2ee9dzAZoNmzeDECXjoQTh/Xll0UlPTp1ynT4dHHg6NwBoNWsHRaMJH8+bpJ39PFCkCV13l9iOjXDkVOeTJwmGzwW3tMCpXzqGg4cMoVw4WfA/587sqhBYLxMbCnLkYV14ZPgEvJ558Eh59VL12+js5Fc9q1WD218pa40lxv5hpWnbuDL6sGg1awdFowkfTplCvnucoIcOA/k9gxHjxMRn/MVx9tWrrvLA4X1etCpMmBV7uEGM0bw7/7YERI+G226BtW3jjTdj9H0bbtuEW77LBsFjgo/Hwyyp44EFlGWzTBr6YCus3KH+wtWu9T4larTB7duiE1lzWGCLeirvkTRITE4mPjychIYG4uLhwi6O5jJH//oMWzWHfvvRIKqtVWXY6dICZszCiorz3ce6ciqaaOEElXitbFno+DD16YBQqFPyd0GgA2boVal7rvVFUFAx8GmPYsNAIpclzZOX6reMqNZowYlxxBbJxE0yZAlO/gJMnoVp1NRXQoYNfeV2MAgWgb1+1aDThokIFiI6GlBTPbVJToXr10MmkuazRFhxtwdFoNJqAID17wNSp7tMXGIbypTp8RCnlGk02yMr1W/vgaDQajSYwvPkWlC6d2a/MaYmcMFErN5qQoRUcjUaj0QQEo0wZWPM7dO2qwvudNG4MCxdh3Hdf+ITTXHboKSo9RaXRaDQBR86cgQMHIC4Oo2zZcIujySPoKSqNRqPRhBWjUCGMq66KKOVGzp9Hxo1DGjZAypZFrmuIjB+violq8hw6ikqj0Wg0eR45fhxuagFbt15cIXDkMKzvCx+PR35ahlGkSDhF1ASYkFhwxo4dyxVXXEFsbCyNGzfm999/99i2RYsWGIaRaWnXrl1am+7du2f6vE2bNqHYFY1Go9HkRh7tpeq6iaTnnHK+3rwZ+vQJr3yagBN0BWfGjBkMHDiQoUOHsn79eurUqUPr1q05evSo2/Zz5szh0KFDacvmzZuxWq3cfffdLu3atGnj0m7atGnB3hWNRqPR5EJkzx6YN89zaRSHA2bPQg4eDK1gmqASdAXn3XffpVevXvTo0YNrrrmG8ePHkz9/fiZPnuy2fdGiRSldunTa8uOPP5I/f/5MCk5MTIxLuyLatKjRaDQad6xenW618YRpwm+/hUYeTUgIqoKTkpLCunXraNmyZfqAFgstW7Zk9erVfvUxadIk7rvvPgpckjth+fLllCxZkho1atCnTx9OnDjhsY/k5GQSExNdFo1Go9FcJngqAJrddppcQVAVnOPHj+NwOChVqpTL+lKlSnH48GGf2//+++9s3ryZRx55xGV9mzZt+Pzzz1m6dCnDhw9nxYoVtG3bFocH8+OwYcOIj49PWypUqJD9ndJoNBpN7uKGG9KTDXrCZoP//S808mhCQkSHiU+aNIlatWrRqFEjl/X33Xcf7du3p1atWnTs2JHvvvuOtWvXsnz5crf9vPDCCyQkJKQt+/btC4H0Go1Go4kEjLJl4d57VSFbd1it8OCDGCVLhlYwTVAJqoJTvHhxrFYrR44ccVl/5MgRSpcu7XXbc+fOMX36dB5++GGf41SpUoXixYvzzz//uP08JiaGuLg4l0Wj0Wg0lxEfjYeGDdVrpzXHqfA0aQLvfxAeuTRBI6gKTnR0NA0aNGDp0qVp60zTZOnSpTRt2tTrtrNmzSI5OZkHH3zQ5zj79+/nxIkTlClTJscyazQajSbvYcTFwYqV8OVXcPPNcNXV6nnadPhpGUbBguEWURNggl6qYcaMGXTr1o2PP/6YRo0aMWbMGGbOnMnff/9NqVKl6Nq1K+XKlWPYsGEu291www2UK1eO6dOnu6w/e/Ysr776KnfddRelS5fm33//5bnnnuPMmTNs2rSJmIz1TzygSzVoNBqNRpP7yMr1O+iZjO+9916OHTvGkCFDOHz4MHXr1mXhwoVpjsd79+7Fconz1/bt2/nll19YvHhxpv6sVisbN27ks88+4/Tp05QtW5ZWrVrx+uuv+6XcaDQajUajyfvoYpvagqPRaDQaTa5AF9vUaDSaAJOQAMeOqXxwGo0m8tEKjkaj0Xhh3jwVZFO4MJQsCRUqwPDhkJISbsk0Go03tIKj0Wg0Hhg9Gjp2hLVr09cdPAgvvgh33AGpqWETTaPR+EArOBqNRuOGf/+Fp59Wry+dljJN+PFHmDgx9HJpNBr/0AqORqPRuGHCBN/Z/T/8MDSyaDSarBP0MHGNJtjI33/D55/D4cNQpgx07YpRo0a4xdLkEkRgwwbYtQuKFlVli6KiYPNm8FDeLm27v/9Wz7m9RmNCAnzxBaxYofaleXN46CHQQaaa3IxWcDS5FnE4oH8/GD9eFcpzMuwtpG9feP8DDF+34JrLmtWroXdv2LgxfV3JkvDmm1CwoMrk703JiY3N/crNypXKn+jMmfR9mT0bXnoJvvsOrr8+vPJpNNlFn/01uZehQ+Hjj9Vruz19ARg3Dl57LXyyaSKetWvhppuUpSYjR49Cr16QL5935cZmg7vvDq6MwWbfPmjbFs6eVZYo01SLiFJ42rSBAwfCLaVGkz20gqPJlUhiIox+V52JPfHOKOTcudAJpclVPPOM0oc95bWZPh2qVnU1DjoxDLUMHBhcGYPNRx9BcrL778A0ISkp/R5Co8ltaAVHkzv56Se4cMF7m3PnYPnykIijyV3s2aOmZrxZaJKToW9fqF5dvbfZ1GIYavrq22+hdu3QyBss5s71/h04HKqNRpMb0T44mtzJ+fOBbae5rDh0yHcbq1VZMDZtgsWLYcECldyvQQPo0kUpObmd5OTAtNFoIhGt4GhyJzVr+tfu2muDK4cmV3Kx1q9XHA4oXVqFirdpo5ackpQEs2Yp593kZKhbV/n7lCuX876zQ6NGyg/H6bp2KTYbXHddaGXSaAKFLrap4yBzLdKkCaz7w72N3WqFJk0wfv4l9IJpcgX/+x/89ptnH5zYWJV5ID4+MOPt3AktW8LevUppMk11mBqGyrnTvXtgxskKP/8MN97ovc2qVdCsWWjk0Wh8oYttai4PJk9WiTou9QK12SAuHiZOCo9cmlzBiBFK0fCUSeC11wKn3CQnK+XGGZHkVKocDmU96dlTKRuh5oYbVDg4KGXLifP10KFaudHkXrSCo8m1GNdcA3+sg27dICZGrYyNhe49YN26yzLZ35kzyhrw9NPq4rRpU7glilz+9z9VbqFyZdf18fHw3nsqyipQfP21stx4cui1WmHkSM/bm5j8xm/MYx5/8AdC4Azvb7wBc+ZA06bpCl+zZvDNN/DKKwEbRqMJOXqKSk9R5QkkJQUSEyE+HiMqKtzihIUZM5Ql4MIFZcQyTXVBbd8evvoKChQIt4SRiYiahnFmMm7ZUunJgeSBB9Tv4y1iyWpVTsyXWpTmMY8BDGA3u9PW1aAGH/IhLWkZUDmdliWdH1MTqWTl+q0VHK3gaPIAP/2kLsyQOTWQ1Qq33abCmjXh4e67lRXH19k2NdV1xnUOc+hMZwAXq40FCwYGP/ADt3JrMETWaCIS7YOj0VxmvPKKuut2dwF1OGD+fPjrr+z3L6LyxgwfDqNGwZ9/Zr+vy5H69b2XdDAMuOYaV+XGjp1+9APINCVlYiII/ekf0OkqjSYvoRUcjSaXc/y4clD1VVZg9uzs9b9jB9SqpQowvvQSDBoE9eqp90eOZK/P7HCBC0xiEjdzM3Wowz3cw4/8mCsu8D17ujrxXooIPPmk67qf+IlDHPK4fyYm29nOH/wRQEk1oUaOHUPefBOpVQupVBFp2waZNw/xFN6n8RudB0ejyeWcPeu7jWEoB+SscvSoirQ5cUK9z6hE/for3HwzrFsXeJ+VSznIQW7iJnawAwsWTEy2spVZzKILXficz7HiRYMIM6VKqYL3DzygLG3OvDPOcPHOneHhh123OYB/RaD2s5/r0MlqciOyZQvc1AJOnkx3gDp4EBYtgvvuQ76YiuFNM9Z4RVtwNJpcTunSkD+/9zZ2OxQq5J8ylJGPPlLKjTvrkN0OW7eqxHXBpjOd+Zd/AWW5ADWFAzCNaQxnePCFyCH33aeUwo4dITpaKTc1a8LEifD59BS+ts6kO93pQhfe4R3ykc+vfkvhR9bCMGNiso997GVv2u93uSMOB7S/A06dck3G5PyzzZgBY8aERba8gnYy1k7GmjzAE0+oAurepqlAWVp69FChwUWL+u63alUVXeQJiwVuvRUWLsyavFlhLWtpRCOvbYpRjIMcJJro4AkSYESUZe1f/uVWbmU3u7FhS1MAbNiIIYYzuDe9GRhUohL/8i+WCL1XNTEZxzhGMYo97AGgHOUYwACe4qmItroFG/nuO6XgeKNcOfhvj7biZEA7GWs0lxlDh6p8Lr7Og0lJ8MknKgfM6dO++z11yvvnpql8gILJEpb4bHOCE2xjW1DlOMc5jnM8YBYIw4AkkriFW9jHPkBZpcyLj1RSOYtnk5sgvMu7EavcCEJvetOf/uxlb9r6AxzgWZ7lQR68vK05P/8MvlJaHDigEihpskVk/jM0Gk2WKFZMlR3o3dv3dJXDocoGjBjhu9+qVb3nRLHZoFq1rMmaVbaz3a925zgXlPGXsYxbuZWCFKQEJShNaV7lVc6T80Kus5jFHvakTbdlRBCsWGlEI4pRzOWz0pRmJjO5kztzLEOw+ImfmMAEIHMUmCBMZzrzmR8O0XIX3sLvNF7RCo5Gk0coVgw+/FBZVAYM8K6YOBwwfrzvKa3evT3XagLlh9OrV/bk9Rd/LRQGgb8QfMmX3MItLGNZ2rpjHOM1XuMmbsqxkjOf+V73z46dTWziIAeZz3wmMpEf+IF97ONu7s7R2MFmPOOxeYljsWJlHONCKFF4kD17kCFDkPvuRR55BFm0SEVI3XSTSnzkjYoV1aLJFjqKSqPJY+TLp4IynBE6njh1SiV/LlLEc5uHHoLPPlOZfi/tyzCgSxd1ng4m1anuV7s4AutPd4ITPMzDCIIDV03QxOQP/mAkIxnK0GyPkUSSz2maZJKJIorbuT3b44SDzWx2a5ly4sDBFraEUKLQI++8A88/p/4sIupPOXmSKtH+3QJl/ty1y/OdxoCBGDqtdLbR35xGkwfxp0ikxeJ+Oss0VbSVaapon4UL4amnoGDB9DbFisHrryvlJ9gW9La09dmmHOW4iqsCOu4XfEEqnu+wTUzGMjZHfiR1qOPV0daChZrUDIp1Ktj4o3AWolAIJAkPMmsWPPtMes0U00zPD7Bhg8oN8O18KFHC9U/kzPbYvTv07x9yufMSWsHRaPIg99yTfi51h80Gd96ZXqMUVPqNJ5+EwoVVSHnBgmqK6uhReOcdOHwYfv8d1q9XbV96ybdTcyCoQx1u4RavUzmDGORXRM4mNvE4j9OEJrSgBWMYw2lOu227mc0+p8eOcYxT+PDE9kIvenlNVGhi0p/ceZG7j/u8KmYWLHShSwglCh0iAm+87ln7t9vh55WQkABbtsLIUdCwIVSrDrffDj8shEmTtfUmp8hlSEJCggCSkJAQblEiErvYxRQz3GJocoBpitxyi4jVKqJs4+mLYYhERYmsW5fefvdukdKlM7e32USKFBHZsiVsuyIiIsfluDSUhoIgVrEKgtjEJggyQAb4dbyOkBEu2yGIIYYUl+Lyl/yVqX1/6e/S1tPjrJzN0b59LB+77JdTLkMM6SSdxC72HPUfLk7JKSktpV32y/mwmlYpcKGo9Hv9sLz1lsjOneGWNrCYBw6IaeB9ibKJ+dJL4RY115GV67dWDzUApJDC+7xPNaphw0YssdzP/axnfVDHlZ07lQNer17qeefOzG1ME9m2DVm/HklMDKo8uZUzZ2DKFHjzTZU47vRpmDsX2l6c3bFa0yNSixaFBQtUfSQnjz4Kx45ldgWw25WfTteuodgLzxSjGKtZzTzmcTd305rWPMZj/MmfvMu7PqdwFrCA53gOwMUvRBBOcYpWtOICF1y2uZM7vfqQWLHSkpYUIGdl2h/lUZaylFu4JW0/qlGNsYxlJjNzba6YwhRmBSuoTGUAoi4+AMx95TjXaDkfv1aKwYOVK0rXrpCcHE6JA0hSku82huFfO032CYHCFXFoC44rSZIkN8vNaXeNzrss28XHfJkf8DFNh0PMJ/qrOxmbVd3N2Kzqfb/HxXQ4VLvJk8WsUjn9ric2Rsxej4h5/HjAZYp0HA6RI0dETpxwXT92rEi+fMoyY7Op55gYkTffVJaczZvV65dfFpk+XSQpyXX7f//NbOVxt6xfH7p9DTTNpblbS0LGxxSZ4rKNKaY0lsYetzPEkCWyJKBypkqqXJALAe0z3NjFLgtkgTwjz8id/z4tdPhGsKZmOr4sFpFu3cItbWAwk5LEjI/3bcX54otwi5rryMr1Wys4GnlL3hKLWDyexAtIAUmUxICOab7yivc//pAhYr7+unptMVw/s1nFvKqGmKdOBVSmSCU1VWTUKJEKFdIvBnXrKmVlyhTvSsnIkb77/+Yb/xScTz8N+q4GhVRJdVHc3T2sYpUH5cFM2x6TY9JYGguC2/9IBakgy2RZ6HcqF2KaItWrKwXc0zFmGCK7doVb0sBgPvts+k3bpYvVImbRImJeyFvKbCjQU1QavzEx+YAPPEaCCMJ5zvMlXwZsTDl3DkaN9N5o1EgYMvjiBpc4YToc8M8/MNJHH3kAh0MFWzz7LOzbl75+40ZV26hfP+/bv/YanPeRqiWffyWP/G4XaTi1EV9t3E1HFac4q1lNe9q7/Y8c4ACtaa0revtg9264+mpVmd5bcSCLJftV7yOOIUOgbr3MCalsNrVMm44R7Cq1lzlawbnMOcEJDnHIaxsrVjawIXCDLlsG53xknb1wwXemuo/Hq2iFPMyXX8K8eZkvCs6cNL6KZ54547tO1PXXq6gpb0RHq5pTWcGXUhEqooiiDnW8RkQJQlOauv1sN7s9Ztw1MXHgYAhDAiJrXiQhAZo3V/ckvrBYlM9XXsAoWBCWL4fXXlc1pUA5wnW+G9b8jtGqVVjluxwIiYIzduxYrrjiCmJjY2ncuDG///67x7ZTpkzBMAyXJfYSLVdEGDJkCGXKlCFfvny0bNmSnW6cUzW+8bc4YQwxvhv5iy/lxokv5eXkSf/7yqV8+KF3Pc8fTp70/nn+/PD0054jWg0D+vTxrzjnSU4ylKGUpSwWLBSlKE/zNAc4kHXBA8gABni0UlqwkJ/8dCWzJ7UgPM3TXpU1Bw4WspCT+PiiL1OmTIH9+31nzQaV2DfYpT9CiVGgAMaLL2Ls2w8XkuBCEsZXX2HUqRNu0S4Lgq7gzJgxg4EDBzJ06FDWr19PnTp1aN26NUePHvW4TVxcHIcOHUpb9uzZ4/L5iBEjeP/99xk/fjxr1qyhQIECtG7dmiTtkZ5l4omnGc18posPaBbVa6/1r52vK3tUlCqPnYfZutV7NmJ/qFLFd5vBg+Gxx9Rrm01FXTnzjd1/v3+zgYc5zHVcx5u8mWYVPMUp3uM96lLX75pSwaArXemFqimRMSrJho0oopjDHApT2GUbQXiMx/iGb3z2L4hWcDzw5Ze+71VAKdKFCqkp2byIEROj89qEmmA7BDVq1Egef/zxtPcOh0PKli0rw4YNc9v+008/lfj4eI/9maYppUuXlpEZvCdPnz4tMTExMm3aNL9k0k7GrsyX+R6dL21ik1pSSxziCOiYZtOmnh3wbFYxr77adw6JB7oEVKZIpEQJ/xyAPS2xsSJDhojs3+/feFu2iDz7rMj994sMGCCyYYP/snaSTh4jjqxilQbSIFvfQaAwxZS5MldulpuliBSR0lJa+kpf+Vv+dtt+gSzwmQMn4/8k0I74eYVq1fw7Vg1DZMaMcEuriXQiJooqOTlZrFarzJ0712V9165dpX379m63+fTTT8VqtUrFihWlfPny0r59e9m8eXPa5//++68AsuGSM++NN94oTzzxhNs+k5KSJCEhIW3Zt2+fVnAu4QP5QCxiEatYxRAj7UJ1tVwt+8XPq2MWMLduVVEEUbbMikuRwmJu3izmrS3dK0FWi5j5YsXctCngckUajz+uQr+9XRiiotwn9MsYfhsVJeKn/p8tDsgBj5F4GR9/yB/BEyLAtJN2PkPLncqNuwgsjeKOO7wfnyASHy+yeHG4JdXkBiImiur48eM4HA5KlSrlsr5UqVIcPnzY7TY1atRg8uTJzJs3j6lTp2KaJs2aNWP//v0Aadtlpc9hw4YRHx+ftlSoUCGnu5bn6Ec/drGLF3iBO7mT+7mfOcxhIxspR7mAjiVr18KYMXDVVVC+fPpcSHQ0PPggrP0D49pr4es5cEd79VnGOZNSpWDhIoyaNQMqVyTy5JNqJs6dZdtmg0qVlM92ixae+zBN5dvwwAOwbl1w5NzIRr9qMq0jSAIEgQ1syFRk0x1xxPEar4VAotzJY4/59r+ZNCnrTuwajS8irpp406ZNado0PZqhWbNmXH311Xz88ce8/vrr2erzhRdeYODAgWnvExMTtZLjhkpU4nWy9x37g5gm9Hscxo9XV2e7XSkuDgfUrQsLvscoUyatvVGoEMyZg2zfDvPnq8iq2rWhXTsMW8QdukGhWjUVBXXnncpZ2FmUGJTS8/jj0KwZLFmiil8O8RLMY7HA6NEwdWrg5QyLs3qQ+JEfeZu3OchBn23jiGMNa9Ky9Woyc9ttKqXBjBmZfXEMAzp0UMe3RhNogmrBKV68OFarlSNHjrisP3LkCKVLl/arj6ioKOrVq8c/F2MMndtlpc+YmBji4uJcFk0YGD1aKTeQXgnSeWu3aRP07OF2M6NGDYxnnsEYPBijQ4fLRrlxcuONqpr3paSmwnPPqTtkEVi92ntlb7td6YnBoAlNfFaPtmKlFZERGruYxbSjHUUpSklK0oMe/MVffMzHtKIVK1jhsw8Dg5d4iSu5MgQS514MQynVb74JJUumry9eHF59FWbNynmkoEbjjqAeVtHR0TRo0IClS5emrTNNk6VLl7pYabzhcDjYtGkTZS7e2VeuXJnSpUu79JmYmMiaNWv87lMTeiQ1FUaO8NzA4YBFi5CtW0MnVC5h48Z0y0zGO2Dn6wkT4NtvVR0fX9EqqanBkTE/+RnAAI81oSxYeIiHKEMZt5+Hkpd4ida0ZhGLOMUpjnGMqUylPvXpQx8An1NTVqwUoQg96RkKkXM9Viu88IIKF9+6FbZsURXpBw9On3nWaAJN0PXmgQMHMmHCBD777DO2bdtGnz59OHfuHD16qLv1rl278sILL6S1f+2111i8eDG7du1i/fr1PPjgg+zZs4dHHnkEAMMweOqpp3jjjTf49ttv2bRpE127dqVs2bJ07Ngx2LujyS5btoCX1ACAuo3LkJVOLlxAJk9GWjRHrr4Kue02ZM4cxJ+EGkHi3DllhGraFKpWhVtuUaZ3u+eajDnGOaPnCasVPvgAGjdWr721u+66wMvnZDCD6UY3QIVfZ3xuRSvGMS54g/vJ93zPW7wFuCoxduyYmH4nJyxJSX7iJ4pTPChy5lWiolRG42uuSS/+qtEEi6Drzvfeey/Hjh1jyJAhHD58mLp167Jw4cI0J+G9e/diyWCfPHXqFL169eLw4cMUKVKEBg0a8Ouvv3LNNdektXnuuec4d+4cjz76KKdPn+b6669n4cKFmRICaiKIlBTfbQwjzcQgx47BTS3U7Z7Fojxl//kHFv4At7ZC5s0LeZrzw4dVRlZnTkkR2LMHfvpJKTrz5wennMEff3hXoBwO2LBBVREf4cNI9sQTgZfPiRUrn/Ipj/M4k5nMPvZRkpI8xEM0p7nPit+hYAxjsGL1y3nYE1OZyt3c7bffkSZ3kpICp09DXFyeT7eVdwlBVFfEofPghB4zMVGFdvuqrrt0qWrfulXmEPKMYeIDBoR8H26+2XPItsUi8uSTwRn3xht95xApW1a1/fTT9KriGWUDkT59VMHDy5mCUtDv3DbuHjESI6Zc5l9iFvhH/pGn5Wm5Vq6Vq+Vq6S29ZaNsDLdYmTBNkTlzRG66SaRgQZU/yhnabrOpvFBbtoRbSo1IBOXBiVS0ghMezL59vSf3q15NTNMU8++/fStCBfKLmRi6xGqbN/tWMvLlE3EnkmmKrFghMnGiyKxZImfOZG3s0aO9V2C22UT6909vv2qVSOfOIvnzi0RHizRrphKoXe7KjYhInMRlW7mxiU3ulXvDvQu5hm/kG4mSKJdcQjaxiSGGTJAJ4RYvDdMU6d3b9Wbg0sVqVf+nNWvCLa1GKzg+0ApOeDATEsRs0EBMi6GWjMpN0SJiblR3duZHH7l+7mlZtixkso8b513JcC7Ll7tut2KFSNWqrm0KFBB54w3/FY6TJ0WKFXOfLM1iEYmJEdm+PfD7nBe5V+4Vm9i8KjLuEhYaYohNbLJW1oZ7F4JCiqTIbJktnaST3Cg3Sk/pKatkVbatVf/JfxIlUWKI4fY7NsSImKSPX33lX6Zlq1VlZdY3CuElYhL9aTQZMeLiYOVKGPUOXFlNJfYrWRKefAr+/AujVi3V0N8K4SGsJJ6dodauVcnLdu92XX/uHLz8svecNRkpUgSWLlVhtaCcha1W5bKUL5/y/alePevyXY48xVMe/W8sWChAgbScNjZsWLFiYBBDDDOZSUMahlLckHCSkzSlKZ3pzDzmsZKVfM7n/I//0YtefiVwvJTxjPfqtG3Fynu8x2Y2M5jB9Kc/7/EeJziR093JMqNH+xem7nAo/7uffw6+TJrAYIiE8CoRISQmJhIfH09CQoLOieMF2b8fvvoKDh2CMmXggQcwygU2q7HbcTdvhtq1vDeKjYVDhzHi44MuD8DmzVDLD5GOHFFOiaCUm2XLPGdxtdlU2OwlSbk9cuECzJypkvo5HCrB30MPQYi+gjzDZCbTi14YGGnKjlO5+Z7vaUITFrCA7/iOZJKpT3260Y0iFAmz5MGhDW1YwhKPit8whjGIQVnq8zqu4w/+8NomlliSSMKGLe23sGFjDGPSwvUDTXIy/PADHDigTmlt20LBgv4XtDUMGDsW+gRHPI0fZOn6HXR7UgSip6i8Y5qmmIMGKWdeq0XM6Kj01y++KGYIbLRm8+benYz79A66DJfSooV3J+OMfjCHDvk2eVssIu+9F/Ld0IjIDtkhA2WgNJEmcoPcIMNkmByVo+EWK+RskS0+fY+KS3FJkZQs9dtAGuTImXuWzAr4vk6ZIlKkSHphTxCJi/NdJ+vSZcqUgIumyQJ6ikqTM4YNg+Fvq9saZyEj5+thb8HIkcGX4csvoWJF19S8Tjty06YwclTwZbiEr76CypWVSE6xnHlnmjeH4cPT2x475rs/q1VZfDShpxrVeId3WM1qVrKSQQyiBCXCLVbIWcQiLD7SoR3nOBvZmKV+b+ZmrHhJyuQFA4OhDPU4vZUdvvoKuneHU6fUe+e8RWKisob6m0nZZlOlJzS5A63gaFyQc+fg7WHeG731FnLhQlDlMMqVg/UbYPQYVaeqbFlo0hSmfAZLf8IoUCCo47ujTBlYvx4+/BAaNlSFLm+8EaZNg0WLXHPglC7tvWwCqNw25csHV2aNxht27H7lJ0rFNQW2iclSlvIBHzCZyRzBVVPvTe9s5z0ShK1s5R/+ydb2l+JwwDPPeG/jzxSVYUDv3lDi8tODcy3aB0f74Lgg8+dDh/a+Gy74HqNt2+ALlIu54w413+/JByc6Wrk3FS0aWrk0GicrWEELWnhtE0ssRziSVmtsNat5kAfZxS4MDATBho3HeIzRjCYKlaJ4FrPoQhdAKVKgHLft2LFg8em8vJ711KNeDvcQli+Hm27yr62z9q+7dV27qmSaOgNzeMnK9VtXAdG4cuZMYNtdxgwbppyMk5LcKzlvvqmVG014uZEbuZqr2cEOt07GVqz0pGeacrOJTdzCLSSTDJA2jWTHzjjGcYYzfMZnANzN3dSiFh/yIQtZiAMHLWhBdarzIi96lSuKqIBVaPdnuhjUFPOhQyr6UUQ57xcvrqysDzwA114bEHE0IURbcLQFxwVZtw6u8yMUdsOfGHXqBF+gXM6ffyqz9po16etKloTXXlNVwDWacLOVrdzADSSQkKbkOKeXGtCAn/iJQhQClNLyDd+kWWTcsYUtXMM1Hj9PJpmylOUUp9z62diw0YUuaYpSTlmzBpo08d1u+XLlS6eJbLJy/dYKjlZwXBARqF9PxUW7MztYrVC3LsZa7yGgGle2blWltOLjVXi3NnNrIomDHOQDPuAzPuMUp7iCK+hNbx7lUfKhnMvOc5444rzW8bJh4zme403e9Dre93xPBzogiEt/NmyUoQxrWBOwyvMicNVV6v/nztfGMFQ8w65d/jsba8JHVq7f+ufUuGAYBkyarJK6XFrC2mpVnrQTJ4VHuFzMNddA+/bqDjEnyo2JyQxmcCM3UpSilKc8AxjAbnb73lij8UBZyjKMYRzkIBe4wDa28SRPpik3gIuFxxvHOe6zzW3cxgpWcAu3pFmL8pGPXvRiLWsDptyAUmDGjVPPlyowzojIceO0cpMX0T+pJhNG/frw2xpo3yH9X2+1Qsc7Yc3vemoqCzizZwQCBw4e4AHu4z5WsYpTnOIAB/iAD6hJTX7hl8AMpNG4oShFicV7WW1BqEQlv/prRjMWsYiTnGQPezjJScYxjlL4mfkyC9xyC/z4I9Ss6br+mmtUIIAO/c6b6CkqPUXlFUlIgOPHoXjxkGUNzgssWgSjRql5fdNUqXsGDoQ77/QdPu6J93mfp3jKrd+CBQuFKcx+9rvcdWs0geQxHmMykz364FiwsIc9lCcy8x+IqNl3Zybj2rWz/3/UhAc9RaUJGEZ8PEbVqlq5yQIjR0KbNiqCym5XCs5vv8Fdd8Hzz2evT0EYwxiPn5uYnOQkM5mZvQE0Gj8YwhCKUcxjEr8hDIlY5QaUMlOrlvp/1qmjlZu8jlZwNJoAsmEDPPecep3RR9v5euRIVUsqq5zkJLvZ7TW7qw0bv/Jr1jvXaPykHOVYwxra0tYlkV9pSjOOcQzBzwqyGk0I0HlwNJoAMm6c8s22e4iitdng/fehZcus9etv2nub/ktrgkwlKjGf+exnP9vZTgEK0JCG+tjTRBz6iNRoAsjvv3tWbkB9tnZt1vstTGHqUIdNbPKYAdaOnZZkUXPSaLJJ+YsPjSZS0VNUIeI855nMZO7hHjrRiWEM4yhHwy2WJsDExASmjTue53mPyo0VK5WpzB3ckb3ONRqNJo+hFZwQsIlNVKEKD/MwX/M13/ANL/MyFajA13wdbvE0AaRDB+/5NGw26Ngxe33fz/28zMuqn4vGV+PioxSl+IEf9DSBRqPRXESHiQc5TPwMZ6hKVU5yMlOSLAMDK1bWspa61A2qHJrQcPQoVKsGZ89mzppqGKrA5ubNcOWV2R9jPev5iI/YyEYKUpDOdOZBHkxLp6/RaDSBQETgl1/g11/VndvNN2M0aBBWmXSxzQhiKlM5znG30S/OdaMZHbC6K5rwUrKkyoHTti0kJLh+li8fzJ2bM+UGoD71mcCEnHWi0Wg0XpB//oG7OsGmTSrRK4DDgTRtCrNmY5QtG14B/UArOEFmPvO9fm7HzjzmhUgaTSho0gT27IGpU+Gnn5Ql5/rroXt3XT1co9FEPnLiBDS/Mb0Ue8acF2vXws03Ies3YOTPHx4B/UQrOEEmmWSvuUsAUkgJkTSaULB2rbLipKRAt24qDbzVvyhvTRAR01RmtdhYjHzZy/YsqanwzTfw5Zdw7ChUvRIefhhuvFHVcdNo8gIffwxHjrivTmq3w44dMG2aOvYjGO1kHGQa0tBrDhMrVmpTm+EM5yquoihFqUtdxjKW85wPoaShQf76C/nyS2TuXCQxMdziBJSjR+GGG6BRI3jlFRg2TBXYrNjwKI8deJUqVKEIRahPfT7mY5JJDrfIlwVy4QLy5ptQvhwUKwoF8iOtWiHLl2etn5MnVSn4e++BBd/B6tUwfRrc1AIeeghx+C5EGSzk+HFk6FCkQgUkNgapVBF5/XXk1KmwyaTJxXzxhXvlxolhwJdTQydPdpHLkISEBAEkISEh6GP9K/+KRSyCl0dxKe7Sxrj4qCf15LScDrqMocDcvFnMhg3FNEhf8ucT86WXxLTbwy1ejklJEaldW8Rmc5bXvLhcuUM4VEqwWzP9vs2kmZyVsx77PCWn5G15W6pLdYmTOKkhNWSUjJJESQzhnuVuzPPnxbz+f2JaLa7Hns0qpsUQ84sv/O/rtrZqu4z9OBeLIearr/rfl2mK+dtvYn7yiZhffCHmsWPZ2T3V1549YlaskFk2q0XMqlXEPHgw231rLk/MUiXdH+cZl1o1wyJbVq7fWsEJAeNlvCCIVdIvck6FprSUdlmf8WEVq3STbiGR0R9M0xTzjz/E/P57MTdv9n+7f/4Rs0hh9xcHiyFmn95BlDo0zJp1iWKDCJjCn7WFFJvH3/cJecJtfwfloFSRKpmUY4tYpIbUkKNyNMR7mDsx33gjs3KTcYmJFvP4cd/9bNvm+4RfpLCYFy747uvPP8WsXct12+goMfv3EzM5Oev7ePNNYkbZ3MsUZRPzjtuz3KfGFbtd5LvvRN55R+Tjj0UOHQq3RMHFbNbU+/8myiZmpzvDIptWcHwQagVHRGS5LJfb5XaJkiixiEXqS315S97yatlBEJvYIuJiZs6bJ2b1aq4Hef16Yv7yi+9te3T3fAJ2Ltu3h2AvgkfnziJW6yUKTrNffP6++SW/W4tMK2nlVfG9U8JzcslNmKYpZtky3o87q0XMUaN89/XBB0oZ96XkrF7tvZ9//hEzPs6zsv9Al6ztoz+Kl8UQ87//stSvJp2lS0XKllX/aatVxDDU8+OPK8ttILHbRZYsEfn8c5HFi0VSUwPbv7+Yn33m+7j64YewyJaV67f2wQkRzWnOfOaTTDKppLKOdRSnuM/t7NhZz/oQSOgZmTUL7uwI//zj+sFffylv+lWrPG+bnAxffeW9foHNBp9/Hhhhw8TJk66BBgA0XQ12797F5znPFra4rPuHf1jM4kx5k5w4cPAN37CPfTkROe+TkACHDnlvYxiwZbPvvux2/0pPezvOAYa9BefPuzlYUHrxV18hf/3lexwnf/zhu40IrA/vOSS38vvvqvL44cPqvcOhvk6HQ9Wd69s3a/0lJalTXbt2yp3r4YfVGABffw0VK6o6dV27QqtWUKECTJ8e2H3yi/vvh1taus9aahhwz73QunXo5coiWsEJMQYGlotfu78FFP1tFwwkNRX690s3TGTENNU//cknPHeQmKjCiXzh60IU4dSoofQ0FxxWMHzn0bz09/2d331uIwhryUZRq8uJmBjfSolhQKwfEVWNG3t3ugSIiYVatTx+LHa7ir7ypex/8YVveZxER/vXLirK/z41aQwdqn52dz+9CEycmPm+zxMHDkDt2iqycuFC5aP++efq0GrXDu6+Gw4edN3m8GGla8yYkfN9yQpGVBTMnw8Dn4ZCGRKIFi0KQ1+BqVNzRdSgVnDCyE3chIH3gyQf+WhEoxBJ5IbFi1V4kCdME9avRzZ7uAuOj/ddfEkEckHSKG88+qib69aSlmD1flEsQhFqU9tlXbAqh5/lLJ/wCd3pTk96MpWpJJGUpT5yE0a+fNDyVu8x+nY73Hmn786aNIE6ddxosRexWqF7N4z4eM99nD0LyT4i50RU+Lm/tGjhWSYnFgu8PQzp0wfZsMH/vi9zTp5U6R68BcdZrSpa2hciKqJy92713qkwOc8Z33+f+f4xIwMG+DYOBhojNhZjxAg4dBjW/gHr1sOBgxhDhmD4OuYiBK3ghJHKVKYjHT1e0CxY6E1v4ghuOQmv7N3rX7t97qdLjOhoeOAB7ydhh0PZZHMxdevCwIGXrNxcC5bcAqnuf18DgwEMIAZXBbA5zX0qOdFEcz3XA/A3f7Oc5exgh8f2K1lJecrTm95MZSpf8AUP8RCVqcxfZGFKJIyICLJyJTJhAjJ9OnL6tO+NXnzRs+XFZoN69eCWW3x2YxgGzJwFxYq5KkyGoZa69WDESO+dFCoEBQr4GgjK+V+h2yhZEnr08F4AzTRVqv1JE6FBfWTQIJWCX+OV06e9Kx2gvvYTJ3z3tWqVmiXMrpJy6BBkMatBwDDy58do0ACjXj2M7FYKDhdB9wiKQMLhZOyJU3JKrpPrXKKsnM/tpJ0kSVJY5TNnzfLtbGYg5tq1nvvYvVvMokU9h9g+0T+EexQ8TFNk3DiRihXTHY0LVj4qxQ/Ucomcs4mKqrpf7he7pIfIb5Nt8pg8JsWleFobdw+LWKS39Jaf5CepJ/VcPmskjeQXcXX83i27Jb/kd5uuwCpWKSbF5IScCPXXlSXMVavErHal63GTL1alGXA4vG/75ZcqWspqUc7uTof3+vXEPHw4a3IcPizm4MEqLLtQQTGvvVbM998X8/x5/7bv3z/gDvfm+fNitm2bHt3iz/910qQsjRHpnJEzskSWyCJZFLCgjLNnRaKj3UVHpi8Wi8jo0b77evllNykksrhkIaNBnkZHUfkgkhQcEZEUSZEZMkNuk9ukntSTTtJJFsgCcYj3E3coMM+dU1Ef3iI0ql0ppml672fbNpWPJOO2cYXEfPVVnxeo3IbDIbJ9u8jmzSLnz4skSZJ8KV9KW2krDaWh3Cf3yRJZIqakf2eLZJFEO2LE6sis2BhiuCi+raW1zJN5YhWr2zDyKImSFbIire+n5WmPEVnObUaJ70iicGFu2KCUGU9hq6VLqXwyXpQM8/hxMd95R8wePcTs21fMxYtDetyZR46IuXatUtTKlPasiDz1VPb6N00xf/xRzIceVIqbr6iq6tV8/mdzA8mSLM/IM5Jf8rtEnj4kD8kpOZXj/rt3966YREWJHPVDn3rhBdU2JwrO0qU53p08QcQpOB9++KFUqlRJYmJipFGjRrJmzRqPbT/55BO5/vrrpXDhwlK4cGG55ZZbMrXv1q2bAC5L69at/ZYn0hScSMd8/33vJ8tvvvG/ry1blFVowQIxz50LotS5h9VbT4vlfAHB7jkh5BVyhXSWzrJAFkiqpMoVckWa4uNOYblGrklToCpJJZ/h6s2kWZi/Bc+Yd9zu2fqXcalXT8xTp8Itrgvmzp1iduzgqpzVvFbMhg1cw86LFBZz2LCAKB3moEH+WXL27g3AHoYPhzikg3TwaJmsLbW9JtL0hz17REqUcJMC4uLy7rv+9fPNNzlTbsqXVyHkmghTcKZPny7R0dEyefJk2bJli/Tq1UsKFy4sR44ccdu+S5cuMnbsWNmwYYNs27ZNunfvLvHx8bJ///60Nt26dZM2bdrIoUOH0paTJ0/6LVOoFZzTclpmyAyZJJNklaxyuXPPLZjvv59uyXGemEuWEHPGjHCLlqv5+2+R2Kc/EBzulRXno4JUSNtmuSz3qbAgyB/yh4iIlJSSPtvWkTph+ga8Y5486V/+GQOlBN13X7hFTsPcsUPMokXcZxi2GGJ++KFS9H/6Scwk/6aizd27xVy6VMz16z0qQ+Yzz6jEgb6+r127Arm7IWeRLPJ6TBtiyHvyXo7H2bVL5I47VP4bp8JRqZLIZ5/530dqqlJSPClKzr4zjuF8bxgiX3+d493IM0SUgtOoUSN5/PHH0947HA4pW7asDBs2zK/t7Xa7FCpUSD7LcDR169ZNOnTokG2ZQqXg2MUuL8lLEiuxLn+8q+VqWSOerViRinn+vJizZ4s5bpyY8+eLGegsV5chHTuKGF88KKR6nkJyPrbIFhERmSJT/FJwZstsEfGeNBBRJv3u0j2cX4NHzJ07/VNuMio5Bw6EW2wRETHb3+G9tIOfmY9FLpY6ueUW1z6urOr2BsMvv7kSxcUMVxa5AHGP3OPVV80QQ66VawM23oEDIitWiKxfr6ahs8q6dSLx8a5KjsWinlu2FJkzR6RyZVcFp1IltV6TTsQoOMnJyWK1WmXu3Lku67t27Srt27f3q4/ExESJjY2V+fPnp63r1q2bxMfHS4kSJaR69erSu3dvOe4l3XpSUpIkJCSkLfv27QuJgvOEPOF2GsEiFskn+WSjbAzq+JrI5tixiye4yd0Fu3cLDoI8Jco/4zv5zi8FZ7ksFxGRb+Vbn23Ximcn8XBiJiT47zjrXGbPDrfYYh465J/lado0331t3eo5+7GBmBMnurZPSVF+Pp58lqwWMV95JVi7HjIaSSOfx3WcxLnd9i/5Sx6Xx6W5NJc75A75XD6XC+KfspkT9u4VefZZkTJlRAoWFKlfX2TixPSMyA6HyC+/iMycKfLzz9lTpPI6EaPgHDhwQAD59ddfXdY/++yz0qhRI7/66NOnj1SpUkUuZLjTmTZtmsybN082btwoc+fOlauvvlquu+46sXuYpBw6dGgmn51gKzi7ZbdHHwlEzRF3kk5BG18T+WzcePFO7b6v/FJYrpQrRUQ5LReRIl7blpWyaRFappjSS3ql3dVmVLQRZKgMDeO34Bvz/vuypuREgD3f/O03/2R97DHfffnyQSpYQMwzZzKPX6ig6/fmVHha3ZqtmleRRntp79UyiSBVpIrLNqaYMlgGC5Iezej8H1SVqrJH9oRpbzT+kmcUnGHDhkmRIkXkr7/+8tru33//FUCWLFni9vNwWHDelDd9/vksYpEE0Y7OlysHD15UcKKTPBbkzPjI6IczTsZ5bfu5fO4ylimmTJJJUlNqprVpJI1klswK2f6aJ0+KuXKluvj66XMicnGaKq6QfxaRKFuWQ7+Dgbl9u38KTv163vs5fNj3flsMMadMybztrl1iPvWUqgxdIL+Y9eqKOWFCnplani2zfZ5f35A3XLb5Qr7w2N4mNqkpNSMielXjmYipRVW8eHGsVitHjhxxWX/kyBFKly7tddtRo0bx9ttvs3jxYmrXru21bZUqVShevDj/eMiZHRMTQ1xcnMsSbI5wJK0kgydMTE7gR5YoTZ6kTBmViNbqiIFv71B2RQ/YsNGMZmnv+9CH93mfAqjEcc7EgHHE8Qmf8BAPuWxvYNCTnmxiE+c4xwUusIY1dKZzwPfrUuT0aeSRh6FMaWh+IzRtAuXKIm+9hfgqfwAqy1lKiu+sa1Yr3Hc/RqlSgRE8A7J9O/L440jZMkixYkirW5Fvv/WcMK9aNd9J/QD+/df75/v3+95vmw327Mm02qhcGWP0aIzDRzDOnsNYvwHjkUdUGv48QAc60IQmbpNi2rBRjnL0oU/aOkEYxjCP2ePt2NnMZn7ip6DJrAkxwda2GjVqJP369Ut773A4pFy5cl6djIcPHy5xcXGy2kdlXif79u0TwzBk3rx5frUPhZPxcBnuNnzx0juGM3LGd2eaPMuvv6o8G0bDP3xacFbKykzbn5Wz8qV8Ke/IOzJdpst58S/hXKgwz5wRs3Ytz9WzH+7pNTTaTEpSDrGe/Emc/RiI2bSJmImZK7PneB9++EElCsw43ePcn759PEcz1arp24IT795HJK2P3bt992G1iPnhhwHf79zAaTktd8ldmdwBrpfr5T9xraB+SA75/I/ZxCbPyDNh2pvci3n+vJhTpoj56KNi9umjglGC5MQeMVNUIipMPCYmRqZMmSJbt26VRx99VAoXLiyHL5qRH3roIRk0aFBa+7fffluio6Nl9uzZLmHgZy7OMZ85c0aeeeYZWb16tezevVuWLFki9evXl2rVqkmSn2bvUCg4B+SAVwXHJjbpIl2CNr4m97BkiQoh5ZkR6uhISZ/atJrq9SuSO51CzREjvCsnBmL+9pvn7b/6yvcFPjpKzM8/D4pfiXnypJre8TZNNHWq+21fftn7djarmO1u8z7+nj2+vz+bVUwPaTcuF3bLbpkkk+Rj+Vj+EvcuDftkn08FJ0qi5El5MrTCB4A//xT58kuVbycIOr5XzFWrxCxeLP2/6ExRcEUlMbdtC/h4EaXgiIh88MEHUrFiRYmOjpZGjRrJbxlOaM2bN5du3bqlva9UqZJbh+ChQ4eKiMj58+elVatWUqJECYmKipJKlSpJr1690hQmfwhVmPhQGer2T2QVqxSWwrJTdgZ1fE3w2b5dpH9/Fc5ZpoxIp04iy5ZlvR+7XWTRIpF+8xZLnf1tJcaMlRiJkZbSUhbIgkCLHTLMqlV9+8z06uV5+wED/Mvpsnt3cOR/913vSorVImbDhu633bvXt+yLF3sf/9lnfSs4rVoFY9fzHHaxSykp5VPJ+VK+DLeofrNxo0iDBq6h5fnziwweHJoILHP3buXk7u4YtVlVNN/p0wEdM+IUnEgjVAqOKaaMltFSVIq6/IFukBtkq2wN6tia4DN/vkq/njGVu/P14MHhli4y8Es5aXlLevuNG5WJu24dMRtdJ+YN1/sXQRWk3DfmPXf7VjAMxPQQwWnOmuVa/8qp1BmI+dprvsevWMH32C1aBHq38yxvypseLesWsUhxKR72+n/+smOHSFyc++SBhiGSwTMkaJhPP+09ws9iiPn++wEdM2KcjC93DAye4ikOcYilLGUe8/ibv1nJSq7m6nCLp8kBR47A3Xer6sAZKwQ7X7/+Onz/fc7GOM1pVrGKtawlhZScdRYuihTx/rnVCiVKACDvvQd1asPECfDXX7B2rSrD7KsEs2HA5s0BEtiNfL6wWJQMbjA6d4YNf0LPh6FcOShVCu64A35ahjF4sO++z53z3ebsGd9tvCDnziG//YasWYNcuJCjviKdZ3iGVrQCcAkCsWEjlljmMpcYckfF7Ndeg/PnweHI/JkIfPihbx/2HDN7lnsBMvL17CAL4Rmt4ISAaKK5mZtpT3tqUCOssohpIuvXI8uWIXv3Bm+clBRk1izkxReRV19F1q0L2ljhYNIk74E9ViuMHp29vk9zmkd4hFKU4nqupxGNKEc5RjACEz+ijiKJrt28KwkOB3R5AFm2DAY8pdZlVGh8RRA56dgB2bUr22J65JaW4C3Sy2qFFjdhWDyfSo1rr8UYPx5j336MQ4cxvp6D0aKFf+Nfe633789mg5q1/OvrEiQpCXnmGShdCpo1VdFtZcogL72EpORShdoH0UTzLd8ykYnUoQ6xxFKc4vSmN3/xF9dzfbhF9IsLF2DGDO+6v9UKX3wRZEF8KeAicPZskIXwOv7lx+VabNP88ksxK1/haj5s3VrM7dsDO86KFSr3htPpzGmSv/kmMb1knM5NtG3ru0BebGzW+z0jZ6SW1PKYQ+kx8Z0YLpIw9+9XDojuzNg2q5j/ayam3e5/QU1vjrYDBwZe/nPnVM01b7L98EPAx00bf9o03/vuxUnbY78pKWLecrP76TeLIWaH9iGttq7JGmk5tLwsUVEijz4aXDnMm1p4/29E2cTs2SOgY+opKk0m5KOP4MEH4L//MqwUWLoEmjZBPOQQyvI4W7dCm9Zw/LhakZqafpuxciXcdht+5T6JcDzMSGS5zaWMYxxb2IID92bfj/mYdeQea5hRrhys/Bmuvjglm3E65/bbYcH3GFYrLFni29TtDYcDvpmbc4EvwcifHxYugvh41x/UZlPPI0dhtGkT8HHTuOce6Nw588HkfP/0MxiNG2e935kz4aef3FunRODbb+G777LeryYkFCkCvtIZmSaULRtkQfo+7v1/a7fDY72DLIRntIJzGSCnT8PTA91/6HDAmTPw4ouBGWzkSHVQuztxOhyw9ndYvDgwY4WRW25R12pP2GyqTVYZz3iv01A2bExkYtY7DiPG1VfDXxvh519g1Dvw/gewYyfG3G8w4uNVsrzU1JwPlJyc8z7cYNSrBzv/UbI3bw6NGsGjj8HGTRhPPx2UMdPGtljgq2kwchSUL5/+wVVXweRPYcSI7HX8ycfeD2CrVflCaSKS2Fjo0iVdz3aHacJDD3n+PCB06qQEAVcl3HlsDXoBo1GjIAvhGUPE30nuvENiYiLx8fEkJCSEJKtxuJGPP4a+fbz7M1itcOQoRtGi2R9HBArkh6Qkz41sNnjwQYzJn2Z7nEjg5EmoVEk5+XkySP30E9x0k+u6AxxgHvM4wxlqUIN2tCOK9FuxKKKw492pthWtWMSinO5CxCAvvADD3/bd0GLx/GXbbNCuHcbcbwIqWyQhpgmHD6v/asmSGNkxETr7Kl8ODh703qjGVRjbtmV7DE1w2bULGjRQ96fujCgDBsC77wZfDjFN+OgjGDM63au5dm147nm4//4cHafuyMr124v+p8kz7NmjLgDe7pIdDnXCy4GCg8PhXblxtklMzP4YAUYENmxQM3dFi8L113u/K3JStCgsWAC33aZ22XmCsdmUAWv0aFflJoUUnuAJJjABQbBixY6dkpTkcz6nNa0BiCfea/kOK1aKUzwHexxZyP79MNIPK0R0tPLq9oTdDv36B06wbOJwqOi5339Xx0Lr1tC4cfamKy/FsFgCN+dQrJh3BccwoGSJwIylCQpVqqggw0cegdWr09cXKgTPPRc4o7wvDIsFHn8c6dtX3flZrRiFC4dmcB9oBedyoFgx//wbihXL0TCGzYZUqAD79nluZLHAldVyNE6gWLUK+vSBTZvS15UuDW+/Dd26+d7+xhth506YMAHmz1czJM2aQd++6gYmI73pzRSmICgrmtNKc4xj3M7trGQlTWlKV7ryPu979MFx4KALXbK1vxHJV1/5d/X/7HPYvRtefEFZMJzHs/P1s89hZGdOMICsWwd33qkO/6gopTy/8go0aQJz56pjK2J4qCsMet6zRUwEHgz2/IYmp1xzDfz6K2zZAlu3qvJnLVpA/vyhl8UwjBxfQwJOQN2bcwmXWxSVuW+f92RlNquYLZoHZqxhw3wnRtsZ/gzOv/0mEh0tYrG4j0AYPz5wY+2QHV4zp1rFKq1EZaPdK3uliBRxG0VlFas0k2ZiF/dJ5XIj5pNP+pcM8J9/VPvvvxezZUt1zFotKhHg1197rWcVCv77z3PSNZtN5JprRIJQSSLbmKdOqSSC7pIoRtnErFFdzHPnwi2mRpMJHUWlccEoXx7693d/p2wYannjzcAM1r8/1KuXOXeHc+xXX8O48srAjJUDnn5a3fh7uoF95hn/cqz5wwxmuK147MSBg8Us5gQnqEAFVrKSaigrlwVLWvXjdrTje7732leuo2xZ73lmnCQkAGC0bYvx44+QkgqpdoyVP2N06hTwef6sMmaMOl7cGUrtdnV3PWdOyMXyiFG4MKxYCXXrqhVWa7pjaJOmKhFhOMwAlxHbt8PgwfDoo/Dqq64BrprAoKeoLhdGvaP8GMaMUb44TofN0qVh8qcY//tfQIYxChRAli2HoUNVFMaZi1lWnRlcH3ggIOPkhF271PSUN86ehXnz0gMEcsJJTmLB4nHayckpTlGMYtSkJlvZys/8zO/8zn72E0ccFanIWc4ST3zOhYoUunSBFwZ5b2MYMHky1K+PnD+vQsoTEqBaNaRx47ArN6Bm2rzNAlssMH063HdfzsaR8+dVhrelF8PqmzSFbt2y5fNgXHEF/L4WWbsWfv5Zfc833YThVHo0QcFuh8cfh08+UX5ahqFOxa++Cs8+q6bII+CQzhuEwKIUcVxuU1QZMY8dE3PSJDFHjxbzu+9cStqbpinm2rVqGmDz5pyPtW+fmDfdlDmJ2B23i3nsWI77zy4//+w7SZbVKjJ8eGDGe1/eF0MMr9NU0RItZ+SMy3YbZINcJVcJQtr2FrFIN+km5+V8YIQLI6ZpirlmjZhFi/ieoipZQsy33xYzrpDr+muuFvPXX8O9KxIb6/uYat48Z2OYGzakJ9B0TtFZDDELFBBz0aKA7Icm+Dz7rKoV5ek4GTEi3BJGNrrYpg8uZwXHE+bcuWJWu9L14tGgvpirVmWvv/Pnxaxdy3MG25rXhm2Of8cO3xcjEPnss8CMd1yOS7REe1RubGKT7tLdZZt/5B+Jkzi3vjgWsUh7aS+mhNbvxHQ4xFy0SBXYe+oplWU3m44l5r59YjZu5H+m4pho9+utFjHzxYq5bl2A9zZr1Kzp/aJls4k8loMk1ObJk2IWK+r+/2S1iBkbE/CM5JrAc+qUSEyM9/NO4cIiSbmj3mdY0AqOD7SC44o5fXq6deXSE2dMdLbukM2JE71fsCyGmJ98EoS98Y/rrvPsYAwi+fKJJCYGbrwP5AMXS0xG5aaklJS9stelfS/pJTaxebX6rJbVgRPQB+bu3WJee026E6rTMbhUSTFXZ00O8+xZMa+s6l+VcOdx6KtMQ5s2Qdpz/xg3zruCAyJ//JH9/s133sn8/7zUMTgU5aM1OWL6dP9urpYsCbekkYt2Mtb4jaSkQL/H1aTvpYkATVNNGD/1ZNY7/vRT75lSAT6dnPV+A8SoUV6LQPPGGyqfRKDoRz++4iuqUjVtnQULHejA7/xOBSqkrTcxmcpUrwn/bNj4ki8DJ6AX5Px5uPkm2LFDrbDb03MqnTgBrW5Fdu9Ob+9wIMuXI9OnIz//nLk0x9SpyhHKV5VwJ6bp3SnB4YDFi5CjR7OwV4GlZ0+44QbPh/yAASopW7aZ9433RJ12O8yNIC9mjVv8DVy4tN3x4yq/0g8/qFQzGv/QCs7lzg8/qIuUp5OnacLatUhWM5oeOuQ9OkZEtQkTN96oThiVKrmuj4+HDz5QF6RAcz/3s4MdbGITv/IrBznIbGZTCVchkkjiAhe89mVicoxjgRfSHdOmqRAPdwqJw6FKG3/wAQAyaxZUvkIpRF3uh+Y3QtUqyPz56dt85adi5ozwq1HDe0VtUMdTGBWcmBhYuBCef14dQ04qVYJx4+Cdd3I4gK8Emv620YSVa6/1r90116jnM2eU8ly2LLRrpxKLlikDjz0WuCjPvIyOorrc2bfPvfXGXTtnwUR/qFQR9vznWcmxWKBiJfefhYhbb1WZxX/+WeWQK1ZMrYuNDd6YBgY1qem1TT7yUYQinOKUxzYWLJkUo6Axe5b3MgkOB0yfhjRpAvfdm/nzvXuhYwfkm3kYd9zhXaHOyBVXwBNPquNzoA+N0zBUpF4YyZcP3npLBRDu2qUiZKpW9W3I9IsGDVXKbU9WL6sV6tfP8TCSkKCi1M6fh1q1dERVgGnUCGrWhG3b3EfdWa3q5uvKK1Xi0FtvhT/+cG2bkgITJ8Lff6ufylfRzcsZbcG53ClRwr+LTYkspm1/+BHvFhzTVDnGw4zFouondu+uotiDqdz4i4FBL3p5zXdjx04PeoRGoMRE37lqzp3zPJXpPL4GPKXqlVWv7t0iYxgq/PmffzGefFKFkntrb7WqOlRZPUaDREyMuheoVi1Ayg2olNvepvQcjhyVqhC7HRk0CMqUhrs7Q7euUL8ecl1DZMuWbPerccUw4PPPlTJ8aUkYm01Z/z7+WL2fNg3WrHGvCJkmrFwZWbmVIhGt4Fzu3H47FCzo+XPnFEFW7+TuvlvVLXB3YbJaoWlTuNfN3b4GgGd5lvKUx+bByDqAAVzFVaER5tqa3gt0OWskHT7suY2IMmusXg29HvWeNEYE+vWDEyeQ995TDlE33Oi+rdWqNIo33/JvX3IpRq1aMPxiza6M/ymnBtW7t9LQs0uf3qom2KXTXH/+CTdcj+zalf2+NS7Uq6esMvfem259iYlR5WHWr1eKMagSMN4UZItFtdF4Ifg+z5GHjqJyxRw92nu00/z52ev3zBkxH3nYNRV/lE3Mnj3EPHPGdweXOQfloHSWzmIRS1rkVHEpLiNlZEhDxM0//vAd6dSrl38RUbNmqfw399ztPirIahGz1a3qmIyOUu+dz+7CxRvUFzMn4Um5DHPBAjFvapH+3dWvJ+bnn+eoVIW5ebPviMf69dLKZWgCx4ULIocOuQ8Lr1DBd7RVtWqhlzncZOX6bYj4Mz+Rt8hKufXLARGB99+HIYOVV5vTJ6dkSfhwLEbnzjnr//hxVV4ZoFEjjOJ5pxp2KDjMYbawhXzkoyENiSY65DLIoEEwYnhmfy2LRXk+9ukL7W7z3dHPv2D873+I3a4cVt5/Lz0sJC5eTcVcdRX06O5+e8OAtrepOcVq1TDq1MnpruVK5GKdESMADhgyaBC8+45/UW1PPgnvvKsqSGuCynXXqQKunq7QFgv8739qqupyIivXb63gaAUnDTl/XoUWHT2qwj9atQrICTS3YJqwfLmqEVOokLpuFy3q2saOnW/5lvnMJ4kk6lCHHvSgFJ4dXHexi9/4DQsWbuAGylEuuDsSBEREOQ8Mf1t5N4IK5+j/hCrsZRhQoTwcOeK+A8NQTsM7/3G5OEpKiiqFLKIcV2JjoXo15f3tCYsF9uzFKJf7vsdIRHp0hy+/9D9s/9XXMAYPDqpMGhV916+fdxfJyZOhR4hc8SIFreD4QCs4mkv5+Wc1B757d7qRIiYGnnoK3nxTuT3sYQ+taMUOdmDDholyvLViZTKTeZAHXfo8ylF60pPv+R5B/c0sWLiHe/iYj4kj9x17IqJ8bex2KFsWI4M/iEyfrkLDL8WZw2bOXIwOHdLbHzmicuLs2QPFiytn4qQkqF3LuxCGAR98iNG3bw73RZW0slqV4XLZMuUa1Lixcju7XJAXX4RRI/1XcAoWhEOHMQoUCK5glznnzkHDhrBzZ2aXNatVRWP99ltkBEaEkixdv4M3Uxa5aB8cTUbWrVPp091lNjYMkX79RFIlVapLdY/ZhQ0xZKWsTOvzjJyRGlLDbakFq1ilqTSVFEkJ414HB3P6dDHLlXX14ahYQcy5c13bDR+u/LGcPjbOEgRNm/j244myifn229mW0W4Xef99kSpVPPs23HKLyP79Ofwycgnm33/7XzLDuXz3XbjFviw4elSkbdvM56T27UVOnAi3dOFB++D4QFtwNBlp1w4WLfIc2GMY8NHhufQu2cljH1astKUt81EJ7d7jPQYwIM1y444ZzOAe7smR7JGIOBywYoWy9JQrBzfc4DotNXEiPNorZ4PM/cbFGuQkIUHlCPn0UzXTWrEi9OqlrHOxsWoa8r77YPZs76Z/mw3Kl1dRLUWKKMveH3+oqJcbb8w8dZnbkf79YOxY/zeYPgPjnrx37EYq//wDv/yizkU33giVK4dbovChp6h8oBUcjZOTJ9XsiLd/gdUKddf15K86X3gtn2DBQjLJ2LBRhzpsYpNHBceKlVu5lR/4Iae7kKsQh0MlgTx4MGcd/bsL45Kz/MGDqlzCf/+lp+1xzo41bKiSon37LTz0kH9DWCzw3HMqUnrRovRjJDpapXB69101jZkXENNU4fgjhqskf77YtBnD37S8Gk0Aycr1W7vCa7KNHDqEjBqFPPUUMmwYsmdPuEXKMidP+s5zaLHAWUdSms+NJ0zMNAXoEIe8Wm8cODjAgSzLG+mICDJzJnLD9UiB/EjheKRbV+TPP1WDdetyrtxYLMq78hIeeEAlTc6Yk9Bp2F+/XvlTffih/8n3TBOGD1clGDIeIykpMH48dO7sX47M3IBhsWAMGQJHj3nPUGixqDoCbw9DmjVF2rdHZsxQzuIaTaQR3NmyyET74OQM0zTFfPVV5TeR0YfCYoj51JNiOhzhFtFvEhJEbDbvuSYsFpHbf37bJR+NOx+cqlI1rd+6UjdT5fBL/XDaSbsw7nngMU1TzId7plf4zugzE2UTc/ZsMZcuzbq/h7ulVSuXsTdv9p0zJCpKpEABEar/LYx5Qth8jbDlauH9fkKNbX5Veb50Wbo0TF92EDE3bRKzcHzmau82a3pOK+dnzvxE9eqJefx4uEXXXAboauKa4PLBB/DKUOW0YpqqsrTDoc75770Hr7wSbgnTEIFff1V+GG3bqpDKn35Kv/OOi1NJl30l6n27Rg+vpRMAnuCJtNeP4L0MhQMHPenp937kCr78Mt2yktGhyW5X7x/oohxavFUG9wfDgBjXXECrV/veLDUVzHunwZZroe84uHYrXLMNeo+HzTWhS9aqs9tsMGVK+vtt21Ro74cfqrJRuRWjZk1Y+4eKanOmiYiOhlq10yOtnM9Oc9mmjfDgA6EXNsSsYAUd6EChi492tGMJS8ItlsYTIVC4Ig5twck+ZnKymMWLeb+7zhcrZgR8t6mpIl26qDttp5XG+dymjcj586rdP/+IFCkiYrW6v0t3BuxMlaliiOESSWVcfLSVti5RUefknNSSWm6jqCxikRbSQlIlNQzfSvAwGzZIv6N3t1gtYr71lpi3tXW18GRnufoqMRcvTht70iQ/LC41tolhtwoONzY1E8FuEa7ekiULzk03qUiXW29Nj3AxDPW6cWORPXvC+IMEAPP8eTEPHhTz9Gkxixbx/bts2RJukYPGaBktCC7/f+frYTIs3OJdNmTl+q0VHE2WMH/6yb8L0MyZ4RZVBg1Kv9i4m3bq2TO97d9/q9DgjG3KlBH5+GPXPn+Wn+UOuSNtuupKuVLek/fchnyfkBNyr9zrMrUVJVHyiDwiZ+VskPc+tJgOh3flxpnyv9OdYv77r5glimeeAsnK4hzrww9FROTffz3/1mnhtR/2E4vDfZg/gpBiEz7s67dyY7OJ3H+/SM2a7qc5bTaVbv/kSe/f3ZEjImPGiDz3nMi774ocPBiCHyyLmL/95t9v8t574RY1KKyX9Z6Pm4uPVbIq3GJeFmgFxwdawck+5rx5/l2AJk0Kq5xnzojkz+/7AnXokOt2u3aJLFwosmqVsgB5wi52SRI3BWTccEAOyFyZK/NknhyTYznYq8jFNE3XmmOeLoD33qPa79kjZo/u6bWlLIaYhQqmv/ZX0bFYxNy5U0REOnTwbIUDEbbV8HmRYnu1LFlwnnvOt//WiBGevjOR119Xx6HFonyELBa1Dy+9pD6PFMxVq/xTcN55J9yiBoWH5WGPObCclpz75X6/+nI4RFauFJkxQ2TFCvVe4z/aB0cTPPxN8XpViCpde+DXX31Hu9rtKnQ4I5UrQ+vWqhC6N78cK1Zi8C9GuCxl6UhH2tOe4uTNOlyGYUCrVu6rxzsxTWjVWrWvWBFj8qdw4iTs2g0nT8HBQzDqHahWHQoUUIloChXyPrDFgI8/BlTuG2clZgDq/AnDBsH4x+C54RCV6ntHLCb0mAyrmsG+8rCuPvT7AAqczdT0tttUUJi3qCzTdPXTych778Hgweo4dLqymaZyV3rzTRXBFTHUrOk7Za5pQpMmoZEnxPzKr15TRNixs4pVPvuZPx+qVFG5bO69F5o3V+ecuXMDKa0mjRAoXBGHtuB4xvzzTzHnzBFz2TIxPZgwzBtv8OxDYbMq/4gw337On+/fHXiYDU15CnPZMs939zarmKVKinnuXNb6zJ/Pt+XglptFRGUeLldxh/zvhVZS6MRF3ycHQopF+dc4DPXscYrKKhwqme6PI6htHIawrbpQ8nDacXPXXaoSdK1avo+xEiUy71dSkvL78rZdoUIiWfy6gorZt6/3/32d2mH/3weLWlLLp/UvYxSlO7791tVHK23q9OK62bNDtDO5nIiz4IwdO5YrrriC2NhYGjduzO/OytIemDVrFldddRWxsbHUqlWL77//3uVzEWHIkCGUKVOGfPny0bJlS3bu3BnMXYh45ORJZORI5LqGSI0aSOe7kCVLEGe4kK/t16xB6teDenXhrk5w801QsQLy6aeZG380XtWjudTEYbWqaItPp6g7+jBSt65/wToNGwZdlGxjYrKYxTzFU/ShD5OYxDnOhVssjxgtWsD4j5VJw2nJMQy1FC0KPy7ByJ8/a51G+1E5/d9/kT//5I2Rc7nwRw1WvbGYM0UuRnFZgCgTrCZYRD27+0sIYHNAieNgoNqB2sYiUHUXfN4Vm01ZimbPVkn+fJVvctYYTRtGVN2zvn3h1Cnv2545Az/+6Hv3Q8bbb0P9Bum/qROrFYoVg5mzwv6/Dxa3c7vXKEobNtrRjvnMpze96UEP3ud9TqF+ZNOE/v1V20tPyU5V58knPWdT12STYGtb06dPl+joaJk8ebJs2bJFevXqJYULF5YjR464bb9q1SqxWq0yYsQI2bp1q7z88ssSFRUlmzZtSmvz9ttvS3x8vHzzzTfy119/Sfv27aVy5cpy4cIFv2TKaxYcc8sWdXec0cnT6cD5aC+fd1Xm2rVixsZ4dhK96Mjpss3OnWLef79rPoyOHcT8669g7WaW6dDBc44bm02kWbNwS+iZfbJPakrNNMfkKIkSBImTOFksi313EEbMf/8V87nnxLzlZjHb3SbmuHFiJiZmr6/u3X07I1stkhyFlNtriCXVx322eclzmpXm4rOPx68n/k6TbdAg/6yERYuKjB0rsn27ckh2+ub4s+3nnwfqVwkM5vnzYn74oZi1aimfqUoVxRw8WMzDh8MtWlDZI3skn+Rzm9vKEEOiJEqqSJU0fxyb2MQQQ/JJPpkjc2TlSv9+77yYVynQRJSTcaNGjeTxxx9Pe+9wOKRs2bIybJj7sLp77rlH2rVzTYDWuHFjeeyxx0REOTOWLl1aRo4cmfb56dOnJSYmRqZNm+aXTHlJwTHtdjErX+E97HbcOO99tGjuffsC+T1eoMzERHVBO306GLuXIw4dUgUVL72YWK0ipUqpyJtIJFmSPRb2tIhFoiVaNskm3x3lAcy//lIKjg/H45mdfboPe1Z4nIsfj4kyUURE9u3zHbXlTqn26gTtZvnttzD/AJo0fpQfJb/kd4mKtIhFYiRGykk5t/9XQwyxilXeXPy7X7/3F1+Eey8jn4iZokpJSWHdunW0bNkybZ3FYqFly5as9pCZa/Xq1S7tAVq3bp3Wfvfu3Rw+fNilTXx8PI0bN/bYZ3JyMomJiS5LnmHBAlV8x1ulyHff8ThVJXv3qsKI3myj58/DnDnuuy9UCKNKFYz4+CwKHnxKl1YFEocOVTUfLRYoWRKefVbVF6pSJdwSumcuc9nBDrdOjebFxzu8EwbJso+cOYOsX49s3qzqUfmJUbs2zP5azQd5mf5Y3gKislMtwMiw+NVcNfzyS/9LPjhx5jv0B6sVrr0WGjXK2hi5DbHbkQULkLFjkenT1XEiguzahWzciCQkhFvENFrSkt3s5g3eoCUtuYVbeIVX+JAPOcABt/9XQTAw+LHOSL/GKFMm0FJf3gRVwTl+/DgOh4NSpUq5rC9VqhSHDx92u83hw4e9tnc+Z6XPYcOGER8fn7ZUqFAhW/sTkSxfnp5t1B0i8O+/cOiQ+8/9qQtks8GB3Fk3qUgRGDIE9u9XF5cjR2DYMKX8RCpzmON1vt+OnVnMCqFE2UcSEpC+faFUSWjYAGrXgiqVkY8+8ts/zGjfHvbth/YdPI8TAtcPA4PmNMc0Yc2azL4UgcLpyjZpUs6TPkcyMm8eVKwAd9wOT/SHLvdDieJQtgxcWRXq1oFSJZEePZAjR8ItLgAlKckLvMCP/MgSljCYwaxghc//66oS31C+gnj9PcuWhRYtAi/z5cxlESb+wgsvkJCQkLbs27cv3CIFDn/Psp7aXaIousXhiGyNII9xlrM48H6rf4ELIZIm+8jZs9D8RpjwCSQlpX+wbx883hcGDfKvnz//VGa4bVs9XvFv+BlS/fBHzi5WrLSjHfxblWuvVWG9GYt6BgrDgDZtVJqDxo0D33+kIIsXQ6c71R0HpJ+fUlLS1znffzkVmjRGjh4NvaB+cJ7zPgvxphqpjH7Pe5vRo71nWdBknaAqOMWLF8dqtXLkEu37yJEjlPZwwSxdurTX9s7nrPQZExNDXFycy5JnuOEGlUDDG1dc4dH2aVSuDE2bere3x8RAp07Zl1GTJa7lWq93hAYGNfAzH1E4+eAD2LzZ87zMyBHIli0eNxcRZOBAqF8PPh4PO3Z4VNQ7zYHSh8DqI6opuxgYnLafofHbc9jxT+A1G6tVKTZHj8J336kowLyKiMBzzzrf+N7Ablcm2NdeC65g2aQWtbB4uZQaGFSnOp3vtDJ7tpouz0jZsjBjBtxzT5AFvQwJqoITHR1NgwYNWLp0ado60zRZunQpTZs2dbtN06ZNXdoD/Pjjj2ntK1euTOnSpV3aJCYmsmbNGo995mnat1cJ0byp/k8NwPCmwAwfoRQcT22GvoJRuHCOxNT4Ty96+bwj7Ee/EEmTAz76yLuZw2ZT8zCeGDwYxoxWr304r0Snwne3Q6Ezlyg5AZpGsmPnV8svnJhwF+bnD4AlsPG8Dgc8/TQUz5t5IF35+2/YuDFrc3wOB3w6GcloCYwQfBXWBeiPihHv1An27IGlS+GLL1Si0b17tXITNILr76zCxGNiYmTKlCmydetWefTRR6Vw4cJy+GJY4UMPPSSDBg1Ka79q1Sqx2WwyatQo2bZtmwwdOtRtmHjhwoVl3rx5snHjRunQocPlHSb+119iFivqGubtjIrq2lVMP3KBm0uWiFm1imt0Sny8mKNH59nkXZHMSBmZFqVxaRTVrXKr29pXkYTpcPhXaqFjB/fbr1yZtZINF5cDZZAhryBXbUXK7kUKJiIWezYjrDw9HIYwcFSWoqG8LYahisJeLn8zc8WKLP+uaUuEVi/9WD4WhEzFdQ0xpJW0ivj/a24iosLERUQ++OADqVixokRHR0ujRo3ktwyxj82bN5du3bq5tJ85c6ZUr15doqOj5dprr5UFCxa4fG6apgwePFhKlSolMTExcsstt8j27dv9lievKTgiIuaRI2K+/rqY114jZsUKYt52m5jz52dJOTFNU518Jk8W85tvxHSW287DbNwo8vDDqrBmiRIqd06k5KKYI3PkOrku7WRZRsrIW/KWJEtyuEXzi7TaUp6WKJuY3btl3i41VcySJbN/EcywnI5DXn4NKXEkkAoOwt7yguHIpKzExaljyV/lplgxVY/Kbvf/e3U4RBYtEunXT6RXL5VjJzedysxdu7L/m/qqXBpGFskiuUluSjtOKkpFGSWjtHITYCJOwYk08qKCo8k6M2eqvCQZkwE6X7/ySrilS+eEnJBDckgckruq8pmPPeY7Sd/ChZm387egaxYWx+uvyVk5K3axyzJZJm2kjUtF+E7SKeuKToU9mfIrtWihlJVBg1T+pYw5mDIeW7//LrJunUhyFnXVAwdEatdO789mUxag/PlFvvkmQD9cCDCb3+g999ali80qZqtW4RbbL87LeTktp8WUy8QkF2K0guMDreBo9u5V1Zu9JWtbtCjcUuZuzJ07lRXH3YXMZhXzf83cTp+ar77qWzHKyoXx1VfdWjJTJVUuiJrWfkfeyTS94PNRbl/68VLkhFBzo4z/dn9a/1u2iPTpI1KxokjZsiJ3362qSJtm9qajUlNFrrnGfXZuw1Dr167Ner/hwFy3TtUZ80fJsRjqePjll3CLrYkAIibRn0YTqXz8sfJ/9eTnaLWqas+a7GNceSUs/Sk9bMRmS3eGb90avlvg3vk9JsY/B1SbzXeimF9XYwwZ4rZGkg0bsagK2dWo5jM0Pw3TgH+rwIFyUHkXzLgHjpaETbXpfUd5/sf/WM5yrrkGxo1TTqX790PnzvD88yptVUwMtG2rnE395bvvYOtW9/WvnF/XiBH+9xdOjPr1YcVKuO461w8KFFDPVmt6fq/CheHrORj/+19IZfSH4xxnJCO5i7u4h3uYyMSIrhd3uWGIBCtdVeSSmJhIfHw8CQkJeStkXOM3zZvDypXe2xQqBHkp6XW4EIcDFi2C9evVlb1dO4xrrvHcfssWqFXTe6eGoaL/nOHGl2KxwN13Y0yb7peMduxUoAJHUM46vig4/WHOrq8GL74FBc+pQp3OoS8Gp85lLu1pjwg89RS8/74SyxlYZrWq4KD33oMnnvAtY7du8NVX3gt8RkVBcnJ4EwRKQgJMnw47d0J8PNxzD0YNz2kNZPt2lY29WDFo0EAlJp0zB86ehauvhk6dMGJiQrcDfjKf+dzDPaSQgqAyFpuYlKAEi1hEPeqFW8Q8SZau30G3J0UgeopKc/PNvh1ACxcOt5SXL+Ztbb1PX7ytatmZEyaoQrEWQ8zoqPSprbs7++0kbxe77Jbd8ql8KhaxuC2o6IyIcRcp46ltcSkuyZIs333nO4pqy5bMcp09K7J4sch336naV507+1f/KiWMPq3mlClq6sn5ezh/wwe6iJmUFD7BAswW2SJREuX2WLGKVYpKUTklp8ItZp5ET1Fp8hRimsiFC36n9veHW2/1ntvQZoNWrQI2nCarfDVNJaCE9Kkom029f3kwPPc8AMYjj8CBgzDmPejdBwa9ABs3YcychZEvn9chHDgYxSgqUpHKVKYHPShM4bR6U5dSiEJp2/lCEI5znO/4jvff956mympVKYOc2O3w0ksqyXirVnD77VCxosqZ6M0yYxiqvpq3yi3BRMaNhR7d4cIFpWulpqbnL5o+HR7tFR7BgsAYxqRpNJfiwMEpTvEZn4VBMk1G9BRVEKao7NhZwAJWsjKtfs1t3OY1O60mM7JlCwx/W6X5TE1VZ/zefWDgQIxChXLU97FjULmyOhe7y0VnGCpdfpMmORpGkwNEBH76CaZNg4TTUKUqPPIIRrVqOe7bxOQBHmAGM/yaksoONmy8yZsML/YcJ096b3vddfD770ov6NpVFfO89MyccXrLHYYB77wDAwbkXPasIH/9BY89Br+v8d7QMGDHToyqVUMjWBApSUmOccxrm5u5maVkwclK4xdZuX7bQiTTZcNmNnM7t7OHPUShbqXe4R0qU5kFLOBqrg6zhKFBRODcOYiKytb8uaxcCW1aq9tZp9PBkSPwxuvw9Wxk5c85yq5cooQqxN6unauSY7Op1x9/rJWb7ODAgQWLRytIVjAMA265RS0BZj7zmY5//jnZxYGDeOKJ9qNGVqzydWbNGpg61X0b01Q6gki6/44Ti0X5lfXtm3O5s4Js2QLX/0/9iXxhsSjfmmc9+E3lIlLwXbo+N9SLy+voKaoAcoxjtKAF+9kPQOrFB8Be9tKCFpzEx61cLkdSUpB33oEqlSGuEOTPh7Rpgyxf7n8fqalw7z2q0N6lHpUOB2zbBi+/nGNZmzdX/oyvvqpmQxo2hH79VPeP+M6+rrmIickkJlGb2tiwEUUU7WjHClaEWzSPfMRHQbeoWrHSkY507Jg+u+YOi0VVXAH49FPvbUWgaFHIGFBUpgy88Qb88IPy4Q4pL76gCqn6U3nUYskzXvv1qe/1+LFhoxGNQiiRxi3BdQeKTILlZPymvJkptX7Gh0UsMlJGBnTMSMJMThbz1paZU+zbrGrdlCn+9fP1175zY+TPJ+aZM0HeI40vHOKQ++X+tOM7o6OlIYZMlInhFtEtFaRC1hP7ZeFhiCFPypMiIrJ1q+ecS1arSJEiIsePK7natvXtRGyxqLaJiSLHjqnMxuHAPHYs6+U0Pv88PMIGmLky1+fvv1W2hlvMPIl2Mg4T05jmtUiiick0poVQohAzdqxK7HGp84DDodY92gs5fNh3P3/95dtT8sIF2L07+7JqAsJUpqYd0xmPfQcOBOFRHmUPe8Ilnkd8FTPNMgKYFiyipuf60pdRjAJUpPOcOcq6YrGoaSbnUriwiqAvVkx1U6qUdwsOKAsOqDQGxYt7d5YPKkeO+JevCNTOxsWpZEB5gA50oDe9AVwqiTutOu/x3mXjjhDJaAUngCTi2/x6hjMhkCRMfPiB988dDmWD90VsrH8mb6fjgiZsvM/7Lif4SzEwmMCEEErkmxWs4AAHAteh3YBz+WH8Y1heGMG8P/fwIR9iy+DiePvtsG8fDBumpqPuvFMlAfzvP9dcd127es9zY7VCz56BEz1HlCjhX8IdpzY3abLPyLbcgoHBOMbxJV/SgAYYGFix0pKW/MiPadXDA0ESSSwxf+Kl1d9xQ9fdVKwItWrBW2+pYAmNF0JgUYo4gjVFdZvc5jVHhk1s0lE6BnTMSMG8cMG3edpqEfP++3z3tXGj79Tt1a7UVc4jgCiJ8jld01bahltMF9pIm6yXZfD22FZdqLEtbfqoVq3sVwY3TTVNlbGGVcZaViVLihw8GNjvIyeYrVr5LrfQpLGYP/0UblGDikMcAa895RCHDJNhEm/Gux5vC28VrtglFosqEOwuh1JeRk9RhYk+9PGaI8OOnT70CaFEISQqyret3GKBWN93cEatWiqPvafkISLw0stu0+/nBbZvh7lzYfFi5b8ZyTgjBT1hYKSVQ4gEUkllMYt95rK5hmuoRS3KUc57h6YBFoHtKlOvacKmTbBuXfbkMwz4+mvo3j3z4d+wIaxapZyKI4a33lJzap7++088gbH6N4ybbgqtXCEmUJGDGXmGZ3iBF0gwElw/uPknWN0Us/QBTp6EO+5wjajTpKMVnADSjnY8yIOZ1jsP/J705FZuDbVYIcGwWlXMtbeMZnY7dOjgX4dfTUsPFXGeQK1WdQV47XWMbt1yLnSEsX073HADXHUVdOqkyjWVLg1vv+2/q0OoaU97l6mYSxGEO7gjhBJ5x47dp/+NFSt1qctGNtKLXl73D4tA9Z1Q2dUfbOfO7MuYLx9MmqTqV33+OUycCBs2wOrVcOWV2e83GBgNGsCPS+DS3DYFCsDrb8DoMWGRK7ezgx2MZrT7D6McUOwEDHobhwN27VJ+XJrM6Dw4AeAc5/iQDxnPePawh1hisWHjLGcBqEQlnuZp+tI34Fp+RPHc8yq5jDtsNnV2btfOr66M+Hhk2XJYtkwl+ktMgKpXQs+eGFWqBE7mCGHXLhWqfmkUbUICvPACnDwZmYUUn+EZZjELAwPBVQuzYqUUpbiXe8MkXWZiiaUylfmP/zLJ60QQ6lAHUPlO/PrPxiS7vA1E/tDSpeGhh3LeT7Axrr8e+Xu7Mi/t3Kl2vnVrjIIFwy1awEkiiWMcI5544gheHcPP+AwrVs+Wxig79JwMA0YTZbGxciXcdlvQxMm9hGDKLOIIpA/OaTktdaVupvBwm9ikgBSQ7+Q7cUiY4jjDgDltmpgx0crfxmZNrw10zdVi7t0bbvEilu7dlY+Ft3pFu3eHW0r3zJJZEi3RaXWcnP4t5aW8bJNt4RYvE+/Kux7rTTkfTaWpzJAZMlNm+vbBSSgkxJ5P+63i40UuXAj3XmoCyQE5II/KoxIrsYKolAh3yB3yh/wRlPG6Slexic33sVf4pNhsIoMGBUWMiET74ISQF3mRTWzKZPa2YyeJJB7n8TBJFh6M++5TtYGGj4D774fuPeDb+ao+UIUK4RYvIklK8l0l2mKBL74InUxZoTOd2cc+3uRNOtGJe7iHL/iCnezkKq4Kt3iZ6Ec/2tAG4+LDHb/zO/dyL7OZTUlKeo4Us1thQi9ISvcte/llHeCXl9jHPhrSkMlMJgnlFGdi8j3f04xmLGd5wMcsSUnfjZJi4GxB7HZo0SLgIuQJdC2qHNiSz3KWEpRIO+g98QM/0IY22R5Hk7c5eBDK+fBltVhU/pNq1ZQpulcvlTNFkz1SSeUjPmIMY9iN53xKBgZP8ASf8AmppGLnohZ6Me8N6xpga/0TZmJBLBZ4+mlVGPO//9Tvdc89qgCmJvfSmc7MY176b58BCxZKU5q97A1oZuyNbEybJnVLqg0+fwjrY5OpWlVlXw9bPqQQk5Xrt1ZwcqDgrGMdDWnotY0NG0MZysvkvLRAJCEisGKF8rlJSYH69eGee/JMnovs4nCo3BQxMVCkiH/bnD+vEr6lpvrX3mKB/Pnh+++VU7LGO0kkcYITxBNPQVz9Qj7jM7rT3eO2BgZXcAULWMA7vMM0pnGe81zBFTx0tg9xn/fj+N78lCmjfr/BgyE5Ob2mmWnCww+rnDfhqvKtyT5HOEJZyvp0TF/AAm4jsE4wXenKVKZm9hWzW+FcAWi4jjLnrmTFCnXjc7mQpet3cGfLIpNA+eBskk0+50gtYpERMiJAkkcG5sGDYjZsoHxromxiRkep10UKi7lkSbjFCwvnz4sMHaryUjh9MZo2FZk/37/tu3Tx7oPjLl1/oULpKf41mTkgB+QxeUzySb60/2JH6SgbZENam8fkMb98HY7JsbRt3PnUzZzp3X+qb99Q7LEm0PwsP/s8NqxiDUoJnhRJkSflyUy5pqL/riXXdvlT3n1X5NSpgA8b8WTl+q0tODmw4DhwUIlKPrOibmYz13JttscBZVJPIIFCFCKGUFfUS0fsdqhXV8U0X+o0YrGo29S1f2DUrBkW+cJBUhLceiv8+qtrAmaLRb0fO9Z3left21WekwsX/M9pYbHA8OHwzDPe25mYXrMNX8ppTjOVqWxlKwUoQCc60YQmuSoCcC97aUxjjnPcZWrBihUbNn7kR27gBh7ncT7hE7fTDxnZzW5SSKE4xSlKUZfPRFRo/86dnsP5rVbYuxfKls3xrmlCyAY2UJ/6Xts4sxo7SzcEmhOcYBGLuMAFalKTRjTKVf/FQKMtOD4IZBTVB/KBV82+jbTJUf8H5IA8Lo9LfskvCBIlUfKAPBC26BSfhTCjbGJ2756zMez2XJWlePhw95lnM1pb9u3z3c+GDSK1a/tvxQGR1q3d93VCTshgGSylpJQgSLzEy5PypOwV75FsX8lXEiuxYoghURKVZt1oLs3lpJzM+pcTJjpKR4/Zii1ikYpSURzikDkyx+vduSGGxEt8Wl+GGHK73O5iBdq82ffvZBgiY8eG7/vQZA+HOKSSVPJppT8gB8It6mVDVq7fWsHJIaaY8rQ8LQhpFwPncxNpkqOLwn/yn5SW0plO1M4Q9LWyNsfyZxXzgS6+U7Pnz5f1fi9cEHPkSDErV1Z9xMaI+dCDYm7cGIS9CCwVK3q/uFmtIq+84l9fpiny++8iU6aIREf7vnDeckvmPg7LYakiVdweN0WkiMcqxz/JTx7Dp61ilebSPODp6IPBQTnoMwwcQRbKQkmVVLlCrvBauuHSFBBWsUo+ySerZbWIiKxe7ft3stlEhg0L8xejyRafyqdej41H5dFwi3hZocPEQ4iBwShGsZGN9KUvt3M793EfC1jAKlZRBD89Td3Qj34c41imZE/OEPQHeAAhxDOMZ876nkNJSlJOyH4i58/DrS1h0PPw38WIluRkmD4dGl2HLFmSA4GDS3Kymnrwhghs3epff4ahii926wY33ug9MbTF4t7JuD/92cMet8dNIom0ohW96c1ABrKSlWnH0Ou87nEqy4GDFaxgNasBOMYxtrCF4xz3KN9xjjOCETSnOc1oxtM8zQ52+PgGcs4Odvj8XxgYbGUrNmwsZCElKekSNu7MXmxgZHIwdeAgyUym7ZHufDhWKFLEdwSL3Q7Vq2d/nzThozvdGclIbNiwYCGKqLTjowtd+AAfRYY14SP4+lbkEaxim4Fkr+z16y50pawMqVzmc895t+BYDDGrVctany+/rBIDeirQWbSImOfPB2mPcobD4ds52GYT6dEj630vWOB9yiMqSmT/ftdtDsmhTBYHTxaZjJbGHbLD5zY2sclD8pC0kTZpx6YhhrSTdvKX/OUix6/yq8RJnIssVrGKRSzyiXySg2/cN2tlrc99QZDe0jttm0RJlLEyVm6Wm+U6uU7ukrv86oNmqyQmRqRePWWp8/RbFS8ukpwc1N3WBJnDclhGykjpK31lsAz2aAnVBBc9ReWD3KDgLJJFPk+uhhgyTsaFVC5z506lxHhTcMaM8b+/lBQxixX1XYn8s8+CuFc5o3Nn30rOd99lr++XX06f5sqoMNlsIl9/nbm9P8eNO2UnXuL9aud8XLo+v+RPy+p6Uk5KvMR7VLQMMWSVrMrBN+4du9iltJT2uT/VpJrHKbdv5Bv/vr3uk9N+l7i4zMeB1aqW7P7+Go3GFT1FlQfIT36fbQTxq10gMa68Eoa9rd5cape3WNS8Su8sRBMcPKgKLXkjKkpVG4xQnn9ePbsrbm6zQZ060CabeR5ffx1+/FEl9ytRQkXh9Oypvo5OnTK3z06EnQMHCST41c7EzDT15cBBMsn0ohcAk5hEAgkec4dYsfIu72ZZTn+xYqU5zX2228lOtrHN7WeFKOTfYIkqisNiUQn+7r1X/eZObrhBlVPzswSbJhdhx85JTpJCSrhF0XgiBApXxJEbLDjJkizFpbjXu0eb2OSIHAmLfObMmWLWrZNuYSlRXMyhQ8XMYhEe89Ah39abKJuYzz8fpD0JDN9+K1KgQPrUkfNOvmFDkcOHQyfHBbnglzUmWI9pMk1iJMZnu4JSUExT5Nw55VgdSA7JISkhJfyS91f51W0fyZIsxaSY963P5hcKJrpYbPbuFUlIENm2LbS/eygwT54U8513xGzcSMyrrxLz7rvFXLo0V0U8BoJDckiekCekoBQUJD2yVU9ZhQY9ReWD3KDgiIiMltEeT64WsUhfCX/2MPPIETH37hUzNTV725ummHVqe/bBcS4//xxgyQPPmTMiH38s0qePyIABIsuWuV6816wRuftukXz5lALUsKHIF18oP55A8pq85pf/VjAeznQGvh625HxSsKBSCgoWFOnf379Qel/8J/9JWSnrlwyGGHJIDnns63153/PWJsKQVzJNRW7ZkvN9iETMbdvELF3KdXraWUi3T+/LRsnZJ/uknJRzG6GYX/LLGlkTbhHzPFrB8UFuUXBMMeUFeSGtQrPt4gNBukgXSZa84bVozpzp3XrTpHGuP4F++aXKh5PRR8OZO6dr18AqOXaxyyPySMCUFkMMaSpN/Wrrj4MzqVZh6c2ZHLFLlBDZuTP7+/27/O63gmURi7SX9l772ypbpZk0S1doUi2C3RDsFmH4s4LhcNmHqCjlGB7s00pKisiJE+o5FJh2u5hVq3gPLhg/PjTChJmO0tFj5murWOVKuTJXpFLIzWgFxwe5RcFxskt2yVAZKj2khzwnz8lGiazcMOb27WKOGSPmiBHZNlmbI0aou0ObVT077w7r1hEzl9v6Dx5UFz9vTsiB9qH2lrsjO4+v5WuJk7icKzfOx+3fus0XdP312dvfFEmRMlLGb8tVnMTJP/KPx/5Gy2gxxEi/mJkXl8SCwk1LvP6WsbEi/fqJZHG21if//SfSq5fq3zlOr14iu3cHdpxLMb/91rt11WKIeWXVXH8T4osDcsCv42uZLAu3qHkareD4ILcpOJGKefq0mB3ap4dzO+/wqlcT888/s97fv/+K+cILYna6U8yuD6kTq90eBMlDy+uv+850XL9+4MYzxZRr5Bq/TsbeEtw5P68m1cQhDhkuw722ddZ88vl4+zmvCkJ2pnlmySz/lStBvpVvPfb1vXzvectUq7C/rBCd5DO5X3y8+0i37PD33yJFi2aO0rLZRIoUUT4/wcIcMCC93py35UDezua7RJb4PK4sYpH35f1wi5qn0VFUmqAjpgl33K6qiYMquuRMALhrF9zUAtmzJ0t9GlWqYLz1FsbXczA++xzjjjswvGW6yyWsXetao+pSTBP+/FNdsgJBAglsZSuC7w6b0pTv+Z5nUAWtMia4MzAoQxm+53ssWHiWZxnCEJeEZxYs2LAxkIG+I7jEgB9bwqDhXptt3OjffmZkNauJwr9y3YUoREtaevx8BCOw4uG4szmg3EHoPNvnOAkJcNdd8NZbfonllZ49VX+Xln+z2yExUX0eNPw9MAN1AEco/kSsmpghj2yNJMQ0kUWLkPvuRZo0Rjp2RObMUTUMwyLQZYi24OQc84cffEc+PflkuMWMCDp39m7BAVWWIVCclJM+7zRtYpNu0s1lu9/kN+ku3aWhNJSb5Wb5SD6SM3ImU/9H5Ii8J+/JIBkkH8gHsl7WS3EpLhbTjymqJr/6tHzMnZv1fX5Wns1UddndwxBDnpFnPPaTKqk+LV9Wsco9SQ9Jw4a+f1fnsmFD1vfJiT+1rkBk06bsj+ENc/Zs39abKyqJGWhv+QgjVVKlpJT0eWx4c1zPy5hJSWK2v8PVAd1p1W/WVMwAXW8jZorqxIkT0qVLFylUqJDEx8dLz5495cyZzCfMjO379esn1atXl9jYWKlQoYL0799fTp8+7So0ZFqmTZvmt1xawck5ZteHfNekKlI43GJGBJMne78w2WwiHTsGbjxTTKkhNXxeqKfK1ICM10W6iMXh3vESQfmuCMKY/j4VgthYkUv+7n7xo/zoW7kS5Ea5Uc6L56zYyZLssw+LWOR+uV/KlfNP8bDZRB7NQbmi6dP9GycLp8AsYaakiFm+nOf/exaTe+Zm3pP3vB4XvaRXuEUMG+bAgZ6jYW1WMe+5JyDjRIyC06ZNG6lTp4789ttv8vPPP8uVV14p999/v8f2mzZtkk6dOsm3334r//zzjyxdulSqVasmd911l6vQIJ9++qkcOnQobbmQBY8+reDkHLPdbb7v6qyWPO946A/nzomULu09lf8vvwR2zAkywetdZkkpKUmSlONxTstpsXpTbpwKztT7BUwxDM8XaMMQefbZ7MnhEIdcK9d6jHBBkK7S1a/Iw5pS06tyaIghY2SM1KsnXvcn49KgQfb2S0TlWPJnjG++yf4YvjD//FOVTMmo5DhfP/BAnrfeODHFlBflRbeRrffKvQH5T+VGzIQEMfPn8+2MvmdPjseKCAVn69atAsjatekVr3/44QcxDEMOZMEZbebMmRIdHS2pGfKsADI3O3bsi2gFJ+eY/fqlmyE9LZUqhVvMiGHzZpEyZdIv5JCexn/KlMCPZ4opj8ljguBy0beIRQpL4YBVot+Uus233SQ5SoVVX3JBtlpdQ+e7dhXJZjolERHZLbvlCrkiTQnJuO9Py9N+h+9OlIlelZv8kl9OySl57z3/FZzsRoeJqPxK+fN77z9/fpHExOyP4Q/moUNivvKKmFfVELNcOTFbtxLzm2/c3sSYDkeevrlxRrZ2k27yjDwjG2RDuEUKK+aiRb5veA3EDMDJLiIUnEmTJknhwq5TFKmpqWK1WmXOnDl+9zNhwgQpXry4yzpAypYtK8WKFZPrrrtOJk2a5PXPlJSUJAkJCWnLvn37tIKTQ8wNG3xbb956K9xiRhTnzolMmiTSqZPIbbeJDBmiMt8GC1NMWSgL5Q65QypKRblarpahMlQOysGAjTH1x8O+FZxUq/D8sEwX5TvuELn3XpGnnsqZj0pGzsk5mSSTpJW0ksbSWHpKT/ldfs9SHw5xSFfpmmbtcu6HTWwSJVGyQBaIiFIoqlb1reQYhsi77+ZsvwYP9jyOYYi89FLO+g8EpmmKOX26mI0bq/+/1SJmy5Zi/vBDuEXTBBnz++/9U3AmTszxWBGh4Lz55ptSvXr1TOtLlCgh48b5VyDy2LFjUrFiRXnxxRdd1r/22mvyyy+/yPr16+Xtt9+WmJgYee+99zz2M3ToULd+O1rByRlm/36e51tr1RQz2LeUmrAzdqwIP7VQSoynh8MQKu3OZL0ZNSrc0nvGIQ6ZITPkerleCkpBKSbF5FF5VLaIawz7gQMijRt7Vm6sVpFixUROnsyZPHa7SO/e6T49zgVEHntMfR5OTNMU88kn0m9uLp3GGjkyvAJqgop5+LBvi76BmJs353isoCo4zz//vFtlIeOybdu2HCs4CQkJ0qhRI2nTpo2k+EjZOXjwYClfvrzHz7UFJziYpqlq05QqmX4Ax8aI+cjDYp46FW7xNJdgF7tMkAlSW2qLRSyST/LJ/XK/rJN12e5z+nQR/vezkGJTWX7dKTcfPeb24v/69B0yX+bLMlmW67NyT5yYnoDPYkn3typVSiQbKaE8snWryKBBIt26qeetEVL+yFywwPfF7a+/wi2mJoiYXbp4dkSPsol5440BGScrCo4hIpKVsPJjx45x4sQJr22qVKnC1KlTefrppzl16lTaervdTmxsLLNmzeLOO+/0uP2ZM2do3bo1+fPn57vvviM2NtbreAsWLOD2228nKSmJmBjf1ZQTExOJj48nISGBuLg4n+2Dwfnzqvp0vnxhGT6gSGqqSl6SkgJXX41RuHC4RdJcgh07d3M33/ANBgaC+ts7897MYhYd6Zjlfs+ehVKl4Hzz72FKdyh5DFKtYDXBtMBHfWDAaHBkKLFd42/45DG4cWXaquIUZzCD6U9/DNyUZc8FJCbC1KmwahVYrdCyJdxzD/g4feUJ5Lbb4MfF6bmwLsVmg4cfwfjoo9AKpgkZcvIktGgOW7ZcXHFRtbBYoHx5+PkXjAoVcjxOlq7fAVGp3OB0Mv7jjz/S1i1atMink3FCQoI0adJEmjdvLufOnfNrrDfeeEOKFCnit2zhcjI2TZHPPxepUyf9LrZ+fZGvvgp8RWVN7mLPHpE331RFJ996K/C+OR/IBx4jgwwxJFZi5YScyFbfw4dfPJ5tKUKHucKzw4XHPhJKHcpsuanyj3CysBh291Nar8grgd1xTUgwS5bwbcEJZLpuTURinj2ryvZcc42Y8XGqhMebb4p5InvnFndEhA+OiAoTr1evnqxZs0Z++eUXqVatmkuY+P79+6VGjRqyZo2qwJqQkCCNGzeWWrVqyT///OMSBm6/OMn87bffyoQJE2TTpk2yc+dOGTdunOTPn1+GDBnit1zhUHBMU+SJJ9JN2M4TvvP1c8+FTBRNGLHbRb77TuTBB0XathXp21dFDxmGmtaIilLPhiHy/POBUXxNMeVKudJn6PO7kj1PWNMUGTYsfYrGOT2TL5/aH8NQzxaLCF88IIbdcyi3VawBc4JOThaZM0f5+kyenHM/mEs5fFjlnvn88+CWSsgNmBXK+1Zw/tcs3GJq8gARo+CcOHFC7r//filYsKDExcVJjx49XBL97d69WwBZtmyZiIgsW7bMo1/P7osV5X744QepW7euFCxYUAoUKCB16tSR8ePHiyMLeRjCoeD8+KPvUNKVK0MmjiYMnD4t0qyZqxLgK/HdsGE5H/ecnPMZ6WQVqzwgD+R4/z77TCkUM2eqYpOnT4uMH6/8Rd4Yc0ZspvecORaxyAgZkdbn/v0iY8aIDB2q+vbTqCuzZyvn3ozfdUyMilzLacqW8+dFHn44c12om25SlrjLEZ9pI6wWMYcPD7eYmjxAxCg4kUo4FJyOHTOfEDMuNpsKmdXkXW6/3XOyP09LXJy6oOaEZEn2mdXYZtqkh/TIct+JiSJLlogsWiRy7Jj3trtkl09FK0qi5Al5QlJT1XSdxaIWZzX2QoVEpvpIwPzDD95DtwcPzvJupuFwiLRp414xtdlEypf3/T3kRczt21WAgcVwH1VZpLCYx4+HW0xNHkAX24xA1q/PXCgvI3Y7bNgQOnk0oeXvv+G77zz7YHoiMRGWLcvZ2NFEczM3ey4gCdgNO1X/bud3n8nJ8PTTysG4ZUto3RrKlIHu3VVRSHcUpSgWvJ9yTExKUpKnn4YPP1SFSE0TUlPV52fOwEMPqe/SHSLw/PPKgd8Tw4eDjzgJjyxZAgsXui+earfDoUNK7ssNo3p1mPuNipowDLVYLOo5vjAsWoxRrFi4xQwaduwkkoiJl6q6mpCjFZwQkd+PArP+tNFkDdm2DXn8caRKZaRiReTBB5Dffgu5HAsXqvN9djh7NufjP8/zOPCgXaVa4d8qvNqgPX/84bsv01RVsseMgQsX0tfb7SqK6OabVZTgpcQTT3vae1W0TExuPfoAY8emB2G448UX3X++Y4cK6PNWvT01FebO9fy5Nz7/XAUEecLhgEmTstd3bsdo0wb27oNR78Cdd6qD5KPxsGcPxnXXhVu8oLCJTXShC/nJTzzxlKAEL/Iipzjle2NN0NEKTojo3FmFjnrCYlHnA03gkNmzoU5tmPAJ/Pcf7N8HM2dCs6bIO++EVJaUFO9WBW9cfXXOx7+VWxmR+BE4LGC3Ks82x8W//4Hy0GoxZnIUL77ou68ffoAFC9wrEQ6HskROmeJ+21d5lWii3So5BgaP8zhrZ13hVbkRgU2b4J9/Mn/mj2XGas2+BefQIe+WWICjR7PXd17AKFoUY8AAjNlfY8yYifHooxgFCoRbrKCwkpU0ohGzmEUqysR4kpOMYARNaMIJsnmQaQKGVnBCRO/eykLjTsmxWiEuDnr1Cr1ceRXZswce6KKuuBmvSM7Xzz6D/PxzyORp0CDr01NWK1x3HdSqFRgZYj/rjXHlLnh7EHx3O3x9FzwwFWpsh11VcTjgxx/h8OHM2yYkKOvFO+/Aa6/5tkZ98on79bWpzTKWcSVXuspGLC/wAmMYw6lT/lm7Tp/OvK5iRd/b2e1QqZLvdu4oX967BQfUVJ0mb2PHzr3cSwop2HHVeB04+Jd/eZ7nwySdxomPv6omUJQrB4sXw+23q7tHq1Xd0dvtULQofP+98mfQBIjx45WJwZMpwGaD99+HG24IiTg33QRXXgm7d/un6FitSiEO5HTHkSNgO1CJ1MFveG139CiULq1eiyiflVdfhaQkJZcv+UVg717PnzemMdvYxq/8yja2UZCCtKUt8cQDULWqbysJwJ490LChq2WsfHnlE7RsmWc54+OhY0ff/buje3el6HnCYtE3KpcDC1jAYdzcCVzEgYOpTOVd3iWO8CST1WgLTkhp0kSd+CdNggcfVMuUKeknak0AWbHC+5XYboflOfTezQIWC8yeDQULZrYAWCzqouu0WthscPfdsHZt4Kw3oJRsX4qDYaQrNwAjRsALLyjlBvy3QpUs6WMcDP7H/3iER7iP+9KUG1DuG4ULe5/SMwz1HdWvDwcPun42erTydb3UWursb+zY7GcXbtFCyefOwmSzQeXK8Pjj2etbk3vYyMa0LOCeSCaZf3Azj6oJGVrBCTH580PPnkqx+fRT6NYtb5RriDgsfji8ZNcpJpvUqQN//QV9+6oLuMUCV1wBb70F+/erKZfdu+HkSZg2DWrUCOz499zjfXrFaoXbbktXTs6eVdNRWcVigR49sicjKOXDOcXlaarKaZjbvBlatXJV3GrWhF9/hRtvdN2mRg3lXPzAA9mXzTBg+nR44glXJckw1Hf3yy/qt40E5L//kGefVQ72pUshrVsh336LZK06j/cxUlIQbx7deZR85Esrd+KrnSaMBD9q/f/tnXd8VMXagJ+zuyTUEJASAkqvAgJ6QVCBK1FAVECv0lRAiiheGxbwXkFFARVF8UNApFhARARsNAuIaAxFQC8EBKQqBCGQEErI7r7fH+MuLNmabMtmnv2dX7LnzJl5Z8/ZnffMvCX6iFSqBk34sI8e7TnxmyP5W98+viuKMZxpFdxkvS5dWuSXX86X/fDDwGL2OGLB1KwZnKjBy5eLXHmlf+0uWeK+jr17RVavVv0KdjqUEydUVOrFi6MvwJ/9++/FXqa063fA8f/gQWIvxIdhP3NG7BMnir12rfPfpTvvEPv69UHsQXSzXbb7jOlUV+qKXXQOnmCjA/35QCs4sY/94EGxlyrpPvCYgdr/d4qQ4oTdLvLWWyKVKrkqCFdeKbLxoqTib77pPWCeu619++Dm0bLbzwf587SZzSJ33x28Nos69lOnxF6xgooe7EnBf+edgtV95ozY21+Xv+4SFrV99lmQexO99JSeYhb3OdUQZJbMirSIMYkO9Kcp9hjVq8MniyAuztUYw2JR6wlTp2G0bh05ASOEYcD99yu7lW++gUWLVNyYDRuUPcuF1KrlPRaNgxdegOnTlev2d99BEBIGO7HZzgf584TdDqdOBa/NIs+HH8Lx456DARkGTHqtYHW/8opKl35x3Varulh9+yAnTxas7iLGu7zL9VwPgAUL5r9fBgYv8AIDKcQ6rSYoaC8qTcxidO2K7PgNpk5VkfasedC+AzzwAMbll0davIhSooQKyOeNLl2UPc5ff7lXdMxmaN0a/vMf9f74cRUjx25XRvPB8Aq0WKBOHWWb5EnZMpmgSZPCtxUz/PCD+uA8WZSLwLZtSE4ORtmyflcrNhu8NcWz4iSiIjzOmwf33VcAwYsW5SjHClbwIz8yn/mc4AR1qctABlKTAsYh0AQVreBoYhrjsstg/Hi1aQLCYlHe9rffrh76L1QwzGalJE2erKIZjxgBs2apFA6Oc3v1UmkLCmt0O3w4PP645+MiMHhw4dqIKfwNmR2okf3RoyrWgDcsFti8ObB6I4ANG8tZzkIWkkMOjWnMYAZzGX4EUroAhzfgNVwTIkk1hUEvURUxdrGLMYzhPu7jOZ5jD3sCrmMPe3iER6hKVUpRiuY0ZxrTOMe5EEisKcr07KliNF084dWunfIYatkSbr1VLVE5lBtQkwfz56v4PxemcygIw4dDhw75x23H+0mTCh64Lybp1Ml7PACTCa68KqAIw2KzwZrv/CtcUB/8MHGEI1zFVdzMzXzAB3zCJ4xjHLWpzSQmRVo8TTAJg01Q1FEUjYxtYpMH5UFBELOYpYSUELOYxRBDHpPHxCY2v+pJkzQpK2XFIhanMZzx96ujdJQzcibEPdEURex2ka1bRVatEtm9+/z+xYu9GwAbhsjUqYVv/+xZkbFjRapWPV9327Yixcim1W/sZ8+KvXqydy/CefPEPmOG2FtcIfa4EmJPKCf2AQPEfqEbnaO+jAyxt2rlua6Lt2++iUCv/cMudmkjbVx+/y5+fSKfRFpMjRcCGb8NkSAGRSgiZGdnU758ebKyskhIKBpRJkczmhd4wWPshRd4gf/wH691WLFSk5pkkOE28aIJE0/zNGMZGxSZNbHPLbcouxtPAQANQ8X/efxxZcgcFwddu6oZmYKEIbLZ1EpJfHz0xJuJRuTXX6HT9SpsuuMn3mGXM+ppZRH+xeeua48OA/wln2J07arqEVHTdRs3+I4SabGoyJQbNmKEOcaUv6xlLdfhOXq5CRMtackG/Mg6q4kIgYzfWsEpAgrOSU6SRBKncZOi+W8SSOAQhyiN55Tki1nMbdzmta0KVOAwh4kjrsDyaooPzZursdIbjjG0RAn112pVHluffw7JyeGRszgix4+raKKffAKnT6n1xGH3KyPkx0e4t9o2DBWN9M9DGOXKqXxtHdrnL+eOZs1g+QqMKE7G9RRP8Rqv5csfdTFHOEJlKodJKk0gBDJ+axucIsA3fONVuQHIJpvVrPZaZh3rKEEJr2WOc5x97AtURE0xJTnZt02rYxzNyzs/CfDLLypnlC8XcE3BMSpUwHjsMYwffsDYtBlj1myVvfXNyZ5d0hyeUHPnqveff+47uyjA+x/Az5uiWrkBOMtZDHzPLp3lbBik0YQareAUAU7hX5APX+UsWPwKL+5LCdJoHAwY4Nlr2BtWK6Snq/QJ775bsDo0BeDECdi713sZs1klQgOVhMyf5aYOHTAuTv4VhbSkJXl416orUpEkkryW0RQNtIJTBGiCf0E+Lsd7bJcudPE6NWtgUJe6OoaDxm9uu03Fwino2LZnj1KS+vXTSk5YKOHnw0vc30vUV1zhe5rtkkuCE/QoDNzJnZSnPCYPQ58JEw/wgH7IixG0glMEaElLWtEKM+5HETNm2tHOpyLUjnZcxVUes+AKwlM85dcUrkYDahxcuVK5k1/8oB+Inen8+fDOO8GVTZMfo2xZuOYa7+uKVqvKHArQuzeUK+f5YppMcP8DGP4qThGmNKWZz3zMmPP9Dpow0YY2jGJUhKTzzKZNaqZzwQIVUFPjH1rBKSLMYQ5lKJPvS2nBQgIJzGCGzzoMDD7lU+pRD8D5FOOo83EeZzA6YpomMMqXh48/Visf770Hc+bAjh3QqJH/So5hwBtvhFJKjZMnn/I8XWaxQP36TgXHKFMG5n2opugutsUxmaBNGxg5MsQCB5cudGEd67iDO5wzNTWpyXjG8w3feHXUCDdbt6qo4K1aqZnOXr2gWjUVWNOXU5tGe1EVCS8qBzvZyfM8z0d8RB55xBFHX/ryDM9Qhzp+13OOcyxiEfOZTxZZNKIRQxlKS1qGUHpNceP//g8eesi/fFYOcnPPr44UB+T4cfjqK2XY26wZxpVXhqfdSZOUJ5XJpHzvTSal9NSqBd98i1G7tmv5jRvhpZdgyWI1staoAQ8Mh4cfxihVKiwyhwJBnL+l0caePUqxOXkyfxgGw4D+/ZWTXHFDu4n7oKgqOA7OcIYTnKACFShJdEcN1RRfzp1T+ay++84/+xqTSZ0TaltV+eMPNd1UoQI0bhyRmC1itcKokUoLvDAEdMuWMOddjGbNQi/Drl0wYwb8+guUKQM9esK//oURH+/5HLsdzp3DiPJoxbHAkCFqNtTbTM0vvyjv/OKEVnB8UNQVHI2mqHD2LEyYAK+9pp5EPWE2K7fx5ctDJ4vs2AGPPaoacfzsNW4M48ZjdO8euobdyTJ4kHr8vvjn12yGsmVVsLy6dcMqkyZ6sFqV6dNZL97qFgs8+ii8/HL45IoGdBwcjUYTFZQsCc8+C4cOqZg5nmZnbDZ44onQySG//QZtr1YW0RcqFdu3Q88eyAcfhK7xi2XZulVlJnX3bGmzwalTMO7FsMmjiT5ycrwrN6Bun8OHwyNPUUUrOBqNJuSUKQOrVikDSThvfGw2q6WpadNUjsiQ8cTj7o0ZHErG8AeQ096DaQaN99/3HjzPaoW5cxEdBbHYUq6cCijtDcOA6tXDI09RRSs4Go0mLDRooLyrZs2CHj2Ufc6TT8KuXXDffaFrVw4fhi++8JwwC5Tys2hR6IS4kCMZvsucOwfZ2aGXRROVmM3Ka8qXHty/f9hEKpL4EYNbo9FogkPp0jBwoNrCxoEDvl25LBblthIOkqv7lqdUKdD2gcWaUaNU+IXjx90bGj/wgArFoPGMnsHRaDSxTcWKvsvYbCoibzi45x7vs0kWC9zTv8gEzytqZJPNVKbSn/4MYhALWMA5zkVarHzUqAE//QTXXZT8vFw5eO45ePPNyMhVlNBeVPopSaOJeeSqK2HzZu8B7g4cxAhTygF55GGYPNm9HImJsPFnjEsvDYssxYmVrOR2bucUpzBhwsDAipXLuIwVrKAR0TklsnOnCvpXqpRSeHzZ58QygYzfeolKowkBkpur3JGPHFGPYjfcgOFPVmZNaBg3Hrp2UZaZFz/TGQY88mjYlBsAXpsElavAKy+72tpcdx28PUMrNyEgnXRu4RasWBEEG+dn0f7gD67nen7jN8pSNoJSuqd+fbVpAkPP4OgZHE2QkXfeUdazJy5IGlO1Kkx+E+OOO0Lf/pkzkJamDFWbN8dICn1mZNmwAdasUW/at8e46qqQtxkosmgRDB0CmZnKitNuV38ffQzGjYtINmw5cwbWrlWRjC+/HKNevcDOF4Hvv1fu7zYbXH01dOumlWk3DGMYM5npMeGwgcE0pjGUoWGWTBMIOtCfD7SCowkV8s47ahB1h2HAJ4swevQITds2G4wdC69POj8rYDbDv/6llKvKlYPf5oEDcOcdSqFyJHC021WOogUfR91MhOTmwuefw++/q6Wgnj1D8rmEAzlwALrfqpbeLBZ1f+XlwaWXwuIlGK1aRVrEqKIylTnKUY/HDQw605llLAujVJpA0QqOD7SCowkFkpsLydU8p/s1DJXrZ+cuDG/ZnAvStgjcO1Blu3QXHbdOHUhbh5GYGLw2s7OhxRVw8GB+Nw+LRQ20mzZj6O9Y0JEzZ6B5M9i3L/9n74iG/MuvUadgRpJylCOHHK9lruM61rAmTBJpCkLURDLOzMykX79+JCQkkJiYyKBBg8jJ8X6DdezYEcMwXLZhw4a5lNm/fz/dunWjdOnSVKlShSeeeAKrTq0aNk5wgnWsYwtbXNaxiz0rVnhWbkApHnv2wLp1wW973Tp4913P0XF371Z5j4LJnDnuB1hQ+/buVTJpgs9HH6lr6u6zt9nUDN4DDyC+wuEWI5rTHJOXIc+CxWfC4exs+OADlXpkwQI4cybYUmqCSUgVnH79+rF161a++uorvvjiC9asWcPQob7XN4cMGcKhQ4ec28sXJNuw2Wx069aNc+fO8eOPP/Luu+8yZ84cRo8eHcquaIBMMhnMYJJIog1taEELLuMypjAFodhNBObnyJHglguEWbO8RwWz2+Ht6cFt84P3fZd5/73gtqlRfDT//JKgO0Tgyy+gVk3k55/DJ1cU8yAPYsdz1lcrVu7DfcRJEXj1VUhKgrvvVmlFevVSkbnnzAmRwJrCIyFi27ZtAsj69eud+5YtWyaGYcgff/zh8bwOHTrIww8/7PH40qVLxWQyyeHDh537pk6dKgkJCZKbm+uXbFlZWQJIVlaWX+U1IlmSJY2lsZjFLLh5PSlPRlrEiGNftkzsBr63jRuD33bXLr7bNZuC22btWr7brF0rqG0WZey7dol9wQKxL1ki9uPHC1dXm9b+3WsWs9grVhB7RkZwOlGEsYlN+kgfQRBDDOdvl+M37WV52eO5kyaJKDXH/TZ/fvj6UdwJZPwO2QxOamoqiYmJXHWBN0VKSgomk4m0tDSv586dO5dKlSrRtGlTRo0axekLcsSkpqbSrFkzql7g0tm5c2eys7PZunWr2/pyc3PJzs522TSBMYlJ/MZvHpekXuZl0kkPs1RRRkqKesTzhMkEl18OLb1PgxeIKlW8z+CAfwHvAqFePc/ZM0EdC9ArKBaRgweRLp2hfj3odSf07AHVkpBHHkbOFTDAXJMmvq83qOWqrCx4552CtRNDmDDxAR8wlak0oIFzf1va8hmf8QTus72ePg2+FgieespziKVIIdnZyCefIO++i6xbp+z0ihkhU3AOHz5MlSpVXPZZLBYqVqzIYS8pUPv27csHH3zAqlWrGDVqFO+//z533XWXS71VL4pX4Xjvqd7x48dTvnx553apNrwLmGlM82pvY8HCTGaGUaLow7BYYPKbypjYkU3SgcmktjcmY1x8LBj0u8u9PYYDsxkGBDk/wpCh3iPy2mwwNIRJpooAcvQoXNMOvv3W9UBurrKJ6tunYAPP0Pu8X+8Lsdvhk4WBtxGDmDAxjGFsZzs55HCGM3zP99zCLR7PWbZMpSrzxr59oTGtKwhityOjR0O1JLjjXzBwAFzdBq5ojmzcGGnxwkrACs7IkSPzGQFfvG3fvr3AAg0dOpTOnTvTrFkz+vXrx3vvvcfixYvZvXt3gescNWoUWVlZzu3AgQMFrqs4YsXKYTwrpQA2bPzO7wHVe4YzzGEOAxhAf/ozgxmc4lRhRI04xr/+BYsWQ+3argcaN4YVKzGuvz40DXfqBJ1S3NtlmM1QoQI88khw27ztNuja1X2bJhPcdBP07BncNosab7wBf/7pXhmx21WCzx9+8Ls6+fZbpEd3uPWWwMLZ5hTt71UoKEMZSlLSZ7ljx/yr76hnD/TwMuIxeGFsfgvo9HTo0B7Zti0yckWAgKNBjRgxggEDBngtU6dOHZKSkjhykTGl1WolMzOTpAACj7Vp0waAXbt2UbduXZKSklh3kaqckaGy83qqNz4+nvj4eL/b1LhixkxpSnOa017LVMT/JZCNbKQrXfmLvzCjljne4z2e4ik+53Ou4ZpCyx0pjO7dkVtvVY90jkjGLVqEZubG0abJhCxZAsPug3nzXL2pmjeHD+djJCcHt02zGVm0GJ59Fqa+dT72TkIC3P8APPdcRILnRRUz3/Gdd2rOHLj2Wp9VyZgxMPZ5dY5DYTKZfK+NWCyhWRYtJtSqFdxyoUT27HGfAgTUfXjunPq+LlgQVrkiRqgMgRxGxhs2bHDuW7FihU8j44tZu3atALJlyxYROW9knHGB0dz06dMlISFBzp4961ed2sg4cIbIELGIxa2BseP1jXzjV11H5IhUkApuDZZNYpIyUkb2y/4Q9yh2sR84IPaZM8U+darYLzDyD2mbp06JPS1NbadOhaXNooDdbPJtCNy1i+96Vqzwz6jY0/bdd2HobWxitYpUry5iGO4NjE0mkZYtIy2lwj52rDIs92V4np0daVELTCDjd8gUHBGRLl26SMuWLSUtLU3Wrl0r9evXlz59+jiPHzx4UBo2bChpaWkiIrJr1y55/vnnZcOGDbJnzx759NNPpU6dOtK+fXvnOVarVZo2bSo33nijbN68WZYvXy6VK1eWUaNG+S2XVnACZ6fslLJS1q1SYhazdJSOYhe7X3WNk3FiEpNHRcksZnlang5xjzSa0GNPqup9sClhEfu99/qup9tN3gcuk+H0lLvQa85uIPbHHgtDT2Obzz9XiszFSo7JJBIfL5KaGmkJFfYHHxR7XAnfCu/evZEWtcBEjYJz7Ngx6dOnj5QtW1YSEhJk4MCBcvLkSefxPXv2CCCrVq0SEZH9+/dL+/btpWLFihIfHy/16tWTJ554Il9H9u7dK127dpVSpUpJpUqVZMSIEZKXl+e3XFrBKRjrZb3UklpOJcShpPSUnpIl/n+WV8qVXmeCEKS+1A9hTzSa8GB/+mnfT9R+zK7YE8r5HrQaNhR7s6bn37e4Quzvvy92u38PHtHCWTkreeL/73m4WLlSpHlzVwWnXTuRn36KtGTnsY8f7/t+K2ERe05OpEUtMIGM3zpVgw4jHxB27HzFV2xiE/HE041uLi6X/tCEJj5dymtQgwNoY3BN0Ub++gtatYSMjPyGxiYT3Hyzyhvlwz5LKlaAEye8N3b99Rhff4OcPAmGgVE2+rJie8KOnXd4h9d5nXTSMTC4nut5kie5kRsjLZ4TEWWr6zCti7YoCHLgANSq6T6iOSh7rF69MN7/ILyCBZGoSdWgiT1MmOhMZ0Yykkd5NGDlBqAVrbB4sW/3J2S6RlMUMCpXhh9+hPbtXQ/ExcGwYfDRAv+Mzzt39h73xmSCG5QiYJQrV+SUm3704z7uYzvKA1cQVrOaznRmClMiLOF5DEOFIOrYMfqUG0DlHhs5yv1BsxnKlIExz4ZVpkiiZ3D0DE7Y+ZEffXpJrWBFVD25aTSFRX77DTZuVMpNx44Yl1zi/7k//aTi6bj7uTaZoFQp+H1PkcyM/j7vcw/3eDxuwsRv/EZd6haqnZwcmDsXvv5aORS1bQsDB0KlSoWqNuoQR16JcS+6zvpdcw1MfxujSZOIyRYMdDZxH2gFJ/I8zdOMZzwmTM78MI7/H+RBJjMZg9C5VWs0RQ2ZORPuG6oUmgvdxEuVgi++xOjQIbICFpDWtGYjGz3miTJj5jEe42VednvcHzZsgC5dIDNTzcKIqL/x8bBwoQrZFGtIbi6sWaM0u0aNMBo3jrRIQUErOD7QCk50sIAFTGQi61kPwBVcwQhGcBd3aeVGo3GD/PYbTJ0KP/4AlhJqZB48GOOi6O5FiVKU4izes56nkMJXfFWg+o8dU8tJJ0/mD0lkGFCiBPzyCzRsWKDqNWEmkPE74EB/Gk2wuPPv11nOIgilKBX0Ng5ykLd5m+Usx4qV9rTnfu6nIfrXTFP0MBo0gEmTIi1GUIkjzquCY2AU6rdh1iwVg9JdPEQRtf/NN1XmDE1soY2MNRGnJCVDotysZCX1qc84xrGe9WxiE1OYQhOaMIc5QW8vEogIsmYNMm4cMn48kpZWbJLqiQjy2WdIl85IjepIo4bImDHIoUORFk0TAD3p6dXpQBC6073A9X/6qfdgz1YrLF5c4Oo1UYxeotJLVDHJn/xJPeo5Z4cuxsBgAxtoRasISBccZNcuuK0n/O9/57N622zQujUs/ASjRo3IClgI5MQJ+OAD2LZNeX7cdhtcfbXT40jsdhgwAD54X/XdsfZgNkO5cvD1Nxitiu61LU5sYQtXcRU2bPm+q2bMVKUqO9lJaQLIvXUB//iHssHxxiWXRFEuKY1XtJu4ptjzNm+TS65b5QbUD+cbvBFmqYKHHDsGHdqDI7GtzXZ+kP/5Z/hnR+RU0UywKPPmQXI1ePghlcvpjdeVB1Gn65XiAzBlilJuwNWwwmZTxha33Izk5YVbdE0BuIIr+IRPKElJDAxMmJwzOskk8y3fFli5AaXve/OwN5uVEqSJPbSCo4lJVrLSo1cGqAzpy1keRomCzNtvuw8eB2rf778rn9gihnz7Ldx9F5w9qwwk8vLO9/H77+G2nmr2ZtJrykLUHTYbHDoES5aETW5N4biVW/mDP3iVV+lFL/rSlw/5kF3sKrS93P33u/+aOLDZ4MEHC9WEJkrRCo4mJvGm3ARSJmr54H3fWaTnFsFopS+MVa7P7rDZYPVqWLYM9u71HK0VlGvM99+HQkJNiKhABR7lUeYxj3d5l970Jo64QtfbtCm89pr6/8Lk9o7b7KGHYtNNXKMVHE2M0p72mDF7PG7BQnvaezwe9Rw/7v24iAr6UYSQEyeUAnOxL++FWCyw9Ev/KvQnQrCmWPDoo7ByJXTqpG4hk0ktXc2fD6+/rm+VWEUrOJqYZBjDvMbSsWLlYR4Oo0RBpn59zzMdoB5V69cPnzzB4PRp32UMQ81cNWjgfVTKy4N//jN4smmKPDfcACtWwLlzaskqNRV69dLKTSyjFRxNTFKHOrzHey4Gi4Dz/5d4qWjP4Ay9z/sSlc2myhQlKleGxETvZaxWuLwpjHjc8xKV2Qy1aqlElhrNRRiGVmqKC1rB0cQsfejDJjZxD/eQTDJVqUpPerKGNTzJk5EWr3D06gU3dnY/i2MYcGcvlaAxShG7HZk7F2l7NVKmNFLpEhg+HHre5moocTHx8XDXXTB4sCoPri4yhqF8fr9ciuHNdUaj0cQ8Og6OjoOjKaJIbi489xy89RZkZ6mdl1wCjzwKI0dieFMUAmnn0CHYskUZ7rZti1G64C67AGKzQb++sGCBUtAcM1EO44jkZDhwwNUWx2xW5d59D+Ouu1Q9IirXzrSpKtZ+uXJKsRs4EKNChULJqNFoohOdi8oHWsHRxBJy9qyKh2MY0LgxRlzhPU8A5K+/1CzJok/OKyFly8K/H4LnnivwDIm89Rb8+0HvmbEHD4E5syHrb8WtY0f4z38xOnUqWGc0Gk1MoHNRaTTFCKNkSWjRIqh1SlYWXHsN7NnjauuTkwMTxsPevcgHHzgjC/tdr4gK3OcJu10ZG9evD0f+gr/+gjJlMMqXL1hHNGFFEP7iLwShClWiKmnukSNqsvO99+DECahTB4YNg3vugSA9E2iiDG2Do9Fo8vN//we7d7uPkCYCH85TbiiBcuoU7NzpPYaNyQTr12GUKIGRnKyVmyKAILzN2zSkIVWpShJJ1KMeU5gSFfGmduyAZs1g7Filsx8/Dps2wZAhkJICZ85EWkJNKNAKjkajyc+Mt717aVksKk1zoPhjF2QYYNaTy0UFQRjOcO7jPnaxy7l/D3t4kAcZxCCPKVPCIp+oVGbHjrne0o7/f/gB/vvfyMimCS1awdFoNPnxlZHbaoX9+wOu1ihVCq65xruiY7VCly4B162JDKtYxVSmArgoMo7/5zCHZSyLiGyg7NC3bfMcP9JuV5lPimjqNo0XtIKj0WjyU7Gi9+NmMyRVLVjdTz7lebQxm6FmTejevWB1a8LONKa5xJq6GDNm3uKtMErkSmqq74nDnBxITw+PPJrwoRUcjUaTnwEDvY8KNhvcdXeBqjZuuQVefkW9cXhiOYyVq1aFFSsxSpQoUN2a8LOFLVjxnM3Sho1f+CWMErliNns3+bqwnCa20AqORqPJz8MPQ6VKrkH0HJhMcH0nZZ1ZQIzHH4dt6TD8QejQAbp2hbdnwI7fMBo0KITgmnBTjnI+y5SlbBgkcU9Kiu+8tJUqweWXh0ceTfjQlnwazQUIElWurZHCSEpCvl8Ld/WDdevOHzCZoG9fmDoNw1suLH/aaNQIJk0qpKSaSHMnd7KJTR69pUyY6E3vMEt1npYtoX17+PFH906BhqGScWpX8dhDB/rTgf6KPYc5zOu8zixmcZSjVKEKgxnMIzxCJSpFWryII5s3KyUnLg5uuAGjevVIi6SJIo5xjEY04jjHseFqW2XGTAIJpJNOVQposxUEMjLg+uuVsbEjeLbFohSeu+6COXP0ElVRQUcy9oFWcDQO9rCHdrTjL/5y+XE2Y6Y61fmBH6hBjQhKqNFEP1vZSle6coADlEDZT+WRRzLJfMmXtKBFZAUEcnNVdpC5c+HoURVLcuhQFSRbJ98sOmgFxwdawQk+Z87ARx/Bl1+qH5Irr1T5EEP9sH+Oc+xkJ4LQgAbEEdg8c3vak0qqWyNJCxZu4AaWsjRY4mo0MYsVK5/xGatZjSC0pz096OFUeDSaYKAVHB9oBSe4pKcrQ74//zw//WsyqW3mTBUKPdhYsTKe8bzBGxzjGACXcAkP8zCjGOXVbdXBNrZxOd4tCw0MdrOb2tQOitwaTSjIJpuv+IoccmhMY/7BP7QtmSYm0bmoNGHjzBml3GRkqPcObwW7XW0DBkC9etCuXfDatGOnN71ZxCKXwGLHOMYYxrCJTSxkISYfToI/87PPtgRhE5u0glOEOcc51rGO05ymMY25lEsjLVLQsGPnWZ5lIhM5w/l8A01pyhzmcCVXRlA6jSayaDdxTaH46CM1c+Mtbturrwa3zc/5nE/4xG34d0FYzGI+4zOf9fi7nBVPfMAyaiKPILzO61SnOtdxHZ3pTE1qcgu3sJ/AozBHI4/yKC/wgotyA5BOOu1pzza2RUgyjSbyaAVHUyiWLlVLUZ6wWuGLL/wLtOUv05mOGc8uD2bMTGOaz3qu53qf9gGlKMV1XBewjJrI8x/+w6M8ylGOOvcJwjKW0YY2/MmfEZSu8OxhD2/ypltF34aNc5zjOZ6LgGQaTXSgFRxNoTh3zncQLXexJwrDdrbnc0e9EBs2drDDZz2VqMRgBntcyjIweJAHSUDbaRU1fud3JjDB7TEbNo5ylPGMD7NUwWUuc70uw1qx8gmfcJKTYZRKo4ketIKjKRStWnmPH2EywRVXBNcNsyLe8yQZGFSggl91TWISN3MzgNMw2fG3F714kRcLIWnh+ZM/eZVXeZIneZ3XySAjovIUFd7lXZ+D/yxmkUdeGKUKLhlk+LQzs2Ejk8wwSaTRRBdawdEUisGDvS9R2e3w0EPBbbMf/Xx6iNzFXX7VFU88S1jCGtYwgAF0oxv3ci+ppDKPeRFzcRWEp3maS7nUqdyMYAQ1qMFYxrpdltCc5wAHfN4jpzlNFllhkij4VKe6x+jBDixYdLBKTbElpApOZmYm/fr1IyEhgcTERAYNGkROTo7H8nv37sUwDLfbxx9/7Czn7vj8+fND2RWNB5KTYfZsNUNzYdoih9LTt2/w3cTv5V6qU92tHY4FC9Wpzr3c63d9BgbXcR0zmMEXfMF0pnM1V0fUzXYc4xjPeOx/v/LIw44dK1ZGM5rJTI6YbEWBylT2WaYEJfzKoxSt3MVdXhVdCxZ605sylAmjVBpN9BBSBadfv35s3bqVr776ii+++II1a9YwdOhQj+UvvfRSDh065LI999xzlC1blq5du7qUnT17tku5Hj16hLIrGi/066fyvPToAfHxSrlp0UKFP3//fe8zPAWhPOX5ju9oQhNA/ZA7lpUa05jv+I5EEoPbaBg5xSmf9iHP8zznOBcmiYoe/ejnNcO1Y/Avyh5yNajBSEa6PWbGTFnKMoYxYZZKo4keQhboLz09nSZNmrB+/XquuuoqAJYvX85NN93EwYMHSU5O9queli1b0qpVK2bOnHleaMNg8eLFBVZqdKC/0CISntDngvA93/Md3wEqKnF72hf5AGeLWcxt3Oaz3Fd8RQoFz+gd6/SjH/OZn28Zx4yZkpRkAxtoRKMISRccBOFVXuVFXuQEJ5z7r+VapjPd+RCg0cQKgYzfIZvBSU1NJTEx0ancAKSkpGAymUhLS/Orjo0bN7J582YGDRqU79jw4cOpVKkSrVu3ZtasWXjT03Jzc8nOznbZNKEjXHldDAza055n/n51oEORV24Av71estH3sTdmM5thDHPO7jnujbrUZTWri7xyA6pPj/M4hznMSlayiEWkk873fK+VG02xJ2SRjA8fPkyVKlVcG7NYqFixIocPH/arjpkzZ9K4cWPaXRQG9/nnn+f666+ndOnSrFy5kgceeICcnBwe8mDNOn78eJ57TseD0MAGNjCXuRzjGLWpzQAGRF2U4gY0CGq54koccUxhCmMYwzKWcZrTNKUp13JtVCrCgrCLXZzkJLWo5dNb8ELiiecGbiCXXJawhAUsoBzl6ElPalErdEIXktxcFSdr/36oXBluvRX0pLomaEiAPPXUUwJ43dLT0+XFF1+UBg0a5Du/cuXK8tZbb/ls5/Tp01K+fHmZOHGiz7LPPPOM1KhRw+Pxs2fPSlZWlnM7cOCAAJKVleWzbk1scFpOSw/pIQhiEYuY/34ZYsgz8ozYxR5pEZ3YxS5NpImYxSy4eZnFLP+Qf0RaTE0QWSgLpYk0cV5ji1ikr/SVg3LQ7zo+l8+lolQUBCkhJcQkJjHEkP7SX87K2RBKXzDmzhWpUEEEREwm9bdUKZGXXhKxR8/XURNlZGVl+T1+BzyDM2LECAYMGOC1TJ06dUhKSuLIkSMu+61WK5mZmSQlJflsZ+HChZw+fZp7/HDBadOmDWPHjiU3N5f4+PxGg/Hx8W73a4oPwxjmTN9wsfHpWMZSjWrcz/2REC0fBgazmMU/+SfnOOcS1NBhPzKDGRGUUBNM3uZt7uM+l1klK1YWsIDv+I71rKca1bzWsZa19KCH097owvg+7/M+eeQxl7mh6UABWLxYOSc4cAQLPXMGnnpKLXM/8URkZNPEEKHSsrZt2yaAbNiwwblvxYoVYhiG/PHHHz7P79Chg9x+++1+tfXCCy9IhQoV/JYtEA1QU/TZJ/vEEMPtbIjjlSzJYhVrQPXult3ypDwpbaWtXCvXyvPyvBySQ0GTe7NslpvlZqfsJjFJT+kpW2WrS9+ekCfkMrlMLpFLpIN0kI/kI7GJLWhyaEJHpmRKvMR7vC8tYpHBMthnPZ2kk8cZP8crXdLD0CPf2O0ideuKGIaatXG3lSkjcvJkpCXVRCOBjN8hU3BERLp06SItW7aUtLQ0Wbt2rdSvX1/69OnjPH7w4EFp2LChpKWluZy3c+dOMQxDli1blq/Ozz77TGbMmCG//vqr7Ny5U9566y0pXbq0jB492m+5tIJTvHhL3vKp4CDIBtngu7K/mStznctcjvNNYpLSUlq+lq+DKv9ROSrpki7H5JjL/lRJlbJS1kUGx/+9pXfACpsm/Lwpb/q8N0tKScmRHI91HJWjPu9ts5jlWXk2jD3zzIYNnhWbC7cPP4y0pJpoJJDxO6RxcObOnUujRo3o1KkTN910E9deey1vv/2283heXh47duzg9OnTLufNmjWLGjVqcOONN+ars0SJEkyZMoW2bdvSokULpk+fzmuvvcaYMTreg8Y9pzntM6Q9kC8jsyc2s5m7uRvb3y8Hduyc4Qy3cAuHOFRgeS/mEi6hEY1cjE5zyeVWbuUMZ1xkcPz/ER8xhSlBk0ETGnaz2+nl5YmznPWaosOfaMwmTC5u5JHk2DHfZQwDjh71XU6j8UbIvKgAKlasyLx58zwer1Wrllv37nHjxjFu3Di353Tp0oUuXboETUZN7NOMZl6Tc4IK/NaQhn7VN5nJmDC5DZMvCLnkMoMZjGZ0geT1h4Us5C/+8lpmEpP4N/+OSo8hjaICFXymWwAV3NITSSRRkpKc5azHMlas1KVugWQMNjVr+i4jArVqhVwUTYyjc1FpYp4UUqhFLY+zOGbM3M7tfoX3B1jKUq9Rcu3YWc7yAsnqLz/yo9c8WYKwl70c4YjHMprIcyd3elW+zZjpRCcu4RKPZUpTmn708zoTFEcc/ejn8Xg4adgQrr7ac4Rzw4AqVaBz5/DKpYk9tIKjiXlMmPiQD4knPt8gYMZMDWrwOq/7XZ+v2SDI76kVbNzl4SpMOU1kaEQj+tLXrfLtmHl7lmd91jOWsVSlar7721HH67xOBSoUXuAgMXkyxMWB+aLb0xEkdOpUKBGZPLeaGEIrOJpiwdVczQY20JvezpmPBBJ4mIdZz3qSOB+64NQpmDEDevWCf/0LXn3V1W7gOq7z+rRsxsx1XBeyvgB0opOLK/DFGBhczuVen/w14SU3Fz77DGbOhJUrwfq3DjyLWdzN3RgYmDA5788KVGAJS7iWa33WXY1qpJHGndzpcm82pjELWcgwhoWkTwXlH/+A779XMzkX0qQJfPkl3OY7U4lG45OQ5aKKZnQuquJNHnmc4hTlKJdvhmPjRjU1fuyYmkJ35NUqWRI+/hhuuglWs5p/8k+P9ZswsZ3t1Kd+yPpgxUpDGrKPfR5nlN7jPe7m7pDJoPGft9+GkSPh+PHz+6pVgylToGdP9X4ve1nMYk5ykkY0ojvdC5QMNJNM9rKXcpSjHvWi3gZr1y44cEBFMr788vCletEUTQIZv7WCoxUczd9kZkK9epCdDbaLdAbDUFPmW7ZAo0bwIi/yX/6LBYtzOcqCBRs2JmTMxvxBf3JyoGlTuOUWNR0fbH7jNzrSkcOo1CeCOOV5kieZwISoH9yKA2+/Dffdl3+/YyD/7DO4+ebwyqTRFFW0guMDreBoHOTlwZ49arZm8WL1lG334NRiscDQoeqpG2AVq5jMZNawBhMmbrB25egzD/PVhCsxmZR9QV4eVKoE8+bBDTcEX/5ssnmf91nAAk5ykiu4gmEMow1tgt+YJmDOnoWkJMjy4MltGEqp3rFDz1xoNP6gFRwfaAVHk5cH48fDm2+ej7cRFwfnznk/LykJDnkIcdOjB3z+eX4FyaHs/PgjXHWVf/JZrbB0Kfz2G5QvD927K8+SWOKvv+D99+H336FCBejdWy1RxBJLlpxfgvLG+vX+3xsaTXEmkPE7pHFwNJpoxGZTRoxLl7oqI76UG29lfv4ZPv3U/TG7XT2djx3rucyFLF8OAwZARoZSjOx2eOABGD4cJk5UM0lFncmT4fHH1bUwm5Wt0wsvKCVnzhwoaqnjrFZlHLtmjbrWHTooe60Mz/H5XPC3nEaj8Z8Y+KnUaAJjwQL44ovAzzOb4cor3R/76COleFg9eIfbbKrNU6egTBnPbaxdq+wxHIqXwxbIalVKwblz8NZbgcseTXz4ITz88Pn3FyqZCxYog+7Zs8MvlzdOcYp5f7+Oc5zGNGYoQ+lIR7b+z+Dmm2HfvvOuza++CrVr+58wskaN0Mmu0RRX9BKVXqIqdrRvDz/84NnWxhuff+7eIHToUDXzkOfZcxuAw4ehalXPxzt2VErOxUbODgwD9u6Fyy7zU+AoQwQaNIDdu9X/7oi2Ph7gAP/kn+xmNwaGizF3nzMDWVnzHU5kmvJdM7MZLrlEKaeZme7rNpnUstyWLdoGR6Pxh0DGbx0HR1PsSE8PTLlxRFwdPhy6dXNfpm5dz0qJg7JloWJFz8czMuC777zXYzLB/Pne24lm0tOVW7C3xyrDULYr0YAg9KAH+9jnfA/nAzl+WHI2mfdMcnvNbDZl39W1q/u6TSa1TZ6slRuNJhRoBUdT7CjvOa0PoAabxEQ1+BiGMv6cN08ZJHsaiPr39xx6HtTT/KBB3qOz+pOE0GTyr1y0kpPju4zJ5F+5cPAjP/IzP3uNTC2PvQpm98ftdqXULVyYP7dS48Yq4F/HjsGTV6PRnEcrOJpiR79++UPEX8yECWppwWqFtDTo08f7U3ZSErzyivr/4nJms1pu+e9/vbeZnOzbgNhqVbYdRZU6dfzrY+PG4ZHHF9/wjfds3waQfAjq7fJYJDsbbr9dLcv9+KOandq4EX79Ff7pOV6kRqMpJFrB0RQ77r9fzeK4U3IsFpXtuF8/pah4m5W5mEceUTM9DRqc3xcXB3ffDampKh6ONxITVWoIbwpAfLzyNCqqVKoEd9zhvY+VK0dP4Dt/8o4BYHZfzmI57/puMkHbtsrlv1UrvSyl0YQareBoih1JScrWxWHEWqLE+QG3SRNYvVrZyxSEPn3UksT27eopPSNDeQR5Myy+kHHjICHB8wzTa68pRagoM3Gi+jw8KTkmk/IU82XTFA6u4RrfiVMzK8BO92k5rFalUGs0mvCjFRxNsaRpU9i5U8UuefJJGDUKVq2CzZvVDE5hMAxo2FA9pQeqjNSurZbEunZ1fcKvW1e5V8fCYJmcrALbDRrkXsk5cgQefRT69i2Yp1swSSGFetTzmJXdJCaar3kQ8lxzcTiu3b33wo03hlpKjUbjDu0mrt3ENVHKH3+oKL8JCdC8eewtaWzYoLJKe+Ojj+DOO8Mjjye2sY0OdCCTTOwojcuECTt2utCFxfZPmf5mHK+9Bvv3q3Nq1YIRI1SAxkCWOTUajXd0qgYfaAVHo4k8gwbBe+95Do5oNsM116jlxEiTQQZTmcoHfEAWWdSnPvdzP33o4zRCttuVUmoYapZKKzYaTfDRCo4PtIKj0agZlEWLVHTlyy9X9kPlyoWv/X/8Q8ngjYoVi7ZbvEajCS46F5VGo/FIVpby1vr6a2UDYxhqFuXRR+Hdd9WxcFCunGrb2yNW6dLBbdNmU30tarmuNBpN4OhJVI0mhtmyRS0DffwxHD+ulInbblMG1aAG+7w8tf/MGejVC77/Pjyy+VKkzGYlTzBITVXu2XFxKtdV3brwxhv+JVjVaDRFE71EpZeoNDFIerqKrrx+/fl98fFKufnwQ8/nmc3QqROsWBF6GU+ehEaNlCv9xS7hJhOUKgX/+1/+CMCB8tFHyiPLMM634zDYTklRSVDj4jyfr9Foogedi0qjKcbs2wfXXgs//+y6PzdXKTfevLFsNpU+4OTJ0MoIaolq1arzbvklSpxPZVGhgpKjsMrNsWNK0RNxVaJE1Pb11yoFh0ajiT20DY5GE2NMmKDSA3gKlOfPnO3p0+ExOG7QAHbsUPGIvv5aLZldc41avipZsvD1OzK8e+qziFJwHnss9tzwNZrijlZwNJoYwmZThsKeXK/9ITERLrkkaCL5xGJR9jHduwe/7i1bfCsu+/YpT7KCRq/WaDTRiV6i0mhiiNOnlbFwQTGbYdgw3wkxiwrx8b4VHMPQNjgaTSyiFRyNJoYoU0Zt3nAEoLs4EJ3ZrLJ4jxoVGtkiwS23eJ/NMpvhhhu0gqPRxCJawdFoYgiTCQYO9JysE1TE3WnT4Oqrz+9LSFDZ0NeuVf/HCt26KU8tTzNSdjs89VR4ZdJoNOFBu4nH0q+5RoNKF9CqFWRm5p+9MAwYMgSmT1fvjx5Vy1pJSbE7i3HggEp4uX27UnQcCTxNJpgxAwYMiKh4Go0mAHQkY42mGFO9Ovz0EwweDN9+e35/2bIqAeTo0ef3VaoUfvnCzaWXwq+/qng3n36qbJSaNVO5sJKSIi2dRqMJFXoGR8/gaGKYnTtVsLySJaF9e9/2ORqNRhPN6BkcjUYDQP36atNoNJrihjYy1mg0Go1GE3OETMF58cUXadeuHaVLlyYxMdGvc0SE0aNHU61aNUqVKkVKSgo7d+50KZOZmUm/fv1ISEggMTGRQYMGkZOTE4IeaDQajUajKaqETME5d+4cd9xxB/fff7/f57z88stMnjyZadOmkZaWRpkyZejcuTNnz551lunXrx9bt27lq6++4osvvmDNmjUMHTo0FF3QaDQajUZTRAm5kfGcOXN45JFHOHHihNdyIkJycjIjRozg8ccfByArK4uqVasyZ84cevfuTXp6Ok2aNGH9+vVcddVVACxfvpybbrqJgwcPkpyc7JdM2shYo9FoNJqiR5HMJr5nzx4OHz5MSkqKc1/58uVp06YNqampAKSmppKYmOhUbgBSUlIwmUykpaWFXWaNRqPRaDTRSdR4UR0+fBiAqlWruuyvWrWq89jhw4epUqWKy3GLxULFihWdZdyRm5tLbm6u8312dnawxNZoNBqNRhOFBDSDM3LkSAzD8Lpt3749VLIWmPHjx1O+fHnndumll0ZaJI1Go9FoNCEkoBmcESNGMMBHXPM6deoUSJCkv0OKZmRkUK1aNef+jIwMWrRo4Sxz5MgRl/OsViuZmZnO890xatQoHnvsMef77OxsreRoNBqNRhPDBKTgVK5cmcqVK4dEkNq1a5OUlMQ333zjVGiys7NJS0tzemK1bduWEydOsHHjRq688koAvv32W+x2O23atPFYd3x8PPHx8SGRW6PRaDQaTfQRMhuc/fv3k5mZyf79+7HZbGzevBmAevXqUbZsWQAaNWrE+PHj6dmzJ4Zh8Mgjj/DCCy9Qv359ateuzTPPPENycjI9evQAoHHjxnTp0oUhQ4Ywbdo08vLyePDBB+ndu7ffHlSgPLZA2+JoNBqNRlOUcIzbfjmAS4jo37+/APm2VatWOcsAMnv2bOd7u90uzzzzjFStWlXi4+OlU6dOsmPHDpd6jx07Jn369JGyZctKQkKCDBw4UE6ePBmQbAcOHHArm970pje96U1veov+7cCBAz7H+mKZbNNut/Pnn39Srlw5DMMocD0OW54DBw7EdDwd3c/YoTj0EXQ/Yw3dz9iiMP0UEU6ePElycjImk3c/qahxEw8nJpOJGjVqBK2+hISEmL4ZHeh+xg7FoY+g+xlr6H7GFgXtZ/ny5f0qFzWB/jQajUaj0WiChVZwNBqNRqPRxBxawSkE8fHxjBkzJuZd0HU/Y4fi0EfQ/Yw1dD9ji3D1s1gaGWs0Go1Go4lt9AyORqPRaDSamEMrOBqNRqPRaGIOreBoNBqNRqOJObSCo9FoNBqNJubQCo4XXnzxRdq1a0fp0qVJTEz06xwRYfTo0VSrVo1SpUqRkpLCzp07XcpkZmbSr18/EhISSExMZNCgQeTk5ISgB/4RqDx79+7FMAy328cff+ws5+74/Pnzw9EltxTkc+/YsWO+PgwbNsylzP79++nWrRulS5emSpUqPPHEE1it1lB2xSuB9jMzM5N///vfNGzYkFKlSnHZZZfx0EMPkZWV5VIu0tdzypQp1KpVi5IlS9KmTRvWrVvntfzHH39Mo0aNKFmyJM2aNWPp0qUux/35rkaCQPo5Y8YMrrvuOipUqECFChVISUnJV37AgAH5rluXLl1C3Q2fBNLPOXPm5OtDyZIlXcpE4/UMpI/ufmsMw6Bbt27OMtF4LdesWcMtt9xCcnIyhmGwZMkSn+esXr2aVq1aER8fT7169ZgzZ06+MoF+390SUBKnYsbo0aPltddek8cee0zKly/v1zkTJkyQ8uXLy5IlS2TLli1y6623Su3ateXMmTPOMl26dJErrrhCfvrpJ/n++++lXr160qdPnxD1wjeBymO1WuXQoUMu23PPPSdly5Z1yQsGKtfYheUu/BzCTUE+9w4dOsiQIUNc+pCVleU8brVapWnTppKSkiKbNm2SpUuXSqVKlWTUqFGh7o5HAu3nr7/+Krfddpt89tlnsmvXLvnmm2+kfv36cvvtt7uUi+T1nD9/vsTFxcmsWbNk69atMmTIEElMTJSMjAy35X/44Qcxm83y8ssvy7Zt2+S///2vlChRQn799VdnGX++q+Em0H727dtXpkyZIps2bZL09HQZMGCAlC9fXg4ePOgs079/f+nSpYvLdcvMzAxXl9wSaD9nz54tCQkJLn04fPiwS5lou56B9vHYsWMu/fvf//4nZrPZJV9jNF7LpUuXyn/+8x9ZtGiRALJ48WKv5X///XcpXbq0PPbYY7Jt2zZ58803xWw2y/Lly51lAv3sPKEVHD+YPXu2XwqO3W6XpKQkeeWVV5z7Tpw4IfHx8fLhhx+KiMi2bdsEkPXr1zvLLFu2TAzDkD/++CPosvsiWPK0aNFC7r33Xpd9/tzs4aKg/ezQoYM8/PDDHo8vXbpUTCaTy4/t1KlTJSEhQXJzc4MieyAE63ouWLBA4uLiJC8vz7kvktezdevWMnz4cOd7m80mycnJMn78eLfl77zzTunWrZvLvjZt2sh9990nIv59VyNBoP28GKvVKuXKlZN3333Xua9///7SvXv3YItaKALtp6/f4Gi8noW9lpMmTZJy5cpJTk6Oc180XssL8ec34sknn5TLL7/cZV+vXr2kc+fOzveF/ewc6CWqILJnzx4OHz5MSkqKc1/58uVp06YNqampAKSmppKYmMhVV13lLJOSkoLJZCItLS3sMgdDno0bN7J582YGDRqU79jw4cOpVKkSrVu3ZtasWf6luA8Bhenn3LlzqVSpEk2bNmXUqFGcPn3apd5mzZpRtWpV577OnTuTnZ3N1q1bg98RHwTr/srKyiIhIQGLxTVdXSSu57lz59i4caPL98pkMpGSkuL8Xl1MamqqS3lQ18VR3p/vargpSD8v5vTp0+Tl5VGxYkWX/atXr6ZKlSo0bNiQ+++/n2PHjgVV9kAoaD9zcnKoWbMml156Kd27d3f5fkXb9QzGtZw5cya9e/emTJkyLvuj6VoWBF/fzWB8dg6KZbLNUHH48GEAl8HO8d5x7PDhw1SpUsXluMVioWLFis4y4SQY8sycOZPGjRvTrl07l/3PP/88119/PaVLl2blypU88MAD5OTk8NBDDwVNfn8paD/79u1LzZo1SU5O5pdffuGpp55ix44dLFq0yFmvu+vtOBZugnE9jx49ytixYxk6dKjL/khdz6NHj2Kz2dx+ztu3b3d7jqfrcuH30LHPU5lwU5B+XsxTTz1FcnKyy+DQpUsXbrvtNmrXrs3u3bt5+umn6dq1K6mpqZjN5qD2wR8K0s+GDRsya9YsmjdvTlZWFhMnTqRdu3Zs3bqVGjVqRN31LOy1XLduHf/73/+YOXOmy/5ou5YFwdN3Mzs7mzNnznD8+PFCfw8cFDsFZ+TIkbz00ktey6Snp9OoUaMwSRQa/O1nYTlz5gzz5s3jmWeeyXfswn0tW7bk1KlTvPLKK0EdEEPdzwsH+WbNmlGtWjU6derE7t27qVu3boHrDZRwXc/s7Gy6detGkyZNePbZZ12OheN6agrOhAkTmD9/PqtXr3YxwO3du7fz/2bNmtG8eXPq1q3L6tWr6dSpUyREDZi2bdvStm1b5/t27drRuHFjpk+fztixYyMoWWiYOXMmzZo1o3Xr1i77Y+FahpNip+CMGDGCAQMGeC1Tp06dAtWdlJQEQEZGBtWqVXPuz8jIoEWLFs4yR44ccTnParWSmZnpPD8Y+NvPwsqzcOFCTp8+zT333OOzbJs2bRg7diy5ublBy0ESrn46aNOmDQC7du2ibt26JCUl5bPuz8jIAChy1/PkyZN06dKFcuXKsXjxYkqUKOG1fCiupzsqVaqE2Wx2fq4OMjIyPPYpKSnJa3l/vqvhpiD9dDBx4kQmTJjA119/TfPmzb2WrVOnDpUqVWLXrl0RGRQL008HJUqUoGXLluzatQuIvutZmD6eOnWK+fPn8/zzz/tsJ9LXsiB4+m4mJCRQqlQpzGZzoe8PJwFZ7BRTAjUynjhxonNfVlaWWyPjDRs2OMusWLEi4kbGBZWnQ4cO+bxtPPHCCy9IhQoVCixrYQjW57527VoBZMuWLSJy3sj4Quv+6dOnS0JCgpw9ezZ4HfCTgvYzKytLrr76aunQoYOcOnXKr7bCeT1bt24tDz74oPO9zWaT6tWrezUyvvnmm132tW3bNp+RsbfvaiQItJ8iIi+99JIkJCRIamqqX20cOHBADMOQTz/9tNDyFpSC9PNCrFarNGzYUB599FERic7rWdA+zp49W+Lj4+Xo0aM+24iGa3kh+Glk3LRpU5d9ffr0yWdkXJj7wylPQKWLGfv27ZNNmzY5XaA3bdokmzZtcnGFbtiwoSxatMj5fsKECZKYmCiffvqp/PLLL9K9e3e3buItW7aUtLQ0Wbt2rdSvXz/ibuLe5Dl48KA0bNhQ0tLSXM7buXOnGIYhy5Yty1fnZ599JjNmzJBff/1Vdu7cKW+99ZaULl1aRo8eHfL+eCLQfu7atUuef/552bBhg+zZs0c+/fRTqVOnjrRv3955jsNN/MYbb5TNmzfL8uXLpXLlyhF3Ew+kn1lZWdKmTRtp1qyZ7Nq1y8UF1Wq1ikjkr+f8+fMlPj5e5syZI9u2bZOhQ4dKYmKi03vt7rvvlpEjRzrL//DDD2KxWGTixImSnp4uY8aMcesm7uu7Gm4C7eeECRMkLi5OFi5c6HLdHL9RJ0+elMcff1xSU1Nlz5498vXXX0urVq2kfv36EVHAHQTaz+eee05WrFghu3fvlo0bN0rv3r2lZMmSsnXrVmeZaLuegfbRwbXXXiu9evXKtz9ar+XJkyedYyMgr732mmzatEn27dsnIiIjR46Uu+++21ne4Sb+xBNPSHp6ukyZMsWtm7i3z85ftILjhf79+wuQb1u1apWzDH/HBnFgt9vlmWeekapVq0p8fLx06tRJduzY4VLvsWPHpE+fPlK2bFlJSEiQgQMHuihN4caXPHv27MnXbxGRUaNGyaWXXio2my1fncuWLZMWLVpI2bJlpUyZMnLFFVfItGnT3JYNF4H2c//+/dK+fXupWLGixMfHS7169eSJJ55wiYMjIrJ3717p2rWrlCpVSipVqiQjRoxwca8ON4H2c9WqVW7vc0D27NkjItFxPd9880257LLLJC4uTlq3bi0//fST81iHDh2kf//+LuUXLFggDRo0kLi4OLn88svlyy+/dDnuz3c1EgTSz5o1a7q9bmPGjBERkdOnT8uNN94olStXlhIlSkjNmjVlyJAhAQ8UoSCQfj7yyCPOslWrVpWbbrpJfv75Z5f6ovF6BnrPbt++XQBZuXJlvrqi9Vp6+v1w9K1///7SoUOHfOe0aNFC4uLipE6dOi5jqANvn52/GCIR8tvVaDQajUajCRE6Do5Go9FoNJqYQys4Go1Go9FoYg6t4Gg0Go1Go4k5tIKj0Wg0Go0m5tAKjkaj0Wg0mphDKzgajUaj0WhiDq3gaDQajUajiTm0gqPRaDQajSbm0AqORqPRaDSamEMrOBqNRqPRaGIOreBoNBqNRqOJObSCo9FoNBqNJub4fzbnzhIGzgH6AAAAAElFTkSuQmCC",
"text/plain": [
"<Figure size 640x480 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import matplotlib.pyplot as plt\n",
"X, y = spiral_data(samples=100, classes=3)\n",
"plt.scatter(X[:, 0], X[:, 1], c=y, cmap='brg')\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-block alert-danger\">\n",
"\n",
"CREATING LAYERS: FORWARD AND BACKWARD PASS</div>"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"# Dense layer\n",
"class Layer_Dense:\n",
" # Layer initialization\n",
" def __init__(self, n_inputs, n_neurons, \n",
" weight_regularizer_l1=0, weight_regularizer_l2=0, \n",
" bias_regularizer_l1=0, bias_regularizer_l2=0):\n",
" # Initialize weights and biases\n",
" self.weights = 0.01 * np.random.randn(n_inputs, n_neurons)\n",
" self.biases = np.zeros((1, n_neurons))\n",
" # Set regularization strength\n",
" self.weight_regularizer_l1 = weight_regularizer_l1\n",
" self.weight_regularizer_l2 = weight_regularizer_l2\n",
" self.bias_regularizer_l1 = bias_regularizer_l1\n",
" self.bias_regularizer_l2 = bias_regularizer_l2\n",
"\n",
" # Forward pass\n",
" def forward(self, inputs):\n",
" # Remember input values\n",
" self.inputs = inputs\n",
" # Calculate output values from inputs, weights, and biases\n",
" self.output = np.dot(inputs, self.weights) + self.biases\n",
"\n",
" # Backward pass\n",
" def backward(self, dvalues):\n",
" # Gradients on parameters\n",
" self.dweights = np.dot(self.inputs.T, dvalues)\n",
" self.dbiases = np.sum(dvalues, axis=0, keepdims=True)\n",
"\n",
" # Gradients on regularization\n",
" # L1 on weights\n",
" if self.weight_regularizer_l1 > 0:\n",
" dL1 = np.ones_like(self.weights)\n",
" dL1[self.weights < 0] = -1\n",
" self.dweights += self.weight_regularizer_l1 * dL1\n",
"\n",
" # L2 on weights\n",
" if self.weight_regularizer_l2 > 0:\n",
" self.dweights += 2 * self.weight_regularizer_l2 * self.weights\n",
"\n",
" # L1 on biases\n",
" if self.bias_regularizer_l1 > 0:\n",
" dL1 = np.ones_like(self.biases)\n",
" dL1[self.biases < 0] = -1\n",
" self.dbiases += self.bias_regularizer_l1 * dL1\n",
"\n",
" # L2 on biases\n",
" if self.bias_regularizer_l2 > 0:\n",
" self.dbiases += 2 * self.bias_regularizer_l2 * self.biases\n",
"\n",
" # Gradient on values\n",
" self.dinputs = np.dot(dvalues, self.weights.T)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-block alert-danger\">\n",
"\n",
"RELU ACTIVATION: FORWARD AND BACKWARD PASS</div>"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"# ReLU activation\n",
"class Activation_ReLU:\n",
" # Forward pass\n",
" def forward(self, inputs):\n",
" # Remember input values\n",
" self.inputs = inputs\n",
" # Calculate output values from inputs\n",
" self.output = np.maximum(0, inputs)\n",
"\n",
" # Backward pass\n",
" def backward(self, dvalues):\n",
" # Since we need to modify the original variable,\n",
" # lets make a copy of values first\n",
" self.dinputs = dvalues.copy()\n",
" # Zero gradient where input values were negative\n",
" self.dinputs[self.inputs <= 0] = 0"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-block alert-danger\">\n",
"\n",
"SOFTMAX ACTIVATION: FORWARD PASS</div>"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"# Softmax activation\n",
"class Activation_Softmax:\n",
" # Forward pass\n",
" def forward(self, inputs):\n",
" # Get unnormalized probabilities\n",
" exp_values = np.exp(inputs - np.max(inputs, axis=1, keepdims=True))\n",
" # Normalize them for each sample\n",
" probabilities = exp_values / np.sum(exp_values, axis=1,keepdims=True)\n",
" self.output = probabilities"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-block alert-danger\">\n",
"LOSS CLASS </div>"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"# Common loss class\n",
"class Loss:\n",
" # Regularization loss calculation\n",
" def regularization_loss(self, layer):\n",
" # 0 by default\n",
" regularization_loss = 0\n",
"\n",
" # L1 regularization - weights\n",
" # Calculate only when factor greater than 0\n",
" if layer.weight_regularizer_l1 > 0:\n",
" regularization_loss += layer.weight_regularizer_l1 * np.sum(np.abs(layer.weights))\n",
"\n",
" # L2 regularization - weights\n",
" if layer.weight_regularizer_l2 > 0:\n",
" regularization_loss += layer.weight_regularizer_l2 * np.sum(layer.weights * layer.weights)\n",
"\n",
" # L1 regularization - biases\n",
" # Calculate only when factor greater than 0\n",
" if layer.bias_regularizer_l1 > 0:\n",
" regularization_loss += layer.bias_regularizer_l1 * np.sum(np.abs(layer.biases))\n",
"\n",
" # L2 regularization - biases\n",
" if layer.bias_regularizer_l2 > 0:\n",
" regularization_loss += layer.bias_regularizer_l2 * np.sum(layer.biases * layer.biases)\n",
"\n",
" return regularization_loss\n",
"\n",
" # Calculates the data and regularization losses\n",
" # given model output and ground truth values\n",
" def calculate(self, output, y):\n",
" # Calculate sample losses\n",
" sample_losses = self.forward(output, y)\n",
" # Calculate mean loss\n",
" data_loss = np.mean(sample_losses)\n",
" # Return loss\n",
" return data_loss"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-block alert-danger\">\n",
"\n",
"CATEGORICAL CROSS ENTROPY LOSS: FORWARD AND BACKWARD PASS</div>"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"class Loss_CategoricalCrossentropy(Loss):\n",
" # Forward pass\n",
" def forward(self, y_pred, y_true):\n",
" # Number of samples in a batch\n",
" samples = len(y_pred)\n",
"\n",
" # Clip data to prevent division by 0\n",
" # Clip both sides to not drag mean towards any value\n",
" y_pred_clipped = np.clip(y_pred, 1e-7, 1 - 1e-7)\n",
"\n",
" # Probabilities for target values -\n",
" # only if categorical labels\n",
" if len(y_true.shape) == 1:\n",
" correct_confidences = y_pred_clipped[\n",
" range(samples),\n",
" y_true\n",
" ]\n",
" # Mask values - only for one-hot encoded labels\n",
" elif len(y_true.shape) == 2:\n",
" correct_confidences = np.sum(\n",
" y_pred_clipped * y_true,\n",
" axis=1\n",
" )\n",
"\n",
" # Losses\n",
" negative_log_likelihoods = -np.log(correct_confidences)\n",
" return negative_log_likelihoods\n",
"\n",
" # Backward pass\n",
" def backward(self, dvalues, y_true):\n",
" # Number of samples\n",
" samples = len(dvalues)\n",
" # Number of labels in every sample\n",
" # We'll use the first sample to count them\n",
" labels = len(dvalues[0])\n",
"\n",
" # If labels are sparse, turn them into one-hot vector\n",
" if len(y_true.shape) == 1:\n",
" y_true = np.eye(labels)[y_true]\n",
"\n",
" # Calculate gradient\n",
" self.dinputs = -y_true / dvalues\n",
" # Normalize gradient\n",
" self.dinputs = self.dinputs / samples"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-block alert-danger\">\n",
"\n",
"COMBINED SOFTMAX ACTIVATION AND CATEGORICAL CROSS ENTROPY FOR LAST LAYER: FORWARD AND BACKWARD PASS</div>"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"# Softmax classifier - combined Softmax activation\n",
"# and cross-entropy loss for faster backward step\n",
"class Activation_Softmax_Loss_CategoricalCrossentropy:\n",
" # Creates activation and loss function objects\n",
" def __init__(self):\n",
" self.activation = Activation_Softmax()\n",
" self.loss = Loss_CategoricalCrossentropy()\n",
"\n",
" # Forward pass\n",
" def forward(self, inputs, y_true):\n",
" # Output layer's activation function\n",
" self.activation.forward(inputs)\n",
" # Set the output\n",
" self.output = self.activation.output\n",
" # Calculate and return loss value\n",
" return self.loss.calculate(self.output, y_true)\n",
"\n",
" # Backward pass\n",
" def backward(self, dvalues, y_true):\n",
" # Number of samples\n",
" samples = len(dvalues)\n",
" # If labels are one-hot encoded,\n",
" # turn them into discrete values\n",
" if len(y_true.shape) == 2:\n",
" y_true = np.argmax(y_true, axis=1)\n",
" # Copy so we can safely modify\n",
" self.dinputs = dvalues.copy()\n",
" # Calculate gradient\n",
" self.dinputs[range(samples), y_true] -= 1\n",
" # Normalize gradient\n",
" self.dinputs = self.dinputs / samples"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-block alert-danger\">\n",
"\n",
"ADAM OPTIMIZER</div>"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"\n",
"# Adam optimizer\n",
"class Optimizer_Adam:\n",
" # Initialize optimizer - set settings\n",
" def __init__(self, learning_rate=0.001, decay=0., epsilon=1e-7, beta_1=0.9, beta_2=0.999):\n",
" self.learning_rate = learning_rate\n",
" self.current_learning_rate = learning_rate\n",
" self.decay = decay\n",
" self.iterations = 0\n",
" self.epsilon = epsilon\n",
" self.beta_1 = beta_1\n",
" self.beta_2 = beta_2\n",
"\n",
" # Call once before any parameter updates\n",
" def pre_update_params(self):\n",
" if self.decay:\n",
" self.current_learning_rate = self.learning_rate * (1. / (1. + self.decay * self.iterations))\n",
"\n",
" # Update parameters\n",
" def update_params(self, layer):\n",
" # If layer does not contain cache arrays, create them filled with zeros\n",
" if not hasattr(layer, 'weight_cache'):\n",
" layer.weight_momentums = np.zeros_like(layer.weights)\n",
" layer.weight_cache = np.zeros_like(layer.weights)\n",
" layer.bias_momentums = np.zeros_like(layer.biases)\n",
" layer.bias_cache = np.zeros_like(layer.biases)\n",
"\n",
" # Update momentum with current gradients\n",
" layer.weight_momentums = self.beta_1 * layer.weight_momentums + (1 - self.beta_1) * layer.dweights\n",
" layer.bias_momentums = self.beta_1 * layer.bias_momentums + (1 - self.beta_1) * layer.dbiases\n",
"\n",
" # Get corrected momentum\n",
" # self.iteration is 0 at first pass and we need to start with 1 here\n",
" weight_momentums_corrected = layer.weight_momentums / (1 - self.beta_1 ** (self.iterations + 1))\n",
" bias_momentums_corrected = layer.bias_momentums / (1 - self.beta_1 ** (self.iterations + 1))\n",
"\n",
" # Update cache with squared current gradients\n",
" layer.weight_cache = self.beta_2 * layer.weight_cache + (1 - self.beta_2) * layer.dweights**2\n",
" layer.bias_cache = self.beta_2 * layer.bias_cache + (1 - self.beta_2) * layer.dbiases**2\n",
"\n",
" # Get corrected cache\n",
" weight_cache_corrected = layer.weight_cache / (1 - self.beta_2 ** (self.iterations + 1))\n",
" bias_cache_corrected = layer.bias_cache / (1 - self.beta_2 ** (self.iterations + 1))\n",
"\n",
" # Vanilla SGD parameter update + normalization with square rooted cache\n",
" layer.weights += -self.current_learning_rate * weight_momentums_corrected / (np.sqrt(weight_cache_corrected) + self.epsilon)\n",
" layer.biases += -self.current_learning_rate * bias_momentums_corrected / (np.sqrt(bias_cache_corrected) + self.epsilon)\n",
"\n",
" # Call once after any parameter updates\n",
" def post_update_params(self):\n",
" self.iterations += 1"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-block alert-danger\">\n",
"\n",
"DROPOUT LAYER: FORWARD AND BACKWARD PASS</div>"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"\n",
"class Layer_Dropout:\n",
" # Initialize the dropout layer\n",
" def __init__(self, rate):\n",
" # Store the dropout rate, invert it to get the success rate\n",
" # For example, for a dropout of 0.1, we need a success rate of 0.9\n",
" self.rate = 1 - rate\n",
"\n",
" # Forward pass\n",
" def forward(self, inputs):\n",
" # Save input values\n",
" self.inputs = inputs\n",
" # Generate and save the scaled binary mask\n",
" self.binary_mask = np.random.binomial(1, self.rate, size=inputs.shape) / self.rate\n",
" # Apply mask to output values\n",
" self.output = inputs * self.binary_mask\n",
"\n",
" # Backward pass\n",
" def backward(self, dvalues):\n",
" # Gradient on values\n",
" self.dinputs = dvalues * self.binary_mask"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div class=\"alert alert-block alert-danger\">\n",
"\n",
"TRAINING THE NEURAL NETWORK</div>"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"epoch: 0, acc: 0.373, loss: 1.099 (data_loss: 1.099, reg_loss: 0.000), lr: 0.05\n",
"epoch: 100, acc: 0.583, loss: 0.910 (data_loss: 0.885, reg_loss: 0.024), lr: 0.04975371909050202\n",
"epoch: 200, acc: 0.632, loss: 0.847 (data_loss: 0.814, reg_loss: 0.033), lr: 0.049507401356502806\n",
"epoch: 300, acc: 0.636, loss: 0.833 (data_loss: 0.798, reg_loss: 0.035), lr: 0.0492635105177595\n",
"epoch: 400, acc: 0.638, loss: 0.821 (data_loss: 0.785, reg_loss: 0.035), lr: 0.04902201088288642\n",
"epoch: 500, acc: 0.642, loss: 0.813 (data_loss: 0.779, reg_loss: 0.034), lr: 0.048782867456949125\n",
"epoch: 600, acc: 0.653, loss: 0.805 (data_loss: 0.772, reg_loss: 0.033), lr: 0.04854604592455945\n",
"epoch: 700, acc: 0.653, loss: 0.787 (data_loss: 0.756, reg_loss: 0.031), lr: 0.048311512633460556\n",
"epoch: 800, acc: 0.633, loss: 0.816 (data_loss: 0.785, reg_loss: 0.030), lr: 0.04807923457858551\n",
"epoch: 900, acc: 0.648, loss: 0.800 (data_loss: 0.771, reg_loss: 0.030), lr: 0.04784917938657352\n",
"epoch: 1000, acc: 0.663, loss: 0.789 (data_loss: 0.761, reg_loss: 0.028), lr: 0.04762131530072861\n",
"epoch: 1100, acc: 0.662, loss: 0.766 (data_loss: 0.739, reg_loss: 0.027), lr: 0.04739561116640599\n",
"epoch: 1200, acc: 0.653, loss: 0.770 (data_loss: 0.744, reg_loss: 0.027), lr: 0.04717203641681212\n",
"epoch: 1300, acc: 0.663, loss: 0.765 (data_loss: 0.739, reg_loss: 0.026), lr: 0.04695056105920466\n",
"epoch: 1400, acc: 0.653, loss: 0.783 (data_loss: 0.757, reg_loss: 0.025), lr: 0.04673115566147951\n",
"epoch: 1500, acc: 0.659, loss: 0.778 (data_loss: 0.754, reg_loss: 0.025), lr: 0.046513791339132055\n",
"epoch: 1600, acc: 0.662, loss: 0.799 (data_loss: 0.775, reg_loss: 0.024), lr: 0.04629843974258068\n",
"epoch: 1700, acc: 0.650, loss: 0.778 (data_loss: 0.754, reg_loss: 0.024), lr: 0.046085073044840774\n",
"epoch: 1800, acc: 0.672, loss: 0.761 (data_loss: 0.738, reg_loss: 0.023), lr: 0.04587366392953806\n",
"epoch: 1900, acc: 0.661, loss: 0.783 (data_loss: 0.760, reg_loss: 0.023), lr: 0.04566418557925019\n",
"epoch: 2000, acc: 0.655, loss: 0.791 (data_loss: 0.769, reg_loss: 0.022), lr: 0.045456611664166556\n",
"epoch: 2100, acc: 0.667, loss: 0.772 (data_loss: 0.750, reg_loss: 0.022), lr: 0.045250916331055706\n",
"epoch: 2200, acc: 0.671, loss: 0.749 (data_loss: 0.727, reg_loss: 0.022), lr: 0.0450470741925312\n",
"epoch: 2300, acc: 0.669, loss: 0.755 (data_loss: 0.733, reg_loss: 0.021), lr: 0.04484506031660612\n",
"epoch: 2400, acc: 0.662, loss: 0.777 (data_loss: 0.756, reg_loss: 0.021), lr: 0.04464485021652753\n",
"epoch: 2500, acc: 0.665, loss: 0.764 (data_loss: 0.744, reg_loss: 0.021), lr: 0.044446419840881816\n",
"epoch: 2600, acc: 0.661, loss: 0.761 (data_loss: 0.741, reg_loss: 0.020), lr: 0.04424974556396301\n",
"epoch: 2700, acc: 0.659, loss: 0.759 (data_loss: 0.739, reg_loss: 0.020), lr: 0.04405480417639544\n",
"epoch: 2800, acc: 0.673, loss: 0.741 (data_loss: 0.721, reg_loss: 0.020), lr: 0.04386157287600334\n",
"epoch: 2900, acc: 0.649, loss: 0.788 (data_loss: 0.768, reg_loss: 0.020), lr: 0.04367002925891961\n",
"epoch: 3000, acc: 0.677, loss: 0.742 (data_loss: 0.723, reg_loss: 0.019), lr: 0.043480151310926564\n",
"epoch: 3100, acc: 0.666, loss: 0.731 (data_loss: 0.712, reg_loss: 0.019), lr: 0.04329191739902161\n",
"epoch: 3200, acc: 0.667, loss: 0.770 (data_loss: 0.751, reg_loss: 0.019), lr: 0.043105306263201\n",
"epoch: 3300, acc: 0.667, loss: 0.743 (data_loss: 0.725, reg_loss: 0.019), lr: 0.0429202970084553\n",
"epoch: 3400, acc: 0.660, loss: 0.750 (data_loss: 0.732, reg_loss: 0.018), lr: 0.04273686909696996\n",
"epoch: 3500, acc: 0.675, loss: 0.749 (data_loss: 0.730, reg_loss: 0.018), lr: 0.04255500234052514\n",
"epoch: 3600, acc: 0.657, loss: 0.770 (data_loss: 0.752, reg_loss: 0.018), lr: 0.042374676893088686\n",
"epoch: 3700, acc: 0.662, loss: 0.739 (data_loss: 0.721, reg_loss: 0.018), lr: 0.042195873243596776\n",
"epoch: 3800, acc: 0.676, loss: 0.754 (data_loss: 0.736, reg_loss: 0.018), lr: 0.04201857220891634\n",
"epoch: 3900, acc: 0.657, loss: 0.762 (data_loss: 0.745, reg_loss: 0.018), lr: 0.041842754926984395\n",
"epoch: 4000, acc: 0.657, loss: 0.752 (data_loss: 0.735, reg_loss: 0.018), lr: 0.04166840285011875\n",
"epoch: 4100, acc: 0.659, loss: 0.763 (data_loss: 0.746, reg_loss: 0.017), lr: 0.041495497738495375\n",
"epoch: 4200, acc: 0.667, loss: 0.760 (data_loss: 0.743, reg_loss: 0.017), lr: 0.041324021653787346\n",
"epoch: 4300, acc: 0.670, loss: 0.755 (data_loss: 0.739, reg_loss: 0.017), lr: 0.041153956952961035\n",
"epoch: 4400, acc: 0.671, loss: 0.764 (data_loss: 0.747, reg_loss: 0.017), lr: 0.040985286282224684\n",
"epoch: 4500, acc: 0.667, loss: 0.763 (data_loss: 0.747, reg_loss: 0.017), lr: 0.04081799257112535\n",
"epoch: 4600, acc: 0.676, loss: 0.765 (data_loss: 0.749, reg_loss: 0.016), lr: 0.04065205902678971\n",
"epoch: 4700, acc: 0.674, loss: 0.748 (data_loss: 0.732, reg_loss: 0.016), lr: 0.04048746912830479\n",
"epoch: 4800, acc: 0.665, loss: 0.750 (data_loss: 0.734, reg_loss: 0.016), lr: 0.04032420662123473\n",
"epoch: 4900, acc: 0.676, loss: 0.729 (data_loss: 0.713, reg_loss: 0.016), lr: 0.04016225551226957\n",
"epoch: 5000, acc: 0.659, loss: 0.745 (data_loss: 0.729, reg_loss: 0.016), lr: 0.04000160006400256\n",
"epoch: 5100, acc: 0.652, loss: 0.812 (data_loss: 0.796, reg_loss: 0.016), lr: 0.039842224789832265\n",
"epoch: 5200, acc: 0.663, loss: 0.792 (data_loss: 0.776, reg_loss: 0.016), lr: 0.03968411444898608\n",
"epoch: 5300, acc: 0.672, loss: 0.759 (data_loss: 0.743, reg_loss: 0.016), lr: 0.03952725404166173\n",
"epoch: 5400, acc: 0.651, loss: 0.745 (data_loss: 0.730, reg_loss: 0.015), lr: 0.03937162880428363\n",
"epoch: 5500, acc: 0.681, loss: 0.745 (data_loss: 0.730, reg_loss: 0.015), lr: 0.03921722420487078\n",
"epoch: 5600, acc: 0.672, loss: 0.749 (data_loss: 0.734, reg_loss: 0.015), lr: 0.03906402593851323\n",
"epoch: 5700, acc: 0.665, loss: 0.759 (data_loss: 0.744, reg_loss: 0.015), lr: 0.038912019922954205\n",
"epoch: 5800, acc: 0.658, loss: 0.759 (data_loss: 0.744, reg_loss: 0.015), lr: 0.038761192294274965\n",
"epoch: 5900, acc: 0.653, loss: 0.769 (data_loss: 0.754, reg_loss: 0.015), lr: 0.038611529402679645\n",
"epoch: 6000, acc: 0.668, loss: 0.752 (data_loss: 0.736, reg_loss: 0.015), lr: 0.03846301780837725\n",
"epoch: 6100, acc: 0.666, loss: 0.747 (data_loss: 0.731, reg_loss: 0.015), lr: 0.03831564427755853\n",
"epoch: 6200, acc: 0.676, loss: 0.733 (data_loss: 0.718, reg_loss: 0.015), lr: 0.03816939577846483\n",
"epoch: 6300, acc: 0.668, loss: 0.726 (data_loss: 0.711, reg_loss: 0.015), lr: 0.038024259477546674\n",
"epoch: 6400, acc: 0.671, loss: 0.757 (data_loss: 0.742, reg_loss: 0.015), lr: 0.03788022273570969\n",
"epoch: 6500, acc: 0.672, loss: 0.733 (data_loss: 0.718, reg_loss: 0.015), lr: 0.03773727310464546\n",
"epoch: 6600, acc: 0.662, loss: 0.774 (data_loss: 0.759, reg_loss: 0.015), lr: 0.03759539832324524\n",
"epoch: 6700, acc: 0.658, loss: 0.772 (data_loss: 0.758, reg_loss: 0.015), lr: 0.03745458631409416\n",
"epoch: 6800, acc: 0.678, loss: 0.734 (data_loss: 0.719, reg_loss: 0.014), lr: 0.03731482518004403\n",
"epoch: 6900, acc: 0.656, loss: 0.737 (data_loss: 0.723, reg_loss: 0.014), lr: 0.03717610320086248\n",
"epoch: 7000, acc: 0.658, loss: 0.740 (data_loss: 0.726, reg_loss: 0.014), lr: 0.03703840882995667\n",
"epoch: 7100, acc: 0.678, loss: 0.734 (data_loss: 0.720, reg_loss: 0.014), lr: 0.036901730691169414\n",
"epoch: 7200, acc: 0.653, loss: 0.745 (data_loss: 0.731, reg_loss: 0.014), lr: 0.03676605757564617\n",
"epoch: 7300, acc: 0.674, loss: 0.744 (data_loss: 0.729, reg_loss: 0.014), lr: 0.03663137843877066\n",
"epoch: 7400, acc: 0.673, loss: 0.731 (data_loss: 0.716, reg_loss: 0.014), lr: 0.03649768239716778\n",
"epoch: 7500, acc: 0.663, loss: 0.747 (data_loss: 0.732, reg_loss: 0.015), lr: 0.03636495872577185\n",
"epoch: 7600, acc: 0.662, loss: 0.730 (data_loss: 0.716, reg_loss: 0.015), lr: 0.03623319685495851\n",
"epoch: 7700, acc: 0.646, loss: 0.747 (data_loss: 0.732, reg_loss: 0.015), lr: 0.03610238636773891\n",
"epoch: 7800, acc: 0.654, loss: 0.776 (data_loss: 0.761, reg_loss: 0.015), lr: 0.03597251699701428\n",
"epoch: 7900, acc: 0.670, loss: 0.745 (data_loss: 0.730, reg_loss: 0.015), lr: 0.035843578622889706\n",
"epoch: 8000, acc: 0.663, loss: 0.742 (data_loss: 0.727, reg_loss: 0.016), lr: 0.03571556127004536\n",
"epoch: 8100, acc: 0.669, loss: 0.763 (data_loss: 0.748, reg_loss: 0.016), lr: 0.03558845510516389\n",
"epoch: 8200, acc: 0.678, loss: 0.738 (data_loss: 0.723, reg_loss: 0.016), lr: 0.03546225043441257\n",
"epoch: 8300, acc: 0.646, loss: 0.767 (data_loss: 0.752, reg_loss: 0.015), lr: 0.035336937700978836\n",
"epoch: 8400, acc: 0.658, loss: 0.724 (data_loss: 0.709, reg_loss: 0.016), lr: 0.03521250748265784\n",
"epoch: 8500, acc: 0.655, loss: 0.758 (data_loss: 0.742, reg_loss: 0.015), lr: 0.035088950489490865\n",
"epoch: 8600, acc: 0.673, loss: 0.729 (data_loss: 0.713, reg_loss: 0.016), lr: 0.0349662575614532\n",
"epoch: 8700, acc: 0.669, loss: 0.726 (data_loss: 0.711, reg_loss: 0.015), lr: 0.034844419666190465\n",
"epoch: 8800, acc: 0.661, loss: 0.741 (data_loss: 0.726, reg_loss: 0.015), lr: 0.034723427896801974\n",
"epoch: 8900, acc: 0.662, loss: 0.737 (data_loss: 0.722, reg_loss: 0.015), lr: 0.03460327346967023\n",
"epoch: 9000, acc: 0.672, loss: 0.716 (data_loss: 0.701, reg_loss: 0.015), lr: 0.034483947722335255\n",
"epoch: 9100, acc: 0.666, loss: 0.725 (data_loss: 0.710, reg_loss: 0.015), lr: 0.034365442111412764\n",
"epoch: 9200, acc: 0.655, loss: 0.740 (data_loss: 0.725, reg_loss: 0.015), lr: 0.03424774821055516\n",
"epoch: 9300, acc: 0.649, loss: 0.761 (data_loss: 0.746, reg_loss: 0.015), lr: 0.03413085770845422\n",
"epoch: 9400, acc: 0.662, loss: 0.744 (data_loss: 0.728, reg_loss: 0.015), lr: 0.034014762406884586\n",
"epoch: 9500, acc: 0.660, loss: 0.724 (data_loss: 0.709, reg_loss: 0.015), lr: 0.03389945421878708\n",
"epoch: 9600, acc: 0.667, loss: 0.731 (data_loss: 0.716, reg_loss: 0.015), lr: 0.033784925166390756\n",
"epoch: 9700, acc: 0.676, loss: 0.712 (data_loss: 0.697, reg_loss: 0.015), lr: 0.03367116737937304\n",
"epoch: 9800, acc: 0.661, loss: 0.737 (data_loss: 0.722, reg_loss: 0.015), lr: 0.033558173093056816\n",
"epoch: 9900, acc: 0.654, loss: 0.736 (data_loss: 0.721, reg_loss: 0.015), lr: 0.0334459346466437\n",
"epoch: 10000, acc: 0.661, loss: 0.733 (data_loss: 0.718, reg_loss: 0.015), lr: 0.03333444448148271\n",
"validation, acc: 0.737, loss: 0.600\n"
]
}
],
"source": [
"# Create dataset\n",
"X, y = spiral_data(samples=1000, classes=3)\n",
"\n",
"# Create Dense layer with 2 input features and 64 output values\n",
"dense1 = Layer_Dense(2, 64, weight_regularizer_l2=5e-4, bias_regularizer_l2=5e-4)\n",
"\n",
"# Create ReLU activation (to be used with Dense layer)\n",
"activation1 = Activation_ReLU()\n",
"\n",
"# Create dropout layer\n",
"dropout1 = Layer_Dropout(0.1)\n",
"\n",
"# Create second Dense layer with 64 input features (as we take output of previous layer here) and 3 output values (output values)\n",
"dense2 = Layer_Dense(64, 3)\n",
"\n",
"# Create Softmax classifier's combined loss and activation\n",
"loss_activation = Activation_Softmax_Loss_CategoricalCrossentropy()\n",
"\n",
"# Create optimizer\n",
"optimizer = Optimizer_Adam(learning_rate=0.05, decay=5e-5)\n",
"\n",
"# Train in loop\n",
"for epoch in range(10001):\n",
" # Perform a forward pass of our training data through this layer\n",
" dense1.forward(X)\n",
" \n",
" # Perform a forward pass through activation function, takes the output of first dense layer here\n",
" activation1.forward(dense1.output)\n",
" \n",
" # Perform a forward pass through Dropout layer\n",
" dropout1.forward(activation1.output)\n",
" \n",
" # Perform a forward pass through second Dense layer, takes outputs of activation function of first layer as inputs\n",
" dense2.forward(dropout1.output)\n",
" \n",
" # Perform a forward pass through the activation/loss function, takes the output of second dense layer here and returns loss\n",
" data_loss = loss_activation.forward(dense2.output, y)\n",
" \n",
" # Calculate regularization penalty\n",
" regularization_loss = loss_activation.loss.regularization_loss(dense1) + loss_activation.loss.regularization_loss(dense2)\n",
" \n",
" # Calculate overall loss\n",
" loss = data_loss + regularization_loss\n",
" \n",
" # Calculate accuracy from output of activation2 and targets, calculate values along first axis\n",
" predictions = np.argmax(loss_activation.output, axis=1)\n",
" if len(y.shape) == 2:\n",
" y = np.argmax(y, axis=1)\n",
" accuracy = np.mean(predictions == y)\n",
" \n",
" if not epoch % 100:\n",
" print(f'epoch: {epoch}, ' +\n",
" f'acc: {accuracy:.3f}, ' +\n",
" f'loss: {loss:.3f} (' +\n",
" f'data_loss: {data_loss:.3f}, ' +\n",
" f'reg_loss: {regularization_loss:.3f}), ' +\n",
" f'lr: {optimizer.current_learning_rate}')\n",
" \n",
" # Backward pass\n",
" loss_activation.backward(loss_activation.output, y)\n",
" dense2.backward(loss_activation.dinputs)\n",
" dropout1.backward(dense2.dinputs)\n",
" activation1.backward(dropout1.dinputs)\n",
" dense1.backward(activation1.dinputs)\n",
" \n",
" # Update weights and biases\n",
" optimizer.pre_update_params()\n",
" optimizer.update_params(dense1)\n",
" optimizer.update_params(dense2)\n",
" optimizer.post_update_params()\n",
"\n",
"# Validate the model\n",
"# Create test dataset\n",
"X_test, y_test = spiral_data(samples=100, classes=3)\n",
"\n",
"# Perform a forward pass of our testing data through this layer\n",
"dense1.forward(X_test)\n",
"\n",
"# Perform a forward pass through activation function, takes the output of first dense layer here\n",
"activation1.forward(dense1.output)\n",
"\n",
"# Perform a forward pass through second Dense layer, takes outputs of activation function of first layer as inputs\n",
"dense2.forward(activation1.output)\n",
"\n",
"# Perform a forward pass through the activation/loss function, takes the output of second dense layer here and returns loss\n",
"loss = loss_activation.forward(dense2.output, y_test)\n",
"\n",
"# Calculate accuracy from output of activation2 and targets, calculate values along first axis\n",
"predictions = np.argmax(loss_activation.output, axis=1)\n",
"if len(y_test.shape) == 2:\n",
" y_test = np.argmax(y_test, axis=1)\n",
"accuracy = np.mean(predictions == y_test)\n",
"\n",
"print(f'validation, acc: {accuracy:.3f}, loss: {loss:.3f}')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.2"
}
},
"nbformat": 4,
"nbformat_minor": 4
}