{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "5ff49af9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Q5B: AdaBoost, Gradient Boosting, XGBoost, and hard/soft voting on Iris.\n",
    "# Source: https://www.kaggle.com/datasets/uciml/iris\n",
    "# Install xgboost in a new environment if needed: pip install xgboost\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn.ensemble import AdaBoostClassifier, GradientBoostingClassifier, VotingClassifier\n",
    "from sklearn.metrics import accuracy_score, f1_score, precision_score, recall_score\n",
    "from sklearn.metrics import ConfusionMatrixDisplay\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.preprocessing import LabelEncoder\n",
    "from xgboost import XGBClassifier\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "de63cd16",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training samples: 112 Test samples: 38\n",
      "Species: ['Iris-setosa', 'Iris-versicolor', 'Iris-virginica']\n"
     ]
    }
   ],
   "source": [
    "# Load the existing Iris CSV and encode the three species as integers.\n",
    "iris = pd.read_csv(\"Iris.csv\")\n",
    "X = iris.drop(columns=[\"Id\", \"Species\"])\n",
    "encoder = LabelEncoder()\n",
    "y = encoder.fit_transform(iris[\"Species\"])\n",
    "X_train, X_test, y_train, y_test = train_test_split(\n",
    "    X, y, test_size=0.25, stratify=y, random_state=42\n",
    ")\n",
    "print(\"Training samples:\", len(X_train), \"Test samples:\", len(X_test))\n",
    "print(\"Species:\", list(encoder.classes_))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "392ac8e1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Build the three requested boosting models.\n",
    "models = {\n",
    "    \"AdaBoost\": AdaBoostClassifier(n_estimators=60, random_state=42),\n",
    "    \"Gradient Boosting\": GradientBoostingClassifier(n_estimators=80, random_state=42),\n",
    "    \"XGBoost\": XGBClassifier(n_estimators=80, max_depth=3, learning_rate=0.1,\n",
    "                              objective=\"multi:softprob\", num_class=3,\n",
    "                              eval_metric=\"mlogloss\", n_jobs=1, random_state=42),\n",
    "}\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "28e15088",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Compare each model using the same held-out test set.\n",
    "results = []\n",
    "fitted_models = {}\n",
    "for name, model in models.items():\n",
    "    model.fit(X_train, y_train)\n",
    "    fitted_models[name] = model\n",
    "    predicted = model.predict(X_test)\n",
    "    results.append({\n",
    "        \"Model\": name,\n",
    "        \"Accuracy\": accuracy_score(y_test, predicted),\n",
    "        \"Macro precision\": precision_score(y_test, predicted, average=\"macro\", zero_division=0),\n",
    "        \"Macro recall\": recall_score(y_test, predicted, average=\"macro\", zero_division=0),\n",
    "        \"Macro F1\": f1_score(y_test, predicted, average=\"macro\", zero_division=0),\n",
    "    })\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "273f5721",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "                   Accuracy  Macro precision  Macro recall  Macro F1\n",
      "Model                                                               \n",
      "AdaBoost              0.921            0.925         0.923     0.923\n",
      "Gradient Boosting     0.974            0.976         0.974     0.974\n",
      "XGBoost               0.921            0.925         0.923     0.923\n",
      "Hard voting           0.947            0.949         0.949     0.949\n",
      "Soft voting           0.947            0.949         0.949     0.949\n"
     ]
    },
    {
     "data": {
      "image/png": "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f9zfvn37bOnSpXbs2DErVqyYVaxY0TJmzJig5/zll18sT5487nzx4bvvvrMqVapY0aJFfff54YcfbPfu3e778PBwK1KkiN14442WJk3i5PXorjG+2wEAAKQ8YYFAIJAUJ1aVr3fv3vbJJ5+4gKjwtG3bNtuzZ4+9+OKL9vDDD8fbuTZt2mTXXnutnThxIkGCaNmyZW3QoEHWsmVL331uuukmO3TokAtsZ86csWXLllmmTJls7ty5LrAltNhcY0I6deqUa/uivSfy2dAAACTgZ0N7f3NPnjxpGTJksGRbWezVq5dNmTLFFi1aZJUrVw5uV1hUgPJMnjzZqlev7sLlqlWrrEaNGvbHH3/Yrl27LG3atFa8eHG3TdW6UP/884/99ttvrmqWJUuWC7pfK1WqFKmipnGNy5cvd191vHz58l1wDQp5ugZV56pVq+Ye07UePnzYFixY4N6UAgUK2K233hrta27WrJkLbN4bqQD72Wef2TPPPBPcZ+/evS5IpkuXzl1H9uzZIx0jpsfPnTtnCxcudNXa6667LlhF9LvGqO0Q0+v0KNCvWLHCPVaqVCn3nAceeCDRKqQAACBxJUlYVJj58MMP7csvv4wUFCVv3rx23333Be+r+qhgoi5c7atwuGTJElu3bp0LRytXrnRhUIEoa9as7jlff/21Pfroo1a3bl0XrrJlyxbpHM8++6z17ds3GJL0XAWea665xoWv9u3b26effurCnXcN2lfHKlmypM2ePdt69OhhL7/8sguY6kJXgNLrUpXULyyGUtK/6qqrXLXT8+2337qKas2aNe348eO2efNmmzBhgtWuXfuij+u+viroqYrYp08f6969u7v5XWPUdojpdcro0aPtsccec+2q43jtrmpl1Irt2bNn3fvjUTgGAADJT5KERQU8BYk6deoEt23cuNEWL17svlfVrFWrVsHH1F2rSpdXvapatWrwMc1wbtKkiX3wwQcuIKmC1rVrV/v444+tdevWbh8Fxzlz5kR7LQprbdu2tVdffdU6duzots2cOdNNiLnzzjuDIUhdxbNmzbKwsDA3/lBBcsCAAS5gjRgxwp588smLdvGuWbPGzcpWkNJ4QV1rhw4d3GP6vlOnTvbWW2+56xWFuYceesg2bNhw0cdVbdyxY4f9+++/rsqq9lXYk7hco9/rPHLkiHXr1s2++OILu/fee92+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"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Hard voting uses majority class labels; soft voting averages probabilities.\n",
    "for voting in [\"hard\", \"soft\"]:\n",
    "    ensemble = VotingClassifier(estimators=list(models.items()), voting=voting)\n",
    "    ensemble.fit(X_train, y_train)\n",
    "    predicted = ensemble.predict(X_test)\n",
    "    fitted_models[f\"{voting.title()} voting\"] = ensemble\n",
    "    results.append({\n",
    "        \"Model\": f\"{voting.title()} voting\",\n",
    "        \"Accuracy\": accuracy_score(y_test, predicted),\n",
    "        \"Macro precision\": precision_score(y_test, predicted, average=\"macro\", zero_division=0),\n",
    "        \"Macro recall\": recall_score(y_test, predicted, average=\"macro\", zero_division=0),\n",
    "        \"Macro F1\": f1_score(y_test, predicted, average=\"macro\", zero_division=0),\n",
    "    })\n",
    "comparison = pd.DataFrame(results).set_index(\"Model\")\n",
    "print(comparison.round(3).to_string())\n",
    "comparison[\"Macro F1\"].sort_values().plot.barh(figsize=(7, 4), xlim=(0, 1),\n",
    "                                                 title=\"Iris model comparison\")\n",
    "plt.tight_layout()\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "7f466e4a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Best model: Gradient Boosting\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjkAAAG/CAYAAAC66sY1AAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjExLjIsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvgI3uAAAAAAlwSFlzAAAOnAAADpwBB5RT3QAATu9JREFUeJzt3QeYE+X2x/GTpffeizSVKkVAukoRFBH0r4iKIBZERK+9XBFBsPfKBbuCV8GKil1BkGZBpCiidFF67yX/5/d6E7Ihu5vdZEl29vvhmWdJMjN5M0lmTs573hmf3+/3GwAAgMekJLoBAAAA2YEgBwAAeBJBDgAA8CSCHAAA4EkEOQAAwJMIcgAAgCcR5AAAAE8iyAEAAJ5EkIMc5eeff7Y77rjDevXqZaeffrpdccUV9sgjj9hff/11VJ5/2bJldsopp9gPP/wQvK9nz572wgsvWDK46KKLXPsCU/fu3W3IkCH2448/WrJKpu2XnQ4dOmSjR4+2c88910499VR7+eWX47r+3LIdo8X2gBDkIMccIK677jpr3ry5C2guuOACd7tZs2Y2YcIEq169un366afZ3o6dO3fa1KlTbfPmzcH7vv32Wxf8ZBcFc9EeEGfPnm27du2y4cOHu+nKK6+0bdu22YknnmhvvfWWJVJaryO7t1+yGDNmjN10000uQL/rrrtcEBpPXt6OmfkO5IbtgejlzcS8QMKMGjXKnnrqKfvoo4+sW7duqR4bNGiQPfTQQ7Zly5aEtO3999+3ypUrZ9v6p02bZieddFLU85cuXTrVAfSss85yGTBtI2UREiWt15Hd2y9Z6PU3bdrU+vbtmy3r9/J2zOx3wOvbA9Ejk4Okt2nTJnvggQfs4osvPiLAEZ/PZ7fccotLTwd06tTJXn/9dVu8eLELgnT7zz//dI8NGDAg2J3To0cPlxFatGhRxOceP368nX322W565513Is7z4IMP2ldffZXqvrlz57puIrW3d+/e9uabbx6xXKCNv//+uw0cONDNq1/4yhYFqI27d+92v2IDbY60roxUqVLF1q1bd8T9n3zyifXv399OO+00u/TSS12WKpJo5tPruOGGG+zMM890B/Lnn3/eDh48mOHrCN9+0WyXgNdeey3V+xOpOzEt8+bNs2uvvdZlCfSZ+Oyzz7L0ujNq744dO1ybtP4FCxYEX//ff/9tW7dudf///PPPj9iWuv+nn36KavtG2o7xan96Asv++uuvdvnll7vvk9oVoCzrOeecY+edd17E547mu5jeZye973no9njvvffccnPmzEm1bs3TtWtX27BhQ4avFTmULtAJJLM333xTF5H1v/fee1EvkydPHv+VV17p79y5s3/cuHH+r7/+2r9r1y732Jw5c9xtTVrnoEGD3PxTp05NtY5hw4b58+XL5x8xYoSbr1+/fv5bbrnFteXzzz8PzlemTBn/HXfcEbz96quv+vPmzeu/4oor3HJPPvmkv2TJkm7Z8DYOGTLE361bN//48eP9L774oltXnz59gvOojQULFvT3798/2OaVK1em+bpr167t79q1a6r7Fi9e7C9evLj/8ssvT3X/vffe609JSfHfeuutrp1qi8/n8//nP//J9HxLly71lyhRwt+3b1//pEmT3Hum7X/VVVdl+DrCt18020WGDh3qz58/v3/kyJGuXZdeemnE9ycSrVPPo/ZOnDjR/8orr7jne/vttzO9fTJq7/79+93rbdu2rb9x48bB1797927/+vXrXXtfe+21VOucO3euu1/zRbN9I23HeLU/PVp28ODB/u7du7s2PfbYY/4CBQr4x4wZ4/6v9b7//vv+iy66yL1XS5YsSbV8NN/F9D476X3PQ7fHgQMH/G3atHHfj23btrn7vvzyS7d91E54F0EOkt6oUaPcDn/hwoVRL6OdX7ly5YI7tIycd955/tNOOy14e/Xq1W5n/dBDD6Wa7+yzz043yFm7dq2/UKFC/uuvvz7VctqB6wAT+hrUxooVK6Zq43PPPed2vHr+gCJFivjvuuuuqF6HduKlSpXyn3zyyW5q1qyZO7hcdtllwZ1/4KCp57/zzjtTLT9w4EB3QNHBNzPzPfHEE/5ixYr5Dx06lGq+0NeW1uuIFORktF1WrVrl3p9HH3001bp69+6dYZCzZs0at6wOwOG2b9+eqdcdbXulZ8+e7j0JFW2QE832Dd2O2dH+SLRslSpV/Dt37gzep8CratWq/muvvTZ4nwI9fR9vuOEGf2a/i+l9dtL7nod/rpYvX+5+bChQ1OuvXLmyC+zCtym8he4qJL29e/e6v/nz5z+iqyJ0JNHdd9+d6vEzzjjDihUrdsT6VJj79NNPu+6vzp07u2VVsKuUe4C6FvS8/fr1O2L0UnomTZrkUusq+A2lVLza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5UsXsx4dm1jxov98DuAdBw8eso+mzrPfV6yzmlXL2ZmnNrZ8efMkullIUrnqPDkLFy60qlWrJroZOEo6nVjLzuvYINV9NSuVtOmjL7WLuzW2siUK28CeJ9p3zw+0quWK8b7kcLc/8pYNvPNl+3vDVntt0kw7ue8DtmHz9kQ3C3F06NAh633dszbymQ9s/abt9uBzk63n4CftwIGDbOdsyOT4YpiShWcKj1etWmUtWrSw6dOnW506dSLOc/zxx9sPP/xgiTBv3jzr2bOnLV++PCHPn5s898GP7m+JIgXt2GqlUz22Z98B633nRFu5dqu7nZLisylP9XfBzrDnpySkvYjdr0v/sjFvTrWvXrnZmtSr7n7tdx7wkD3xyuc28rpz2MQeMemrn2zOz8vsp/dHWJmSRW3rjt3WrNdwm/Dxd3Zhj1aJbp53+BhCnnQOHjxoa9eutQMH0u52yJs3r1WoUMESYf/+/fb3338n5Llx2F8bdwQDHDl0yG/bdu61lJRcldT0nK9m/WK1qpV1AY7kyZNivTo3sy9m/pLopiGOvpz5i53Ssq4LcKRE0ULWpW0D+2Jm6i5pIMCze/Yff/zRateubRMmTLAOHTpY/fr1j+iu2rFjh1111VVWr149a9Kkid1zzz0uWEpLRvP/8ccfdsEFF7iMUevWre2FF15w92/bts26detme/futYoVK7rpzTffdI99//331r17d5d96tixo02ePDmq5/vrr7+C66pVq5adffbZtnjx4mzZll52arMadmLdyvbGFwsS3RTE4M+1m61y+VKp7qtcvqS7Hx57nyuUjPA+b0lYm7zI56HuKs8GOfv27bOlS5faSy+9ZE899ZRNmTLliGzKvffeaz/99JO98cYb9vrrr7tl3n///TTXmd78yiKpu0wByYcffugCkrvvvtvGjx9vxYoVc38LFCjgltd01llnufa1b9/e2rVrZx9//LH17dvXzjnnHJs6dWqGz6eMVGBdn332mTVs2NAFUponEmW4FGSFTrldy3pV7MXbe9p1T3xiC5auS3RzEKPw3arf/8/OGt7iC3un/X5/Ml1FwBN8HgpyPFOTkxZlUypXruz+v2bNmlSP7dmzx2rWrGmNGjVy3RUjRoxwX5i0pDf/f/7zH2vevLkNGzbM3T722GPd/8eOHWsXXXSRlSlTxt2vzEvA888/byeddJLdfvvtwWVmzJjhgrKTTz453efT7dB1jRw50gVDs2fPdoFTuFGjRrnl8Y/2javbq0PPtpue+czenkKXRk5XpUIp+3R66mzcX+u3uF/58Nb7HJ6d+2v9Vt5n5L5MjhQqVCgY4EQydOhQK1y4sDVt2tTOPfdcl/UJdAepSDjQHTRo0KAM51+yZIl9++23wWU03XzzzS5bkxYVISsDE6pBgwa2bNmyDJ9PmRllihRYVatWzT3fihUrXAF2Wq9VQVNg2rr1cF1KbnNay1r22p1n29WPTibA8YiOrerZ0lUb7KdfVrrbKjx+74sfrXPreoluGuKoU+t6NmXOr7Zxyw53W4XHn3+70Dq3rs92jiMfmZycIaNi0tKlS7tsiqieZeDAge7v/fff7wKKQNePgqWM5q9UqZLrLnrmmWdSPUeePP+cvyFS+k6BSXgQtHr16mCGJr3ne+KJJ1y90ejRo6169equK0y1R2l1V6noWlNucFa7461ejbLWvG5lK1OikN3at62t27TTXpr8kzWuU8Feu/Mcm71otTWqXd5N8sfqTfYWGZ0cq26tSnbl+Sfb+deNtl5dmtnPi1fb5q277F/9uyS6aYijszo2sVffm2HdLnvUFRx/PesXO75WRTvv9BZs5zjyeehkgJ7O5GREXTzqHtK5F1S8qzqXQCZEAUYgI1OiRIkM5+/Xr5998cUXrrtI95ctW9YVOr/66qvu8XLlyrk6GBUMB/Tu3dsVGqumJlAs/eKLL7ri5YyeT11vVapUsZYtW7og55NPPrHff//9KG/B5PblD0ttwlcLU923a89+e/TNmfbt/MgZL+Rc9914ro25u79VKFPcLjzzJPtm/G1WthTnP/LaD9eJTwy2oYN7WJlSRe3my0+395+9lpMBZtcQcl8MU5LIHT/t06DMy4033mhz58513UDNmjULBiWZnV91MxMnTnRdVBdeeKHL4GiE1SOPPOIeVyDSv39/F6woaFIm5vzzz7cxY8a4+7dv32758uVz61cNT0bPd+2117outZIlS7rlunTp4rq6YDZp+mI3RbJk9SZ7YNy3bCaPOuWkum6Cd+n0AD07NU10M5BD+PzpVdrmIAoC1q9f7zImCjA0kmrz5s1Wvvw/3RGBOpaNGzceca6c3bt3u2Xy588f1XNlNL8yNvrFoeAjnLqT1K7ixYsHu8FEQY5GYWX2+QLBUcGCBW3Tpk1unaHrTYvaqGUKnDrKfCm5Otb1vM2f3JroJgCIkfbZJYsWdDWVKk/IDnv/d1wo3fdV8+U58vgVLf/B/bZpXL9sbWu0PHN0UxAQOtpIB/7QACe9kwFGExRkZv703lQFKpHakFaAk9HzhS6nLjYAAGLhoyYHAAAguXkmkwMAAGLn81AmhyAHAAAcxgU6AQAAkhuZHAAAEER3FQAA8CQfNTkAAMCLfB4KcnL1ZR0AAIB3UZMDAAA8mckhyAEAAIcxhBwAACC5kckBAABBdFcBAABP8h3FmpxZs2bZF198Ebz9r3/964gLVm/dutXeeecd27Rpk7Vu3dratGkT9foZXQUAABLi4MGDtmfPHlu1apXdeeedLqAJtWbNGjvhhBPs5ZdftiVLltiZZ55pI0aMiHr9dFcBAICEZHLatm3rpgULFtjYsWOPePzuu++26tWr29dff20pKSnWu3dvO+2002zAgAHu/oyQyQEAAEeOroplipNPPvnE+vTp4wIc6dixo5UrV84+++yzqJYnkwMAAOKeydm7d2+qu/PkyWN582Yu7FA3VrVq1VLdV7VqVVu9enVUy5PJAQAAcVeiRAkrWLBgcBo1alSW1hMecOm23++PalkyOQAAIO6ZHBURFyhQIFUmJ7OqVKlyRNbmzz//dNmcaJDJAQAAQT7988Uw/a8oRwFO6JTZrirp2rWrTZgwIZi5mTZtmv3999/WuXPnqJYnkwMAABJi+fLlNm7cOFu3bp27/eSTT1rx4sXtsssus0qVKtmwYcPspJNOcsFOgwYN3Ly33HKL1axZM6r1E+QAAICEDCEPnCdHgc0dd9zh7tPtQOZGRcfz58+3N998050MUH81wipaBDkAACAhF+isXbt2hgXJZcqUscGDB2epKdTkAAAATyKTAwAAgrhAJwAA8CTfUazJyW5kcgAAQKoYJaY4JXliHGpyAACAN5HJAQAAYZmcWLqrLGkQ5AAAgMNi7K7yJ1GQwxByAADgSWRyAABA3EZXxdTVFWcEOQAAIG6jq5IoxqG7CgAAeBOZHAAAEJSS4nNTlsWybJwR5AAAAE92VxHkAAAATxYeM4QcAAB4EpkcAAAQRHcVAADwJB/dVQAAAMmN7ioAAODJTA5BDgAA8GRNDqOrAACAJ5HJAQAAQXRXAQAAT/J5qLuKTA4AAPBkJoeaHAAA4ElkcgAAQBDdVQAAwJN8dFcBAAAkN7qrAABAEN1VAADAk3x0VwEAACQ3uqtyubUf3GQFChRIdDOQjUp1e4Dt63HL37kh0U1ANtu7d/9R28Y+TgYIAAC8yOeh7ioyOQAAwJOZHM54DAAAPIlMDgAACKK7CgAAeJKP7ioAAIDkRncVAAAIorsKAAB4ks9DQ8gZXQUAADyJ7ioAAODJwmOCHAAA4MnuKoIcAADgyUwONTkAAMCTyOQAAICEdVcdOnTIlixZYtu2bbPatWtb6dKlLV7I5AAAgCBfSJdVliaL3vLly61Ro0bWqVMnGzx4sFWrVs1Gjhxp8UImBwAAJMSwYcOsYsWKNm/ePMubN69NnTrVTjnlFOvTp48de+yxMa+fIAcAAASl+HxuyrJMLLt582Y74YQTXIAjJ554YvD+eCDIAQAAcR9dtXfv3lT358mTJxjMBNxyyy3Wt29fq1evnlWtWtVeeOEF69Wrl7Vo0cLigZocAAAQdyVKlLCCBQsGp1GjRh0xT40aNaxJkyZ277332vDhw2327NnWvXv3uJ1rh0wOAACI++iqrVu3WoECBVJlcsKdc8451rJlS3vvvffccsuWLbPGjRtbpUqVXLATKzI5AAAgKMUX+yQKcEKn8K4q0dDxVq1aBQOjmjVrukJk3R8PZHIAAMBhMWZyMlPQo0yORljpXDnly5e3Dz74wP7880/r1q2bxQNBDgAASIjRo0e7YuOPPvrIduzYYbVq1bJZs2ZZ3bp147J+ghwAAJCQa1epG0snAdSUHQhyAABAkO9//7IqlmXjjcJjAADgSWRyAABAUOgIqazwJ08ihyAHAAAk7irk2YlMDgAASEjhcVIEORq/rikaKSkpbgIAAEikqKKRu+++2/LlyxfVpHkBAEDOvgp5SgxTjsrkDBkyxPr06RPVCsuWLRtrmwAAQIL4clt3lQIXghcAAJCTZLl45pdffrH/+7//s2OOOcbuv/9+++GHH+yRRx6Jb+sAAEBCRlf5YphydJCzfv16O/XUU61evXrWoUMH27NnjzVt2tReeeUV++233+LfSgAAcFS7q3wxTMkiS0GOrhLasWNHGzVqlNWuXfufFaWkuIBHF9kCAADIkefJ2bZtm1WqVOmI+5Wi0sW2AABAzpQS4wgpfxKlcrKUyWnWrJm9//77tn379uB9+v+kSZOsRYsW8WwfAAA4inxxmHJ0JkfdUi1btnQ1OSVLlrS8efO6epzOnTsT5AAAkIP5uKyD2euvv25vvfWWTZs2zQ4ePOgCn969eyf6vQEAAIj92lXnnnuutW3b1v0/Uo0OAADIWVI8dBXyLJ8n5+2337Zq1apZ5cqV3VS9enV7991349s6AABwVPly+3lyFixYYP369bPbb7/dVq5caatWrbJbbrnF+vbtawsXLox/KwEAAI5Gd9UXX3zhrmU1ePDgVNe30lmP9ViDBg2ysloAAJBgvtx27apwZcqUcSOqwukq5HoMAADkTD4Pja7KUndVjx49bObMmW6E1Y4dO9w0btw4d9+ZZ54Z/1YCAABkR5Bz9913u8xNYNIVyVWXc9FFF1mxYsXcdPHFF7t6nCeffDKzbQAAAEk2uiolhilHdVcNHDjQzjrrrKhWWLFixVjbBAAAEsTnoe6qvNEGLgQvAAB4ny/GSzP4vHIywJ9//tkWLVpkW7ZsCd7XvHlzNwEAAOS4IMfv99uFF17ohosXKlTI3afiY12B/L777iPIAQAgh0rJ7Vch//jjj23evHm2bNkyu/TSS920ZMkSK1GihJ1yyinxbyUAADiq58nxxTDl6CBn/vz5bqh40aJF3blx9u3b586Pc8YZZ9gHH3wQ/1YCAAAcjSBn9+7dVrhwYff/ChUquIyO7Ny50/bu3ZuVVQIAgCTg89C1q2IqPJZu3brZdddd52p0dIHO6dOnx6dludjq1atdbdMzzzyT6KZ4gmrIJnz8nU2Z86sVKpjf+pzR0lqeUCvRzUIMtA996d+9grc/nrXE3vwy9XXzjq1a2np3amCVyxazP1Zvslc+mWcbt+5mu+dgq/7aZPeOfj94u9/Z7a110zoJbZMX+Tx0WYcsZXJ0MU5NUrVqVfvss8/c33feecdOPPHEuDVu5MiR9v3331tOCUyuvvrquKxrw4YNNmbMmLisC2Yjnp5kw596z5rWP8ZKlyhiPQY9aV/N+oVNk4P5/WbvTP3FTXWqlrIGNcunevysdsfbS3f0tD17D9j0n1da64bVbNqzA6x8qSIJazNiV6JYIevRsambvv1hia3+exObFfHP5AS6qgLatGnjpsx4+OGH7bjjjkv3JIPHH3+8lSpVynICjTJr3LhxopuBMJu27LBnX//Kxj880Lq0/efCsXv27Ld7Rn9oHVvVY3vlYJOmL3Z/B3RvcsRjMxessvaDX3LBkEz4cqEtHDfYzmhdx16ePO9oNxVxUrxoITvjlH/e72FPvMN2zSYpuW101aFDh+zAgQNRTZo3Gu+9957NmTMn3Xl69+5ttWvXtpxAhdc6MzSSy5z5/9SLhQY0CnZ++nWl7dqzL4EtQ3Zav2VXMMCRPHlSrHDBfLZtJ+85kJFcN7pK167SKKpoJs2bFcOGDbMff/zRXejzpptuciO4wrurli9f7mpV9Pibb77pai3Scuutt7r1hfr888/t/vvvD95WQKb1aN4HHnjArT9AxdSqNfrzzz/t0UcftZtvvtnd/+mnn9rtt99uw4cPt59++ind7iqtf8KECW5+rWPbtm3Bx/bs2WPPPfecey263temTemnXdObP622wmz9pu2ui0oHuYDyZYrboUN+27hlB5solxh5+am2ZsMO+2jGb4luCpD0fB4qPI4qyBkyZIj98ssvUU2aNyt0RfOePXva119/bbVq1XLn3FEA8vvvv7vH161bZ82aNXO3q1SpYpMmTbJrrrkmzfVt3rzZnnjiiVT3KWhStkn0t1OnTvbYY4+5C44qQFA9kc7/I2vXrnWFv6effrpt377d6tevby+++KK7EGnBggUtf/78NmjQIPvmm28i1tFo/TpnkJ5TFzBds2aNG2IfGJ2ms0K/+uqrbnSaTqrYsGFD14ZIMpo/UlvDqT0a+RY65QZ586TYvv+95wH79h8IPgbvu6N/ezu9VR07f9hE27v/YKKbAyDZanIUBGjKbgpynn766YiPKYDSGZVfeOGF4H2rVq1Kc10DBgywzp07u/UpyPjjjz9sxowZNn78ePf4Sy+9ZH/99Ze7NIUCFlH9jzJRb7/9djAwGDt2rLVq1crdvuKKK6xfv3521113udsqvlZwE8nzzz9vK1assF9//TV4Vmhle0TBkDIzX331lct+KfOigOuee+6xZ5999oh1RTN/eFvDjRo1ykaMGGG5TY2q5WzLtt22ZdsuK1n8n1qyZavXW+GC+a1CmeKJbh6y2T0DO1q3VnWs+82v26p1hzOpANKmn3+x/ARMu48lBw4hj6f27dun+ZgO3spedOzY0Xr06GEdOnQIjuSaNm1aMHgRHfhbt25t1atXt4kTJ7ozMr/88ssuMKhWrZqbZ9asWS6ldu211waXU1ASyByJAoqTTjopePvyyy+3Cy64wLZu3Wonn3yyC6LSunCp6o1OO+20YIAjGoEm6uZSW7T+gK5du7oh+JFEM394W8MNHTrUdZsFKJOjbJnXNW9YwyqUKWbPv/WN3XRpNzt48JC9/M63dvrJjSwlhUyOVylb/ti13axl/Sp2xk3jbe2mnYluEpBj+HLbVciPFmVq0ntMNTWBjIxqU0qXLu2yLir6bdKkyREbWNkcZWwuueQS19Xz4IMPBufJmzfvEcvp/6Ejx5ThCX2zFET89ttv9t1337luKt3WOs8///wj2qtld+3aFfG16DGdJTqUbgcySlmZP7yt4fR6NeU2+fLmsWfuutguue0F+2LGItu0Zaer5Xp2+MWJbhpiNGpgR6tarrjVr1HOqpQrZtUrlLAZC1bZ2Pd/sMt7NLP+pze2afNW2ANXdQkuo5qciV8vYtvnYFcNe8n93bZjt7327nT7auZC69WluXVt3yjRTUMSyjFHvYULF1qRIkXcaCtNJ5xwggtKFEioBiVSHYrqZ+644w7X3aNalV69Dp88rEuXLvbJJ5+4EVwKlkTrmj17dpptUJClDI6yRJrUVaXC4khBjrI86t5Sl1oge6QTJbZr185NCtJUPKznVleU6o/UXRdJZudHahpZNe/9EfbdguVuhI1OBJg/X4756CMNX3y31IoXKeDOlROwat1W93fKj8ut/6j3jlhmyaqNbM8cTufICf0rdY6pkMAWeY/Pp2HkWV/+UPIkcnJOkKNf3927d3ddPpUqVXL1Keo6Cj9nTyjNp26d66+/3nU1hWaKzj33XBd01K1b10499VRX06JuoUC9TVp1QVdddZXrJtP8Ognia6+9FnFerV8FwgrG1G2lAEVBmgKWvn37uq4mnVdHQZMyQ6oHCpxgMVxm58eRSpUoYqf97zw58IYpcw+Phgy3ZPUmN8F7AufJQfZJiTHIiWXZePP50xuHnQ4d8FXnoSHeOvArMzJlyhS78cYbo1r+/ffft8qVK1uLFi3c7f/+978uO1KjRo3gPMqSKKAInCtHdSTqJlLBcL169YLLpkdD0b/99lt3+YnQdQeoBmfu3LmupqVt27ZWrly54GguXWz0sssuSzW/RkkpOFLXkAIWBVKyceNG13UWfq6cRYsWuRFbmk8BSmiXkrJG6v5Spkf1SHny5El3XWnNn1Zb06NtqVFiW3bsSbebEDlfqW4PJLoJyGbL37mBbexx2mcfU76Yy+Rn1z577/+OC9e8Nc/y5otcPhGNA/v32VPnNs7WtmZrkLN+/Xpr1KiRy46oWFdBiM5zo+6jt956y53JGMmNICf3IMjxPoIc7zuaQc61b/8cc5Dz5P+dkBRBTpaGlyhroFFOGpYcyLJopIpGPH300UfxbiMAADjK3VUpMUw5uiZHZ+4NdNOEUldMoqM2AACQdbn+KuQ687BqajRiKUD/11mIo6mTAQAACJXFEuH4d1epW6ply5au+Fc1OLrYpkYRadg0QQ4AADn/KuQpMUyZ8cMPP7jLIKknSANrdF67uL2WrC6oa009/vjj7ky8GmWkC1yGXnIBAADk3Ms6pMQwRUsjhhXgnHnmmW5Qk0Yj64oESXGeHJ0LRhMAAEBmaQCTTkGjE96qu0q1vZGu4XhUg5w33njDTZH06dPHTQAAIPcWHu/duzfV/Tq3W/jlhXR+vXPOOceaNm1qCxYscOez08WkL7zwQktYkKOT+DVv3jx4e//+/TZ16lRbu3atewwAAORMKZb5uprw5SX8ItC6osDw4cNT3aerAegakx9//LGr9VWdr87yX6dOHXc7IUGOCo81Rbpfly4AAAC529atW1OdViZwlv5QxYoVs9NPP93atGnjbqsn6JFHHgkGPQkrPI6kVatW7pIHAAAgZ3dX+WKYRAFO6BTeVRU4JY2uBRlKtyPNm9AgRycI/Prrr6148eLxWiUAAPDwGY+HDBnirtU4efJkd93GMWPGuGtj9urVKy6vJUuh0qOPPuqmAFVEa+iXCofOP//8uDQMAAAcfSkuUImhJicTi6qravTo0W50lS6+XbduXfvwww+tQYMGlrAgRxGWTv4XoCFfFSpUcI0Kvco2AABAevr16+em7JClIOfNN9+0gwcP2tChQ+PfIgAAkDC+OA0hTwZZqsnROPbVq1fHvzUAACChUjx0FfIsBTndu3e37777zhUKhZ/sBwAAIBlkqrvqs88+c391XYm5c+e6YEc1OCkph2OlYcOGuQkAAOQ8vv/9i2X5HBnkzJgxw/0dNGiQnXXWWRHnqVixYnxaBgAAjrqUGLuckqm7KkuFxwpkCGYAAEAyy3SQs27dOncRrbSUL1/eTQAAIOdJyc2ZHJ20R1NaIl2ACwAA5Aw+ny+mc94l0/nyMh3kXH/99XbDDTek+TiXdQAAIOdKyc2ZHAUxVatWzZ7WAAAAxEl8LvMJAAA8weehMx5nKsjp3Llz9rUEAAAkXIrOfxfTBTp9OTPIadeuXfa1BAAAII7orgIAAEG5uvAYAAB4mC/GupqcfoFOAACAZEcmBwAABKWYz01ZFcuy8UaQAwAAgnLtEHIAAOBtKR4qPKYmBwAAeBKZHAAAEJRrTwYIAAC8zeehmhy6qwAAgCeRyQEAAEF0VwEAAE/y0V0FAACQ3OiuAgAAqYp1YynYTaZiX4IcAAAQ5PP53JRVsSwbbwQ5AAAgSCGKRy5CnlRZJQAAgLghkwMAAIIYQg4AADzJR3cVAABAcqO7CgAAePJkgAQ5AADAk0PIGV0FAAA8iUwOAAAI4ozHAADAk3we6q4ikwMAAIIYQg4AAJDkyOQAAIAguqsA5BibP7k10U1ANivVYgjb2OP8hw4etedKiXHodTIN206mtgAAAMQN3VUAACCI7ioAAOBJPi7QCQAAkNyoyQEAAEdcoDOWKSseeeQRa968uU2dOtXihZocAAAQlGI+N2VVVpb98ccf7cUXX7QlS5bY5s2bs/zcR7YFAAAgQZmcvXv32iWXXGJjxoyxlJT4hiVkcgAAQNwpeAmVJ08ey5v3yLDjzjvvtFNOOcXatWsX9zaQyQEAAEG+OPyTEiVKWMGCBYPTqFGjLNyMGTPsnXfesfvuu8+yA5kcAAAQFEvxcGB52bp1qxUoUCBVJifUrl27bMCAAa6bqkiRIpYdCHIAAEDcKcAJDXIiFRuvWLHCbr318KVn9u3bZzfddJPNnDnTHnjggZjbQJADAACCfDGOrgp0V2WkSZMmNn369FT3tW3b1q666io7++yzLR4IcgAAQNy7qzJStGhRd16c1Mv6rHbt2larVi2LB4IcAACQFFSIHK8ARwhyAADAUc/kRNKsWTOLJ4IcAAAQFDoMPCtiWTbeCHIAAEBQiu+fKatiWTbeOBkgAADwJDI5AAAgiO4qAADgSb4EFh7HG91VAADAk+iuAgAAQXRXAQAAT0phdBUAAEByo7sKAAAE0V0FAAA8yeeh0VVkcgAAQJBilFjilCSKcRhCDgAAvIlMDgAACEoxn6XE0Oek5ZMFQQ4AAAiiuwoAACDJkckBAACeTOUQ5AAAAE+eJ4cLdAIAAE8ikwMAAII4GSAAAPAkn3dKcsjkAAAAb0Y51OQAAABPoiYHAAB4cnQVQQ4AAPBk4THdVQAAwJPI5AAAAC/WHRPkAAAAb0Y5dFcBAABPorsKAAAEMboKAAB4ks9Do6vI5AAAAC+W5FCTAwAAvIlMDgAA8GQqhyAHAAB4svCYIeQAAMCTyOQAAIAgRlcBAABP8nmnJIfuKgAA4E05urvqt99+M5/PZ8cee2y2rH/atGnWuHFjK168eJaW37Fjh/3www928sknZ8v8iM7uPfvsgec+tilzfrVCBfPbRT1aWd+zWrP5PGbdxm12z+gP7cdFK6x8mWI2+MKO1ql1/UQ3CzE49pgKNu7hK4K3735mkn005edU83Rt19Au7tnaKpcvZb+vXGtPvvaFLfjtT7Z7LHzeSeUkbeHx0qVL7aeffkp3ng8//NAmT56cbW249957bfXq1Vle/u+//7a777472+ZHdIaMHG9fzfrFRl13tl1+Xnv796Nv27hJM9l8HnLw4CE799pnbe3GbfbwredblzYN7KKbxtrseUsT3TTEYMWajdb3pufcVLpEEStetFCqx7u1b2jndWtur70/066/77+2buN2+2jMdVatYim2exxGV/li+JcskjaTM3bsWJs1a5ZNmTIlzXluuOGGbG3Dxx9/HNPyderUsS+//DLb5kfGVv+92d757Af74uWb7MQGNdx9y//caE+++gXZHA/5evavtnjZ3zZp9LVWsnhhO6lxLft+4XJ79vWv3P+RM+3bf8CWrFjr/n/wkP+Ixz+fscg+mbYgeHver6vswjNPslZNatuqT74/qm31Ei8VHidtJifcr7/+an/88Yft37/fFixY4DI96q5asmRJqvnWrVtnc+bMsQ0bNqS7vnnz5tny5ctT3bdr1y4XVOk5At1V27ZtCz4+depU16W0ZcsWF4Dt3LnT3b9mzRqXddq7d69b58KFC939mlfLBGhdWqf8+eef9uOPP9ru3buDj4fPH6B51F49T4CeS23VpNcb2k4c9uOi5VawQL5ggCNtmtZxO85tOw5ve+RsPyxcbvXrVHIBTuj7/MPCFQltF7I/gxeqecMaVrhQfhfsAEmdyQl3//3326pVq2zFihVWrlw5GzBggAsS8ubNa08//bSb54477rAnn3zSGjRoYCtXrrSLLrrIHnrooYjre++991zA8cUXXwTvGz9+vD388MO2ePFid/v00093j7dq1crd7tSpk/Xu3dumT59uNWvWtJdfftkeeeQR97du3bq2fv16O/74410Nz1tvvWW///67W+bAgQNu+UWLFtlpp51mPXr0cP/ft2+fC2wUqBx33HFHzC9PPfWUDR061I455hjbvHmznXvuufbYY4+5oGb48OFuHq1DbVbbr7zyymx8F3KeLdt2W6mQA58o7f3PY7uOSH8jZ9J7GXhfA3R7y7Z/fojA22a88W8rWriglS5ZxK4a/pr9tvyf7A8st5fk5JwgR5TNUGBTvXp1d3vQoEHBx5R9efDBB12G5cQTT3T3vfjii2muq3///jZy5EgXDAXWp2BFwVN6FIAoi6TgatKkSfb666+7gEXr0LqaNm1qp556aprL79mzx7p06WITJkwwv99vZ599tj3++OP27LPPHjGvgp+bb77Z/Q0EWmqjKNAL7cpTJkkFy7169bIKFSpEbPfBgwdTZYJyA2VxduxK/Vp37Nrj/qoIGV56n/eluk/vO+9x7tDv1uetcMH8dkrLuvb4vy+wNWu32OyfqcfKMg9FOTmmu0rOOuusYEASLl++fFa/fn0bN26cy2oogLj00kvdY+pWCnTtaFJ3U40aNVxQ8Morr7h51PU1e/Zs69evX7ptUGClAEc++eQTO+ecc4Jt0t//+7//S3d5LRsIpDQyrF27di5oiuTdd991rzkQ4Mgll1ySah5lf7799lv3msqWLWtz586NuK5Ro0ZZwYIFg1OJEiUsNzi+ZkXbvnOP/bl2c/C+xUv/tlIlClu50sUS2jbE933+fcVaO3DgcCC/eOlfdlyNimzmXOD3Fevs58Wr3ciqOfOX2dldmiW6ScgE9Y4o6XDffffZd999Z7k2yCldunSGG0rFu3fddZc1bNjQdV8p2FGdjrp2AlOgFkfBhjIjmuell16yrl27WuXKlaNuw9atW48IFkqWLJnu8gUKFAgGSaL/h3ZPhdq0aZOVKVMm4mPLli1z3XKnnHKK3XTTTe51qbts7drIaVp1eSmLFJjU9tzghOOrWt2aFe2h5z927/PWHbvt2f9+bb27tUx00xBH3do3sgMHD9lzE75xt5ev3mBvTJ5jvU9vwXb2sP5nt7XjahzOXDc8too1qVvNFv1xuH4RyT26SiUYOj6pN0bHL/WEPPDAA5Yru6vSo/qW/Pnz29VXX+0mZW8UsKhrSIFApFFayrpoXj322muv2RNPPJGp51T9TfhoKEWhaQUmmdWoUSN79dVX7dChQ5aSkhIsji5cuLA988wzro5H2R5RoKRMkg7kkSiYCg2ucgtly1687zK75LbnrVbnW23P3v12covjbejgHoluGuJIBccv3jvABg9/zR59+VOXvbu4Zxt3/hTkbLMnDnV/y5QoYsOuPsuu69/Fnhn/lb363gybv3i1PXPXxVa9Umk3+qpwwXz2wlvT3GPIuqM5umrYsGF2wgknBG+rvvW2226zW265xe2/Y+WZo54yE4oAr7jiCreRVLujwKdatWppLlOoUCE7//zzXbGualRUEJwZAwcOtEcffdSuueYalwX67LPPXJdX9+7d4/CK/ukaU62O6myUdVJmR0GPRmApgHv77bddbY+yQ88//7x7HEeqV7uSzZ54p636e5Prty9TsiibyYN04r+FH41yXZOlIpxTBTmTzpETbv3m7e6vTvzYZcDD7v3OlzfF1m/akeYPPRx94bWfefLkOeLHdmiAI0pW6Ed9PAKcpA5yatWq5bpVAhS4hHcNKZOhjRYoxFUhsEYjqVamSpUqLkNTu3btdJ9HAY7qcRQcaeOGat++faqzHauGp2jRwwfIihUruqBGo5oUZLRt29atR/UxonlDz16sdWmdoapWrerOqpzW/Coo1mgqdatVqlTJdavJtdde64I41RSpxka1RAro1CZEVq1i+t2dyPny5s1jx1Qpm+hmII4C58lJz+atjKJLxrrjEmHHbJWSBEYFR6IRxKrLUQ9LvPj8hL0x0TlslBEKaNmypesGu/XWWy3ZI2wFR1t27HGZIAA5V6kWQxLdBGQz/6GDtvfn/7gf/9m1z977v+PC/BWbLH8Mz7Fv715rdExp18MS2tZImZwAzaseEf1Yf+ONN4IJDM9mcnKKiy++2Dp27OgyMhMnTnQnLMxohBYAAMnKF+OlGQLLKsCJJiDTyXt1DjmNkFbvRLwCnBw3uioZ6Rw3OuuyLkOhgmN1L6lbCQAApE9n8u/QoYO1aNHC1ZzGM8ARMjkxUgZHNTMAAHiCL8brT2Vi2W7durmLU6vsI/R6lDpvTrFisZ/LjCAHAAAk5ITHKjIOvYZjADU5AAAgR7sym6+3SCYHAAB48tpVBDkAACDuo6uSAaOrAACAJ5HJAQAACbl2VXYjyAEAAF4sySHIAQAA3oxyqMkBAACeRHcVAADw5OgqghwAAODJwmO6qwAAgCeRyQEAAF6sOybIAQAAh9FdBQAAkOTorgIAAJ7ssCLIAQAAnuyuIsgBAAAezOMwhBwAAHgUmRwAABBEdxUAAPAkn4cu68AZjwEAgCfRXQUAADxZeUyQAwAAvBjj0F0FAAC8iUwOAAAIYnQVAADwJJ+HRleRyQEAAJ4symEIOQAA8CQyOQAAwIuJHIIcAADgzcJjuqsAAIAn0V0FAACCGF0FAAA8yUd3FQAAQHKjJgcAAHgSNTkAAMCT3VUEOQAAwJOFx3RXAQAATyKTAwAAguiuAgAAnuTz0GUd6K4CAACeRHcVAADwZCqHIAcAAAQxugoAACDJkckBAABBjK4CAACe5PNOSQ6ZHAAAkLgo5+DBgzZjxgzbtGmTNW/e3KpUqWLxQncVAABIiG3btlnnzp1tw4YNVqtWLZs1a5Y99dRTNmDAgLisnyAHAAAkZHTVvffea3v27LGFCxdaoUKF7I033rBLL73UzjzzTCtXrpzFipMBAgCAIwqPY5mi9e6771r//v1dgCPnnXeeFS5c2D799FOLBzI5uZTf73d/9+7dm+imAIiR/9BBtmEueY8D++7stDfG40Jg+fD15MmTx/LmTR12LF261HVThc5TvXp1d388EOTkUvv27XN/K5QpkeimAAAyse8uWLBgtmyvPHnyuKLfeBwXihUrZiVKpF7PXXfdZcOHDw/eVsCmouP8+fOnmq9AgQJ24MABiweCnFyqaNGitnXrVvfh8mUmt5iD6VeFvnR63foSwZt4n70vN77HCggU4GjfnV3y5s1ry5cvd4FHPNobfmxREBVKj5cvX97+/vvvVPfrdoUKFWJug3sO/9HIfQFJsmPULyAVueWWHWNuxPvsfbzH3nH++efb/v377Z133nG3VYDcsGFDmz9/vvsbKzI5AAAgIe68805r1aqVXXXVVS6oeeKJJ+yiiy6KS4AjjK4CAAAJoWDmu+++c6Or9Pemm26yl19+OW7rJ5ODXEP9wSp8C+8XhrfwPnsf77G31KtXzx599NFsWTc1OQAAwJPorgIAAJ5EkIOkoYF+GjoYj+GLwNG0evVq2717d6699tD27duzbf3r1q1zo2+ySudbWbt2bbbNj+RGkIOjRjuO9M6kqYNEkyZNbM2aNQkLsA4dOnTUn9srNm/e7C6ylxsDE40OmTp1qnnNjh073JWh03PPPffYfffdl21taN26tRtOnFWLFy+2E088MdvmR3KjJgdHjU409d5777kLryWbLVu2WKlSpWzVqlVWtWrVRDcn6eikazt37rTKlSunOc8DDzzgAsXHHnvMcgIdPO+//347+eSTY16XPjPPP/+8devWzbzktttuc1eFnjJlSqKbAmQJmRwkRHjmRL8W9f9I3VVKVWfmF3dG8+tkgOGnDA9kINavX+/aoF+woXSAT+u8mWk9nzJXWpcyHDnd6NGj7Ywzzkh3nltvvTXHBDgyc+bMuAQ4uS3YDXRN6Xuk70la3VW6PyP63uu7FUrf/9B9Q3h3lb5Xge+vfpwE/q/v565du9z/1S49Fqn7SevSOgPLhD9/et1V+p6HZnsD+yxN0bxeHH0EOUiIjRs3WqVKlezuu++2ihUrWv369V33ge5TNkW001DWR9dA0f0dO3Z0pxxPS0bz//DDD3bSSSdZ2bJlrWTJku5Mm4EdYY8ePdzfrl27ui6zZ555xt3+7LPP7LjjjnOnHi9evLhde+21wS63jJ5Pz6V11axZ0y3/0ksvmVfo4KT3UHSQ0P8jdVfpIKADSkbdgJonPBjUMtqe4fUYOrhGOqDoc6PHAusLvUhgoK3RdFdp/rRqTHSQz8zFC9OaP622Jrt//etfdumll1q7du1c9konbrvlllvs9ttvD86jz3m5cuXcRRZ1av7nnnsuzfWNGjXK+vXrl+q+t99+25o1axb8UaGLN+q7G6BrK+lUEHr+448/3v744w97+umnXSZW+xJ1NQ0cONAuv/xyN/+CBQvcMgFal76Tw4YNc+0rU6aM624MBDbh88vkyZPdPkr7Dr22Z5991t2vZfQd16RltN5PPvkkxq2MeCLIQULNnTvXfv/9d/dLqHTp0qke085S9+vAqQOgLuw2Y8aMNNeV3vw6yKkr4eKLL3YHyMCB5eabbw7+qpcff/zRrUNZCR0Ezz77bLvxxhvdL0PVBWhnpy6OaNqnA7QeVyD1/vvv2/XXX2+//fabeYGC0759+1r79u2tTp067hwX6q667rrrgvOMGzfOBXeNGjVyB4f06jZ0INS2DvXpp5+6g10gQFqyZImdeuqpwQNomzZt3AEuoGnTpq57RQebFi1auM+WDqAKaHUejrp16wbf50h1NKrF0Pp1sNT6+/TpE8zoff/993bCCSe4+/X4WWed5bJ+aclo/vC2xlJzcrR99NFH7r3W5/6OO+44IgsyePBge/HFF93n/pdffkn3atIDBgywDz/8MFUQqhPB6X1L73xW06ZNs3nz5rkgQ8sq0FK79N1+6qmn7N133033NSjjo++/6v8UsOfLl88eeeSRiPPqvTnnnHNcIKfgV6/nzz//dI/px00gk6PHHn74Yfe9UHCL5ECQg4RSYJDWBed0gNTOSDsUXcitQ4cOduGFF7rHtBMJ7FwCO8j05td1UXRwPPfcc12Ao53hoEGDgtdLiWTSpElWo0YNu/LKK9369H8FPK+//nqGzxdKAZB+4emg+vXXX5tXfPnll67o9K+//nJ/I/3q1y9eHYi0jQJdCZH079/fpk+fnuqAqIPdBRdc4K4zpgsT9uzZ021DbU9NCrB0QAmlIObnn3+2FStWuHk+//xzF6zqPddB8Keffor4/DrgKRBRZkDL6TOloEtBlNqt/ytrpwO3Xo+CH52GPpJo5w9ta/PmzS2n0Gtr27ZtxMcUmCgzsnLlSrdN9cMlENwqAAp8ZzXpPVUArGn8+PFuHgUdyp4q+EmPAg49j0yYMCFVmxT86nuenpSUFBsxYoSrEyxcuLB7r3TNpEhee+0169Spk/uBpOV0YdDwz7uyTvrMqA1ql4JcJAeCHCSUfgmlRQc4/VLUrzT98r3kkkuC3UFKNQfSxLrOSUbz60CnA2hgGU16XL/g0qrf0Y64WrVqqe5Tijxwxdz0nk87cKXMFcApONLzKWuQiJFj2UVdewrs0qJtpV/yCih1yvaRI0cGay60nQKTggLNqwPJK6+84uZRoKHsl7pGRMWvmlddEHovFRjo177uD9RXyA033BA8+KlIWu+Duh+UDapdu3aagYkCDh2Y1f2ioEoHM3VnNm7c2D2mX/s6KCqYVfekuktURB9paHO084e21SvfWb1efc5//fVXV++kSUGCKGAM/f4FAgEFNIGu3FdffdUFsgo2o22D3v/wgvjw7qZw+jzqYr0Bes/T6jJUgK7vcCQKYpXl0fqU0dTrWrZsmae+5zkdQQ6Sln4dKYDRwU7dSOpv1y9+0cEo8Isw0Aee3vzaAekgF/pLUpOyENpBBVLjocXF2rFpZx1aT6Jfe4EdXnrPp2yPRqSoKy6QdVLmwUvnAFI9Q3rU3aQgQ/VOOnDpPRN125xyyinBSRmcwMFOQY62q7afDnSBobw60ChAUCAUWK579+52zDHHpApyQtukAEWZOmWEWrZs6eafPXt2xLbqc6DMXKSr0ysToyygAuIAHVT1XkYaMh/t/Bltv5xI752+Z+oyUgCqba/AUtck0vsZ+t1TxkWU/VQwrCyb3v9AYBstfQb0PQ2l9cWL9h3hGcDAfkLdUwrI9Z7rb+CHkZe+5zkd165CUndl6aCjVLL+KhOTP3/+LM2v9LWKHNVFpZ2uHtfBVd1HSpXr17bS0OreOP30091tLaO0uOpMhgwZ4nacDz30kKtHyOj5FDQpQ6HsgwpzdbBV944OtrmBDgI6iAfS+gpsGjRo4A50qo2KVEDeq1cv997oPdHBMfRgp+JvbdtFixa57oUAHUzSqt3QY4FsQqBGSO9VpFoarV+BlA5SClYDFOCq8DVQuxGoG1M3k9oROm9AZuf3EgWLymiqW1c1UAoOFOiGBnzhVLOkrsirr77aFWT37t07U8+p4FhdXhosoOyiurvUNanPUzyou/rxxx93r0mZRL2vqt/Rd1qfPf2IUWZR+4D//Oc/LpOD5EEmB0eNdvCBFLG6A3QQDD1Ahd+nomCNQFFfuOoltGx6I5TSm1/ZGgU12tlqJ6wUs9LlDz74YHB57aD0C1TZA+0wNZpKy2jHrSyAghtNgVEb6T2ffp2qu0NdKgqa1MWi51XwlBuoC1DnodFIGf3K1nZUXUpa9Vei7acuQAWWCgoC3ZCi90TZG9VeqDtEGTV1bahQOC16XEHTN9984wLUOXPmpPn8Wr+yRPpcKMjSCBwV0GoZjZJTd6TeZ92vg6iulKyRduqeCZfZ+ZOZPq+hAwL0Q0Dfi1Ch9yljpYJqBQV6vxQMKDujbpz06Dul7ix9R8LfI+0TQn/caD8SGjQpQFVQ88Ybb7ggVtv8sssuC+5rNG9ocKl1hWfRihQpEnyd4fPrNelzoO+wAid1UQcK7PW+qsBcn0t9drQOBVra3yBJ+AEgA88++6z/9NNPD94eMWKE/9Zbb001z/333++/7rrrgre///57/3nnneevV6+e/+STT/aPGzcuw+2sZY455hj/ZZdddsRju3fv9t97773+Dh06+Bs1auS/5JJL/EuWLAk+3rRpU//MmTODtw8ePOgfO3asm79Bgwb+Pn36+BcuXBh8vFWrVv4pU6YEb+/cudM/dOhQd3/Lli39o0ePDj62ceNG/9VXX+1v0qSJv02bNv6HHnrIf+DAgTTXldH84W1FbA4dOpTqdufOnf3Dhg1js8LPGY8BADnaFVdc4bKAKmCfOHGiO8WBsoEZFTDD+6jJAQDkaBrJqBGXOpeSCoXVpUmAAyGTAwAAPInCYwAA4EkEOQAAwJMIcgAAgCcR5AAAAE8iyAEAAJ5EkAMgIQJnFU7W59cZqyNdfiISXf5BlwGJ5cKMmXk+ANEhyAGQELpcxuTJkxN2kA9//nC6JIWuMh1tkKP5dcX1rMrM8wGIDicDBHAEXUx09OjRwWv56ErPuhBidp5gTUGOLtYYDWVNHnvsMXfFZwBIC5kcAEfQlZR1oco+ffq4i48q66ELEc6bNy/btpYucKiLPUab9dDVnwEgPWRyAESkKykrYyK6LpCu/D1mzBh79tln7Z577rGGDRvahg0bbNasWe7qzLpS+4QJE9wp9aVnz5522mmnBdenK7brKu+LFi2yBg0aWI0aNY7I5Ogq76H3a326iriuUK/rEzVq1MiuueYa99gNN9zgrn6tq7zrqtOB+bP6/BnR82/evNllto499lhXzxN6tWrR9hgxYoStWLHCWrVq5a6urbaHvp602gcg/sjkAIhKrVq1bN26de7/06ZNs0svvdRmz55tHTt2dN1Y/fr1s1GjRrlApF69eu7xsWPHBpdXMPLOO+9Yu3btXGboqquuSrcm5aKLLrJ///vfLqA47rjjXMCgwl4FU4H1KdN04oknutuxPn9GFJTo+Xr06OHa0bRp0yNqcBSoKag56aST7MEHH7Qrr7wy+FhG7QOQDbgSO4Bwzz33nL9KlSrB25s3b/ZXqlTJf9ddd7nbXbt29ffq1Sv4+MyZM/1FihTxb9iwIXjf559/7q9QoYL7/5dffukvXry4f8uWLcHHBw8e7D/mmGOCt/PkyeOfO3eu+/+0adP8BQsW9K9atSr4+O7du/27du1y/9eua/78+XF9/nCh7YmkS5cu/jFjxrj/79+/37XpscceCz6+cOFCf0pKin/ZsmUZti+a5wOQeXRXAYho06ZNrrtq//79NmfOHKtatapdf/31wcdbtmyZaji2unFCMxd79+61tWvXuvXMnz/f1fSE1tx06NDBPvroo4jPPXfuXKtfv757zoCCBQum+U7F+/kjWbBggY0fP95WrVrlur7++OMPN4Vq37598P9qf+nSpV33mGqc0muf5gMQfwQ5ANKsyVH3jA7Ow4cPtyZNmpjP5ws+rvsDChcu7AIIzR+qf//+bj1FihSxnTt3pnos/HaoYsWK2Y4dO6J+Z+L9/OEUqLRp08YGDRpkXbt2detUfU5661TCadeuXe65M2ofgOxBTQ6AdAuPVYui+pPQACec6nKUkVAhrpbRpNqVffv2ufUoa6JMiDJCovtffvnlNNd36qmn2sqVK10NTYCWDdQEqeA4tB4m3s8f7vvvv3dZJRVGX3zxxdapUydbunTpEfM999xzLriRcePGWf78+d22y6h9ALIHmRwAMdN5dF544QU3DLxOnTpWtGhR++WXX+zqq692j6tweOTIke5gr4yIum9q1qyZ7vqef/55V5z70EMPWd68/+yqAifvU4DQt29fF0CcccYZbnRVPJ8/XJcuXVwRtLJZCnY00ixSF5OCsMaNG1uZMmVcQKU2KSDTlF77AGQPnwpzsmndAHIonXlYXTQKICKZPn26lS9f3gUPodTFpPoXdds0a9bsiEBA6128eLEbXaQsh2pvNOpJlLVRhiS0bkajrXRungIFCljz5s2DwY52WxrZpVFOGvWl4CPW5w8X3h51Pc2YMcMOHDjg6pGUaRI9t9qj0WHqylKb9DwKdsKHmKfXvkivH0BsCHIAAIAnUZMDAAA8iSAHAAB4EkEOAADwJIIcAADgSQQ5AADAkwhyAACAJxHkAAAATyLIAQAAnkSQAwAAPIkgBwAAeBJBDgAAMC/6f9AWEp4QZuXQAAAAAElFTkSuQmCC"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Inspect predictions from the top-scoring model.\n",
    "best_name = comparison[\"Macro F1\"].idxmax()\n",
    "best_predictions = fitted_models[best_name].predict(X_test)\n",
    "print(\"Best model:\", best_name)\n",
    "ConfusionMatrixDisplay.from_predictions(y_test, best_predictions,\n",
    "                                        display_labels=encoder.classes_, cmap=\"Blues\")\n",
    "plt.title(best_name + \" confusion matrix\")\n",
    "plt.tight_layout()\n",
    "plt.show()\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
