diff --git a/.gitignore b/.gitignore index c5cb3da..f949526 100644 --- a/.gitignore +++ b/.gitignore @@ -176,4 +176,12 @@ cython_debug/ *.csv -/lab_2/aimenv \ No newline at end of file +aimenv/ + +/lab_2/aimenv +/lab_3/aimenv +/lab_4/aimenv + +lab_2/aimenv +lab_3/aimenv +lab_4/aimenv \ No newline at end of file diff --git a/lab_3/lab3.ipynb b/lab_3/lab3.ipynb new file mode 100644 index 0000000..7c9e25e --- /dev/null +++ b/lab_3/lab3.ipynb @@ -0,0 +1,545 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Вариант задания: Прогнозирование цен на автомобили\n", + "### Бизнес-цели:\n", + "Повышение эффективности ценообразования на вторичном рынке автомобилей:\n", + "Цель: Разработать модель машинного обучения, которая позволит точно прогнозировать рыночную стоимость автомобилей на вторичном рынке.\n", + "Ключевые показатели успеха (KPI):\n", + "Точность прогнозирования цены (например, RMSE, MAE).\n", + "Сокращение времени на оценку стоимости автомобиля.\n", + "Увеличение количества продаж за счет более конкурентоспособных цен.\n", + "Оптимизация рекламных бюджетов для онлайн-площадок по продаже автомобилей:\n", + "Цель: Использовать прогнозы цен на автомобили для оптимизации таргетинга рекламы и повышения конверсии на онлайн-площадках.\n", + "Ключевые показатели успеха (KPI):\n", + "Увеличение CTR (Click-Through Rate) рекламных объявлений.\n", + "Повышение конверсии (процент пользователей, совершивших покупку после клика на рекламу).\n", + "Снижение стоимости привлечения клиента (CPA).\n", + "### Цели технического проекта:\n", + "Для бизнес-цели 1:\n", + "Сбор и подготовка данных:\n", + "Очистка данных от пропусков, выбросов и дубликатов.\n", + "Преобразование категориальных переменных в числовые.\n", + "Разделение данных на обучающую и тестовую выборки.\n", + "Разработка и обучение модели:\n", + "Исследование различных алгоритмов машинного обучения (линейная регрессия, деревья решений, случайный лес и т.д.).\n", + "Обучение моделей на обучающей выборке.\n", + "Оценка качества моделей на тестовой выборке с помощью метрик RMSE, MAE и др.\n", + "Развертывание модели:\n", + "Интеграция модели в существующую систему или разработка нового API для доступа к прогнозам.\n", + "Создание веб-интерфейса или мобильного приложения для удобного использования модели.\n", + "Для бизнес-цели 2:\n", + "Анализ данных о пользователях и поведении:\n", + "Анализ данных о просмотрах, кликах и покупках на онлайн-площадке.\n", + "Определение сегментов пользователей с разным уровнем интереса к покупке автомобилей.\n", + "Разработка рекомендательной системы:\n", + "Создание модели, которая будет рекомендовать пользователям автомобили, соответствующие их предпочтениям и бюджету.\n", + "Интеграция рекомендательной системы в рекламные кампании.\n", + "Оптимизация таргетинга рекламы:\n", + "Использование прогнозов цен на автомобили для более точного таргетинга рекламы на пользователей, готовых к покупке.\n", + "Тестирование различных стратегий таргетинга и оценка их эффективности." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Index(['ID', 'Price', 'Levy', 'Manufacturer', 'Model', 'Prod. year',\n", + " 'Category', 'Leather interior', 'Fuel type', 'Engine volume', 'Mileage',\n", + " 'Cylinders', 'Gear box type', 'Drive wheels', 'Doors', 'Wheel', 'Color',\n", + " 'Airbags'],\n", + " dtype='object')\n" + ] + } + ], + "source": [ + "import pandas as pn\n", + "import matplotlib.pyplot as plt\n", + "import matplotlib\n", + "import matplotlib.ticker as ticker\n", + "df = pn.read_csv(\".//static//csv//car_price_prediction.csv\")\n", + "print(df.columns)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Разделим на 3 выборки\n" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Размер обучающей выборки: 12311\n", + "Размер контрольной выборки: 3078\n", + "Размер тестовой выборки: 3848\n" + ] + } + ], + "source": [ + "from sklearn.model_selection import train_test_split\n", + "\n", + "# Разделение данных на обучающую и тестовую выборки (80% - обучение, 20% - тест)\n", + "train_data, test_data = train_test_split(df, test_size=0.2, random_state=42)\n", + "\n", + "# Разделение обучающей выборки на обучающую и контрольную (80% - обучение, 20% - контроль)\n", + "train_data, val_data = train_test_split(train_data, test_size=0.2, random_state=42)\n", + "\n", + "print(\"Размер обучающей выборки:\", len(train_data))\n", + "print(\"Размер контрольной выборки:\", len(val_data))\n", + "print(\"Размер тестовой выборки:\", len(test_data))" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkQAAAHHCAYAAABeLEexAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABI9UlEQVR4nO3deVxVdf7H8fdlVxRckK1IERVzNysHHbdCFJdyssylxMbSccAWW4yZTLQF08bMdHSaUmu0sWyxpmks3LKS1FTcM3Uw0wR3rmKiwPf3hz/ueL2gQsIFz+v5eJzHg3PO95zzOd+7vTnLvTZjjBEAAICFebi7AAAAAHcjEAEAAMsjEAEAAMsjEAEAAMsjEAEAAMsjEAEAAMsjEAEAAMsjEAEAAMsjEAGAm5w4cUK7d+9Wfn6+u0vBVWSM0bFjx7Rr1y53l4JSIBABQAU5d+6cJk+erNatW8vX11e1a9dW48aNtWzZMneXViVs3bpVixcvdoxnZGTo3//+t/sKusDJkyf1zDPPKDo6Wj4+Pqpbt66aNGminTt3urs0XCEvdxeAymHevHl64IEHHOO+vr664YYbFBcXp3HjxikkJMSN1QFVX15enuLi4vTtt9/qD3/4g5577jlVr15dnp6eateunbvLqxJOnjypkSNHKjQ0VHXr1tUjjzyi+Ph49e7d2611HT16VF26dNG+ffs0evRodezYUT4+PvL29laDBg3cWhuuHIEITiZOnKjIyEidOXNGX3/9tWbNmqXPPvtMW7duVfXq1d1dHlBlvfTSS1qzZo0+//xzde3a1d3lVEkxMTGOQZKaNGmihx56yM1VSU8++aQOHjyo9PR0NW/e3N3loIwIRHASHx+vm2++WZL04IMPqm7dupo6dao+/vhjDRo0yM3VAVVTfn6+pk2bpscff5ww9CstXrxY27dv1y+//KKWLVvKx8fHrfUcOnRIb731lmbPnk0YquK4hgiXdNttt0mSMjMzJUnHjh3TE088oZYtW6pGjRoKCAhQfHy8Nm3a5LLsmTNnlJKSoiZNmsjPz09hYWG66667tGfPHknS3r17ZbPZShwu/OBYuXKlbDab3n33Xf3pT39SaGio/P39dccdd+inn35y2faaNWvUs2dPBQYGqnr16urSpYu++eabYvexa9euxW4/JSXFpe38+fPVrl07VatWTXXq1NHAgQOL3f6l9u1ChYWFmjZtmpo3by4/Pz+FhIRo5MiROn78uFO7Bg0aqE+fPi7bSUpKcllncbVPmTLFpU+l86dxxo8fr0aNGsnX11cRERF66qmnlJeXV2xfXahr165q0aKFy/SXX35ZNptNe/fudZp+4sQJPfroo4qIiJCvr68aNWqkl156SYWFhY42Rf328ssvu6y3RYsWxT4n3n///RJrHDZs2BWdsmjQoIHj8fHw8FBoaKjuvfde7du377LLStJf//pXNW/eXL6+vgoPD1diYqJOnDjhmL9z504dP35cNWvWVJcuXVS9enUFBgaqT58+2rp1q6PdihUrZLPZ9NFHH7ls45133pHNZlN6erqj5mHDhjm1KeqTlStXOqZ99dVXuueee3TDDTc4HuPHHntMv/zyi9OyKSkpLs+lBQsWqE2bNvLz81PdunU1aNAglz4ZNmyYatSo4TTt/fffd6lDkmrUqOFSs3Rlr6uuXbs6Hv9mzZqpXbt22rRpU7Gvq+Jc/DoPCgpS7969nfpfOv/6SUpKKnE98+bNc3p+r1u3ToWFhTp79qxuvvnmS/aVJC1fvlydOnWSv7+/atWqpTvvvFM7duxwalP0WHz//fcaMGCAAgICHKcIz5w541Lvha/3/Px89erVS3Xq1NH27dud2l7p+5dVcYQIl1QUXurWrStJ+u9//6vFixfrnnvuUWRkpLKzs/W3v/1NXbp00fbt2xUeHi5JKigoUJ8+fbRs2TINHDhQjzzyiE6ePKm0tDRt3bpVUVFRjm0MGjRIvXr1ctpucnJysfW88MILstlsGjt2rA4dOqRp06YpNjZWGRkZqlatmqTzbzjx8fFq166dxo8fLw8PD82dO1e33XabvvrqK916660u673++uuVmpoqSTp16pRGjRpV7LbHjRunAQMG6MEHH9Thw4f12muvqXPnztq4caNq1arlssyIESPUqVMnSdKHH37o8kE3cuRIx/VbDz/8sDIzMzVjxgxt3LhR33zzjby9vYvth9I4ceKEY98uVFhYqDvuuENff/21RowYoRtvvFFbtmzRK6+8oh9++MHp4tVf6/Tp0+rSpYsOHDigkSNH6oYbbtDq1auVnJysgwcPatq0aVdtW2XVqVMnjRgxQoWFhdq6daumTZumn3/+WV999dUll0tJSdGECRMUGxurUaNGaefOnZo1a5bWrVvneAyP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EcA3bdqkJ554wtFmy5Yt+uGHH/TWW29p6NChjulpaWkl9kNsbKwCAwP17LPPlljv1fqywdK+rqTzd/QdOnSo2LtAL6d27dpOj3HXrl0VHh6uuXPnOt3Icf311zu1q1GjhoYMGVLsKcYLH9ui081FLuyrC58rF/v+++8VFBTk8hzftWuXY/2StHv3bhUWFrr0f/fu3TVr1iydOXNGixcv1ogRIxx3HEpl62cr4hoilIqnp6eMMU7TFi1apAMHDjhN69+/v44cOeLyX60kl+VL4+2339bJkycd4++//74OHjyo+Ph4SVK7du0UFRWll19+WadOnXJZ/vDhwy61e3p6FntL+4XuuusueXp6asKECS71G2Mcd5pI5297/eCDD3Trrbde8j+vAQMGqKCgQM8995zLvPz8/F91TUx6ero+/vhjTZo0qcSwM2DAAB04cEB///vfXeb98ssvys3NLfP2i9tWenq6Pv/8c5d5J06cuKq/5VVYWCgPD49fHfKKbku/1FcQxMbGysfHR9OnT3d6Xrz55pvKyclxfINyvXr1dPPNN+utt95yOm21Z88effLJJ4qPj3f6zz0oKEjx8fGaP3++FixYoJ49exZ7V5eHh4datGih2NhYxcbGunzjddE6L6zNGKNXX331kvvepk0bhYSE6O9//7tOnz7tmP7VV1/pu+++u+zr5UqV5nUlnb9e7IUXXtBjjz12yaOvV+pKHmPpf0eeizu60rZtW4WGhmr27NlO67m4r8LCwtSmTRu99dZbTq/trVu36osvvnC501Y6fwnDhV577TVJcrzfFenQoYM8PT3l7++v2bNna9WqVU6v69L2s1VxhAil0qdPH02cOFEPPPCAOnTooC1btmjBggVO/x1L5w/5v/322xozZozWrl2rTp06KTc3V0uXLtUf//hHl4v+rlSdOnX029/+Vg888ICys7M1bdo0NWrUyHE6xcPDQ2+88Ybi4+PVvHlzPfDAA7ruuut04MABrVixQgEBAfrXv/6l3NxczZw5U9OnT1eTJk2cvi+lKEht3rxZ6enpiomJUVRUlJ5//nklJydr79696tevn2rWrKnMzEx99NFHGjFihJ544gktXbpU48aN0+bNm/Wvf/3rkvvSpUsXjRw5UqmpqcrIyFBcXJy8vb21a9cuLVq0SK+++qruvvvuMvXTF198oe7du1/yiMz999+v9957T3/4wx+0YsUKdezYUQUFBfr+++/13nvv6fPPP7/skbNTp05pyZIlTtOK/gP+8ssv5e3treuuu05PPvmkPvnkE/Xp00fDhg1Tu3btlJubqy1btuj999/X3r17y3wbd0ZGhmrUqKH8/HytX79eb7/9tu68885iP7wu5b///a/mz58v6fzF6DNmzFBAQMAlL6yuV6+ekpOTNWHCBPXs2VN33HGHdu7cqb/+9a+65ZZbnC6Cnjx5suLi4hQTE6MHH3zQcdu9n5+fXnjhBZd1Dx061PH4Fxear0TTpk0VFRWlJ554QgcOHFBAQIA++OADl2uJLubt7a2XXnpJw4YNU8eOHZWQkKBjx47p1Vdf1XXXXedyu3tBQYHT8yAjI0PS+VM5F174X1BQoAMHDmjt2rW69dZbr/h1VWTDhg0KCgoq8dTr5WRnZzse4yNHjuhvf/ubvLy8XALevn37tGTJEscpsxdeeEH169dX27ZtXY5Se3l5afLkyRo6dKg6deqkIUOGOE7HXX/99U59NWXKFMXHxysmJkbDhw933HYfGBhY7BGvzMxM3XHHHerZs6fS09M1f/58DR48WK1bty5xH3v06KH77rtPTz31lPr27auwsLBS97NlVeQtbai8im4dXbdu3SXbnTlzxjz++OMmLCzMVKtWzXTs2NGkp6cXe0vr6dOnzZ///GcTGRlpvL29TWhoqLn77rvNnj17jDFlu8X6n//8p0lOTjbBwcGmWrVqpnfv3k63DhfZuHGjueuuu0zdunWNr6+vqV+/vhkwYIBZtmyZ07YvN1x8K/YHH3xgfvvb3xp/f3/j7+9vmjZtahITE83OnTuNMcaMHj3adO7c2SxZssSlpotvuy/y+uuvm3bt2plq1aqZmjVrmpYtW5qnnnrK/Pzzz442pb3t3mazmfXr1ztNL+4xOnv2rHnppZdM8+bNja+vr6ldu7Zp166dmTBhgsnJyXHZ3sXru1z/zZ0719H+5MmTJjk52TRq1Mj4+PiYoKAg06FDB/Pyyy+bs2fPGmPK9pwoGry8vEz9+vXNww8/bI4fP26MKd1t9xeuKygoyMTFxZn09PTLLmvM+dvsmzZtary9vU1ISIgZNWqUo4YLLVu2zHTs2NFUq1bNBAQEmN69e5stW7YUu868vDxTu3ZtExgYaH755ZcrqqO42+63b99uYmNjTY0aNUxQUJB56KGHzKZNm1wen+KenwsXLjRt2rRxPDfuvfdes3fvXqc2CQkJV/RaunC4+Hl4udeVMf97vr3yyitOy5b0urrYxc/XWrVqmY4dO5rPPvvMqd2FbWw2mwkNDTV33XWX2bFjhzHG9bb7Iu+9955p27at8fX1NXXq1DGDBg0q9r1p6dKlTs+Bvn37mu3btxe7T9u3bzd33323qVmzpqldu7ZJSkpyeS7ooq/ZMMaYI0eOmHr16pnf/e53TtOvpJ+tzGbMrzh/AVSQlStXqlu3blq0aFGZj5pcaO/evYqMjFRmZmaJ10OkpKRo7969mjdv3q/enhU1aNBAKSkpxX4zMS4vPz9f4eHh6tu3r8s1e1XZvHnzNG/ePJdvscb/FH3Z5+HDh6/aF2Di8riGCAAqocWLF+vw4cNOF0MDKD9cQwRLKrpr5FIXPbdq1crxUyQovS5duji+0BNXbs2aNdq8ebOee+45tW3bVl26dHF3SVfVddddV+zP5wDuRiCCJQUFBTkurizJXXfdVUHVXJveeustd5dQJc2aNUvz589XmzZtrsnTtd27d7/s934B7sA1RAAAwPK4hggAAFgegQgAAFge1xBdgcLCQv3888+qWbNmuf/EAQAAuDqMMTp58qTCw8Odfqi8OASiK/Dzzz9f1R+6BAAAFeenn37S9ddff8k2BKIrULNmTUnnOzQgIMDN1QAAgCtht9sVERHh+By/FALRFSg6TRYQEEAgAgCgirmSy124qBoAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFgegQgAAFieWwPRqlWr1LdvX4WHh8tms2nx4sVO8202W7HDlClTHG0aNGjgMn/SpElO69m8ebM6deokPz8/RUREaPLkyRWxewAAoIpwayDKzc1V69atNXPmzGLnHzx40GmYM2eObDab+vfv79Ru4sSJTu1Gjx7tmGe32xUXF6f69etr/fr1mjJlilJSUvT666+X674BAICqw8ud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jR49WmPHjr3iOu12uwIDA5WTk3PZU3YAAKByKM3nt1sDUVVBIAIAoOopzed3pb6GCAAAoCIQiAAAgOURiAAAgOURiAAAgOURiAAAgOURiAAAgOURiAAAgOURiAAAgOURiAAAgOURiAAAgOURiAAAgOURiAAAgOURiAAAgOURiAAAgOURiAAAgOURiAAAgOURiAAAgOURiAAAgOURiAAAgOURiAAAgOURiAAAgOURiAAAgOURiAAAgOURiAAAgOURiAAAgOURiAAAgOURiAAAgOWVKRA1bNhQR48edZl+4sQJNWzY8FcXBQAAUJHKFIj27t2rgoICl+l5eXk6cODAry4KAACgInmVpvEnn3zi+Pvzzz9XYGCgY7ygoEDLli1TgwYNrlpxAAAAFaFUgahfv36SJJvNpoSEBKd53t7eatCggf7yl79cteIAAAAqQqkCUWFhoSQpMjJS69atU1BQULkUBQAAUJFKFYiKZGZmXu06AAAA3KZMgUiSli1bpmXLlunQoUOOI0dF5syZ86sLAwAAqChlCkQTJkzQxIkTdfPNNyssLEw2m+1q1wUAAFBhyhSIZs+erXnz5un++++/2vUAAABUuDJ9D9HZs2fVoUOHX73xVatWqW/fvgoPD5fNZtPixYud5htj9OyzzyosLEzVqlVTbGysdu3a5dTm2LFjGjJkiAICAlSrVi0NHz5cp06dcmqzefNmderUSX5+foqIiNDkyZN/de0AAODaUaZA9OCDD+qdd9751RvPzc1V69atNXPmzGLnT548WdOnT9fs2bO1Zs0a+fv7q0ePHjpz5oyjzZAhQ7Rt2zalpaXp008/1apVqzRixAjHfLvdrri4ONWvX1/r16/XlClTlJKSotdff/1X1w8AAK4NNmOMKe1CjzzyiN5++221atVKrVq1kre3t9P8qVOnlr4Qm00fffSR47uOjDEKDw/X448/rieeeEKSlJOTo5CQEM2bN08DBw7Ujh071KxZM61bt04333yzJGnJkiXq1auX9u/fr/DwcM2aNUt//vOflZWVJR8fH0nS008/rcWLF+v777+/otrsdrsCAwOVk5OjgICAUu8bAACoeKX5/C7TEaLNmzerTZs28vDw0NatW7Vx40bHkJGRUZZVusjMzFRWVpZiY2Md0wIDA9W+fXulp6dLktLT01WrVi1HGJKk2NhYeXh4aM2a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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAj4AAAHHCAYAAAC/R1LgAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABWY0lEQVR4nO3deVxU5f4H8M/sbA6rMKAIKCIuoIUbpVlJImHL1W6bt7Rral600rKiW7l0u1b2M8u05VZqt8WkzfKapriUiqYkIqKIhqIou6wCAzPP7w+aEyOggMAA5/N+veal55znnPM9z2wfzjYKIYQAERERkQwobV0AERERUXth8CEiIiLZYPAhIiIi2WDwISIiItlg8CEiIiLZYPAhIiIi2WDwISIiItlg8CEiIiLZUNu6ACIioq7AaDSisLAQZrMZPj4+ti6HGsE9PkRE1KF9+umnOH36tDS8Zs0aZGVl2a6gOg4ePIgHH3wQHh4e0Ol08Pb2xqRJk2xdFl0Bg08XsmbNGigUCulhZ2eHoKAgzJ49Gzk5ObYuj4ioRX755Rc888wzOH36NLZs2YKYmBgolbb/+tqwYQNGjRqF1NRUvPLKK9i6dSu2bt2K999/39al0RXwUFcXtHjxYgQEBKCyshK7d+/Gu+++i02bNiElJQUODg62Lo+IqFnmzp2Lm2++GQEBAQCAefPmwdvb26Y1FRYW4tFHH0VkZCTi4uKg1WptWg81HYNPFxQVFYWhQ4cCAB599FG4u7tj2bJl2LBhAx544AEbV0dE1DzBwcE4deoUUlJS4OHhgT59+ti6JKxevRqVlZVYs2YNQ08nY/t9hdTmbr31VgBARkYGgNq/VJ5++mmEhITAyckJer0eUVFROHz4cL15KysrsXDhQgQFBcHOzg7e3t6YOHEiTp06BQA4ffq01eG1yx8333yztKydO3dCoVDgyy+/xPPPPw+DwQBHR0fceeedOHv2bL1179+/H+PHj4ezszMcHBwwZswY7Nmzp8FtvPnmmxtc/8KFC+u1/fTTTxEWFgZ7e3u4ubnh/vvvb3D9V9q2usxmM5YvX46BAwfCzs4OXl5emDlzJi5evGjVzt/fHxMmTKi3ntmzZ9dbZkO1L126tF6fAkBVVRUWLFiAwMBA6HQ6+Pr64plnnkFVVVWDfVXXzTffjEGDBtUb/8Ybb0ChUFidVwEARUVFePLJJ+Hr6wudTofAwEC89tprMJvNUhtLv73xxhv1ljto0KAGXxNfffVVozVOnToV/v7+V90Wf39/6flRKpUwGAy47777kJmZ2aR5p06dajVuxowZsLOzw86dO63Gr1q1CgMHDoROp4OPjw9iYmJQVFRk1aap/Vq35oYelu2u26dvvvkm/Pz8YG9vjzFjxiAlJaXeerZv347Ro0fD0dERLi4uuOuuu3Ds2LGr9lvdR93tbuy1W1dznncAyM3NxbRp0+Dl5QU7OzsMHjwYa9eubXCZa9asgaOjI0aMGIE+ffogJiYGCoWi3nPWWE2Wh0ajgb+/P+bPnw+j0Si1s5wmcPDgwUaXdfPNN1ttw759+zBkyBD8+9//lt4Pffv2xauvvmr1fgCAmpoavPzyy+jTpw90Oh38/f3x/PPP13uPWvr5p59+wpAhQ2BnZ4cBAwbgm2++sWpnqbfu+/Po0aNwdXXFhAkTUFNTI41vyntWbrjHRwYsIcXd3R0A8Pvvv+O7777DX//6VwQEBCAnJwfvv/8+xowZg9TUVOlqBJPJhAkTJiA+Ph73338/nnjiCZSWlmLr1q1ISUmx+qvrgQcewO2332613tjY2AbreeWVV6BQKPDss88iNzcXy5cvR0REBJKSkmBvbw+g9oM7KioKYWFhWLBgAZRKJVavXo1bb70Vv/zyC4YPH15vuT179sSSJUsAAGVlZZg1a1aD637xxRdx77334tFHH0VeXh5WrFiBm266CYcOHYKLi0u9eWbMmIHRo0cDAL755ht8++23VtNnzpyJNWvW4JFHHsHjjz+OjIwMvPPOOzh06BD27NkDjUbTYD80R1FRkbRtdZnNZtx5553YvXs3ZsyYgf79++PIkSN48803ceLECXz33XfXvG6LS5cuYcyYMcjKysLMmTPRq1cv7N27F7Gxsbhw4QKWL1/eautqqdGjR2PGjBkwm81ISUnB8uXLcf78efzyyy/NWs6CBQvw0Ucf4csvv7T6slu4cCEWLVqEiIgIzJo1C2lpaXj33Xdx4MCBFj3Xy5cvR1lZGQDg2LFj+Pe//43nn38e/fv3BwA4OTlZtf/kk09QWlqKmJgYVFZW4q233sKtt96KI0eOwMvLCwCwbds2REVFoXfv3li4cCEqKiqwYsUK3Hjjjfjtt98aDJGWfqtbR1uqqKjAzTffjJMnT2L27NkICAhAXFwcpk6diqKiIjzxxBONznvy5En85z//adb6LO/hqqoqbNmyBW+88Qbs7Ozw8ssvt3gbCgoKsHv3buzevRt///vfERYWhvj4eMTGxuL06dN47733pLaPPvoo1q5di3vuuQdPPfUU9u/fjyVLluDYsWP1Pk/S09Nx33334bHHHsOUKVOwevVq/PWvf8XmzZtx2223NVjL2bNnMX78eAQHB2P9+vVQq2u/2jvDe9YmBHUZq1evFgDEtm3bRF5enjh79qxYt26dcHd3F/b29uLcuXNCCCEqKyuFyWSymjcjI0PodDqxePFiadzHH38sAIhly5bVW5fZbJbmAyCWLl1ar83AgQPFmDFjpOEdO3YIAKJHjx6ipKREGr9+/XoBQLz11lvSsvv27SsiIyOl9QghxKVLl0RAQIC47bbb6q3rhhtuEIMGDZKG8/LyBACxYMECadzp06eFSqUSr7zyitW8R44cEWq1ut749PR0AUCsXbtWGrdgwQJR923zyy+/CADis88+s5p38+bN9cb7+fmJ6OjoerXHxMSIy9+Kl9f+zDPPCE9PTxEWFmbVp//973+FUqkUv/zyi9X87733ngAg9uzZU299dY0ZM0YMHDiw3vilS5cKACIjI0Ma9/LLLwtHR0dx4sQJq7bPPfecUKlUIjMzUwjRstdEXFxcozVOmTJF+Pn5XXE7hKjt3ylTpliNe/DBB4WDg0Oz5n3//fcFALFixQqrNrm5uUKr1Ypx48ZZvX/eeecdAUB8/PHH0rjm9KuFpS927NhRb5qlT+u+j4UQYv/+/QKAmDt3rjRuyJAhwtPTUxQUFEjjDh8+LJRKpXj44YfrLbtHjx7ikUceuWIdjb12G6qxKc/78uXLBQDx6aefSuOMRqMIDw8XTk5O0ueDZZmrV6+W2t17771i0KBBwtfXt97z3VhNdecXQggfHx9x++23S8OWz84DBw40uqwxY8ZYbcOYMWMEALFw4UKrdlOnThUAxJEjR4QQQiQlJQkA4tFHH7Vq9/TTTwsAYvv27dI4Pz8/AUB8/fXX0rji4mLh7e0trrvuunr1ZmRkiMLCQjFgwADRr18/kZ+fb7WOpr5n5YaHurqgiIgIdO/eHb6+vrj//vvh5OSEb7/9Fj169AAA6HQ66YoIk8mEgoICODk5oV+/fvjtt9+k5Xz99dfw8PDAnDlz6q3j8kMzzfHwww+jW7du0vA999wDb29vbNq0CQCQlJSE9PR0PPjggygoKEB+fj7y8/NRXl6OsWPH4ueff663m7ayshJ2dnZXXO8333wDs9mMe++9V1pmfn4+DAYD+vbtix07dli1t+wK1+l0jS4zLi4Ozs7OuO2226yWGRYWBicnp3rLrK6utmqXn5+PysrKK9adlZWFFStW4MUXX6y3ByAuLg79+/dHcHCw1TIthzcvX/+1iIuLw+jRo+Hq6mq1roiICJhMJvz8889W7S9dulRvW00mU4PLLi0tRX5+fr1DRs1VVVWF/Px85ObmYuvWrdi+fTvGjh3b5Pk3bNiAf/zjH5g/fz5mz55tNW3btm0wGo148sknra4omj59OvR6Pf73v/9ZtTeZTPW2/9KlS9e0fXfffbf0PgaA4cOHY8SIEdJ758KFC0hKSsLUqVPh5uYmtQsNDcVtt90mtavLaDRe8TVuYXntFhQUWB1KuVxTnvdNmzbBYDBYnXOo0Wjw+OOPo6ysDLt27Wpw2YmJiYiLi8OSJUuadVVXWVkZ8vPzkZWVhQ8++ADZ2dkNvi6Ki4uRn5+P0tLSJi1XpVJh7ty5VuOeeuopAJBeD5Y+nzdv3hXbWfj4+OAvf/mLNKzX6/Hwww/j0KFDyM7OtmpbWVmJO++8E3l5edi8ebO0V9+iue9ZueChri5o5cqVCAoKglqthpeXF/r162f1IWE2m/HWW29h1apVyMjIsPpQqvvGOXXqFPr16yftNm0tffv2tRpWKBQIDAyUjlenp6cDAKZMmdLoMoqLi+Hq6ioN5+fn11vu5dLT0yGEaLTd5YcpLF/Cl4eNy5dZXFwMT0/PBqfn5uZaDf/000/o3r37Feu83IIFC+Dj44OZM2fWOxcmPT0dx44da3SZl6//WqSnpyM5ObnJ61qwYAEWLFhQr53lkExdf//736X/Ozk54Y477sCbb77ZYNsrWbduHdatWycNDxs2DB9++GGT5k1KSsL69ethMplQWFhYb/qZM2cAAP369bMar9Vq0bt3b2m6xfHjx5v9XF9NQ6/doKAgrF+//oo1AkD//v2xZcsWlJeXw9HRURpfXFx8xde4Rd3XrkqlQmhoKF599VWMGzfOql1TnvczZ86gb9++9cKL5RDf5X1p8dxzz2H06NGYMGFCvWB6JXPmzLH6A+6RRx6pF1iA2j8aLVxcXPDAAw9g6dKlVv1loVAo4OPjA71ebzXe8nlr+Tw7c+YMlEolAgMDrdoZDAa4uLjU29bAwMB6f1gGBQUBqD1nyWAwWG3Hvn37YGdn12AYbe57Vi4YfLqg4cOHS1d1NeTf//43XnzxRfz973/Hyy+/DDc3NyiVSjz55JMd4oQ3Sw1Lly7FkCFDGmxT94PaaDTiwoULjR7/rrtchUKBH3/8ESqV6orLBCD9dVX3g6ahZXp6euKzzz5rcPrlHzgjRozAv/71L6tx77zzDjZs2NDg/MeOHcOaNWvw6aefNnj+iNlsRkhICJYtW9bg/L6+vo3W3lxmsxm33XYbnnnmmQanWz6cLWbMmIG//vWvVuOmT5/e4LwvvfQSRo8ejerqaiQmJmLx4sUoKipqcA/FlYwbNw7z588HAJw7dw6vvfYabrnlFhw8eFA6f6wxhw8fRlRUFMaOHYv58+fjb3/7W70TcpvD39+/3rkocXFx+OCDD1q8zNZWWFgIo9F4xde4Rd3X7vnz5/Haa6/hL3/5C44ePWp13lBznvfm+Omnn7Bt2zYkJCQ0e9758+dj3LhxMJlMOHr0KBYvXgwhBFavXm3VzvJHY1VVFXbu3CmdqL1q1ap6y7za6+ly17KXvDG//fYbNmzYgNmzZ2PGjBnYvn271fTmvmflgsFHhr766ivccsst+Oijj6zGFxUVwcPDQxru06cP9u/fj+rq6lY5QdfCskfHQgiBkydPIjQ0VFovULuLt+5fYI05fPgwqqurrxj2LMsVQiAgIKBJb/jU1FQoFIoG/3quu8xt27bhxhtvbNIHoYeHR71tutIJyLGxsRgyZAjuu+++Rtd/+PBhjB07tk0+WC9fV1lZWZOeE6B278TlbRv6yxkAQkJCpLZRUVHIzMzE2rVrr3hIpSHe3t5W6+zXrx9uuOEGfPfdd1e9lUNISAji4uJgb2+PuLg4zJgxA8nJydIhVD8/PwBAWloaevfuLc1nNBqRkZHR4LZePi4pKalZ23O5y987AHDixAkpeNSt8XLHjx+Hh4eH1XOQmpoK4M89LVdy+Ws3MDAQN954I37++Wer4NOU593Pzw/Jyckwm81We32OHz9utR0WQgg899xz+Mtf/oKRI0detdbLDRgwQKopMjISVVVVeP755/HKK69Y/bRE3T8ao6OjcfjwYWzevLnBZQYEBOCnn35CaWmp1aH7EydOwGw2Wz0nZrMZ6enpVv2ck5ODoqKiett68uRJCCGs3s8nTpwAgHonpn/44Ye48847oVKpMGHCBHz00UeYNm2aNL2571m54Dk+MqRSqSCEsBoXFxdX7xbwkyZNQn5+Pt555516y7h8/uawXJli8dVXX+HChQuIiooCAISFhaFPnz544403pCte6srLy6tXu+WNfyUTJ06ESqXCokWL6tUvhEBBQYE0XFNTg6+//hrDhw+/4mGAe++9FyaTqcGrQ2pqaq7pnJWEhARs2LABr776aqOh5t5770VWVlaDV7lUVFSgvLy8xetvaF0JCQnYsmVLvWlFRUXNDilXYvlCvNYwV1FRAQBNurT/+uuvh6OjI5RKJT788EOcPn0aixcvlqZHRERAq9Xi7bfftnr9fPTRRyguLkZ0dPQ11doU3333ndX79Ndff8X+/ful9463tzeGDBmCtWvXWr32UlJS8NNPP9W78nLdunXQarUYNWpUs2ux7JltaO/p1dx+++3Izs7Gl19+KY2rqanBihUr4OTkhDFjxtSrMzk5ucErG1vC8rqoe0l7Q8xmc6Pbd/vtt8NkMtX7fLTsfbW8Hix9fvkVVJe3szh//rzVlV4lJSX45JNPMGTIkHp75ixXm0ZHR+P+++/H/Pnzre7S357v2c6Ee3xkaMKECVi8eDEeeeQR3HDDDThy5Ag+++wzq79igdqTkD/55BPMmzcPv/76K0aPHo3y8nJs27YN//jHP3DXXXe1aP1ubm4YNWoUHnnkEeTk5GD58uUIDAyUdodbvniioqIwcOBAPPLII+jRoweysrKwY8cO6PV6/PDDDygvL8fKlSvx9ttvIygoyOq+I5bAlJycjISEBISHh6NPnz7417/+JV1uevfdd6Nbt27IyMjAt99+ixkzZuDpp5/Gtm3b8OKLLyI5ORk//PDDFbdlzJgxmDlzJpYsWYKkpCSMGzcOGo0G6enpiIuLw1tvvYV77rmnRf30008/4bbbbrviX2sPPfQQ1q9fj8ceeww7duzAjTfeCJPJhOPHj2P9+vXYsmXLVfeElZWV1fur1rLHYNeuXdBoNOjRowfmz5+P77//HhMmTMDUqVMRFhaG8vJyHDlyBF999RVOnz5ttcewOZKSkuDk5ISamhokJibik08+wV133dXsL9Xff/8dn376KYDak8Lfeecd6PX6Zp3gDNTed+bZZ5/Fq6++ivvvvx+hoaHo3r07YmNjsWjRIowfPx533nkn0tLSsGrVKgwbNgx/+9vfmrWOlggMDMSoUaMwa9YsVFVVYfny5XB3d7c6lLF06VJERUUhPDwc06ZNky5nd3Z2lu4NlZ6ejgULFuCLL77Ac889V+88lYZYTqAFak+ifu211+Ds7Ixbbrml2dsxY8YMvP/++5g6dSoSExPh7++Pr776Cnv27MHy5cut9qAAte+F6dOnX3Hv65UkJCRArVZLh7pWrFiB6667rt4elISEBOTn50uHuuLj4/H00083uMzbb78dERER+Oc//4mMjAwMGTIE27dvx9dff43HHntMuo/T4MGDMWXKFHzwwQcoKirCmDFj8Ouvv2Lt2rW4++676/VfUFAQpk2bhgMHDsDLywsff/wxcnJy6h2Wu9xbb72F/v37Y86cOdI5X235nu3UbHQ1GbWBplySKUTt5exPPfWU8Pb2Fvb29uLGG28UCQkJ9S7XFKL2EvJ//vOfIiAgQGg0GmEwGMQ999wjTp06JYRo2aXLX3zxhYiNjRWenp7C3t5eREdHizNnztSb/9ChQ2LixInC3d1d6HQ64efnJ+69914RHx9vte6rPS6/5PXrr78Wo0aNEo6OjsLR0VEEBweLmJgYkZaWJoQQYs6cOeKmm24SmzdvrlfT5ZezW3zwwQciLCxM2Nvbi27duomQkBDxzDPPiPPnz0ttmns5u0KhEImJiVbjG3qOjEajeO2118TAgQOFTqcTrq6uIiwsTCxatEgUFxfXW9/ly7ta/9W9FLi0tFTExsaKwMBAodVqhYeHh7jhhhvEG2+8IYxGoxCiZa8Jy0OtVgs/Pz/x+OOPi4sXLwohmnc5e91leXh4iHHjxomEhIQmzXv566SyslIEBweLYcOGiZqaGmn8O++8I4KDg4VGoxFeXl5i1qxZUq0WbXU5+9KlS8X//d//CV9fX6HT6cTo0aPF4cOH67Xftm2buPHGG4W9vb3Q6/XijjvuEKmpqdL0L774QgwaNEi89dZbVreMaKyOxvp23759DdZ4ucufdyGEyMnJEY888ojw8PAQWq1WhISE1LvsvO5l/FlZWVbTGnrOGus3y0OpVIqePXuKKVOmWN0WwPLZaXlotVoRGBgoXnrpJVFVVSWEaPi9V1ZWJubOnSt8fHyERqMRgYGB4tVXX613u5Dq6mqxaNEi6XPU19dXxMbGisrKynrbFB0dLbZs2SJCQ0OFTqcTwcHB9W73UPdy9rrWrl0rAIjvv/9eGteU96zcKIS4hmMWRM2wc+dO3HLLLYiLi2vxXpC6Tp8+jYCAAGRkZDR6Z9+FCxfi9OnTWLNmzTWvT478/f2xcOHCq94hl9qW5bW+dOnSRvdAUOfn7++PQYMGYePGjbYupUvjOT5EREQkGzzHhzotJycnTJ48+YonH4eGhlpdtUHNM2bMGKsb5hERdXYMPtRpeXh4SCeyNmbixIntVE3XdPmPRhIRdXY8x4eIiIhkg+f4EBERkWww+BAREZFs8Bwf1N6d8/z58+jWrVub3/afiIiIWocQAqWlpfDx8an3o7eNYfBB7S3CW/PHHImIiKj9nD17Fj179mxSWwYfQLo9+tmzZ5t063YiIiKyvZKSEvj6+tb7mZMrYfABpMNber2ewYeIiKiTac5pKjy5mYiIiGSDwYeIiIhkg8GHiIiIZIPBh4iIiGSDwYeIiIhkg8GHiIiIZIPBh4iIiGSDwYeIiIhkg8GHiIiIZIPBh4iIiGSDwYeIiIhkg8GHiIiIZIPBh4iIiGSDwYeIiIhkQ23rAroyo9GI5ORkq3GhoaHQarU2qoiIiEjeGHzaUHJyMpat3w6DXx8AQPaZU5gHYOjQobYtjIiISKYYfNqYwa8PfINCbF0GERERgef4EBERkYww+BAREZFsMPgQERGRbDD4EBERkWww+BAREZFsMPgQERGRbDD4EBERkWww+BAREZFsMPgQERGRbDD4EBERkWww+BAREZFsMPgQERGRbDD4EBERkWww+BAREZFsMPgQERGRbDD4EBERkWww+BAREZFsMPgQERGRbDD4EBERkWww+BAREZFsMPgQERGRbNg0+CxcuBAKhcLqERwcLE2vrKxETEwM3N3d4eTkhEmTJiEnJ8dqGZmZmYiOjoaDgwM8PT0xf/581NTUtPemEBERUSegtnUBAwcOxLZt26RhtfrPkubOnYv//e9/iIuLg7OzM2bPno2JEydiz549AACTyYTo6GgYDAbs3bsXFy5cwMMPPwyNRoN///vf7b4tRERE1LHZPPio1WoYDIZ644uLi/HRRx/h888/x6233goAWL16Nfr37499+/Zh5MiR+Omnn5Camopt27bBy8sLQ4YMwcsvv4xnn30WCxcuhFarbe/NISIiog7M5uf4pKenw8fHB71798bkyZORmZkJAEhMTER1dTUiIiKktsHBwejVqxcSEhIAAAkJCQgJCYGXl5fUJjIyEiUlJTh69Gij66yqqkJJSYnVg4iIiLo+mwafESNGYM2aNdi8eTPeffddZGRkYPTo0SgtLUV2dja0Wi1cXFys5vHy8kJ2djYAIDs72yr0WKZbpjVmyZIlcHZ2lh6+vr6tu2FERETUIdn0UFdUVJT0/9DQUIwYMQJ+fn5Yv3497O3t22y9sbGxmDdvnjRcUlLC8ENERCQDNj/UVZeLiwuCgoJw8uRJGAwGGI1GFBUVWbXJycmRzgkyGAz1rvKyDDd03pCFTqeDXq+3ehAREVHX16GCT1lZGU6dOgVvb2+EhYVBo9EgPj5emp6WlobMzEyEh4cDAMLDw3HkyBHk5uZKbbZu3Qq9Xo8BAwa0e/1ERETUsdn0UNfTTz+NO+64A35+fjh//jwWLFgAlUqFBx54AM7Ozpg2bRrmzZsHNzc36PV6zJkzB+Hh4Rg5ciQAYNy4cRgwYAAeeughvP7668jOzsYLL7yAmJgY6HQ6W24aERERdUA2DT7nzp3DAw88gIKCAnTv3h2jRo3Cvn370L17dwDAm2++CaVSiUmTJqGqqgqRkZFYtWqVNL9KpcLGjRsxa9YshIeHw9HREVOmTMHixYtttUlERETUgSmEEMLWRdhaSUkJnJ2dUVxc3Krn+xw8eBCf7z8D36AQAMDZE0fw4Ag/DB06tNXWQUREJFct+f7uUOf4EBEREbUlBh8iIiKSDQYfIiIikg0GHyIiIpINBh8iIiKSDQYfIiIikg0GHyIiIpINBh8iIiKSDQYfIiIikg0GHyIiIpINBh8iIiKSDQYfIiIikg0GHyIiIpINBh8iIiKSDQYfIiIikg0GHyIiIpINBh8iIiKSDQYfIiIikg0GHyIiIpINBh8iIiKSDQYfIiIikg0GHyIiIpINBh8iIiKSDQYfIiIikg0GHyIiIpINBh8iIiKSDQYfIiIikg0GHyIiIpINBh8iIiKSDQYfIiIikg0GHyIiIpINBh8iIiKSDQYfIiIikg0GHyIiIpINBh8iIiKSDQYfIiIikg0GHyIiIpINBh8iIiKSDQYfIiIikg0GHyIiIpINBh8iIiKSDQYfIiIikg0GHyIiIpINBh8iIiKSDQYfIiIikg0GHyIiIpINBh8iIiKSDQYfIiIikg0GHyIiIpINBh8iIiKSDQYfIiIikg0GHyIiIpINBh8iIiKSDQYfIiIiko0OE3xeffVVKBQKPPnkk9K4yspKxMTEwN3dHU5OTpg0aRJycnKs5svMzER0dDQcHBzg6emJ+fPno6ampp2rJyIios6gQwSfAwcO4P3330doaKjV+Llz5+KHH35AXFwcdu3ahfPnz2PixInSdJPJhOjoaBiNRuzduxdr167FmjVr8NJLL7X3JhAREVEnYPPgU1ZWhsmTJ+M///kPXF1dpfHFxcX46KOPsGzZMtx6660ICwvD6tWrsXfvXuzbtw8A8NNPPyE1NRWffvophgwZgqioKLz88stYuXIljEajrTaJiIiIOiibB5+YmBhER0cjIiLCanxiYiKqq6utxgcHB6NXr15ISEgAACQkJCAkJAReXl5Sm8jISJSUlODo0aONrrOqqgolJSVWDyIiIur61LZc+bp16/Dbb7/hwIED9aZlZ2dDq9XCxcXFaryXlxeys7OlNnVDj2W6ZVpjlixZgkWLFl1j9URERNTZ2GyPz9mzZ/HEE0/gs88+g52dXbuuOzY2FsXFxdLj7Nmz7bp+IiIisg2bBZ/ExETk5ubi+uuvh1qthlqtxq5du/D2229DrVbDy8sLRqMRRUVFVvPl5OTAYDAAAAwGQ72rvCzDljYN0el00Ov1Vg8iIiLq+mwWfMaOHYsjR44gKSlJegwdOhSTJ0+W/q/RaBAfHy/Nk5aWhszMTISHhwMAwsPDceTIEeTm5kpttm7dCr1ejwEDBrT7NhEREVHHZrNzfLp164ZBgwZZjXN0dIS7u7s0ftq0aZg3bx7c3Nyg1+sxZ84chIeHY+TIkQCAcePGYcCAAXjooYfw+uuvIzs7Gy+88AJiYmKg0+nafZuIiIioY7Ppyc1X8+abb0KpVGLSpEmoqqpCZGQkVq1aJU1XqVTYuHEjZs2ahfDwcDg6OmLKlClYvHixDasmIiKijqpDBZ+dO3daDdvZ2WHlypVYuXJlo/P4+flh06ZNbVwZERERdQU2v48PERERUXth8CEiIiLZYPAhIiIi2WDwISIiItlg8CEiIiLZYPAhIiIi2WDwISIiItlg8CEiIiLZYPAhIiIi2WDwISIiItlg8CEiIiLZYPAhIiIi2WDwISIiItlg8CEiIiLZYPAhIiIi2WDwISIiItlg8CEiIiLZYPAhIiIi2WDwISIiItlg8CEiIiLZYPAhIiIi2WDwISIiItlg8CEiIiLZYPAhIiIi2WDwISIiItlg8CEiIiLZYPAhIiIi2WDwISIiItlg8CEiIiLZYPAhIiIi2WDwISIiItlg8CEiIiLZYPAhIiIi2WDwISIiItlg8CEiIiLZYPAhIiIi2WDwISIiItlg8CEiIiLZYPAhIiIi2WDwISIiItlg8CEiIiLZYPAhIiIi2WDwISIiItlg8CEiIiLZYPAhIiIi2WDwISIiItlg8CEiIiLZYPAhIiIi2WDwISIiItlg8CEiIiLZaFHw6d27NwoKCuqNLyoqQu/eva+5KCIiIqK20KLgc/r0aZhMpnrjq6qqkJWVdc1FEREREbUFdXMaf//999L/t2zZAmdnZ2nYZDIhPj4e/v7+rVYcERERUWtqVvC5++67AQAKhQJTpkyxmqbRaODv74//+7//a7XiiIiIiFpTsw51mc1mmM1m9OrVC7m5udKw2WxGVVUV0tLSMGHChCYv791330VoaCj0ej30ej3Cw8Px448/StMrKysRExMDd3d3ODk5YdKkScjJybFaRmZmJqKjo+Hg4ABPT0/Mnz8fNTU1zdksIiIikokWneOTkZEBDw+Pa155z5498eqrryIxMREHDx7ErbfeirvuugtHjx4FAMydOxc//PAD4uLisGvXLpw/fx4TJ06U5jeZTIiOjobRaMTevXuxdu1arFmzBi+99NI110ZERERdj0IIIVoyY3x8POLj46U9P3V9/PHHLS7Izc0NS5cuxT333IPu3bvj888/xz333AMAOH78OPr374+EhASMHDkSP/74IyZMmIDz58/Dy8sLAPDee+/h2WefRV5eHrRabZPWWVJSAmdnZxQXF0Ov17e49ssdPHgQn+8/A9+gEADA2RNH8OAIPwwdOrTV1kFERCRXLfn+btEen0WLFmHcuHGIj49Hfn4+Ll68aPVoCZPJhHXr1qG8vBzh4eFITExEdXU1IiIipDbBwcHo1asXEhISAAAJCQkICQmRQg8AREZGoqSkRNpr1JCqqiqUlJRYPYiIiKjra9bJzRbvvfce1qxZg4ceeuiaCzhy5AjCw8NRWVkJJycnfPvttxgwYACSkpKg1Wrh4uJi1d7LywvZ2dkAgOzsbKvQY5lumdaYJUuWYNGiRddcOxEREXUuLdrjYzQaccMNN7RKAf369UNSUhL279+PWbNmYcqUKUhNTW2VZTcmNjYWxcXF0uPs2bNtuj4iIiLqGFoUfB599FF8/vnnrVKAVqtFYGAgwsLCsGTJEgwePBhvvfUWDAYDjEYjioqKrNrn5OTAYDAAAAwGQ72rvCzDljYN0el00pVklgcRERF1fS061FVZWYkPPvgA27ZtQ2hoKDQajdX0ZcuWtbggy6XxYWFh0Gg0iI+Px6RJkwAAaWlpyMzMRHh4OAAgPDwcr7zyCnJzc+Hp6QkA2Lp1K/R6PQYMGNDiGoiIiKhralHwSU5OxpAhQwAAKSkpVtMUCkWTlxMbG4uoqCj06tULpaWl+Pzzz7Fz507prtDTpk3DvHnz4ObmBr1ejzlz5iA8PBwjR44EAIwbNw4DBgzAQw89hNdffx3Z2dl44YUXEBMTA51O15JNIyIioi6sRcFnx44drbLy3NxcPPzww7hw4QKcnZ0RGhqKLVu24LbbbgMAvPnmm1AqlZg0aRKqqqoQGRmJVatWSfOrVCps3LgRs2bNQnh4OBwdHTFlyhQsXry4VeojIiKirqXF9/HpSngfHyIios6nJd/fLdrjc8stt1zxkNb27dtbslgiIiKiNtWi4GM5v8eiuroaSUlJSElJqffjpUREREQdRYuCz5tvvtng+IULF6KsrOyaCiIiIiJqKy26j09j/va3v13T73QRERERtaVWDT4JCQmws7NrzUUSERERtZoWHeqaOHGi1bAQAhcuXMDBgwfx4osvtkphRERERK2tRcHH2dnZalipVKJfv35YvHgxxo0b1yqFEREREbW2FgWf1atXt3YdRERERG2uRcHHIjExEceOHQMADBw4ENddd12rFEVERETUFloUfHJzc3H//fdj586dcHFxAQAUFRXhlltuwbp169C9e/fWrJGIiIioVbToqq45c+agtLQUR48eRWFhIQoLC5GSkoKSkhI8/vjjrV0jERERUato0R6fzZs3Y9u2bejfv780bsCAAVi5ciVPbiYiIqIOq0V7fMxmMzQaTb3xGo0GZrP5mosiIiIiagstCj633nornnjiCZw/f14al5WVhblz52Ls2LGtVhwRERFRa2pR8HnnnXdQUlICf39/9OnTB3369EFAQABKSkqwYsWK1q6RiIiIqFW06BwfX19f/Pbbb9i2bRuOHz8O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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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iRPtsUtERETUTNj1Z1/eeecd+Pv7Y9WqVdK0oKAg6W8hBJYsWYLXXnsNDz74IADgiy++gMFgwIYNG/Doo4/ixIkT2Lp1Kw4ePIiePXsCAD788EPce++9ePfdd+Hn51e/O0VERETNgl2PRP3000/o2bMn/vnPf8LHxwe33XYb/vOf/0jzU1JSkJ6ejvDwcGmam5sb+vTpg+joaABAdHQ03N3dpQAFAOHh4VAqlThw4ECl2y0uLobJZLJ5EBEREdWEXUPUqVOnsGLFCrRv3x7btm3D5MmT8dxzz2HNmjUAgPT0dACAwWCwWc5gMEjz0tPT4ePjYzNfrVbD09NTanO9BQsWwM3NTXr4+/vX9q4RERFRE2fXEGW1WnH77bfjrbfewm233YaJEydiwoQJWLlyZZ1uNzIyEnl5edLj7Nmzdbo9IiIianrsGqJ8fX0REhJiM61Tp05ITU0FABiNRgBARkaGTZuMjAxpntFoRGZmps18s9mMnJwcqc31dDod9Hq9zYOIiIioJuwaou644w4kJCTYTEtMTERgYCCAskHmRqMRUVFR0nyTyYQDBw4gLCwMABAWFobc3FzExMRIbXbu3Amr1Yo+ffrUw14QERFRc2TXq/OmT5+Ofv364a233sLDDz+MP//8E5988gk++eQTAIBCocC0adPw5ptvon379ggKCsLrr78OPz8/PPTQQwDKjlwNGzZMOg1YWlqKKVOm4NFHH+WVeURERFRn7BqievXqhfXr1yMyMhLz589HUFAQlixZgjFjxkhtZs2ahcLCQkycOBG5ubm48847sXXrVjg4OEhtvv76a0yZMgWDBw+GUqnEqFGjsHTpUnvsEhERETUTCiGEsHcR9mYymeDm5oa8vLxaHR8VHx+PNftOwxjYDulnkjGuX+sKY8CIiIhInrr6/q4uu//sCxEREVFjxBBFREREJANDFBEREZEMDFFEREREMjBEEREREcnAEEVEREQkA0MUERERkQwMUUREREQyMEQRERERycAQRURERCQDQxQRERGRDAxRRERERDIwRBERERHJwBBFREREJANDFBEREZEMDFFEREREMjBEEREREcnAEEVEREQkA0MUERERkQwMUUREREQyMEQRERERycAQRURERCQDQxQRERGRDAxRRERERDIwRBERERHJwBBFREREJANDFBEREZEMDFFEREREMjBEEREREcnAEEVEREQkA0MUERERkQwMUUREREQyMEQRERERycAQRURERCQDQxQRERGRDAxRRERERDIwRBERERHJwBBFREREJANDFBEREZEMDFFEREREMjBEEREREcnAEEVEREQkA0MUERERkQwMUUREREQyMEQRERERycAQRURERCSDXUPU3LlzoVAobB4dO3aU5hcVFSEiIgItWrSAi4sLRo0ahYyMDJt1pKamYsSIEXBycoKPjw9mzpwJs9lc37tCREREzYza3gV07twZO3bskJ6r1f8rafr06fjll1+wbt06uLm5YcqUKRg5ciT++OMPAIDFYsGIESNgNBqxb98+XLhwAU8++SQ0Gg3eeuutet8XIiIiaj7sHqLUajWMRmOF6Xl5efjss8/wzTff4O677wYArFq1Cp06dcL+/fvRt29f/Prrr4iPj8eOHTtgMBjQo0cPvPHGG3jppZcwd+5caLXa+t4dIiIiaibsPiYqKSkJfn5+aNOmDcaMGYPU1FQAQExMDEpLSxEeHi617dixIwICAhAdHQ0AiI6ORteuXWEwGKQ2Q4cOhclkwvHjx6vcZnFxMUwmk82DiIiIqCbsGqL69OmD1atXY+vWrVixYgVSUlLQv39/5OfnIz09HVqtFu7u7jbLGAwGpKenAwDS09NtAlT5/PJ5VVmwYAHc3Nykh7+/f+3uGBERETV5dj2dN3z4cOnvbt26oU+fPggMDMR3330HR0fHOttuZGQkZsyYIT03mUwMUkRERFQjdj+ddy13d3cEBwcjOTkZRqMRJSUlyM3NtWmTkZEhjaEyGo0VrtYrf17ZOKtyOp0Oer3e5kFERERUEw0qRBUUFODkyZPw9fVFaGgoNBoNoqKipPkJCQlITU1FWFgYACAsLAzHjh1DZmam1Gb79u3Q6/UICQmp9/qJiIio+bDr6bwXX3wR999/PwIDA3H+/HnMmTMHKpUKjz32GNzc3DB+/HjMmDEDnp6e0Ov1mDp1KsLCwtC3b18AwJAhQxASEoKxY8di4cKFSE9Px2uvvYaIiAjodDp77hoRERE1cXYNUefOncNjjz2GixcvwtvbG3feeSf2798Pb29vAMDixYuhVCoxatQoFBcXY+jQofjoo4+k5VUqFTZt2oTJkycjLCwMzs7OGDduHObPn2+vXSIiIqJmQiGEEPYuwt5MJhPc3NyQl5dXq+Oj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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Пример оценки сбалансированности целевой переменной (цена автомобиля)\n", + "import seaborn as sns\n", + "import matplotlib.pyplot as plt\n", + "\n", + "# Гистограмма распределения цены в обучающей выборке\n", + "sns.histplot(train_data['Price'], kde=True)\n", + "plt.title('Распределение цены в обучающей выборке')\n", + "plt.show()\n", + "\n", + "# Гистограмма распределения цены в контрольной выборке\n", + "sns.histplot(val_data['Price'], kde=True)\n", + "plt.title('Распределение цены в контрольной выборке')\n", + "plt.show()\n", + "\n", + "# Гистограмма распределения цены в тестовой выборке\n", + "sns.histplot(test_data['Price'], kde=True)\n", + "plt.title('Распределение цены в тестовой выборке')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Процесс конструирования признаков\n", + "Задача 1: Прогнозирование цен на автомобили\n", + "Цель технического проекта: Разработка модели машинного обучения для точного прогнозирования рыночной стоимости автомобилей.\n", + "\n", + "Задача 2: Оптимизация рекламных бюджетов\n", + "Цель технического проекта: Использование прогнозов цен на автомобили для оптимизации таргетинга рекламы и повышения конверсии на онлайн-площадках.\n", + "\n", + "\n", + "### Унитарное кодирование категориальных признаков (one-hot encoding)\n", + "\n", + "One-hot encoding: Преобразование категориальных признаков в бинарные векторы." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "\n", + "# Пример категориальных признаков\n", + "categorical_features = ['Model', 'Category', 'Fuel type', 'Gear box type', 'Leather interior']\n", + "\n", + "# Применение one-hot encoding\n", + "train_data_encoded = pd.get_dummies(train_data, columns=categorical_features)\n", + "val_data_encoded = pd.get_dummies(val_data, columns=categorical_features)\n", + "test_data_encoded = pd.get_dummies(test_data, columns=categorical_features)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Дискретизация числовых признаков \n", + "это процесс преобразования непрерывных числовых значений в дискретные категории или интервалы (бины). Этот процесс может быть полезен по нескольким причинам" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "# Пример дискретизации признака 'year'\n", + "train_data_encoded['Year bin'] = pd.cut(train_data_encoded['Prod. year'], bins=5, labels=False)\n", + "val_data_encoded['Year bin'] = pd.cut(val_data_encoded['Prod. year'], bins=5, labels=False)\n", + "test_data_encoded['Year bin'] = pd.cut(test_data_encoded['Prod. year'], bins=5, labels=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Ручной синтез\n", + "Создание новых признаков на основе экспертных знаний и логики предметной области. Например, для данных о продаже автомобилей можно создать признак \"возраст автомобиля\" как разницу между текущим годом и годом выпуска." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "# Пример синтеза признака \"возраст автомобиля\"\n", + "train_data_encoded['Age'] = 2024 - train_data_encoded['Prod. year']\n", + "val_data_encoded['Age'] = 2024 - val_data_encoded['Prod. year']\n", + "test_data_encoded['Age'] = 2024 - test_data_encoded['Prod. year']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Масштабирование признаков - это процесс преобразования числовых признаков таким образом, чтобы они имели одинаковый масштаб. Это важно для многих алгоритмов машинного обучения, которые чувствительны к масштабу признаков, таких как линейная регрессия, метод опорных векторов (SVM) и нейронные сети." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.preprocessing import StandardScaler, MinMaxScaler\n", + "\n", + "# Пример масштабирования числовых признаков\n", + "numerical_features = ['Airbags', 'Age']\n", + "\n", + "scaler = StandardScaler()\n", + "train_data_encoded[numerical_features] = scaler.fit_transform(train_data_encoded[numerical_features])\n", + "val_data_encoded[numerical_features] = scaler.transform(val_data_encoded[numerical_features])\n", + "test_data_encoded[numerical_features] = scaler.transform(test_data_encoded[numerical_features])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Конструирование признаков с применением фреймворка Featuretools" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\featuretools\\entityset\\entityset.py:724: UserWarning: A Woodwork-initialized DataFrame was provided, so the following parameters were ignored: index\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\featuretools\\synthesis\\deep_feature_synthesis.py:169: UserWarning: Only one dataframe in entityset, changing max_depth to 1 since deeper features cannot be created\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\featuretools\\computational_backends\\feature_set_calculator.py:143: FutureWarning: The behavior of DataFrame concatenation with empty or all-NA entries is deprecated. In a future version, this will no longer exclude empty or all-NA columns when determining the result dtypes. To retain the old behavior, exclude the relevant entries before the concat operation.\n", + " df = pd.concat([df, default_df], sort=True)\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\woodwork\\logical_types.py:841: FutureWarning: Downcasting behavior in `replace` is deprecated and will be removed in a future version. To retain the old behavior, explicitly call `result.infer_objects(copy=False)`. To opt-in to the future behavior, set `pd.set_option('future.no_silent_downcasting', True)`\n", + " series = series.replace(ww.config.get_option(\"nan_values\"), np.nan)\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\woodwork\\logical_types.py:841: FutureWarning: Downcasting behavior in `replace` is deprecated and will be removed in a future version. To retain the old behavior, explicitly call `result.infer_objects(copy=False)`. To opt-in to the future behavior, set `pd.set_option('future.no_silent_downcasting', True)`\n", + " series = series.replace(ww.config.get_option(\"nan_values\"), np.nan)\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\woodwork\\logical_types.py:841: FutureWarning: Downcasting behavior in `replace` is deprecated and will be removed in a future version. To retain the old behavior, explicitly call `result.infer_objects(copy=False)`. To opt-in to the future behavior, set `pd.set_option('future.no_silent_downcasting', True)`\n", + " series = series.replace(ww.config.get_option(\"nan_values\"), np.nan)\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\featuretools\\computational_backends\\feature_set_calculator.py:143: FutureWarning: The behavior of DataFrame concatenation with empty or all-NA entries is deprecated. In a future version, this will no longer exclude empty or all-NA columns when determining the result dtypes. To retain the old behavior, exclude the relevant entries before the concat operation.\n", + " df = pd.concat([df, default_df], sort=True)\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\woodwork\\logical_types.py:841: FutureWarning: Downcasting behavior in `replace` is deprecated and will be removed in a future version. To retain the old behavior, explicitly call `result.infer_objects(copy=False)`. To opt-in to the future behavior, set `pd.set_option('future.no_silent_downcasting', True)`\n", + " series = series.replace(ww.config.get_option(\"nan_values\"), np.nan)\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\woodwork\\logical_types.py:841: FutureWarning: Downcasting behavior in `replace` is deprecated and will be removed in a future version. To retain the old behavior, explicitly call `result.infer_objects(copy=False)`. To opt-in to the future behavior, set `pd.set_option('future.no_silent_downcasting', True)`\n", + " series = series.replace(ww.config.get_option(\"nan_values\"), np.nan)\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\woodwork\\logical_types.py:841: FutureWarning: Downcasting behavior in `replace` is deprecated and will be removed in a future version. To retain the old behavior, explicitly call `result.infer_objects(copy=False)`. To opt-in to the future behavior, set `pd.set_option('future.no_silent_downcasting', True)`\n", + " series = series.replace(ww.config.get_option(\"nan_values\"), np.nan)\n" + ] + } + ], + "source": [ + "import featuretools as ft\n", + "\n", + "# Определение сущностей\n", + "es = ft.EntitySet(id='car_data')\n", + "es = es.add_dataframe(dataframe_name='cars', dataframe=train_data_encoded, index='id')\n", + "\n", + "# Определение связей между сущностями (если есть)\n", + "# es = es.add_relationship(...)\n", + "\n", + "# Генерация признаков\n", + "feature_matrix, feature_defs = ft.dfs(entityset=es, target_dataframe_name='cars', max_depth=2)\n", + "\n", + "# Преобразование признаков для контрольной и тестовой выборок\n", + "val_feature_matrix = ft.calculate_feature_matrix(features=feature_defs, entityset=es, instance_ids=val_data_encoded.index)\n", + "test_feature_matrix = ft.calculate_feature_matrix(features=feature_defs, entityset=es, instance_ids=test_data_encoded.index)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Оценка качества каждого набора признаков\n", + "Предсказательная способность\n", + "Метрики: RMSE, MAE, R²\n", + "\n", + "Методы: Обучение модели на обучающей выборке и оценка на контрольной и тестовой выборках.\n", + "\n", + "Скорость вычисления\n", + "Методы: Измерение времени выполнения генерации признаков и обучения модели.\n", + "\n", + "Надежность\n", + "Методы: Кросс-валидация, анализ чувствительности модели к изменениям в данных.\n", + "\n", + "Корреляция\n", + "Методы: Анализ корреляционной матрицы признаков, удаление мультиколлинеарных признаков.\n", + "\n", + "Цельность\n", + "Методы: Проверка логической связи между признаками и целевой переменной, интерпретация результатов модели." + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\featuretools\\entityset\\entityset.py:724: UserWarning: A Woodwork-initialized DataFrame was provided, so the following parameters were ignored: index\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\featuretools\\synthesis\\deep_feature_synthesis.py:169: UserWarning: Only one dataframe in entityset, changing max_depth to 1 since deeper features cannot be created\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\featuretools\\computational_backends\\feature_set_calculator.py:143: FutureWarning: The behavior of DataFrame concatenation with empty or all-NA entries is deprecated. In a future version, this will no longer exclude empty or all-NA columns when determining the result dtypes. To retain the old behavior, exclude the relevant entries before the concat operation.\n", + " df = pd.concat([df, default_df], sort=True)\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\woodwork\\logical_types.py:841: FutureWarning: Downcasting behavior in `replace` is deprecated and will be removed in a future version. To retain the old behavior, explicitly call `result.infer_objects(copy=False)`. To opt-in to the future behavior, set `pd.set_option('future.no_silent_downcasting', True)`\n", + " series = series.replace(ww.config.get_option(\"nan_values\"), np.nan)\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\woodwork\\logical_types.py:841: FutureWarning: Downcasting behavior in `replace` is deprecated and will be removed in a future version. To retain the old behavior, explicitly call `result.infer_objects(copy=False)`. To opt-in to the future behavior, set `pd.set_option('future.no_silent_downcasting', True)`\n", + " series = series.replace(ww.config.get_option(\"nan_values\"), np.nan)\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\woodwork\\logical_types.py:841: FutureWarning: Downcasting behavior in `replace` is deprecated and will be removed in a future version. To retain the old behavior, explicitly call `result.infer_objects(copy=False)`. To opt-in to the future behavior, set `pd.set_option('future.no_silent_downcasting', True)`\n", + " series = series.replace(ww.config.get_option(\"nan_values\"), np.nan)\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\featuretools\\computational_backends\\feature_set_calculator.py:143: FutureWarning: The behavior of DataFrame concatenation with empty or all-NA entries is deprecated. In a future version, this will no longer exclude empty or all-NA columns when determining the result dtypes. To retain the old behavior, exclude the relevant entries before the concat operation.\n", + " df = pd.concat([df, default_df], sort=True)\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\woodwork\\logical_types.py:841: FutureWarning: Downcasting behavior in `replace` is deprecated and will be removed in a future version. To retain the old behavior, explicitly call `result.infer_objects(copy=False)`. To opt-in to the future behavior, set `pd.set_option('future.no_silent_downcasting', True)`\n", + " series = series.replace(ww.config.get_option(\"nan_values\"), np.nan)\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\woodwork\\logical_types.py:841: FutureWarning: Downcasting behavior in `replace` is deprecated and will be removed in a future version. To retain the old behavior, explicitly call `result.infer_objects(copy=False)`. To opt-in to the future behavior, set `pd.set_option('future.no_silent_downcasting', True)`\n", + " series = series.replace(ww.config.get_option(\"nan_values\"), np.nan)\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\woodwork\\logical_types.py:841: FutureWarning: Downcasting behavior in `replace` is deprecated and will be removed in a future version. To retain the old behavior, explicitly call `result.infer_objects(copy=False)`. To opt-in to the future behavior, set `pd.set_option('future.no_silent_downcasting', True)`\n", + " series = series.replace(ww.config.get_option(\"nan_values\"), np.nan)\n" + ] + } + ], + "source": [ + "import featuretools as ft\n", + "\n", + "# Определение сущностей\n", + "es = ft.EntitySet(id='car_data')\n", + "es = es.add_dataframe(dataframe_name='cars', dataframe=train_data_encoded, index='id')\n", + "\n", + "# Генерация признаков\n", + "feature_matrix, feature_defs = ft.dfs(entityset=es, target_dataframe_name='cars', max_depth=2)\n", + "\n", + "# Преобразование признаков для контрольной и тестовой выборок\n", + "val_feature_matrix = ft.calculate_feature_matrix(features=feature_defs, entityset=es, instance_ids=val_data_encoded.index)\n", + "test_feature_matrix = ft.calculate_feature_matrix(features=feature_defs, entityset=es, instance_ids=test_data_encoded.index)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\metrics\\_regression.py:492: FutureWarning: 'squared' is deprecated in version 1.4 and will be removed in 1.6. To calculate the root mean squared error, use the function'root_mean_squared_error'.\n", + " warnings.warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "RMSE: 234661.34107821883\n", + "R²: 0.8029264507217629\n", + "MAE: 7964.677649030692\n", + "Cross-validated RMSE: 259310.71680259163\n", + "Train RMSE: 109324.02870848698\n", + "Train R²: 0.7887252013114727\n", + "Train MAE: 3471.173866063129\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\metrics\\_regression.py:492: FutureWarning: 'squared' is deprecated in version 1.4 and will be removed in 1.6. To calculate the root mean squared error, use the function'root_mean_squared_error'.\n", + " warnings.warn(\n" + ] + }, + { + "data": { + "image/png": "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ekm6cx7V/Pnzde7cOZ08edLcHhsbq969e+vMmTPKkiWLSpcurd9++83hOQAASO88PT21detWszSFhIRoypQpql+/vsXJACDzSvLiEN9++62aN28ub29vubu7KyoqSqNHj1afPn1SOmOycuYEMAAArLJt2zbVqVNHgwYNUs+ePTlfFwBSgDPdIMlnlI4aNUodO3ZUZGSkrl69qg8//FAjR4585LAAAGRm//zzjzp37nzXQkcVK1bUqVOn9O6771KaACANSPKMU9asWRUeHq5ChQpJunPYnI+Pj86cOaPAwMAUDZmcmHECAKQFCQkJmj17tgYOHKgrV66oTJky2r59u9zcnD79GADwkFJkxunmzZsOT+bh4SEvLy9FR0c/fFIAADKhLVu2qHLlyurcubOuXLkiSTp27Jj27dtncTIAwP049Wut2bNnK2vWrOb9+Ph4zZ8/X9mzZzfHUns5cgAA0ouLFy9qwIABmjt3rsN4q1atNGbMGC6vAQBpWJIP1cufP79sNtuDn8xm07Fjx5IlWErhUD0AQGqLj4/XzJkz9f777+vatWvmeKlSpTR9+nRVr17dunAAkIk50w2SPON04sSJR80FAECm1KVLF3366afmfT8/Pw0fPlxdunThnCYASCeSfI4TAAB4OGFhYXJxufNfbtu2bRUREaHu3btTmgAgHeEnNgAAySguLk5nzpxR/vz5zbHSpUtr/Pjxqly5sqpUqWJdOADAQ6M4AQCQTNauXauwsDAZhqHw8HB5eHiY23r27GldMADAI+NQPQAAHtHp06fVvHlzPfPMM9q/f78OHDigqVOnWh0LAJCMKE4AADyk2NhYjR49WkWLFtXXX39tjleqVEk1a9a0MBkAILkl6VC9qKioJD8hS3wDADKDX3/9Vd26dVNERIQ5lj17dn300Udq166duRgEACBjSFJxypYtW6LXcPpXQkLCIwUCACAtO336tHr06KGlS5eaYy4uLnr77bc1bNgwBQQEWJgOAJBSklSc1q5da/75xIkT6t+/v9q2bWuuDLR582Z99tlnGjVqVMqkBAAgjYiOjtby5cvN+1WrVtX06dMVGhpqXSgAQIqzGYZhOPOAOnXqqEOHDmrZsqXD+MKFCzVr1iz9/vvvyZkv2TlzdWAAAO6lX79++vzzzzVmzBi98cYbST4qAwCQtjjTDZwuTlmyZNHu3btV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169XYGBgSmVNFixHDiAzs9vtWrRokZo1ayZPT09zPCoqSlu2bFG9evUsTAcAQOpyphs4fahecHCwdu/ercWLF2v37t2Kjo5W+/bt9frrrzssFgEASFu2bdumrl27atu2bTp58qQGDBhgbvPz86M0AQDwAE7NOMXFxalo0aJasWKFihUrlpK5UgwzTgAym8uXL2vgwIGaPXu2/v2RnyVLFp08eVKPP/64xekAALBOil0A193dXbdv336kcACA1JGQkKAZM2YoJCREn376qVmaihcvrhUrVlCaAABwgtOLQ3Tt2lWjR4/mQogAkIZt3rxZlSpVUpcuXXT16lVJkq+vryZMmKDw8HDVrl3b4oQAAKQvTp/jtG3bNq1evVq//vqrSpUqJR8fH4ftS5cuTbZwAADndenSRTNmzHAYe+ONNzR69Gjlzp3bolQAAKRvThenbNmy6eWXX06JLACAZBAQEGD+uXTp0po+fbqefvppCxMBAJD+Ob0ceXrH4hAAMhrDMGSz2cz7N2/eVJUqVdSxY0d17txZbm5O/44MAIBMIUWWI7fb7Ro7dqyWL1+u2NhY1alTR4MHD2YJcgCwyLlz59S3b18VLFhQQ4cONcezZMmiXbt2ycXF6dNYAQDAfST5f9URI0Zo4MCBypo1q/LkyaPJkyera9euj/TF169fr8aNGysoKEg2m03fffddoo/5/fffVa5cOXl6eqpQoUKaP3/+I2UAgPQmLi5OEyZMUJEiRbRgwQKNHj1aR48eddiH0gQAQPJK8v+sn3/+uT7++GP98ssv+u677/TDDz9owYIFstvtD/3Fb9y4oTJlymj69OlJ2v/48eNq1KiRateurfDwcPXs2VMdOnTQL7/88tAZACA9Wbt2rUJDQ9W7d29dv35d0p0ZpoiICIuTAQCQsSX5HCdPT08dOXJEwcHB5piXl5eOHDmivHnzPnoQm03Lli1TkyZN7rvPu+++qx9//FH79u0zx1q0aKFr165p5cqVSfo6nOMEID06ffq0evfura+//tocs9ls6tixo0aMGKHs2bNbmA4AgPQpRS6AGx8fLy8vL4cxd3d3xcXFPVzKh7B582bVrVvXYax+/fravHnzfR8TExOjqKgohxsApBexsbEaPXq0ihYt6lCaKlWqpK1bt+qTTz6hNAEAkAqSvDiEYRhq27atPD09zbHbt2+rc+fODtdySsnrOJ0/f145c+Z0GMuZM6eioqJ069atey5UMWrUKIeTpgEgPfnkk0/Uv39/83727Nn10UcfqV27dpzHBABAKkry/7pt2rRRYGCg/P39zVurVq0UFBTkMJbWDBgwQJGRkebt1KlTVkcCgCTr2LGjChYsKBcXF3Xt2lURERFq3749pQkAgFSW5BmnefPmpWSOJMmVK5cuXLjgMHbhwgX5+fndd1l0T09Ph1kyAEirbt++rY0bN6pOnTrmmJeXlz777DP5+PgoNDTUunAAAGRy6epXllWqVNHq1asdxlatWqUqVapYlAgAksePP/6okiVLqkGDBjp48KDDtmrVqlGaAACwmKXFKTo6WuHh4QoPD5d0Z7nx8PBwnTx5UtKdw+xat25t7t+5c2cdO3ZM/fr108GDB/Xxxx/r66+/1jvvvGNFfAB4ZEePHlXjxo31/PPP6+jRo4qPj+dnGgAAaZClxWn79u0qW7asypYtK0nq1auXypYtqw8++ECSdO7cObNESVKBAgX0448/atWqVSpTpozGjx+v2bNnq379+pbkB4CHdfPmTX3wwQcqUaKEVqxYYY7XqFFDY8aMsTAZAAC4lyRfxymj4DpOAKxkGIa+//579ezZU3///bc5HhQUpHHjxqlFixay2WwWJgQAIPNwphskeXEIAMCjuXTpkt544w398ssv5pibm5veeecdvf/++/L19bUwHQAAeBCKEwCkkmzZsjkcflynTh1NnTpVxYoVszAVAABIinS1qh4ApGfu7u6aNm2agoOD9c0332jVqlWUJgAA0gmKEwCkgAMHDqh+/fravXu3w/gzzzyjw4cPq1mzZpzLBABAOsKhegCQjK5fv65hw4Zp0qRJio+P182bN7V+/XqHksRFuQEASH+YcQKAZGAYhhYuXKgiRYpo3Lhxio+PlySdPn1aZ86csTgdAAB4VBQnAHhEe/fuVa1atfT666/r3Llzku7MKg0ePFj79+9X3rx5LU4IAAAeFYfqAcBDunbtmoYMGaJp06YpISHBHH/hhRc0ceJEPfnkkxamAwAAyYniBAAPqUWLFg7XZCpYsKCmTJmihg0bWpgKAACkBA7VA4CH9P7770uSvL299eGHH2rfvn2UJgAAMihmnAAgCa5evap//vlHhQoVMseqVaum6dOnq1GjRsqXL5+F6QAAQEpjxgkAHsBut2v2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1K1bN61fv15nz561Oo5TGjRooHPnzunw4cPq3bu3hgwZorFjx95z39jYWElSjhw5lCVLltSMCQCZVlhYmDZv3qyvvvpKe/bs0SuvvKIGDRro8OHD99x/9uzZCgkJUfXq1Z36OhQnAECKio6O1uLFi/X222+rUaNGmj9//l37/PDDD6pYsaK8vLyUPXt287eKtWrV0t9//6133nnHnPmR7hyvHhoa6vAckyZNUv78+c3727Zt07PPPqvs2bPL399fNWvW1M6dO53O7+npqVy5cilfvnx6++23VbduXS1fvlzSnRmpJk2aaMSIEQoKClKRIkUk3T1Ldu3aNXXq1Ek5c+aUl5eXSpYsqRUrVpjbN2zYoOrVq8vb21vBwcHq3r27bty44XRWAMhsTp48qXnz5umbb75R9erVVbBgQfXp00dPP/205s2bd9f+t2/f1oIFC5yebZIoTgCAFPb111+raNGiKlKkiFq1aqW5c+fKMAxz+48//qimTZuqYcOG2rVrl1avXq1KlSpJkpYuXaq8efNq2LBh5nHpSXX9+nW1adNGGzZs0JYtW1S4cGE1bNhQ169ff6TX4+3tbc4sSdLq1at16NAhrVq1yqEM/ctut+u5557Txo0b9eWXX2r//v366KOP5OrqKkk6evSoGjRooJdffll79uzR4sWLtWHDBoWFhT1STgDIDPbu3auEhASFhIQoa9as5m3dunU6evToXfsvW7bM/P/BWW7JERgAgPuZM2eOWrVqJenOYW+RkZFat26datWqJUkaMWKEWrRooaFDh5qPKVOmjCQpICBArq6u8vX1Va5cuZz6us8884zD/VmzZilbtmxat26dnn/+eadfh2EYWr16tX755Rd169bNHPfx8dHs2bPl4eFxz8f99ttv2rp1qw4cOKCQkBBJ0pNPPmluHzVqlF5//XX17NlTklS4cGFNmTJFNWvW1IwZM+Tl5eV0VgDILKKjo+Xq6qodO3aYv5D6V9asWe/af/bs2Xr++eeVM2dOp78WxQkAkGIOHTqkrVu3atmyZZIkNzc3NW/eXHPmzDGLU3h4uDp27JjsX/vChQt677339Pvvv+vixYtKSEjQzZs3dfLkSaeeZ8WKFcqaNavi4uJkt9v12muvaciQIeb2UqVK3bc0SXdeX968ec3S9F+7d+/Wnj17tGDBAnPMMAzZ7XYdP35cxYoVcyovAGQmZcuWVUJCgi5evJjoOUvHjx/X2rVrzcOtnUVxAgCkmDlz5ig+Pl5BQUHmmGEY8vT01LRp0+Tv7y9vb2+nn9fFxcXhcD9JiouLc7jfpk0b/fPPP5o8ebLy5csnT09PValSxeEwu6SoXbu2ZsyYIQ8PDwUFBcnNzfG/zsSuA5LY64uOjlanTp3UvXv3u7Y98cQTTmUFgIwoOjpaR44cMe8fP35c4eHhCggIUEhIiF5//XW1bt1a48ePV9myZXXp0iWtXr1apUuXdljNde7cucqdO7eee+65h8pBcQIApIj4+Hh9/vnnGj9+vOrVq+ewrUmTJlq0aJE6d+6s0qVLa/Xq1WrXrt09n8fDw0MJCQkOYzly5ND58+dlGIa5YER4eLjDPhs3btTHH3+shg0bSpJOnTqly5cvO/06fHx8VKhQIacf96/SpUvr9OnTioiIuOesU7ly5bR///5H+hoAkJFt375dtWvXNu/36tVL0p1fkM2fP1/z5s3Thx9+qN69e+vMmTPKnj27nnrqKYfDsu12u+bPn6+2bdvedUhfUlGcAAApYsWKFbp69arat28vf39/h20vv/yy5syZo86dO2vw4MGqU6eOChYsqBYtWig+Pl4//fST3n33XUl3Vqhbv369WrRoIU9PT2XPnl21atXSpUuXNGbMGDVr1kwrV67Uzz//LD8/P/NrFC5cWF988YUqVKigqKgo9e3b96Fmtx5VzZo1VaNGDb388suaMGGCChUqpIMHD8pms6lBgwZ699139dRTTyksLEwdOnSQj4+P9u/fr1WrVmnatGmpnhcA0ppatWrddZTB/3J3d9fQoUMdzpX9LxcXF506deqRcrCqHgAgRcyZM0d169a9qzRJd4rT9u3btWfPHtWqVUvffPONli9frtDQUD3zzDPaunWrue+wYcN04sQJFSxYUDly5JAkFStWTB9//LGmT5+uMmXKaOvWrerTp89dX//q1asqV66c3njjDXXv3l2BgYEp+6LvY8mSJapYsaJatmyp4sWLq1+/fuYsWunSpbVu3TpFRESoevXqKlu2rD744AOHwxsBANazGQ+qbwAAAAAAZpwAAAAAIDEUJwAAAABIBMUJAAAAABJBcQIAAACARFCcAAAAACARFCcAAAAASATFCQAAAAASQXECAAAAgERQnAAAAAAgERQnAAAAAEgExQkAAAAAEvH/ADkyCDY9Et2KAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import pandas as pd\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.ensemble import RandomForestRegressor\n", + "from sklearn.metrics import mean_squared_error, r2_score, mean_absolute_error\n", + "from sklearn.model_selection import cross_val_score\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "\n", + "# Удаление строк с NaN\n", + "feature_matrix = feature_matrix.dropna()\n", + "val_feature_matrix = val_feature_matrix.dropna()\n", + "test_feature_matrix = test_feature_matrix.dropna()\n", + "\n", + "# Разделение данных на обучающую и тестовую выборки\n", + "X_train = feature_matrix.drop('Price', axis=1)\n", + "y_train = feature_matrix['Price']\n", + "X_val = val_feature_matrix.drop('Price', axis=1)\n", + "y_val = val_feature_matrix['Price']\n", + "X_test = test_feature_matrix.drop('Price', axis=1)\n", + "y_test = test_feature_matrix['Price']\n", + "\n", + "# Выбор модели\n", + "model = RandomForestRegressor(random_state=42)\n", + "\n", + "# Обучение модели\n", + "model.fit(X_train, y_train)\n", + "\n", + "# Предсказание и оценка\n", + "y_pred = model.predict(X_test)\n", + "\n", + "rmse = mean_squared_error(y_test, y_pred, squared=False)\n", + "r2 = r2_score(y_test, y_pred)\n", + "mae = mean_absolute_error(y_test, y_pred)\n", + "\n", + "print(f\"RMSE: {rmse}\")\n", + "print(f\"R²: {r2}\")\n", + "print(f\"MAE: {mae}\")\n", + "\n", + "# Кросс-валидация\n", + "scores = cross_val_score(model, X_train, y_train, cv=5, scoring='neg_mean_squared_error')\n", + "rmse_cv = (-scores.mean())**0.5\n", + "print(f\"Cross-validated RMSE: {rmse_cv}\")\n", + "\n", + "# Анализ важности признаков\n", + "feature_importances = model.feature_importances_\n", + "feature_names = X_train.columns\n", + "\n", + "# importance_df = pd.DataFrame({'Feature': feature_names, 'Importance': feature_importances})\n", + "# importance_df = importance_df.sort_values(by='Importance', ascending=False)\n", + "\n", + "# plt.figure(figsize=(10, 6))\n", + "# sns.barplot(x='Importance', y='Feature', data=importance_df)\n", + "# plt.title('Feature Importance')\n", + "# plt.show()\n", + "\n", + "# Проверка на переобучение\n", + "y_train_pred = model.predict(X_train)\n", + "\n", + "rmse_train = mean_squared_error(y_train, y_train_pred, squared=False)\n", + "r2_train = r2_score(y_train, y_train_pred)\n", + "mae_train = mean_absolute_error(y_train, y_train_pred)\n", + "\n", + "print(f\"Train RMSE: {rmse_train}\")\n", + "print(f\"Train R²: {r2_train}\")\n", + "print(f\"Train MAE: {mae_train}\")\n", + "\n", + "# Визуализация результатов\n", + "plt.figure(figsize=(10, 6))\n", + "plt.scatter(y_test, y_pred, alpha=0.5)\n", + "plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'k--', lw=2)\n", + "plt.xlabel('Actual Price')\n", + "plt.ylabel('Predicted Price')\n", + "plt.title('Actual vs Predicted Price')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Точность предсказаний: Модель показывает довольно высокий R² (0.8029), что указывает на хорошее объяснение вариации цен. Однако, значения RMSE и MAE довольно высоки, что говорит о том, что модель не очень точно предсказывает цены, особенно для высоких значений.\n", + "\n", + "Переобучение: Разница между RMSE на обучающей и тестовой выборках не очень большая, что указывает на то, что переобучение не является критическим. Однако, стоит быть осторожным и продолжать мониторинг этого показателя.\n", + "\n", + "Кросс-валидация: Значение RMSE после кросс-валидации немного выше, чем на тестовой выборке, что может указывать на некоторую нестабильность модели." + ] + } + ], + "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.12.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/lab_4/aimenv/Scripts/Activate.ps1 b/lab_4/aimenv/Scripts/Activate.ps1 new file mode 100644 index 0000000..3045241 --- /dev/null +++ b/lab_4/aimenv/Scripts/Activate.ps1 @@ -0,0 +1,502 @@ +<# +.Synopsis +Activate a Python virtual environment for the current PowerShell session. + +.Description +Pushes the python executable for a virtual environment to the front of the +$Env:PATH environment variable and sets the prompt to signify that you are +in a Python virtual environment. Makes use of the command line switches as +well as the `pyvenv.cfg` file values present in the virtual environment. + +.Parameter VenvDir +Path to the directory that contains the virtual environment to activate. The +default value for this is the parent of the directory that the Activate.ps1 +script is located within. + +.Parameter Prompt +The prompt prefix to display when this virtual environment is activated. By +default, this prompt is the name of the virtual environment folder (VenvDir) +surrounded by parentheses and followed by a single space (ie. '(.venv) '). + +.Example +Activate.ps1 +Activates the Python virtual environment that contains the Activate.ps1 script. + +.Example +Activate.ps1 -Verbose +Activates the Python virtual environment that contains the Activate.ps1 script, +and shows extra information about the activation as it executes. + +.Example +Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv +Activates the Python virtual environment located in the specified location. + +.Example +Activate.ps1 -Prompt "MyPython" +Activates the Python virtual environment that contains the Activate.ps1 script, +and prefixes the current prompt with the specified string (surrounded in +parentheses) while the virtual environment is active. + +.Notes +On Windows, it may be required to enable this Activate.ps1 script by setting the +execution policy for the user. You can do this by issuing the following PowerShell +command: + +PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser + +For more information on Execution Policies: +https://go.microsoft.com/fwlink/?LinkID=135170 + +#> +Param( + [Parameter(Mandatory = $false)] + [String] + $VenvDir, + [Parameter(Mandatory = $false)] + [String] + $Prompt +) + +<# Function declarations --------------------------------------------------- #> + +<# +.Synopsis +Remove all shell session elements added by the Activate script, including the +addition of the virtual environment's Python executable from the beginning of +the PATH variable. + +.Parameter NonDestructive +If present, do not remove this function from the global namespace for the +session. + +#> +function global:deactivate ([switch]$NonDestructive) { + # Revert to original values + + # The prior prompt: + if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) { + Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt + Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT + } + + # The prior PYTHONHOME: + if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) { + Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME + Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME + } + + # The prior PATH: + if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) { + Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH + Remove-Item -Path Env:_OLD_VIRTUAL_PATH + } + + # Just remove the VIRTUAL_ENV altogether: + if (Test-Path -Path Env:VIRTUAL_ENV) { + Remove-Item -Path env:VIRTUAL_ENV + } + + # Just remove VIRTUAL_ENV_PROMPT altogether. + if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) { + Remove-Item -Path env:VIRTUAL_ENV_PROMPT + } + + # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether: + if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) { + Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force + } + + # Leave deactivate function in the global namespace if requested: + if (-not $NonDestructive) { + Remove-Item -Path function:deactivate + } +} + +<# +.Description +Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the +given folder, and returns them in a map. + +For each line in the pyvenv.cfg file, if that line can be parsed into exactly +two strings separated by `=` (with any amount of whitespace surrounding the =) +then it is considered a `key = value` line. The left hand string is the key, +the right hand is the value. + +If the value starts with a `'` or a `"` then the first and last character is +stripped from the value before being captured. + +.Parameter ConfigDir +Path to the directory that contains the `pyvenv.cfg` file. +#> +function Get-PyVenvConfig( + [String] + $ConfigDir +) { + Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg" + + # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue). + $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue + + # An empty map will be returned if no config file is found. + $pyvenvConfig = @{ } + + if ($pyvenvConfigPath) { + + Write-Verbose "File exists, parse `key = value` lines" + $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath + + $pyvenvConfigContent | ForEach-Object { + $keyval = $PSItem -split "\s*=\s*", 2 + if ($keyval[0] -and $keyval[1]) { + $val = $keyval[1] + + # Remove extraneous quotations around a string value. + if ("'""".Contains($val.Substring(0, 1))) { + $val = $val.Substring(1, $val.Length - 2) + } + + $pyvenvConfig[$keyval[0]] = $val + Write-Verbose "Adding Key: '$($keyval[0])'='$val'" + } + } + } + return $pyvenvConfig +} + + +<# Begin Activate script --------------------------------------------------- #> + +# Determine the containing directory of this script +$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition +$VenvExecDir = Get-Item -Path $VenvExecPath + +Write-Verbose "Activation script is located in path: '$VenvExecPath'" +Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)" +Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)" + +# Set values required in priority: CmdLine, ConfigFile, Default +# First, get the location of the virtual environment, it might not be +# VenvExecDir if specified on the command line. +if ($VenvDir) { + Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values" +} +else { + Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir." + $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/") + Write-Verbose "VenvDir=$VenvDir" +} + +# Next, read the `pyvenv.cfg` file to determine any required value such +# as `prompt`. +$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir + +# Next, set the prompt from the command line, or the config file, or +# just use the name of the virtual environment folder. +if ($Prompt) { + Write-Verbose "Prompt specified as argument, using '$Prompt'" +} +else { + Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value" + if ($pyvenvCfg -and $pyvenvCfg['prompt']) { + Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'" + $Prompt = $pyvenvCfg['prompt']; + } + else { + Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)" + Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'" + $Prompt = Split-Path -Path $venvDir -Leaf + } +} + +Write-Verbose "Prompt = '$Prompt'" +Write-Verbose "VenvDir='$VenvDir'" + +# Deactivate any currently active virtual environment, but leave the +# deactivate function in place. +deactivate -nondestructive + +# Now set the environment variable VIRTUAL_ENV, used by many tools to determine +# that there is an activated venv. +$env:VIRTUAL_ENV = $VenvDir + +if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) { + + Write-Verbose "Setting prompt to '$Prompt'" + + # Set the prompt to include the env name + # Make sure _OLD_VIRTUAL_PROMPT is global + function global:_OLD_VIRTUAL_PROMPT { "" } + Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT + New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt + + function global:prompt { + Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) " + _OLD_VIRTUAL_PROMPT + } + $env:VIRTUAL_ENV_PROMPT = $Prompt +} + +# Clear PYTHONHOME +if (Test-Path -Path Env:PYTHONHOME) { + Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME + Remove-Item -Path Env:PYTHONHOME +} + +# Add the venv to the PATH +Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH +$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH" + +# SIG # Begin signature block +# MIIvIwYJKoZIhvcNAQcCoIIvFDCCLxACAQExDzANBglghkgBZQMEAgEFADB5Bgor +# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG +# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBnL745ElCYk8vk +# dBtMuQhLeWJ3ZGfzKW4DHCYzAn+QB6CCE8MwggWQMIIDeKADAgECAhAFmxtXno4h +# MuI5B72nd3VcMA0GCSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK +# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNV +# BAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0xMzA4MDExMjAwMDBaFw0z +# ODAxMTUxMjAwMDBaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ +# bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0 +# IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB +# AL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3EMB/z +# G6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKyunWZ +# anMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsFxl7s +# Wxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU15zHL +# 2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJBMtfb +# BHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObURWBf3 +# JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6nj3c +# AORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxBYKqx +# YxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5SUUd0 +# viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+xq4aL +# T8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjQjBAMA8GA1Ud +# EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTs1+OC0nFdZEzf +# Lmc/57qYrhwPTzANBgkqhkiG9w0BAQwFAAOCAgEAu2HZfalsvhfEkRvDoaIAjeNk +# aA9Wz3eucPn9mkqZucl4XAwMX+TmFClWCzZJXURj4K2clhhmGyMNPXnpbWvWVPjS +# PMFDQK4dUPVS/JA7u5iZaWvHwaeoaKQn3J35J64whbn2Z006Po9ZOSJTROvIXQPK +# 7VB6fWIhCoDIc2bRoAVgX+iltKevqPdtNZx8WorWojiZ83iL9E3SIAveBO6Mm0eB +# cg3AFDLvMFkuruBx8lbkapdvklBtlo1oepqyNhR6BvIkuQkRUNcIsbiJeoQjYUIp +# 5aPNoiBB19GcZNnqJqGLFNdMGbJQQXE9P01wI4YMStyB0swylIQNCAmXHE/A7msg +# dDDS4Dk0EIUhFQEI6FUy3nFJ2SgXUE3mvk3RdazQyvtBuEOlqtPDBURPLDab4vri +# RbgjU2wGb2dVf0a1TD9uKFp5JtKkqGKX0h7i7UqLvBv9R0oN32dmfrJbQdA75PQ7 +# 9ARj6e/CVABRoIoqyc54zNXqhwQYs86vSYiv85KZtrPmYQ/ShQDnUBrkG5WdGaG5 +# nLGbsQAe79APT0JsyQq87kP6OnGlyE0mpTX9iV28hWIdMtKgK1TtmlfB2/oQzxm3 +# i0objwG2J5VT6LaJbVu8aNQj6ItRolb58KaAoNYes7wPD1N1KarqE3fk3oyBIa0H +# EEcRrYc9B9F1vM/zZn4wggawMIIEmKADAgECAhAIrUCyYNKcTJ9ezam9k67ZMA0G +# CSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ +# bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0 +# IFRydXN0ZWQgUm9vdCBHNDAeFw0yMTA0MjkwMDAwMDBaFw0zNjA0MjgyMzU5NTla +# MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UE +# AxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEz +# ODQgMjAyMSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDVtC9C +# 0CiteLdd1TlZG7GIQvUzjOs9gZdwxbvEhSYwn6SOaNhc9es0JAfhS0/TeEP0F9ce +# 2vnS1WcaUk8OoVf8iJnBkcyBAz5NcCRks43iCH00fUyAVxJrQ5qZ8sU7H/Lvy0da +# E6ZMswEgJfMQ04uy+wjwiuCdCcBlp/qYgEk1hz1RGeiQIXhFLqGfLOEYwhrMxe6T +# SXBCMo/7xuoc82VokaJNTIIRSFJo3hC9FFdd6BgTZcV/sk+FLEikVoQ11vkunKoA +# FdE3/hoGlMJ8yOobMubKwvSnowMOdKWvObarYBLj6Na59zHh3K3kGKDYwSNHR7Oh +# D26jq22YBoMbt2pnLdK9RBqSEIGPsDsJ18ebMlrC/2pgVItJwZPt4bRc4G/rJvmM +# 1bL5OBDm6s6R9b7T+2+TYTRcvJNFKIM2KmYoX7BzzosmJQayg9Rc9hUZTO1i4F4z +# 8ujo7AqnsAMrkbI2eb73rQgedaZlzLvjSFDzd5Ea/ttQokbIYViY9XwCFjyDKK05 +# huzUtw1T0PhH5nUwjewwk3YUpltLXXRhTT8SkXbev1jLchApQfDVxW0mdmgRQRNY +# mtwmKwH0iU1Z23jPgUo+QEdfyYFQc4UQIyFZYIpkVMHMIRroOBl8ZhzNeDhFMJlP +# /2NPTLuqDQhTQXxYPUez+rbsjDIJAsxsPAxWEQIDAQABo4IBWTCCAVUwEgYDVR0T +# AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUaDfg67Y7+F8Rhvv+YXsIiGX0TkIwHwYD +# VR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMG +# A1UdJQQMMAoGCCsGAQUFBwMDMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYY +# aHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2Fj +# ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNV +# HR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRU +# cnVzdGVkUm9vdEc0LmNybDAcBgNVHSAEFTATMAcGBWeBDAEDMAgGBmeBDAEEATAN +# BgkqhkiG9w0BAQwFAAOCAgEAOiNEPY0Idu6PvDqZ01bgAhql+Eg08yy25nRm95Ry +# sQDKr2wwJxMSnpBEn0v9nqN8JtU3vDpdSG2V1T9J9Ce7FoFFUP2cvbaF4HZ+N3HL +# IvdaqpDP9ZNq4+sg0dVQeYiaiorBtr2hSBh+3NiAGhEZGM1hmYFW9snjdufE5Btf +# Q/g+lP92OT2e1JnPSt0o618moZVYSNUa/tcnP/2Q0XaG3RywYFzzDaju4ImhvTnh +# OE7abrs2nfvlIVNaw8rpavGiPttDuDPITzgUkpn13c5UbdldAhQfQDN8A+KVssIh +# dXNSy0bYxDQcoqVLjc1vdjcshT8azibpGL6QB7BDf5WIIIJw8MzK7/0pNVwfiThV +# 9zeKiwmhywvpMRr/LhlcOXHhvpynCgbWJme3kuZOX956rEnPLqR0kq3bPKSchh/j +# wVYbKyP/j7XqiHtwa+aguv06P0WmxOgWkVKLQcBIhEuWTatEQOON8BUozu3xGFYH +# Ki8QxAwIZDwzj64ojDzLj4gLDb879M4ee47vtevLt/B3E+bnKD+sEq6lLyJsQfmC +# XBVmzGwOysWGw/YmMwwHS6DTBwJqakAwSEs0qFEgu60bhQjiWQ1tygVQK+pKHJ6l +# /aCnHwZ05/LWUpD9r4VIIflXO7ScA+2GRfS0YW6/aOImYIbqyK+p/pQd52MbOoZW +# eE4wggd3MIIFX6ADAgECAhAHHxQbizANJfMU6yMM0NHdMA0GCSqGSIb3DQEBCwUA +# MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UE +# AxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEz +# ODQgMjAyMSBDQTEwHhcNMjIwMTE3MDAwMDAwWhcNMjUwMTE1MjM1OTU5WjB8MQsw +# CQYDVQQGEwJVUzEPMA0GA1UECBMGT3JlZ29uMRIwEAYDVQQHEwlCZWF2ZXJ0b24x +# IzAhBgNVBAoTGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9uMSMwIQYDVQQDExpQ +# eXRob24gU29mdHdhcmUgRm91bmRhdGlvbjCCAiIwDQYJKoZIhvcNAQEBBQADggIP +# ADCCAgoCggIBAKgc0BTT+iKbtK6f2mr9pNMUTcAJxKdsuOiSYgDFfwhjQy89koM7 +# uP+QV/gwx8MzEt3c9tLJvDccVWQ8H7mVsk/K+X+IufBLCgUi0GGAZUegEAeRlSXx +# xhYScr818ma8EvGIZdiSOhqjYc4KnfgfIS4RLtZSrDFG2tN16yS8skFa3IHyvWdb +# D9PvZ4iYNAS4pjYDRjT/9uzPZ4Pan+53xZIcDgjiTwOh8VGuppxcia6a7xCyKoOA +# GjvCyQsj5223v1/Ig7Dp9mGI+nh1E3IwmyTIIuVHyK6Lqu352diDY+iCMpk9Zanm +# SjmB+GMVs+H/gOiofjjtf6oz0ki3rb7sQ8fTnonIL9dyGTJ0ZFYKeb6BLA66d2GA +# LwxZhLe5WH4Np9HcyXHACkppsE6ynYjTOd7+jN1PRJahN1oERzTzEiV6nCO1M3U1 +# HbPTGyq52IMFSBM2/07WTJSbOeXjvYR7aUxK9/ZkJiacl2iZI7IWe7JKhHohqKuc +# eQNyOzxTakLcRkzynvIrk33R9YVqtB4L6wtFxhUjvDnQg16xot2KVPdfyPAWd81w +# tZADmrUtsZ9qG79x1hBdyOl4vUtVPECuyhCxaw+faVjumapPUnwo8ygflJJ74J+B +# Yxf6UuD7m8yzsfXWkdv52DjL74TxzuFTLHPyARWCSCAbzn3ZIly+qIqDAgMBAAGj +# ggIGMIICAjAfBgNVHSMEGDAWgBRoN+Drtjv4XxGG+/5hewiIZfROQjAdBgNVHQ4E +# FgQUt/1Teh2XDuUj2WW3siYWJgkZHA8wDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQM +# MAoGCCsGAQUFBwMDMIG1BgNVHR8Ega0wgaowU6BRoE+GTWh0dHA6Ly9jcmwzLmRp +# Z2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENvZGVTaWduaW5nUlNBNDA5NlNI +# QTM4NDIwMjFDQTEuY3JsMFOgUaBPhk1odHRwOi8vY3JsNC5kaWdpY2VydC5jb20v +# RGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEzODQyMDIxQ0Ex +# LmNybDA+BgNVHSAENzA1MDMGBmeBDAEEATApMCcGCCsGAQUFBwIBFhtodHRwOi8v +# d3d3LmRpZ2ljZXJ0LmNvbS9DUFMwgZQGCCsGAQUFBwEBBIGHMIGEMCQGCCsGAQUF +# BzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wXAYIKwYBBQUHMAKGUGh0dHA6 +# Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENvZGVTaWdu +# aW5nUlNBNDA5NlNIQTM4NDIwMjFDQTEuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZI +# hvcNAQELBQADggIBABxv4AeV/5ltkELHSC63fXAFYS5tadcWTiNc2rskrNLrfH1N +# s0vgSZFoQxYBFKI159E8oQQ1SKbTEubZ/B9kmHPhprHya08+VVzxC88pOEvz68nA +# 82oEM09584aILqYmj8Pj7h/kmZNzuEL7WiwFa/U1hX+XiWfLIJQsAHBla0i7QRF2 +# de8/VSF0XXFa2kBQ6aiTsiLyKPNbaNtbcucaUdn6vVUS5izWOXM95BSkFSKdE45O +# q3FForNJXjBvSCpwcP36WklaHL+aHu1upIhCTUkzTHMh8b86WmjRUqbrnvdyR2yd +# I5l1OqcMBjkpPpIV6wcc+KY/RH2xvVuuoHjlUjwq2bHiNoX+W1scCpnA8YTs2d50 +# jDHUgwUo+ciwpffH0Riq132NFmrH3r67VaN3TuBxjI8SIZM58WEDkbeoriDk3hxU +# 8ZWV7b8AW6oyVBGfM06UgkfMb58h+tJPrFx8VI/WLq1dTqMfZOm5cuclMnUHs2uq +# rRNtnV8UfidPBL4ZHkTcClQbCoz0UbLhkiDvIS00Dn+BBcxw/TKqVL4Oaz3bkMSs +# M46LciTeucHY9ExRVt3zy7i149sd+F4QozPqn7FrSVHXmem3r7bjyHTxOgqxRCVa +# 18Vtx7P/8bYSBeS+WHCKcliFCecspusCDSlnRUjZwyPdP0VHxaZg2unjHY3rMYIa +# tjCCGrICAQEwfTBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIElu +# Yy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgQ29kZSBTaWduaW5nIFJT +# QTQwOTYgU0hBMzg0IDIwMjEgQ0ExAhAHHxQbizANJfMU6yMM0NHdMA0GCWCGSAFl +# AwQCAQUAoIHIMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcC +# AQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCBnAZ6P7YvTwq0fbF62 +# o7E75R0LxsW5OtyYiFESQckLhjBcBgorBgEEAYI3AgEMMU4wTKBGgEQAQgB1AGkA +# bAB0ADoAIABSAGUAbABlAGEAcwBlAF8AdgAzAC4AMQAyAC4ANQBfADIAMAAyADQA +# MAA4ADAANgAuADAAMaECgAAwDQYJKoZIhvcNAQEBBQAEggIAoXbLeBCFQhwr4rTK +# R0WSySG7AtpuY1n5vhwkJPE0JgQ11PFJYphroU2ouWWM8ifejqa6m21JEWGjC9En +# Rpzpe1+eps7ClsdO+y5NxZc/3vD1j7IddJdzZh77QqDFMqJEeDNY+00OxxnnhbN1 +# wJk29w8qRyIJ7HpCM0E5b8R8Atooip5ihAgrdrIsyyA3Mnl5Y+YMdqtQYe4QtOhE +# QcEoxAMoI5nLSGsbLhEM8CArl36EmX31eHTVMRJMaM98p0DkURHL030ALmW2V70h +# M7ovmhOezFyndR1d3HtcfwRB3nr5vHWZe6ythZ3wVgpsN++RdDOvHjb9LC9lkth/ +# BGbcmVqsA9ZHnub1iPt89GsQBSiXjaOnWUxgJi0Qd3s2pwswLxHp05QDUE/d8EF7 +# Wy6aNPI43+G2BjPLVeM3iVbMWd/yxhH6pddaVPAMKVvxJoJ7PfDLihMNyonHt0on +# xuaM5r2KaVMWpHIkgLiB9tyvdIQb0IW+YU05VAnOqh7CDaEtP7jM6P0usxY9ufEC +# BFZnOGb3M/c4KbcOuHOIkY3jGqw+DLZFrcWiIe2wbi2TsXDixs+pz8vm/KQczrQ2 +# RJ1R8jrbK7IIRyZmTYf+dStZG3NhNQn1xcPYraHKNOm9CzNmeXJTdfAe0BEApqUN +# 9AiLj6uvSEp278ysr/EE3ayw2Qmhghc/MIIXOwYKKwYBBAGCNwMDATGCFyswghcn +# BgkqhkiG9w0BBwKgghcYMIIXFAIBAzEPMA0GCWCGSAFlAwQCAQUAMHcGCyqGSIb3 +# DQEJEAEEoGgEZjBkAgEBBglghkgBhv1sBwEwMTANBglghkgBZQMEAgEFAAQgpuSq +# fyINa45wSs5Sa6msoQk+zCLDcSK24OqaBM/0/2cCEFtb0VJATq3jxU9l7ewmqjcY +# DzIwMjQwODA2MjEwMDM5WqCCEwkwggbCMIIEqqADAgECAhAFRK/zlJ0IOaa/2z9f +# 5WEWMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdp +# Q2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2 +# IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0EwHhcNMjMwNzE0MDAwMDAwWhcNMzQxMDEz +# MjM1OTU5WjBIMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4x +# IDAeBgNVBAMTF0RpZ2lDZXJ0IFRpbWVzdGFtcCAyMDIzMIICIjANBgkqhkiG9w0B +# AQEFAAOCAg8AMIICCgKCAgEAo1NFhx2DjlusPlSzI+DPn9fl0uddoQ4J3C9Io5d6 +# OyqcZ9xiFVjBqZMRp82qsmrdECmKHmJjadNYnDVxvzqX65RQjxwg6seaOy+WZuNp +# 52n+W8PWKyAcwZeUtKVQgfLPywemMGjKg0La/H8JJJSkghraarrYO8pd3hkYhftF +# 6g1hbJ3+cV7EBpo88MUueQ8bZlLjyNY+X9pD04T10Mf2SC1eRXWWdf7dEKEbg8G4 +# 5lKVtUfXeCk5a+B4WZfjRCtK1ZXO7wgX6oJkTf8j48qG7rSkIWRw69XloNpjsy7p +# Be6q9iT1HbybHLK3X9/w7nZ9MZllR1WdSiQvrCuXvp/k/XtzPjLuUjT71Lvr1KAs +# NJvj3m5kGQc3AZEPHLVRzapMZoOIaGK7vEEbeBlt5NkP4FhB+9ixLOFRr7StFQYU +# 6mIIE9NpHnxkTZ0P387RXoyqq1AVybPKvNfEO2hEo6U7Qv1zfe7dCv95NBB+plwK +# WEwAPoVpdceDZNZ1zY8SdlalJPrXxGshuugfNJgvOuprAbD3+yqG7HtSOKmYCaFx +# smxxrz64b5bV4RAT/mFHCoz+8LbH1cfebCTwv0KCyqBxPZySkwS0aXAnDU+3tTbR +# yV8IpHCj7ArxES5k4MsiK8rxKBMhSVF+BmbTO77665E42FEHypS34lCh8zrTioPL +# QHsCAwEAAaOCAYswggGHMA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBYG +# A1UdJQEB/wQMMAoGCCsGAQUFBwMIMCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsGCWCG +# SAGG/WwHATAfBgNVHSMEGDAWgBS6FtltTYUvcyl2mi91jGogj57IbzAdBgNVHQ4E +# FgQUpbbvE+fvzdBkodVWqWUxo97V40kwWgYDVR0fBFMwUTBPoE2gS4ZJaHR0cDov +# L2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0UlNBNDA5NlNIQTI1 +# NlRpbWVTdGFtcGluZ0NBLmNybDCBkAYIKwYBBQUHAQEEgYMwgYAwJAYIKwYBBQUH +# MAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBYBggrBgEFBQcwAoZMaHR0cDov +# L2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0UlNBNDA5NlNI +# QTI1NlRpbWVTdGFtcGluZ0NBLmNydDANBgkqhkiG9w0BAQsFAAOCAgEAgRrW3qCp +# tZgXvHCNT4o8aJzYJf/LLOTN6l0ikuyMIgKpuM+AqNnn48XtJoKKcS8Y3U623mzX +# 4WCcK+3tPUiOuGu6fF29wmE3aEl3o+uQqhLXJ4Xzjh6S2sJAOJ9dyKAuJXglnSoF +# eoQpmLZXeY/bJlYrsPOnvTcM2Jh2T1a5UsK2nTipgedtQVyMadG5K8TGe8+c+nji +# kxp2oml101DkRBK+IA2eqUTQ+OVJdwhaIcW0z5iVGlS6ubzBaRm6zxbygzc0brBB +# Jt3eWpdPM43UjXd9dUWhpVgmagNF3tlQtVCMr1a9TMXhRsUo063nQwBw3syYnhmJ +# A+rUkTfvTVLzyWAhxFZH7doRS4wyw4jmWOK22z75X7BC1o/jF5HRqsBV44a/rCcs +# QdCaM0qoNtS5cpZ+l3k4SF/Kwtw9Mt911jZnWon49qfH5U81PAC9vpwqbHkB3NpE +# 5jreODsHXjlY9HxzMVWggBHLFAx+rrz+pOt5Zapo1iLKO+uagjVXKBbLafIymrLS +# 2Dq4sUaGa7oX/cR3bBVsrquvczroSUa31X/MtjjA2Owc9bahuEMs305MfR5ocMB3 +# CtQC4Fxguyj/OOVSWtasFyIjTvTs0xf7UGv/B3cfcZdEQcm4RtNsMnxYL2dHZeUb +# c7aZ+WssBkbvQR7w8F/g29mtkIBEr4AQQYowggauMIIElqADAgECAhAHNje3JFR8 +# 2Ees/ShmKl5bMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK +# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNV +# BAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0yMjAzMjMwMDAwMDBaFw0z +# NzAzMjIyMzU5NTlaMGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg +# SW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1 +# NiBUaW1lU3RhbXBpbmcgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +# AQDGhjUGSbPBPXJJUVXHJQPE8pE3qZdRodbSg9GeTKJtoLDMg/la9hGhRBVCX6SI +# 82j6ffOciQt/nR+eDzMfUBMLJnOWbfhXqAJ9/UO0hNoR8XOxs+4rgISKIhjf69o9 +# xBd/qxkrPkLcZ47qUT3w1lbU5ygt69OxtXXnHwZljZQp09nsad/ZkIdGAHvbREGJ +# 3HxqV3rwN3mfXazL6IRktFLydkf3YYMZ3V+0VAshaG43IbtArF+y3kp9zvU5Emfv +# DqVjbOSmxR3NNg1c1eYbqMFkdECnwHLFuk4fsbVYTXn+149zk6wsOeKlSNbwsDET +# qVcplicu9Yemj052FVUmcJgmf6AaRyBD40NjgHt1biclkJg6OBGz9vae5jtb7IHe +# IhTZgirHkr+g3uM+onP65x9abJTyUpURK1h0QCirc0PO30qhHGs4xSnzyqqWc0Jo +# n7ZGs506o9UD4L/wojzKQtwYSH8UNM/STKvvmz3+DrhkKvp1KCRB7UK/BZxmSVJQ +# 9FHzNklNiyDSLFc1eSuo80VgvCONWPfcYd6T/jnA+bIwpUzX6ZhKWD7TA4j+s4/T +# Xkt2ElGTyYwMO1uKIqjBJgj5FBASA31fI7tk42PgpuE+9sJ0sj8eCXbsq11GdeJg +# o1gJASgADoRU7s7pXcheMBK9Rp6103a50g5rmQzSM7TNsQIDAQABo4IBXTCCAVkw +# EgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUuhbZbU2FL3MpdpovdYxqII+e +# yG8wHwYDVR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQD +# AgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMIMHcGCCsGAQUFBwEBBGswaTAkBggrBgEF +# BQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRw +# Oi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNy +# dDBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGln +# aUNlcnRUcnVzdGVkUm9vdEc0LmNybDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglg +# hkgBhv1sBwEwDQYJKoZIhvcNAQELBQADggIBAH1ZjsCTtm+YqUQiAX5m1tghQuGw +# GC4QTRPPMFPOvxj7x1Bd4ksp+3CKDaopafxpwc8dB+k+YMjYC+VcW9dth/qEICU0 +# MWfNthKWb8RQTGIdDAiCqBa9qVbPFXONASIlzpVpP0d3+3J0FNf/q0+KLHqrhc1D +# X+1gtqpPkWaeLJ7giqzl/Yy8ZCaHbJK9nXzQcAp876i8dU+6WvepELJd6f8oVInw +# 1YpxdmXazPByoyP6wCeCRK6ZJxurJB4mwbfeKuv2nrF5mYGjVoarCkXJ38SNoOeY +# +/umnXKvxMfBwWpx2cYTgAnEtp/Nh4cku0+jSbl3ZpHxcpzpSwJSpzd+k1OsOx0I +# SQ+UzTl63f8lY5knLD0/a6fxZsNBzU+2QJshIUDQtxMkzdwdeDrknq3lNHGS1yZr +# 5Dhzq6YBT70/O3itTK37xJV77QpfMzmHQXh6OOmc4d0j/R0o08f56PGYX/sr2H7y +# Rp11LB4nLCbbbxV7HhmLNriT1ObyF5lZynDwN7+YAN8gFk8n+2BnFqFmut1VwDop +# hrCYoCvtlUG3OtUVmDG0YgkPCr2B2RP+v6TR81fZvAT6gt4y3wSJ8ADNXcL50CN/ +# AAvkdgIm2fBldkKmKYcJRyvmfxqkhQ/8mJb2VVQrH4D6wPIOK+XW+6kvRBVK5xMO +# Hds3OBqhK/bt1nz8MIIFjTCCBHWgAwIBAgIQDpsYjvnQLefv21DiCEAYWjANBgkq +# hkiG9w0BAQwFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5j +# MRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBB +# c3N1cmVkIElEIFJvb3QgQ0EwHhcNMjIwODAxMDAwMDAwWhcNMzExMTA5MjM1OTU5 +# WjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL +# ExB3d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJv +# b3QgRzQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1K +# PDAiMGkz7MKnJS7JIT3yithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2r +# snnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C +# 8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBf +# sXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY +# QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8 +# rhsDdV14Ztk6MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaY +# dj1ZXUJ2h4mXaXpI8OCiEhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+ +# wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw +# ++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+N +# P8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7F +# wI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo4IBOjCCATYwDwYDVR0TAQH/BAUw +# AwEB/zAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wHwYDVR0jBBgwFoAU +# Reuir/SSy4IxLVGLp6chnfNtyA8wDgYDVR0PAQH/BAQDAgGGMHkGCCsGAQUFBwEB +# BG0wazAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsG +# AQUFBzAChjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1 +# cmVkSURSb290Q0EuY3J0MEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRp +# Z2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwEQYDVR0gBAow +# CDAGBgRVHSAAMA0GCSqGSIb3DQEBDAUAA4IBAQBwoL9DXFXnOF+go3QbPbYW1/e/ +# Vwe9mqyhhyzshV6pGrsi+IcaaVQi7aSId229GhT0E0p6Ly23OO/0/4C5+KH38nLe +# JLxSA8hO0Cre+i1Wz/n096wwepqLsl7Uz9FDRJtDIeuWcqFItJnLnU+nBgMTdydE +# 1Od/6Fmo8L8vC6bp8jQ87PcDx4eo0kxAGTVGamlUsLihVo7spNU96LHc/RzY9Hda +# XFSMb++hUD38dglohJ9vytsgjTVgHAIDyyCwrFigDkBjxZgiwbJZ9VVrzyerbHbO +# byMt9H5xaiNrIv8SuFQtJ37YOtnwtoeW/VvRXKwYw02fc7cBqZ9Xql4o4rmUMYID +# djCCA3ICAQEwdzBjMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIElu +# Yy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0ZWQgRzQgUlNBNDA5NiBTSEEyNTYg +# VGltZVN0YW1waW5nIENBAhAFRK/zlJ0IOaa/2z9f5WEWMA0GCWCGSAFlAwQCAQUA +# oIHRMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAcBgkqhkiG9w0BCQUxDxcN +# MjQwODA2MjEwMDM5WjArBgsqhkiG9w0BCRACDDEcMBowGDAWBBRm8CsywsLJD4Jd +# zqqKycZPGZzPQDAvBgkqhkiG9w0BCQQxIgQglCIBxGudJQwqEBh+XAoT3nqSoAuS +# uMjmJTX95zFjdk0wNwYLKoZIhvcNAQkQAi8xKDAmMCQwIgQg0vbkbe10IszR1EBX +# aEE2b4KK2lWarjMWr00amtQMeCgwDQYJKoZIhvcNAQEBBQAEggIAOkILAZviyFOU +# Qzt10RYNFHl0zO4rgXcR5oCeJlU1n9y+DwjCTvcrax9qdkEuiEJWDewXbak3TPQK +# 0ts7jhUIFMDTEn8GZXysruzDlYNLstKM4RbYIK+f2772phehvABS5mn70+L63GXe +# A5UFYM5M7BAvEY+3DKEwUnN9lAl8YKi1xS545MXYm1B96gI/7oEBDkNV2DoNIZAw +# R2B4wPTcpI2aG5zZ0jFgVtq8bOXLZ9b9pBrhKbf4PZWxPqAFwUtZryQKdt770u3Y +# l0WR2SgemKq4aOEvajD1J4fC56lnUoekXt4yH8/fBueCXYx+ADoEkU4/ota7C1oL +# aCZE4G0iQOH9XFtMUjA87oEPisJG63onir6tsurTjjm/wK8VnFQBSii4ILtfSOfR +# kDMsu7kS0H5SWliY3sPlDTn4Kwl14EThMmyXUr7SFFHnsibHtfLATTmV6XyeJ03l +# BmwDl8hdzt5G0pjH/u3bTFcdJu7J0RQuGYgpmNsVYjHCQnZDrJjzIE2os/QYgL6D +# B/ZYSv96jnYs6cFd93R0ixZMsQPQKcs2gbVYz3nymJL7t605LzW86tENmORsUdgm +# qh0ky+qe/+D/f88WLLjdHi/xfskiFKEL66Y4EWkECoUUMBRcJlIg1GszTCVmwD1N +# foIJo8CaFGMoR+QHwDeamNbOOlrCFMQ= +# SIG # End signature block diff --git a/lab_4/aimenv/Scripts/activate b/lab_4/aimenv/Scripts/activate new file mode 100644 index 0000000..8cf30bf --- /dev/null +++ b/lab_4/aimenv/Scripts/activate @@ -0,0 +1,70 @@ +# This file must be used with "source bin/activate" *from bash* +# You cannot run it directly + +deactivate () { + # reset old environment variables + if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then + PATH="${_OLD_VIRTUAL_PATH:-}" + export PATH + unset _OLD_VIRTUAL_PATH + fi + if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then + PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}" + export PYTHONHOME + unset _OLD_VIRTUAL_PYTHONHOME + fi + + # Call hash to forget past commands. Without forgetting + # past commands the $PATH changes we made may not be respected + hash -r 2> /dev/null + + if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then + PS1="${_OLD_VIRTUAL_PS1:-}" + export PS1 + unset _OLD_VIRTUAL_PS1 + fi + + unset VIRTUAL_ENV + unset VIRTUAL_ENV_PROMPT + if [ ! "${1:-}" = "nondestructive" ] ; then + # Self destruct! + unset -f deactivate + fi +} + +# unset irrelevant variables +deactivate nondestructive + +# on Windows, a path can contain colons and backslashes and has to be converted: +if [ "${OSTYPE:-}" = "cygwin" ] || [ "${OSTYPE:-}" = "msys" ] ; then + # transform D:\path\to\venv to /d/path/to/venv on MSYS + # and to /cygdrive/d/path/to/venv on Cygwin + export VIRTUAL_ENV=$(cygpath "C:\Users\Egor\Desktop\ULSTU\AI\aim\aimenv") +else + # use the path as-is + export VIRTUAL_ENV="C:\Users\Egor\Desktop\ULSTU\AI\aim\aimenv" +fi + +_OLD_VIRTUAL_PATH="$PATH" +PATH="$VIRTUAL_ENV/Scripts:$PATH" +export PATH + +# unset PYTHONHOME if set +# this will fail if PYTHONHOME is set to the empty string (which is bad anyway) +# could use `if (set -u; : $PYTHONHOME) ;` in bash +if [ -n "${PYTHONHOME:-}" ] ; then + _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}" + unset PYTHONHOME +fi + +if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then + _OLD_VIRTUAL_PS1="${PS1:-}" + PS1="(aimenv) ${PS1:-}" + export PS1 + VIRTUAL_ENV_PROMPT="(aimenv) " + export VIRTUAL_ENV_PROMPT +fi + +# Call hash to forget past commands. Without forgetting +# past commands the $PATH changes we made may not be respected +hash -r 2> /dev/null diff --git a/lab_4/aimenv/Scripts/activate.bat b/lab_4/aimenv/Scripts/activate.bat new file mode 100644 index 0000000..11bc012 --- /dev/null +++ b/lab_4/aimenv/Scripts/activate.bat @@ -0,0 +1,34 @@ +@echo off + +rem This file is UTF-8 encoded, so we need to update the current code page while executing it +for /f "tokens=2 delims=:." %%a in ('"%SystemRoot%\System32\chcp.com"') do ( + set _OLD_CODEPAGE=%%a +) +if defined _OLD_CODEPAGE ( + "%SystemRoot%\System32\chcp.com" 65001 > nul +) + +set VIRTUAL_ENV=C:\Users\Egor\Desktop\ULSTU\AI\aim\aimenv + +if not defined PROMPT set PROMPT=$P$G + +if defined _OLD_VIRTUAL_PROMPT set PROMPT=%_OLD_VIRTUAL_PROMPT% +if defined _OLD_VIRTUAL_PYTHONHOME set PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME% + +set _OLD_VIRTUAL_PROMPT=%PROMPT% +set PROMPT=(aimenv) %PROMPT% + +if defined PYTHONHOME set _OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME% +set PYTHONHOME= + +if defined _OLD_VIRTUAL_PATH set PATH=%_OLD_VIRTUAL_PATH% +if not defined _OLD_VIRTUAL_PATH set _OLD_VIRTUAL_PATH=%PATH% + +set PATH=%VIRTUAL_ENV%\Scripts;%PATH% +set VIRTUAL_ENV_PROMPT=(aimenv) + +:END +if defined _OLD_CODEPAGE ( + "%SystemRoot%\System32\chcp.com" %_OLD_CODEPAGE% > nul + set _OLD_CODEPAGE= +) diff --git a/lab_4/aimenv/Scripts/deactivate.bat b/lab_4/aimenv/Scripts/deactivate.bat new file mode 100644 index 0000000..62a39a7 --- /dev/null +++ b/lab_4/aimenv/Scripts/deactivate.bat @@ -0,0 +1,22 @@ +@echo off + +if defined _OLD_VIRTUAL_PROMPT ( + set "PROMPT=%_OLD_VIRTUAL_PROMPT%" +) +set _OLD_VIRTUAL_PROMPT= + +if defined _OLD_VIRTUAL_PYTHONHOME ( + set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%" + set _OLD_VIRTUAL_PYTHONHOME= +) + +if defined _OLD_VIRTUAL_PATH ( + set "PATH=%_OLD_VIRTUAL_PATH%" +) + +set _OLD_VIRTUAL_PATH= + +set VIRTUAL_ENV= +set VIRTUAL_ENV_PROMPT= + +:END diff --git a/lab_4/aimenv/Scripts/debugpy.exe b/lab_4/aimenv/Scripts/debugpy.exe new file mode 100644 index 0000000..6d0e480 Binary files /dev/null and b/lab_4/aimenv/Scripts/debugpy.exe differ diff --git a/lab_4/aimenv/Scripts/ipython.exe b/lab_4/aimenv/Scripts/ipython.exe new file mode 100644 index 0000000..c5d0b33 Binary files /dev/null and b/lab_4/aimenv/Scripts/ipython.exe differ diff --git a/lab_4/aimenv/Scripts/ipython3.exe b/lab_4/aimenv/Scripts/ipython3.exe new file mode 100644 index 0000000..c5d0b33 Binary files /dev/null and b/lab_4/aimenv/Scripts/ipython3.exe differ diff --git a/lab_4/aimenv/Scripts/jupyter-kernel.exe b/lab_4/aimenv/Scripts/jupyter-kernel.exe new file mode 100644 index 0000000..cc1b7f4 Binary files /dev/null and b/lab_4/aimenv/Scripts/jupyter-kernel.exe differ diff --git a/lab_4/aimenv/Scripts/jupyter-kernelspec.exe b/lab_4/aimenv/Scripts/jupyter-kernelspec.exe new file mode 100644 index 0000000..72bf4e7 Binary files /dev/null and b/lab_4/aimenv/Scripts/jupyter-kernelspec.exe differ diff --git a/lab_4/aimenv/Scripts/jupyter-migrate.exe b/lab_4/aimenv/Scripts/jupyter-migrate.exe new file mode 100644 index 0000000..2033e15 Binary files /dev/null and b/lab_4/aimenv/Scripts/jupyter-migrate.exe differ diff --git a/lab_4/aimenv/Scripts/jupyter-run.exe b/lab_4/aimenv/Scripts/jupyter-run.exe new file mode 100644 index 0000000..1d34b22 Binary files /dev/null and b/lab_4/aimenv/Scripts/jupyter-run.exe differ diff --git a/lab_4/aimenv/Scripts/jupyter-troubleshoot.exe b/lab_4/aimenv/Scripts/jupyter-troubleshoot.exe new file mode 100644 index 0000000..de9c4d6 Binary files /dev/null and b/lab_4/aimenv/Scripts/jupyter-troubleshoot.exe differ diff --git a/lab_4/aimenv/Scripts/jupyter.exe b/lab_4/aimenv/Scripts/jupyter.exe new file mode 100644 index 0000000..77e316a Binary files /dev/null and b/lab_4/aimenv/Scripts/jupyter.exe differ diff --git a/lab_4/aimenv/Scripts/pip.exe b/lab_4/aimenv/Scripts/pip.exe new file mode 100644 index 0000000..e378251 Binary files /dev/null and b/lab_4/aimenv/Scripts/pip.exe differ diff --git a/lab_4/aimenv/Scripts/pip3.12.exe b/lab_4/aimenv/Scripts/pip3.12.exe new file mode 100644 index 0000000..e378251 Binary files /dev/null and b/lab_4/aimenv/Scripts/pip3.12.exe differ diff --git a/lab_4/aimenv/Scripts/pip3.exe b/lab_4/aimenv/Scripts/pip3.exe new file mode 100644 index 0000000..e378251 Binary files /dev/null and b/lab_4/aimenv/Scripts/pip3.exe differ diff --git a/lab_4/aimenv/Scripts/pygmentize.exe b/lab_4/aimenv/Scripts/pygmentize.exe new file mode 100644 index 0000000..9c1459b Binary files /dev/null and b/lab_4/aimenv/Scripts/pygmentize.exe differ diff --git a/lab_4/aimenv/Scripts/python.exe b/lab_4/aimenv/Scripts/python.exe new file mode 100644 index 0000000..b58faef Binary files /dev/null and b/lab_4/aimenv/Scripts/python.exe differ diff --git a/lab_4/aimenv/Scripts/pythonw.exe b/lab_4/aimenv/Scripts/pythonw.exe new file mode 100644 index 0000000..ca33b90 Binary files /dev/null and b/lab_4/aimenv/Scripts/pythonw.exe differ diff --git a/lab_4/aimenv/Scripts/pywin32_postinstall.py b/lab_4/aimenv/Scripts/pywin32_postinstall.py new file mode 100644 index 0000000..147f0cd --- /dev/null +++ b/lab_4/aimenv/Scripts/pywin32_postinstall.py @@ -0,0 +1,783 @@ +# postinstall script for pywin32 +# +# copies PyWinTypesxx.dll and PythonCOMxx.dll into the system directory, +# and creates a pth file +import glob +import os +import shutil +import sys +import sysconfig + +try: + import winreg as winreg +except: + import winreg + +# Send output somewhere so it can be found if necessary... +import tempfile + +tee_f = open(os.path.join(tempfile.gettempdir(), "pywin32_postinstall.log"), "w") + + +class Tee: + def __init__(self, file): + self.f = file + + def write(self, what): + if self.f is not None: + try: + self.f.write(what.replace("\n", "\r\n")) + except IOError: + pass + tee_f.write(what) + + def flush(self): + if self.f is not None: + try: + self.f.flush() + except IOError: + pass + tee_f.flush() + + +# For some unknown reason, when running under bdist_wininst we will start up +# with sys.stdout as None but stderr is hooked up. This work-around allows +# bdist_wininst to see the output we write and display it at the end of +# the install. +if sys.stdout is None: + sys.stdout = sys.stderr + +sys.stderr = Tee(sys.stderr) +sys.stdout = Tee(sys.stdout) + +com_modules = [ + # module_name, class_names + ("win32com.servers.interp", "Interpreter"), + ("win32com.servers.dictionary", "DictionaryPolicy"), + ("win32com.axscript.client.pyscript", "PyScript"), +] + +# Is this a 'silent' install - ie, avoid all dialogs. +# Different than 'verbose' +silent = 0 + +# Verbosity of output messages. +verbose = 1 + +root_key_name = "Software\\Python\\PythonCore\\" + sys.winver + +try: + # When this script is run from inside the bdist_wininst installer, + # file_created() and directory_created() are additional builtin + # functions which write lines to Python23\pywin32-install.log. This is + # a list of actions for the uninstaller, the format is inspired by what + # the Wise installer also creates. + file_created + is_bdist_wininst = True +except NameError: + is_bdist_wininst = False # we know what it is not - but not what it is :) + + def file_created(file): + pass + + def directory_created(directory): + pass + + def get_root_hkey(): + try: + winreg.OpenKey( + winreg.HKEY_LOCAL_MACHINE, root_key_name, 0, winreg.KEY_CREATE_SUB_KEY + ) + return winreg.HKEY_LOCAL_MACHINE + except OSError: + # Either not exist, or no permissions to create subkey means + # must be HKCU + return winreg.HKEY_CURRENT_USER + + +try: + create_shortcut +except NameError: + # Create a function with the same signature as create_shortcut provided + # by bdist_wininst + def create_shortcut( + path, description, filename, arguments="", workdir="", iconpath="", iconindex=0 + ): + import pythoncom + from win32com.shell import shell + + ilink = pythoncom.CoCreateInstance( + shell.CLSID_ShellLink, + None, + pythoncom.CLSCTX_INPROC_SERVER, + shell.IID_IShellLink, + ) + ilink.SetPath(path) + ilink.SetDescription(description) + if arguments: + ilink.SetArguments(arguments) + if workdir: + ilink.SetWorkingDirectory(workdir) + if iconpath or iconindex: + ilink.SetIconLocation(iconpath, iconindex) + # now save it. + ipf = ilink.QueryInterface(pythoncom.IID_IPersistFile) + ipf.Save(filename, 0) + + # Support the same list of "path names" as bdist_wininst. + def get_special_folder_path(path_name): + from win32com.shell import shell, shellcon + + for maybe in """ + CSIDL_COMMON_STARTMENU CSIDL_STARTMENU CSIDL_COMMON_APPDATA + CSIDL_LOCAL_APPDATA CSIDL_APPDATA CSIDL_COMMON_DESKTOPDIRECTORY + CSIDL_DESKTOPDIRECTORY CSIDL_COMMON_STARTUP CSIDL_STARTUP + CSIDL_COMMON_PROGRAMS CSIDL_PROGRAMS CSIDL_PROGRAM_FILES_COMMON + CSIDL_PROGRAM_FILES CSIDL_FONTS""".split(): + if maybe == path_name: + csidl = getattr(shellcon, maybe) + return shell.SHGetSpecialFolderPath(0, csidl, False) + raise ValueError("%s is an unknown path ID" % (path_name,)) + + +def CopyTo(desc, src, dest): + import win32api + import win32con + + while 1: + try: + win32api.CopyFile(src, dest, 0) + return + except win32api.error as details: + if details.winerror == 5: # access denied - user not admin. + raise + if silent: + # Running silent mode - just re-raise the error. + raise + full_desc = ( + "Error %s\n\n" + "If you have any Python applications running, " + "please close them now\nand select 'Retry'\n\n%s" + % (desc, details.strerror) + ) + rc = win32api.MessageBox( + 0, full_desc, "Installation Error", win32con.MB_ABORTRETRYIGNORE + ) + if rc == win32con.IDABORT: + raise + elif rc == win32con.IDIGNORE: + return + # else retry - around we go again. + + +# We need to import win32api to determine the Windows system directory, +# so we can copy our system files there - but importing win32api will +# load the pywintypes.dll already in the system directory preventing us +# from updating them! +# So, we pull the same trick pywintypes.py does, but it loads from +# our pywintypes_system32 directory. +def LoadSystemModule(lib_dir, modname): + # See if this is a debug build. + import importlib.machinery + import importlib.util + + suffix = "_d" if "_d.pyd" in importlib.machinery.EXTENSION_SUFFIXES else "" + filename = "%s%d%d%s.dll" % ( + modname, + sys.version_info[0], + sys.version_info[1], + suffix, + ) + filename = os.path.join(lib_dir, "pywin32_system32", filename) + loader = importlib.machinery.ExtensionFileLoader(modname, filename) + spec = importlib.machinery.ModuleSpec(name=modname, loader=loader, origin=filename) + mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(mod) + + +def SetPyKeyVal(key_name, value_name, value): + root_hkey = get_root_hkey() + root_key = winreg.OpenKey(root_hkey, root_key_name) + try: + my_key = winreg.CreateKey(root_key, key_name) + try: + winreg.SetValueEx(my_key, value_name, 0, winreg.REG_SZ, value) + if verbose: + print("-> %s\\%s[%s]=%r" % (root_key_name, key_name, value_name, value)) + finally: + my_key.Close() + finally: + root_key.Close() + + +def UnsetPyKeyVal(key_name, value_name, delete_key=False): + root_hkey = get_root_hkey() + root_key = winreg.OpenKey(root_hkey, root_key_name) + try: + my_key = winreg.OpenKey(root_key, key_name, 0, winreg.KEY_SET_VALUE) + try: + winreg.DeleteValue(my_key, value_name) + if verbose: + print("-> DELETE %s\\%s[%s]" % (root_key_name, key_name, value_name)) + finally: + my_key.Close() + if delete_key: + winreg.DeleteKey(root_key, key_name) + if verbose: + print("-> DELETE %s\\%s" % (root_key_name, key_name)) + except OSError as why: + winerror = getattr(why, "winerror", why.errno) + if winerror != 2: # file not found + raise + finally: + root_key.Close() + + +def RegisterCOMObjects(register=True): + import win32com.server.register + + if register: + func = win32com.server.register.RegisterClasses + else: + func = win32com.server.register.UnregisterClasses + flags = {} + if not verbose: + flags["quiet"] = 1 + for module, klass_name in com_modules: + __import__(module) + mod = sys.modules[module] + flags["finalize_register"] = getattr(mod, "DllRegisterServer", None) + flags["finalize_unregister"] = getattr(mod, "DllUnregisterServer", None) + klass = getattr(mod, klass_name) + func(klass, **flags) + + +def RegisterHelpFile(register=True, lib_dir=None): + if lib_dir is None: + lib_dir = sysconfig.get_paths()["platlib"] + if register: + # Register the .chm help file. + chm_file = os.path.join(lib_dir, "PyWin32.chm") + if os.path.isfile(chm_file): + # This isn't recursive, so if 'Help' doesn't exist, we croak + SetPyKeyVal("Help", None, None) + SetPyKeyVal("Help\\Pythonwin Reference", None, chm_file) + return chm_file + else: + print("NOTE: PyWin32.chm can not be located, so has not " "been registered") + else: + UnsetPyKeyVal("Help\\Pythonwin Reference", None, delete_key=True) + return None + + +def RegisterPythonwin(register=True, lib_dir=None): + """Add (or remove) Pythonwin to context menu for python scripts. + ??? Should probably also add Edit command for pys files also. + Also need to remove these keys on uninstall, but there's no function + like file_created to add registry entries to uninstall log ??? + """ + import os + + if lib_dir is None: + lib_dir = sysconfig.get_paths()["platlib"] + classes_root = get_root_hkey() + ## Installer executable doesn't seem to pass anything to postinstall script indicating if it's a debug build, + pythonwin_exe = os.path.join(lib_dir, "Pythonwin", "Pythonwin.exe") + pythonwin_edit_command = pythonwin_exe + ' -edit "%1"' + + keys_vals = [ + ( + "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\Pythonwin.exe", + "", + pythonwin_exe, + ), + ( + "Software\\Classes\\Python.File\\shell\\Edit with Pythonwin", + "command", + pythonwin_edit_command, + ), + ( + "Software\\Classes\\Python.NoConFile\\shell\\Edit with Pythonwin", + "command", + pythonwin_edit_command, + ), + ] + + try: + if register: + for key, sub_key, val in keys_vals: + ## Since winreg only uses the character Api functions, this can fail if Python + ## is installed to a path containing non-ascii characters + hkey = winreg.CreateKey(classes_root, key) + if sub_key: + hkey = winreg.CreateKey(hkey, sub_key) + winreg.SetValueEx(hkey, None, 0, winreg.REG_SZ, val) + hkey.Close() + else: + for key, sub_key, val in keys_vals: + try: + if sub_key: + hkey = winreg.OpenKey(classes_root, key) + winreg.DeleteKey(hkey, sub_key) + hkey.Close() + winreg.DeleteKey(classes_root, key) + except OSError as why: + winerror = getattr(why, "winerror", why.errno) + if winerror != 2: # file not found + raise + finally: + # tell windows about the change + from win32com.shell import shell, shellcon + + shell.SHChangeNotify( + shellcon.SHCNE_ASSOCCHANGED, shellcon.SHCNF_IDLIST, None, None + ) + + +def get_shortcuts_folder(): + if get_root_hkey() == winreg.HKEY_LOCAL_MACHINE: + try: + fldr = get_special_folder_path("CSIDL_COMMON_PROGRAMS") + except OSError: + # No CSIDL_COMMON_PROGRAMS on this platform + fldr = get_special_folder_path("CSIDL_PROGRAMS") + else: + # non-admin install - always goes in this user's start menu. + fldr = get_special_folder_path("CSIDL_PROGRAMS") + + try: + install_group = winreg.QueryValue( + get_root_hkey(), root_key_name + "\\InstallPath\\InstallGroup" + ) + except OSError: + vi = sys.version_info + install_group = "Python %d.%d" % (vi[0], vi[1]) + return os.path.join(fldr, install_group) + + +# Get the system directory, which may be the Wow64 directory if we are a 32bit +# python on a 64bit OS. +def get_system_dir(): + import win32api # we assume this exists. + + try: + import pythoncom + import win32process + from win32com.shell import shell, shellcon + + try: + if win32process.IsWow64Process(): + return shell.SHGetSpecialFolderPath(0, shellcon.CSIDL_SYSTEMX86) + return shell.SHGetSpecialFolderPath(0, shellcon.CSIDL_SYSTEM) + except (pythoncom.com_error, win32process.error): + return win32api.GetSystemDirectory() + except ImportError: + return win32api.GetSystemDirectory() + + +def fixup_dbi(): + # We used to have a dbi.pyd with our .pyd files, but now have a .py file. + # If the user didn't uninstall, they will find the .pyd which will cause + # problems - so handle that. + import win32api + import win32con + + pyd_name = os.path.join(os.path.dirname(win32api.__file__), "dbi.pyd") + pyd_d_name = os.path.join(os.path.dirname(win32api.__file__), "dbi_d.pyd") + py_name = os.path.join(os.path.dirname(win32con.__file__), "dbi.py") + for this_pyd in (pyd_name, pyd_d_name): + this_dest = this_pyd + ".old" + if os.path.isfile(this_pyd) and os.path.isfile(py_name): + try: + if os.path.isfile(this_dest): + print( + "Old dbi '%s' already exists - deleting '%s'" + % (this_dest, this_pyd) + ) + os.remove(this_pyd) + else: + os.rename(this_pyd, this_dest) + print("renamed '%s'->'%s.old'" % (this_pyd, this_pyd)) + file_created(this_pyd + ".old") + except os.error as exc: + print("FAILED to rename '%s': %s" % (this_pyd, exc)) + + +def install(lib_dir): + import traceback + + # The .pth file is now installed as a regular file. + # Create the .pth file in the site-packages dir, and use only relative paths + # We used to write a .pth directly to sys.prefix - clobber it. + if os.path.isfile(os.path.join(sys.prefix, "pywin32.pth")): + os.unlink(os.path.join(sys.prefix, "pywin32.pth")) + # The .pth may be new and therefore not loaded in this session. + # Setup the paths just in case. + for name in "win32 win32\\lib Pythonwin".split(): + sys.path.append(os.path.join(lib_dir, name)) + # It is possible people with old versions installed with still have + # pywintypes and pythoncom registered. We no longer need this, and stale + # entries hurt us. + for name in "pythoncom pywintypes".split(): + keyname = "Software\\Python\\PythonCore\\" + sys.winver + "\\Modules\\" + name + for root in winreg.HKEY_LOCAL_MACHINE, winreg.HKEY_CURRENT_USER: + try: + winreg.DeleteKey(root, keyname + "\\Debug") + except WindowsError: + pass + try: + winreg.DeleteKey(root, keyname) + except WindowsError: + pass + LoadSystemModule(lib_dir, "pywintypes") + LoadSystemModule(lib_dir, "pythoncom") + import win32api + + # and now we can get the system directory: + files = glob.glob(os.path.join(lib_dir, "pywin32_system32\\*.*")) + if not files: + raise RuntimeError("No system files to copy!!") + # Try the system32 directory first - if that fails due to "access denied", + # it implies a non-admin user, and we use sys.prefix + for dest_dir in [get_system_dir(), sys.prefix]: + # and copy some files over there + worked = 0 + try: + for fname in files: + base = os.path.basename(fname) + dst = os.path.join(dest_dir, base) + CopyTo("installing %s" % base, fname, dst) + if verbose: + print("Copied %s to %s" % (base, dst)) + # Register the files with the uninstaller + file_created(dst) + worked = 1 + # Nuke any other versions that may exist - having + # duplicates causes major headaches. + bad_dest_dirs = [ + os.path.join(sys.prefix, "Library\\bin"), + os.path.join(sys.prefix, "Lib\\site-packages\\win32"), + ] + if dest_dir != sys.prefix: + bad_dest_dirs.append(sys.prefix) + for bad_dest_dir in bad_dest_dirs: + bad_fname = os.path.join(bad_dest_dir, base) + if os.path.exists(bad_fname): + # let exceptions go here - delete must succeed + os.unlink(bad_fname) + if worked: + break + except win32api.error as details: + if details.winerror == 5: + # access denied - user not admin - try sys.prefix dir, + # but first check that a version doesn't already exist + # in that place - otherwise that one will still get used! + if os.path.exists(dst): + msg = ( + "The file '%s' exists, but can not be replaced " + "due to insufficient permissions. You must " + "reinstall this software as an Administrator" % dst + ) + print(msg) + raise RuntimeError(msg) + continue + raise + else: + raise RuntimeError( + "You don't have enough permissions to install the system files" + ) + + # Pythonwin 'compiles' config files - record them for uninstall. + pywin_dir = os.path.join(lib_dir, "Pythonwin", "pywin") + for fname in glob.glob(os.path.join(pywin_dir, "*.cfg")): + file_created(fname[:-1] + "c") # .cfg->.cfc + + # Register our demo COM objects. + try: + try: + RegisterCOMObjects() + except win32api.error as details: + if details.winerror != 5: # ERROR_ACCESS_DENIED + raise + print("You do not have the permissions to install COM objects.") + print("The sample COM objects were not registered.") + except Exception: + print("FAILED to register the Python COM objects") + traceback.print_exc() + + # There may be no main Python key in HKCU if, eg, an admin installed + # python itself. + winreg.CreateKey(get_root_hkey(), root_key_name) + + chm_file = None + try: + chm_file = RegisterHelpFile(True, lib_dir) + except Exception: + print("Failed to register help file") + traceback.print_exc() + else: + if verbose: + print("Registered help file") + + # misc other fixups. + fixup_dbi() + + # Register Pythonwin in context menu + try: + RegisterPythonwin(True, lib_dir) + except Exception: + print("Failed to register pythonwin as editor") + traceback.print_exc() + else: + if verbose: + print("Pythonwin has been registered in context menu") + + # Create the win32com\gen_py directory. + make_dir = os.path.join(lib_dir, "win32com", "gen_py") + if not os.path.isdir(make_dir): + if verbose: + print("Creating directory %s" % (make_dir,)) + directory_created(make_dir) + os.mkdir(make_dir) + + try: + # create shortcuts + # CSIDL_COMMON_PROGRAMS only available works on NT/2000/XP, and + # will fail there if the user has no admin rights. + fldr = get_shortcuts_folder() + # If the group doesn't exist, then we don't make shortcuts - its + # possible that this isn't a "normal" install. + if os.path.isdir(fldr): + dst = os.path.join(fldr, "PythonWin.lnk") + create_shortcut( + os.path.join(lib_dir, "Pythonwin\\Pythonwin.exe"), + "The Pythonwin IDE", + dst, + "", + sys.prefix, + ) + file_created(dst) + if verbose: + print("Shortcut for Pythonwin created") + # And the docs. + if chm_file: + dst = os.path.join(fldr, "Python for Windows Documentation.lnk") + doc = "Documentation for the PyWin32 extensions" + create_shortcut(chm_file, doc, dst) + file_created(dst) + if verbose: + print("Shortcut to documentation created") + else: + if verbose: + print("Can't install shortcuts - %r is not a folder" % (fldr,)) + except Exception as details: + print(details) + + # importing win32com.client ensures the gen_py dir created - not strictly + # necessary to do now, but this makes the installation "complete" + try: + import win32com.client # noqa + except ImportError: + # Don't let this error sound fatal + pass + print("The pywin32 extensions were successfully installed.") + + if is_bdist_wininst: + # Open a web page with info about the .exe installers being deprecated. + import webbrowser + + try: + webbrowser.open("https://mhammond.github.io/pywin32_installers.html") + except webbrowser.Error: + print("Please visit https://mhammond.github.io/pywin32_installers.html") + + +def uninstall(lib_dir): + # First ensure our system modules are loaded from pywin32_system, so + # we can remove the ones we copied... + LoadSystemModule(lib_dir, "pywintypes") + LoadSystemModule(lib_dir, "pythoncom") + + try: + RegisterCOMObjects(False) + except Exception as why: + print("Failed to unregister COM objects: %s" % (why,)) + + try: + RegisterHelpFile(False, lib_dir) + except Exception as why: + print("Failed to unregister help file: %s" % (why,)) + else: + if verbose: + print("Unregistered help file") + + try: + RegisterPythonwin(False, lib_dir) + except Exception as why: + print("Failed to unregister Pythonwin: %s" % (why,)) + else: + if verbose: + print("Unregistered Pythonwin") + + try: + # remove gen_py directory. + gen_dir = os.path.join(lib_dir, "win32com", "gen_py") + if os.path.isdir(gen_dir): + shutil.rmtree(gen_dir) + if verbose: + print("Removed directory %s" % (gen_dir,)) + + # Remove pythonwin compiled "config" files. + pywin_dir = os.path.join(lib_dir, "Pythonwin", "pywin") + for fname in glob.glob(os.path.join(pywin_dir, "*.cfc")): + os.remove(fname) + + # The dbi.pyd.old files we may have created. + try: + os.remove(os.path.join(lib_dir, "win32", "dbi.pyd.old")) + except os.error: + pass + try: + os.remove(os.path.join(lib_dir, "win32", "dbi_d.pyd.old")) + except os.error: + pass + + except Exception as why: + print("Failed to remove misc files: %s" % (why,)) + + try: + fldr = get_shortcuts_folder() + for link in ("PythonWin.lnk", "Python for Windows Documentation.lnk"): + fqlink = os.path.join(fldr, link) + if os.path.isfile(fqlink): + os.remove(fqlink) + if verbose: + print("Removed %s" % (link,)) + except Exception as why: + print("Failed to remove shortcuts: %s" % (why,)) + # Now remove the system32 files. + files = glob.glob(os.path.join(lib_dir, "pywin32_system32\\*.*")) + # Try the system32 directory first - if that fails due to "access denied", + # it implies a non-admin user, and we use sys.prefix + try: + for dest_dir in [get_system_dir(), sys.prefix]: + # and copy some files over there + worked = 0 + for fname in files: + base = os.path.basename(fname) + dst = os.path.join(dest_dir, base) + if os.path.isfile(dst): + try: + os.remove(dst) + worked = 1 + if verbose: + print("Removed file %s" % (dst)) + except Exception: + print("FAILED to remove %s" % (dst,)) + if worked: + break + except Exception as why: + print("FAILED to remove system files: %s" % (why,)) + + +# NOTE: If this script is run from inside the bdist_wininst created +# binary installer or uninstaller, the command line args are either +# '-install' or '-remove'. + +# Important: From inside the binary installer this script MUST NOT +# call sys.exit() or raise SystemExit, otherwise not only this script +# but also the installer will terminate! (Is there a way to prevent +# this from the bdist_wininst C code?) + + +def verify_destination(location): + if not os.path.isdir(location): + raise argparse.ArgumentTypeError('Path "{}" does not exist!'.format(location)) + return location + + +def main(): + import argparse + + parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description="""A post-install script for the pywin32 extensions. + + * Typical usage: + + > python pywin32_postinstall.py -install + + If you installed pywin32 via a .exe installer, this should be run + automatically after installation, but if it fails you can run it again. + + If you installed pywin32 via PIP, you almost certainly need to run this to + setup the environment correctly. + + Execute with script with a '-install' parameter, to ensure the environment + is setup correctly. + """, + ) + parser.add_argument( + "-install", + default=False, + action="store_true", + help="Configure the Python environment correctly for pywin32.", + ) + parser.add_argument( + "-remove", + default=False, + action="store_true", + help="Try and remove everything that was installed or copied.", + ) + parser.add_argument( + "-wait", + type=int, + help="Wait for the specified process to terminate before starting.", + ) + parser.add_argument( + "-silent", + default=False, + action="store_true", + help='Don\'t display the "Abort/Retry/Ignore" dialog for files in use.', + ) + parser.add_argument( + "-quiet", + default=False, + action="store_true", + help="Don't display progress messages.", + ) + parser.add_argument( + "-destination", + default=sysconfig.get_paths()["platlib"], + type=verify_destination, + help="Location of the PyWin32 installation", + ) + + args = parser.parse_args() + + if not args.quiet: + print("Parsed arguments are: {}".format(args)) + + if not args.install ^ args.remove: + parser.error("You need to either choose to -install or -remove!") + + if args.wait is not None: + try: + os.waitpid(args.wait, 0) + except os.error: + # child already dead + pass + + silent = args.silent + verbose = not args.quiet + + if args.install: + install(args.destination) + + if args.remove: + if not is_bdist_wininst: + uninstall(args.destination) + + +if __name__ == "__main__": + main() diff --git a/lab_4/aimenv/Scripts/pywin32_testall.py b/lab_4/aimenv/Scripts/pywin32_testall.py new file mode 100644 index 0000000..a54f9d4 --- /dev/null +++ b/lab_4/aimenv/Scripts/pywin32_testall.py @@ -0,0 +1,124 @@ +"""A test runner for pywin32""" +import os +import site +import subprocess +import sys + +# locate the dirs based on where this script is - it may be either in the +# source tree, or in an installed Python 'Scripts' tree. +this_dir = os.path.dirname(__file__) +site_packages = [ + site.getusersitepackages(), +] + site.getsitepackages() + +failures = [] + + +# Run a test using subprocess and wait for the result. +# If we get an returncode != 0, we know that there was an error, but we don't +# abort immediately - we run as many tests as we can. +def run_test(script, cmdline_extras): + dirname, scriptname = os.path.split(script) + # some tests prefer to be run from their directory. + cmd = [sys.executable, "-u", scriptname] + cmdline_extras + print("--- Running '%s' ---" % script) + sys.stdout.flush() + result = subprocess.run(cmd, check=False, cwd=dirname) + print("*** Test script '%s' exited with %s" % (script, result.returncode)) + sys.stdout.flush() + if result.returncode: + failures.append(script) + + +def find_and_run(possible_locations, extras): + for maybe in possible_locations: + if os.path.isfile(maybe): + run_test(maybe, extras) + break + else: + raise RuntimeError( + "Failed to locate a test script in one of %s" % possible_locations + ) + + +def main(): + import argparse + + code_directories = [this_dir] + site_packages + + parser = argparse.ArgumentParser( + description="A script to trigger tests in all subprojects of PyWin32." + ) + parser.add_argument( + "-no-user-interaction", + default=False, + action="store_true", + help="(This is now the default - use `-user-interaction` to include them)", + ) + + parser.add_argument( + "-user-interaction", + action="store_true", + help="Include tests which require user interaction", + ) + + parser.add_argument( + "-skip-adodbapi", + default=False, + action="store_true", + help="Skip the adodbapi tests; useful for CI where there's no provider", + ) + + args, remains = parser.parse_known_args() + + # win32, win32ui / Pythonwin + + extras = [] + if args.user_interaction: + extras += ["-user-interaction"] + extras.extend(remains) + scripts = [ + "win32/test/testall.py", + "Pythonwin/pywin/test/all.py", + ] + for script in scripts: + maybes = [os.path.join(directory, script) for directory in code_directories] + find_and_run(maybes, extras) + + # win32com + maybes = [ + os.path.join(directory, "win32com", "test", "testall.py") + for directory in [ + os.path.join(this_dir, "com"), + ] + + site_packages + ] + extras = remains + ["1"] # only run "level 1" tests in CI + find_and_run(maybes, extras) + + # adodbapi + if not args.skip_adodbapi: + maybes = [ + os.path.join(directory, "adodbapi", "test", "adodbapitest.py") + for directory in code_directories + ] + find_and_run(maybes, remains) + # This script has a hard-coded sql server name in it, (and markh typically + # doesn't have a different server to test on) but there is now supposed to be a server out there on the Internet + # just to run these tests, so try it... + maybes = [ + os.path.join(directory, "adodbapi", "test", "test_adodbapi_dbapi20.py") + for directory in code_directories + ] + find_and_run(maybes, remains) + + if failures: + print("The following scripts failed") + for failure in failures: + print(">", failure) + sys.exit(1) + print("All tests passed \\o/") + + +if __name__ == "__main__": + main() diff --git a/lab_4/aimenv/pyvenv.cfg b/lab_4/aimenv/pyvenv.cfg new file mode 100644 index 0000000..b18a31c --- /dev/null +++ b/lab_4/aimenv/pyvenv.cfg @@ -0,0 +1,5 @@ +home = C:\Users\Egor\AppData\Local\Programs\Python\Python312 +include-system-site-packages = false +version = 3.12.5 +executable = C:\Users\Egor\AppData\Local\Programs\Python\Python312\python.exe +command = C:\Users\Egor\AppData\Local\Programs\Python\Python312\python.exe -m venv C:\Users\Egor\Desktop\ULSTU\AI\aim\aimenv diff --git a/lab_4/aimenv/share/jupyter/kernels/python3/kernel.json b/lab_4/aimenv/share/jupyter/kernels/python3/kernel.json new file mode 100644 index 0000000..cca38a4 --- /dev/null +++ b/lab_4/aimenv/share/jupyter/kernels/python3/kernel.json @@ -0,0 +1,14 @@ +{ + "argv": [ + "python", + "-m", + "ipykernel_launcher", + "-f", + "{connection_file}" + ], + "display_name": "Python 3 (ipykernel)", + "language": "python", + "metadata": { + "debugger": true + } +} \ No newline at end of file diff --git a/lab_4/aimenv/share/jupyter/kernels/python3/logo-32x32.png b/lab_4/aimenv/share/jupyter/kernels/python3/logo-32x32.png new file mode 100644 index 0000000..be81330 Binary files /dev/null and b/lab_4/aimenv/share/jupyter/kernels/python3/logo-32x32.png differ diff --git a/lab_4/aimenv/share/jupyter/kernels/python3/logo-64x64.png b/lab_4/aimenv/share/jupyter/kernels/python3/logo-64x64.png new file mode 100644 index 0000000..eebbff6 Binary files /dev/null and b/lab_4/aimenv/share/jupyter/kernels/python3/logo-64x64.png differ diff --git a/lab_4/aimenv/share/jupyter/kernels/python3/logo-svg.svg b/lab_4/aimenv/share/jupyter/kernels/python3/logo-svg.svg new file mode 100644 index 0000000..467b07b --- /dev/null +++ b/lab_4/aimenv/share/jupyter/kernels/python3/logo-svg.svg @@ -0,0 +1,265 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lab_4/aimenv/share/man/man1/ipython.1 b/lab_4/aimenv/share/man/man1/ipython.1 new file mode 100644 index 0000000..0f4a191 --- /dev/null +++ b/lab_4/aimenv/share/man/man1/ipython.1 @@ -0,0 +1,60 @@ +.\" Hey, EMACS: -*- nroff -*- +.\" First parameter, NAME, should be all caps +.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection +.\" other parameters are allowed: see man(7), man(1) +.TH IPYTHON 1 "July 15, 2011" +.\" Please adjust this date whenever revising the manpage. +.\" +.\" Some roff macros, for reference: +.\" .nh disable hyphenation +.\" .hy enable hyphenation +.\" .ad l left justify +.\" .ad b justify to both left and right margins +.\" .nf disable filling +.\" .fi enable filling +.\" .br insert line break +.\" .sp insert n+1 empty lines +.\" for manpage-specific macros, see man(7) and groff_man(7) +.\" .SH section heading +.\" .SS secondary section heading +.\" +.\" +.\" To preview this page as plain text: nroff -man ipython.1 +.\" +.SH NAME +ipython \- Tools for Interactive Computing in Python. +.SH SYNOPSIS +.B ipython +.RI [ options ] " files" ... + +.B ipython subcommand +.RI [ options ] ... + +.SH DESCRIPTION +An interactive Python shell with automatic history (input and output), dynamic +object introspection, easier configuration, command completion, access to the +system shell, integration with numerical and scientific computing tools, +web notebook, Qt console, and more. + +For more information on how to use IPython, see 'ipython \-\-help', +or 'ipython \-\-help\-all' for all available command\(hyline options. + +.SH "ENVIRONMENT VARIABLES" +.sp +.PP +\fIIPYTHONDIR\fR +.RS 4 +This is the location where IPython stores all its configuration files. The default +is $HOME/.ipython if IPYTHONDIR is not defined. + +You can see the computed value of IPYTHONDIR with `ipython locate`. + +.SH FILES + +IPython uses various configuration files stored in profiles within IPYTHONDIR. +To generate the default configuration files and start configuring IPython, +do 'ipython profile create', and edit '*_config.py' files located in +IPYTHONDIR/profile_default. + +.SH AUTHORS +IPython is written by the IPython Development Team . diff --git a/lab_4/lab4.ipynb b/lab_4/lab4.ipynb new file mode 100644 index 0000000..7eff299 --- /dev/null +++ b/lab_4/lab4.ipynb @@ -0,0 +1,876 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Выбор бизнес-целей\n", + "### Задача регрессии:\n", + "\n", + "Цель: Предсказать цену автомобиля (Price) на основе других характеристик.\n", + "\n", + "Применение: Это может быть полезно для автосалонов, онлайн-площадок по продаже автомобилей, а также для частных лиц, которые хотят оценить рыночную стоимость своего автомобиля.\n", + "\n", + "Задача классификации:\n", + "\n", + "Цель: Классифицировать автомобили по категориям (например, \"Эконом\", \"Средний\", \"Премиум\") на основе цены и других характеристик.\n", + "\n", + "Применение: Это может быть полезно для маркетинговых кампаний, определения целевой аудитории, а также для анализа рынка автомобилей." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " ID Price Levy Manufacturer Model Prod. year Category \\\n", + "0 45654403 13328 1399 LEXUS RX 450 2010 Jeep \n", + "1 44731507 16621 1018 CHEVROLET Equinox 2011 Jeep \n", + "2 45774419 8467 - HONDA FIT 2006 Hatchback \n", + "3 45769185 3607 862 FORD Escape 2011 Jeep \n", + "4 45809263 11726 446 HONDA FIT 2014 Hatchback \n", + "\n", + " Leather interior Fuel type Engine volume Mileage Cylinders \\\n", + "0 Yes Hybrid 3.5 186005 km 6.0 \n", + "1 No Petrol 3 192000 km 6.0 \n", + "2 No Petrol 1.3 200000 km 4.0 \n", + "3 Yes Hybrid 2.5 168966 km 4.0 \n", + "4 Yes Petrol 1.3 91901 km 4.0 \n", + "\n", + " Gear box type Drive wheels Doors Wheel Color Airbags \n", + "0 Automatic 4x4 04-May Left wheel Silver 12 \n", + "1 Tiptronic 4x4 04-May Left wheel Black 8 \n", + "2 Variator Front 04-May Right-hand drive Black 2 \n", + "3 Automatic 4x4 04-May Left wheel White 0 \n", + "4 Automatic Front 04-May Left wheel Silver 4 \n", + "Index(['ID', 'Price', 'Levy', 'Manufacturer', 'Model', 'Prod. year',\n", + " 'Category', 'Leather interior', 'Fuel type', 'Engine volume', 'Mileage',\n", + " 'Cylinders', 'Gear box type', 'Drive wheels', 'Doors', 'Wheel', 'Color',\n", + " 'Airbags'],\n", + " dtype='object')\n" + ] + } + ], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "import sklearn\n", + "from sklearn.model_selection import train_test_split, GridSearchCV, cross_val_score\n", + "from sklearn.preprocessing import StandardScaler, OneHotEncoder\n", + "from sklearn.compose import ColumnTransformer\n", + "from sklearn.pipeline import Pipeline\n", + "from sklearn.linear_model import LinearRegression, LogisticRegression\n", + "from sklearn.tree import DecisionTreeRegressor, DecisionTreeClassifier\n", + "from sklearn.ensemble import RandomForestRegressor, RandomForestClassifier\n", + "from sklearn.metrics import mean_squared_error, f1_score, accuracy_score, roc_auc_score, confusion_matrix, classification_report\n", + "df = pd.read_csv(\"./static/csv/car_price_prediction.csv\")\n", + "print(df.head())\n", + "print(df.columns)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Предобработка данных" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ID 0\n", + "Price 0\n", + "Levy 0\n", + "Manufacturer 0\n", + "Model 0\n", + "Prod. year 0\n", + "Category 0\n", + "Leather interior 0\n", + "Fuel type 0\n", + "Engine volume 0\n", + "Mileage 0\n", + "Cylinders 0\n", + "Gear box type 0\n", + "Drive wheels 0\n", + "Doors 0\n", + "Wheel 0\n", + "Color 0\n", + "Airbags 0\n", + "dtype: int64\n", + "object\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Users\\Egor\\AppData\\Local\\Temp\\ipykernel_18436\\3209090058.py:21: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method.\n", + "The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy.\n", + "\n", + "For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object.\n", + "\n", + "\n", + " df['Levy'].fillna(df['Levy'].median(), inplace=True)\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\numpy\\lib\\_nanfunctions_impl.py:1241: RuntimeWarning: Mean of empty slice\n", + " return np.nanmean(a, axis, out=out, keepdims=keepdims)\n", + "C:\\Users\\Egor\\AppData\\Local\\Temp\\ipykernel_18436\\3209090058.py:22: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method.\n", + "The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy.\n", + "\n", + "For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object.\n", + "\n", + "\n", + " df['Mileage'].fillna(df['Mileage'].median(), inplace=True)\n", + "C:\\Users\\Egor\\AppData\\Local\\Temp\\ipykernel_18436\\3209090058.py:23: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method.\n", + "The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy.\n", + "\n", + "For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object.\n", + "\n", + "\n", + " df['Engine volume'].fillna(df['Engine volume'].median(), inplace=True)\n" + ] + } + ], + "source": [ + "# Проверка наличия пропущенных значений\n", + "print(df.isnull().sum())\n", + "\n", + "# Очистка столбца 'Levy' от нечисловых значений\n", + "df['Levy'] = pd.to_numeric(df['Levy'], errors='coerce')\n", + "\n", + "# Очистка столбца 'Mileage' от нечисловых значений\n", + "df['Mileage'] = pd.to_numeric(df['Mileage'], errors='coerce')\n", + "\n", + "# Проверка типа данных в столбце 'Engine volume'\n", + "print(df['Engine volume'].dtype)\n", + "\n", + "# Если столбец 'Engine volume' не является строковым, преобразуем его в строку\n", + "if df['Engine volume'].dtype != 'object':\n", + " df['Engine volume'] = df['Engine volume'].astype(str)\n", + "\n", + "# Очистка столбца 'Engine volume' от нечисловых значений\n", + "df['Engine volume'] = df['Engine volume'].str.replace(r'[^0-9.]', '', regex=True).astype(float)\n", + "\n", + "# Заполнение пропущенных значений\n", + "df['Levy'].fillna(df['Levy'].median(), inplace=True)\n", + "df['Mileage'].fillna(df['Mileage'].median(), inplace=True)\n", + "df['Engine volume'].fillna(df['Engine volume'].median(), inplace=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# Определение числовых и категориальных признаков\n", + "numeric_features = ['Levy', 'Prod. year', 'Engine volume', 'Mileage', 'Cylinders', 'Airbags']\n", + "categorical_features = ['Manufacturer', 'Model', 'Category', 'Leather interior', 'Fuel type', 'Gear box type', 'Drive wheels', 'Doors', 'Wheel', 'Color']\n", + "\n", + "# Преобразование категориальных признаков в числовые\n", + "df = pd.get_dummies(df, columns=categorical_features, drop_first=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Разделение данных на тренировочный и тестовый наборы" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "# Задача регрессии\n", + "X_reg = df.drop(['ID', 'Price'], axis=1)\n", + "y_reg = df['Price']\n", + "\n", + "# Задача классификации\n", + "df['Category'] = pd.cut(df['Price'], bins=[0, 10000, 20000, np.inf], labels=['Эконом', 'Средний', 'Премиум'])\n", + "X_class = df.drop(['ID', 'Price', 'Category'], axis=1)\n", + "y_class = df['Category']\n", + "\n", + "X_train_reg, X_test_reg, y_train_reg, y_test_reg = train_test_split(X_reg, y_reg, test_size=0.2, random_state=42)\n", + "X_train_class, X_test_class, y_train_class, y_test_class = train_test_split(X_class, y_class, test_size=0.2, random_state=42)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 5. Построение конвейера и обучение моделей\n", + "#### 5.1. Задача регрессии" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "LinearRegression RMSE: 16981.208711977062\n", + "DecisionTreeRegressor RMSE: 141914.29349587928\n", + "RandomForestRegressor RMSE: 173537.46233609488\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n" + ] + } + ], + "source": [ + "# Конвейер для задачи регрессии\n", + "from sklearn.impute import SimpleImputer\n", + "\n", + "\n", + "numeric_transformer = Pipeline(steps=[\n", + " ('imputer', SimpleImputer(strategy='median')),\n", + " ('scaler', StandardScaler())\n", + "])\n", + "\n", + "preprocessor_reg = ColumnTransformer(\n", + " transformers=[\n", + " ('num', numeric_transformer, numeric_features)\n", + " ])\n", + "\n", + "pipeline_reg = Pipeline(steps=[\n", + " ('preprocessor', preprocessor_reg),\n", + " ('regressor', LinearRegression())\n", + "])\n", + "\n", + "# Обучение моделей\n", + "models_reg = {\n", + " 'LinearRegression': LinearRegression(),\n", + " 'DecisionTreeRegressor': DecisionTreeRegressor(),\n", + " 'RandomForestRegressor': RandomForestRegressor()\n", + "}\n", + "\n", + "for name, model in models_reg.items():\n", + " pipeline_reg.set_params(regressor=model)\n", + " pipeline_reg.fit(X_train_reg, y_train_reg)\n", + " y_pred_reg = pipeline_reg.predict(X_test_reg)\n", + " rmse = np.sqrt(mean_squared_error(y_test_reg, y_pred_reg))\n", + " print(f'{name} RMSE: {rmse}')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 5.2. Задача классификации" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "LogisticRegression F1-score: 0.48010296192139407\n", + "DecisionTreeClassifier F1-score: 0.6836168013771631\n", + "RandomForestClassifier F1-score: 0.6943295967769952\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n" + ] + } + ], + "source": [ + "# Конвейер для задачи классификации\n", + "preprocessor_class = ColumnTransformer(\n", + " transformers=[\n", + " ('num', numeric_transformer, numeric_features)\n", + " ])\n", + "\n", + "pipeline_class = Pipeline(steps=[\n", + " ('preprocessor', preprocessor_class),\n", + " ('classifier', LogisticRegression())\n", + "])\n", + "\n", + "# Обучение моделей\n", + "models_class = {\n", + " 'LogisticRegression': LogisticRegression(),\n", + " 'DecisionTreeClassifier': DecisionTreeClassifier(),\n", + " 'RandomForestClassifier': RandomForestClassifier()\n", + "}\n", + "\n", + "for name, model in models_class.items():\n", + " pipeline_class.set_params(classifier=model)\n", + " pipeline_class.fit(X_train_class, y_train_class)\n", + " y_pred_class = pipeline_class.predict(X_test_class)\n", + " f1 = f1_score(y_test_class, y_pred_class, average='weighted')\n", + " print(f'{name} F1-score: {f1}')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 6. Оценка качества моделей" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "LinearRegression RMSE: 16981.208711977062, MAE: 11731.578355206166\n", + "DecisionTreeRegressor RMSE: 141914.29349587928, MAE: 9887.588955657844\n", + "RandomForestRegressor RMSE: 173537.46233609488, MAE: 12656.846663315797\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n" + ] + } + ], + "source": [ + "# Оценка качества моделей регрессии\n", + "import sklearn\n", + "#from sklearn.base import r2_score #r2 = r2_score(y_test_reg, y_pred_reg)\n", + "from sklearn.metrics import mean_absolute_error\n", + "\n", + "\n", + "for name, model in models_reg.items():\n", + " pipeline_reg.set_params(regressor=model)\n", + " y_pred_reg = pipeline_reg.predict(X_test_reg)\n", + " rmse = np.sqrt(mean_squared_error(y_test_reg, y_pred_reg))\n", + " mae = mean_absolute_error(y_test_reg, y_pred_reg)\n", + " \n", + " print(f'{name} RMSE: {rmse}, MAE: {mae}')" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "LogisticRegression F1-score: 0.48010296192139407, Accuracy: 0.502079002079002, ROC-AUC: 0.6953729054676709\n", + "DecisionTreeClassifier F1-score: 0.6836168013771631, Accuracy: 0.6876299376299376, ROC-AUC: 0.8222065250497814\n", + "RandomForestClassifier F1-score: 0.6943295967769952, Accuracy: 0.6993243243243243, ROC-AUC: 0.856645400908623\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n" + ] + } + ], + "source": [ + "# Оценка качества моделей классификации\n", + "for name, model in models_class.items():\n", + " pipeline_class.set_params(classifier=model)\n", + " y_pred_class = pipeline_class.predict(X_test_class)\n", + " f1 = f1_score(y_test_class, y_pred_class, average='weighted')\n", + " accuracy = accuracy_score(y_test_class, y_pred_class)\n", + " roc_auc = roc_auc_score(y_test_class, pipeline_class.predict_proba(X_test_class), multi_class='ovr')\n", + " print(f'{name} F1-score: {f1}, Accuracy: {accuracy}, ROC-AUC: {roc_auc}')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Выводы по пункту 6: Оценка качества моделей\n", + "Задача регрессии\n", + "Линейная регрессия (LinearRegression):\n", + "\n", + "RMSE: 16981.208711977062\n", + "\n", + "MAE: 11731.578355206166\n", + "\n", + "Вывод: Линейная регрессия показала относительно низкое качество предсказаний. RMSE и MAE достаточно высоки, что указывает на то, что модель плохо предсказывает цены автомобилей.\n", + "\n", + "Дерево решений (DecisionTreeRegressor):\n", + "\n", + "RMSE: 141914.29349587928\n", + "\n", + "MAE: 9887.588955657844\n", + "\n", + "Вывод: Дерево решений показало значительно более высокое значение RMSE по сравнению с линейной регрессией, что указывает на то, что модель сильно переобучилась. Однако MAE ниже, чем у линейной регрессии, что может указывать на то, что модель лучше предсказывает средние значения цен.\n", + "\n", + "Случайный лес (RandomForestRegressor):\n", + "\n", + "RMSE: 173537.46233609488\n", + "\n", + "MAE: 12656.846663315797\n", + "\n", + "Вывод: Случайный лес показал еще более высокое значение RMSE, что указывает на то, что модель также сильно переобучилась. MAE выше, чем у линейной регрессии, что говорит о том, что модель предсказывает цены хуже, чем линейная регрессия.\n", + "\n", + "Задача классификации\n", + "Логистическая регрессия (LogisticRegression):\n", + "\n", + "F1-score: 0.48010296192139407\n", + "\n", + "Accuracy: 0.502079002079002\n", + "\n", + "ROC-AUC: 0.6953729054676709\n", + "\n", + "Вывод: Логистическая регрессия показала низкое качество классификации. F1-score и точность близки к 0.5, что указывает на то, что модель почти не лучше случайного угадывания. ROC-AUC также низкий, что говорит о плохой способности модели различать классы.\n", + "\n", + "Дерево решений (DecisionTreeClassifier):\n", + "\n", + "F1-score: 0.6836168013771631\n", + "\n", + "Accuracy: 0.6876299376299376\n", + "\n", + "ROC-AUC: 0.8222065250497814\n", + "\n", + "Вывод: Дерево решений показало значительно лучшее качество классификации по сравнению с логистической регрессией. F1-score и точность выше, а ROC-AUC значительно лучше, что указывает на то, что модель хорошо различает классы.\n", + "\n", + "Случайный лес (RandomForestClassifier):\n", + "\n", + "F1-score: 0.6943295967769952\n", + "\n", + "Accuracy: 0.6993243243243243\n", + "\n", + "ROC-AUC: 0.856645400908623\n", + "\n", + "Вывод: Случайный лес показал лучшее качество классификации среди всех моделей. F1-score, точность и ROC-AUC выше, чем у дерева решений, что указывает на то, что модель хорошо обобщает данные и различает классы.\n", + "\n", + "Общие выводы:\n", + "Задача регрессии: Линейная регрессия показала лучшее качество предсказаний цен по сравнению с деревьями решений и случайным лесом, несмотря на высокие значения RMSE и MAE. Деревья решений и случайный лес показали сильное переобучение, что привело к очень высоким значениям RMSE.\n", + "\n", + "Задача классификации: Случайный лес показал лучшее качество классификации по сравнению с логистической регрессией и деревом решений. Логистическая регрессия показала низкое качество, в то время как дерево решений и случайный лес показали хорошие результаты, причем случайный лес показал наилучшие результаты" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "LinearRegression Cross-Validation RMSE: 100651.03159099314, Std: 161863.4449796077\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DecisionTreeRegressor Cross-Validation RMSE: 194034.64594171714, Std: 136171.92328322295\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "RandomForestRegressor Cross-Validation RMSE: 181627.2578040142, Std: 137879.8905706371\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "LogisticRegression Cross-Validation F1-score: 0.4742308354293046, Std: 0.007525407236566359\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DecisionTreeClassifier Cross-Validation F1-score: 0.6862381973987357, Std: 0.004587968007336983\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n", + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "RandomForestClassifier Cross-Validation F1-score: 0.692567227648008, Std: 0.004169193228958696\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\Users\\Egor\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages\\sklearn\\impute\\_base.py:598: UserWarning: Skipping features without any observed values: ['Mileage']. At least one non-missing value is needed for imputation with strategy='median'.\n", + " warnings.warn(\n" + ] + } + ], + "source": [ + "# Оценка смещения и дисперсии для задачи регрессии\n", + "for name, model in models_reg.items():\n", + " pipeline_reg.set_params(regressor=model)\n", + " scores = cross_val_score(pipeline_reg, X_reg, y_reg, cv=5, scoring='neg_mean_squared_error')\n", + " rmse_scores = np.sqrt(-scores)\n", + " print(f'{name} Cross-Validation RMSE: {rmse_scores.mean()}, Std: {rmse_scores.std()}')\n", + "\n", + "# Оценка смещения и дисперсии для задачи классификации\n", + "for name, model in models_class.items():\n", + " pipeline_class.set_params(classifier=model)\n", + " scores = cross_val_score(pipeline_class, X_class, y_class, cv=5, scoring='f1_weighted')\n", + " print(f'{name} Cross-Validation F1-score: {scores.mean()}, Std: {scores.std()}')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Оценка смещения и дисперсии моделей\n", + "Задача регрессии\n", + "Дерево решений (DecisionTreeRegressor):\n", + "\n", + "Cross-Validation RMSE: 194034.64594171714\n", + "\n", + "Std: 136171.92328322295\n", + "\n", + "Вывод: Дерево решений показало очень высокое значение RMSE при кросс-валидации, что указывает на сильное переобучение. Стандартное отклонение также высокое, что говорит о нестабильности модели. Это означает, что модель плохо обобщает данные и имеет высокую дисперсию.\n", + "\n", + "Случайный лес (RandomForestRegressor):\n", + "\n", + "Cross-Validation RMSE: 181627.2578040142\n", + "\n", + "Std: 137879.8905706371\n", + "\n", + "Вывод: Случайный лес также показал высокое значение RMSE при кросс-валидации, хотя и немного ниже, чем у дерева решений. Стандартное отклонение также высокое, что указывает на нестабильность модели. Это говорит о том, что модель также переобучена и имеет высокую дисперсию.\n", + "\n", + "Задача классификации\n", + "Дерево решений (DecisionTreeClassifier):\n", + "\n", + "Cross-Validation F1-score: 0.6862381973987357\n", + "\n", + "Std: 0.004587968007336983\n", + "\n", + "Вывод: Дерево решений показало хороший F1-score при кросс-валидации, но стандартное отклонение относительно высокое. Это указывает на некоторую нестабильность модели, хотя и не такую высокую, как в случае регрессии. Модель имеет умеренную дисперсию.\n", + "\n", + "Случайный лес (RandomForestClassifier):\n", + "\n", + "Cross-Validation F1-score: 0.692567227648008\n", + "\n", + "Std: 0.004169193228958696\n", + "\n", + "#### Вывод: Случайный лес показал лучший F1-score при кросс-валидации по сравнению с деревом решений. Стандартное отклонение также ниже, что указывает на более стабильную модель. Это говорит о том, что случайный лес лучше обобщает данные и имеет меньшую дисперсию по сравнению с деревом решений.\n", + "\n", + "Общие выводы:\n", + "Задача регрессии: И дерево решений, и случайный лес показали высокие значения RMSE и высокое стандартное отклонение при кросс-валидации. Это указывает на сильное переобучение и высокую дисперсию. Модели плохо обобщают данные и нестабильны.\n", + "\n", + "Задача классификации: Дерево решений показало хороший F1-score, но с высоким стандартным отклонением, что указывает на некоторую нестабильность. Случайный лес показал лучший F1-score и более низкое стандартное отклонение, что говорит о более стабильной и обобщающей способности модели." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA1QAAAIjCAYAAAAEMVqQAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABdsElEQVR4nO3dd3wUdf7H8fem7GbTQxLASAiBRHpTBBWIBU5A9Cx4AupJsR+IniennkezIXee5x0WrKg/EVEBC5YTQUUQBaSJCAIGQQEhQLLpm+x+f3+ErCzpQ2ATeD0fjzwkM9+d+czMbvy+d2a+YzPGGAEAAAAA6iwo0AUAAAAAQGNFoAIAAAAAiwhUAAAAAGARgQoAAAAALCJQAQAAAIBFBCoAAAAAsIhABQAAAAAWEagAAAAAwCICFQAAAABYRKACgBOczWbT5MmTA11GwJ133nk677zzfL9v375dNptNL730UsBqOtKRNR4rDXHbAaCxIlABQB089dRTstls6tWrl+Vl7Nq1S5MnT9batWvrr7AG7rPPPpPNZvP9hIaGqnXr1rruuuv0448/Brq8Ovnyyy81efJkZWdnB6yGVq1a+e3Ppk2bqm/fvpo/f37AagKAk1VIoAsAgMZk1qxZatWqlVasWKGtW7cqLS2tzsvYtWuXpkyZolatWqlbt271X2QDNm7cOJ155pkqKSnR6tWr9eyzz+r999/Xt99+q6SkpONaS0pKigoLCxUaGlqn13355ZeaMmWKRo4cqdjY2GNTXC1069ZNf/nLXySVvaeeeeYZXXHFFXr66ad1yy23VPtaq9sOAKiIM1QAUEuZmZn68ssv9dhjjykxMVGzZs0KdEmNTt++fXXttddq1KhRmj59uh599FEdOHBAL7/8cpWvyc/PPya12Gw2hYWFKTg4+Jgs/1g79dRTde211+raa6/VX//6Vy1btkwRERH697//XeVrSktL5Xa7G/22A0BDQqACgFqaNWuW4uLiNHjwYF155ZVVBqrs7Gz9+c9/VqtWreRwONSiRQtdd911ysrK0meffaYzzzxTkjRq1CjfJVvl97K0atVKI0eOrLDMI++tcbvdmjhxos444wzFxMQoIiJCffv21aefflrn7fr1118VEhKiKVOmVJi3efNm2Ww2PfHEE5KkkpISTZkyRenp6QoLC1N8fLz69OmjhQsX1nm9knTBBRdIKgurkjR58mTZbDZt3LhRV199teLi4tSnTx9f+1dffVVnnHGGnE6nmjRpomHDhmnnzp0Vlvvss8+qTZs2cjqd6tmzp7744osKbaq6j2jTpk266qqrlJiYKKfTqbZt2+q+++7z1Td+/HhJUmpqqu/4bd++/ZjUWBfNmzdX+/btffuyfPseffRRPf7442rTpo0cDoc2btxoadvL/fLLLxo9erSaNWsmh8Ohjh076sUXX6xQz/Tp09WxY0eFh4crLi5OPXr00GuvvXZU2wgADRGX/AFALc2aNUtXXHGF7Ha7hg8frqefflorV670BSRJysvLU9++ffX9999r9OjROv3005WVlaV3331XP//8s9q3b6/7779fEydO1E033aS+fftKks4555w61eJyufT8889r+PDhuvHGG5Wbm6sXXnhBAwYM0IoVK+p0KWGzZs107rnn6o033tCkSZP85s2ZM0fBwcH6wx/+IKksUEydOlU33HCDevbsKZfLpVWrVmn16tX63e9+V6dtkKRt27ZJkuLj4/2m/+EPf1B6eroefvhhGWMkSQ899JAmTJigq666SjfccIP27dun6dOnKyMjQ2vWrPFdfvfCCy/o5ptv1jnnnKM77rhDP/74o37/+9+rSZMmSk5Orrae9evXq2/fvgoNDdVNN92kVq1aadu2bXrvvff00EMP6YorrtAPP/yg2bNn69///rcSEhIkSYmJicetxqqUlJRo586dFfblzJkzVVRUpJtuukkOh0NNmjSR1+ut87ZLZeH7rLPOks1m09ixY5WYmKgPP/xQ119/vVwul+644w5J0nPPPadx48bpyiuv1O23366ioiKtX79eX3/9ta6++mpL2wcADZYBANRo1apVRpJZuHChMcYYr9drWrRoYW6//Xa/dhMnTjSSzLx58yosw+v1GmOMWblypZFkZs6cWaFNSkqKGTFiRIXp5557rjn33HN9v5eWlpri4mK/NgcPHjTNmjUzo0eP9psuyUyaNKna7XvmmWeMJPPtt9/6Te/QoYO54IILfL937drVDB48uNplVebTTz81ksyLL75o9u3bZ3bt2mXef/9906pVK2Oz2czKlSuNMcZMmjTJSDLDhw/3e/327dtNcHCweeihh/ymf/vttyYkJMQ33e12m6ZNm5pu3br57Z9nn33WSPLbh5mZmRWOQ0ZGhomKijI//fST33rKj50xxvzzn/80kkxmZuYxr7EqKSkp5sILLzT79u0z+/btM+vWrTPDhg0zksxtt93mt33R0dFm7969fq+3uu3XX3+9OeWUU0xWVpZfm2HDhpmYmBhTUFBgjDHm0ksvNR07dqxxOwDgRMAlfwBQC7NmzVKzZs10/vnnSyq7/2bo0KF6/fXX5fF4fO3mzp2rrl276vLLL6+wDJvNVm/1BAcHy263S5K8Xq8OHDig0tJS9ejRQ6tXr67z8q644gqFhIRozpw5vmkbNmzQxo0bNXToUN+02NhYfffdd9qyZYulukePHq3ExEQlJSVp8ODBys/P18svv6wePXr4tTtyUIV58+bJ6/XqqquuUlZWlu+nefPmSk9P913quGrVKu3du1e33HKLb/9I0siRIxUTE1Ntbfv27dOSJUs0evRotWzZ0m9ebY7d8ajxcB9//LESExOVmJiorl276s0339Qf//hHTZs2za/dkCFDfGfQqlKbbTfGaO7cubrkkktkjPHbxgEDBignJ8f33ouNjdXPP/+slStX1np7AKCxOmEC1ZIlS3TJJZcoKSlJNptNb7/9dp2XYYzRo48+qtNOO00Oh0Onnnqq7zIHACcvj8ej119/Xeeff74yMzO1detWbd26Vb169dKvv/6qRYsW+dpu27ZNnTp1Oi51vfzyy+rSpYvvXqbExES9//77ysnJqfOyEhIS1K9fP73xxhu+aXPmzFFISIiuuOIK37T7779f2dnZOu2009S5c2eNHz9e69evr/V6Jk6cqIULF2rx4sVav369du3apT/+8Y8V2qWmpvr9vmXLFhljlJ6e7gsR5T/ff/+99u7dK0n66aefJEnp6el+ry8fpr065cO3Wz1+x6PGw/Xq1UsLFy7UJ598oi+//FJZWVl65ZVX5HQ6/doduS8rU5tt37dvn7Kzs/Xss89W2L5Ro0ZJkm8b7777bkVGRqpnz55KT0/XmDFjtGzZslpvGwA0JifMPVT5+fnq2rWrRo8e7fc//7q4/fbb9fHHH+vRRx9V586ddeDAAR04cKCeKwXQ2CxevFi7d+/W66+/rtdff73C/FmzZunCCy+sl3VVdSbE4/H4jcj26quvauTIkbrssss0fvx4NW3aVMHBwZo6darvvqS6GjZsmEaNGqW1a9eqW7dueuONN9SvXz/ffUKSlJGRoW3btumdd97Rxx9/rOeff17//ve/NWPGDN1www01rqNz587q379/je2ODAVer1c2m00ffvhhpSPTRUZG1mILj63jXWNCQoKlfWlV+X1X1157rUaMGFFpmy5dukiS2rdvr82bN2vBggX66KOPNHfuXD311FOaOHFipYOfAEBjdsIEqkGDBmnQoEFVzi8uLtZ9992n2bNnKzs7W506ddK0adN8o2Z9//33evrpp7Vhwwa1bdtWUu2+1QNw4ps1a5aaNm2qJ598ssK8efPmaf78+ZoxY4acTqfatGmjDRs2VLu86i4fi4uLq/SBsT/99JPf2Yu33npLrVu31rx58/yWd+SgEnVx2WWX6eabb/Zd9vfDDz/o3nvvrdCuSZMmGjVqlEaNGqW8vDxlZGRo8uTJtQpUVrVp00bGGKWmpuq0006rsl1KSoqksrNF5SMISmUDNmRmZqpr165VvrZ8/1o9fsejxmOlNtuemJioqKgoeTyeWgW5iIgIDR06VEOHDpXb7dYVV1yhhx56SPfee6/CwsLqrXYACLQT5pK/mowdO1bLly/X66+/rvXr1+sPf/iDBg4c6LsP4L333lPr1q21YMECpaamqlWrVrrhhhs4QwWc5AoLCzVv3jxdfPHFuvLKKyv8jB07Vrm5uXr33Xclld2vsm7dOs2fP7/Cssyh0eoiIiIkqdLg1KZNG3311Vdyu92+aQsWLKgw7Hb5GZDyZUrS119/reXLl1ve1tjYWA0YMEBvvPGGXn/9ddntdl122WV+bfbv3+/3e2RkpNLS0lRcXGx5vbVxxRVXKDg4WFOmTPHbZqlsH5TX1aNHDyUmJmrGjBl++/Cll16qdH8fLjExURkZGXrxxRe1Y8eOCusoV9XxOx41Hiu12fbg4GANGTJEc+fOrTR47du3z/fvI98ndrtdHTp0kDFGJSUlx2ALACBwTpgzVNXZsWOHZs6cqR07digpKUmSdNddd+mjjz7SzJkz9fDDD+vHH3/UTz/9pDfffFOvvPKKPB6P/vznP+vKK6/U4sWLA7wFAALl3XffVW5urn7/+99XOv+ss87yPeR36NChGj9+vN566y394Q9/0OjRo3XGGWfowIEDevfddzVjxgx17dpVbdq0UWxsrGbMmKGoqChFRESoV69eSk1N1Q033KC33npLAwcO1FVXXaVt27bp1VdfVZs2bfzWe/HFF2vevHm6/PLLNXjwYGVmZmrGjBnq0KGD8vLyLG/v0KFDde211+qpp57SgAEDfMN8l+vQoYPOO+88nXHGGWrSpIlWrVqlt956S2PHjrW8ztpo06aNHnzwQd17773avn27LrvsMkVFRSkzM1Pz58/XTTfdpLvuukuhoaF68MEHdfPNN+uCCy7Q0KFDlZmZqZkzZ9bq/qT//ve/6tOnj04//XTddNNNSk1N1fbt2/X+++9r7dq1kqQzzjhDknTfffdp2LBhCg0N1SWXXHLcajxWarPtjzzyiD799FP16tVLN954ozp06KADBw5o9erV+uSTT3xfQl544YVq3ry5evfurWbNmun777/XE088ocGDBysqKipg2wgAx8TxH1jw2JNk5s+f7/t9wYIFRpKJiIjw+wkJCTFXXXWVMcaYG2+80Ugymzdv9r3um2++MZLMpk2bjvcmAGggLrnkEhMWFmby8/OrbDNy5EgTGhrqG0p6//79ZuzYsebUU081drvdtGjRwowYMcJvqOl33nnHdOjQwYSEhFQYvvpf//qXOfXUU43D4TC9e/c2q1atqjBsutfrNQ8//LBJSUkxDofDdO/e3SxYsMCMGDHCpKSk+NWnWgybXs7lchmn02kkmVdffbXC/AcffND07NnTxMbGGqfTadq1a2ceeugh43a7q11u+bDpb775ZrXtyodN37dvX6Xz586da/r06eP7O96uXTszZswYv7/dxhjz1FNPmdTUVONwOEyPHj3MkiVLKuzDyoYON8aYDRs2mMsvv9zExsaasLAw07ZtWzNhwgS/Ng888IA59dRTTVBQUIUh1OuzxqqkpKTUOHx9+fb985//rHKelW3/9ddfzZgxY0xycrIJDQ01zZs3N/369TPPPvusr80zzzxjMjIyTHx8vHE4HKZNmzZm/PjxJicnp8ZtA4DGxmbMEdclnABsNpvmz5/vu1Rlzpw5uuaaa/Tdd99VuFE4MjJSzZs316RJk/Twww/7XYpQWFio8PBwffzxx5YeWAkAAADgxHZSXPLXvXt3eTwe7d27V3379q20Te/evVVaWqpt27b5Lq354YcfJP12AzEAAAAAHO6EOUOVl5enrVu3SioLUI899pjOP/98NWnSRC1bttS1116rZcuW6V//+pe6d++uffv2adGiRerSpYsGDx4sr9erM888U5GRkXr88cfl9Xo1ZswYRUdH6+OP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jAl0EVa5XC7FxMQoJydH0dHRgS4HAAAAQIAEKhtYeg7V//3f/6lPnz5KSkrSTz/9JEl6/PHH9c4779RrcQAAAADQkNU5UD399NO68847NWjQIGVnZ/sGooiNjdXjjz9e3/UBAAAAQINV50A1ffp0Pffcc7rvvvsUHBzsm96jRw99++239VocAAAAADRkdQ5UmZmZ6t69e4XpDodD+fn59VIUAAAAADQGdQ5UqampWrt2bYXpH330kdq3b18fNQEAAABAo1DnYdPvvPNOjRkzRkVFRTLGaMWKFZo9e7amTp2q559//ljUCAAAAAANUp0D1Q033CCn06m///3vKigo0NVXX62kpCT95z//0bBhw45FjQAAAADQIB3Vc6gKCgqUl5enpk2b1mdNtcZzqAAAAABIgcsGdT5DlZmZqdLSUqWnpys8PFzh4eGSpC1btig0NFStWrWq7xoBAAAAoEGq86AUI0eO1Jdffllh+tdff62RI0fWR00AAAAA0CjUOVCtWbNGvXv3rjD9rLPOqnT0PwAAAAA4UdU5UNlsNuXm5laYnpOTI4/HUy9FAQAAAEBjUOdAlZGRoalTp/qFJ4/Ho6lTp6pPnz71WhwAAAAANGR1HpRi2rRpysjIUNu2bdW3b19J0hdffCGXy6XFixfXe4EAAAAA0FDV+QxVhw4dtH79el111VXau3evcnNzdd1112nTpk3q1KnTsagRAAAAABqko3oOVaDxHCoAAAAAUgN/DtX69evVqVMnBQUFaf369dW27dKlS70UBgAAAAANXa0CVbdu3bRnzx41bdpU3bp1k81mU2Untmw2GyP9AQAAADhp1CpQZWZmKjEx0fdvAAAAAEAtA1VKSookqaSkRFOmTNGECROUmpp6TAsDAAAAgIauTqP8hYaGau7cuceqFgAAAABoVOo8bPpll12mt99++xiUAgAAAACNS50f7Juenq77779fy5Yt0xlnnKGIiAi/+ePGjau34gAAAACgIavzc6iqu3fKZrPpxx9/POqiaovnUAEAAACQGvhzqA7HKH8AAAAAUKZOgeqrr77Se++9J7fbrX79+mngwIHHqi4AAAAAaPBqHajeeustDR06VE6nU6GhoXrsscc0bdo03XXXXceyPgAAAABosGo9yt/UqVN14403KicnRwcPHtSDDz6ohx9++FjWBgAAAAANWq0HpYiM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W1A2v3wZUWGhinaGVtoZzClw62C+W0GHhbKosFDFOkMVFGQ71Dn9LZwUlnjlKipRuD1YUY4QFXvKQk59d7COtvN2Inb+TsRtwtHjfQEAOJkFKhsE/B6qoUOHat++fZo4caL27Nmjbt266aOPPqoxTDUkpxz2DX9jVtM191a/3T9aR3svwIl4L8GJuE04erwvAAA4/gJ+hupoNJQzVAAAAAACK1DZIOAP9gUAAACAxopABQAAAAAWEagAAAAAwCICFQAAAABYRKACAAAAAIsIVAAAAABgEYEKAAAAACwiUAEAAACARQQqAAAAALCIQAUAAAAAFhGoAAAAAMAiAhUAAAAAWESgAgAAAACLQgJdwNEwxkiSXC5XgCsBAAAAEEjlmaA8IxwvjTpQ5ebmSpKSk5MDXAkAAACAhiA3N1cxMTHHbX02c7wjXD3yer3atWuXoqKiZLPZAlqLy+VScnKydu7cqejo6IDWgmOH43zy4FifHDjOJweO88mB43xyqO44G2OUm5urpKQkBQUdvzubGvUZqqCgILVo0SLQZfiJjo7mQ3wS4DifPDjWJweO88mB43xy4DifHKo6zsfzzFQ5BqUAAAAAAIsIVAAAAABgEYGqnjgcDk2aNEkOhyPQpeAY4jifPDjWJweO88mB43xy4DifHBricW7Ug1IAAAAAQCBxhgoAAAAALCJQAQAAAIBFBCoAAAAAsIhABQAAAAAWEajqyZNPPqlWrVopLCxMvXr10ooVKwJdEg6ZPHmybDab30+7du1884uKijRmzBjFx8crMjJSQ4YM0a+//uq3jB07dmjw4MEKDw9X06ZNNX78eJWWlvq1+eyzz3T66afL4XAoLS1NL730UoVaeJ/UnyVLluiSSy5RUlKSbDab3n77bb/5xhhNnDhRp5xyipxOp/r3768tW7b4tTlw4ICuueYaRUdHKzY2Vtdff73y8vL82qxfv159+/ZVWFiYkpOT9Y9//KNCLW+++abatWunsLAwde7cWR988EGda0HlajrOI0eOrPD5HjhwoF8bjnPDN3XqVJ155pmKiopS06ZNddlll2nz5s1+bRrS3+ra1IKKanOczzvvvAqf6VtuucWvDce5YXv66afVpUsX34N3zz77bH344Ye++SfkZ9ngqL3++uvGbrebF1980Xz33XfmxhtvNLGxsebXX38NdGkwxkyaNMl07NjR7N692/ezb98+3/xbbrnFJCcnm0WLFplVq1aZs846y5xzzjm++aWlpaZTp06mf//+Zs2aNeaDDz4wCQkJ5t577/W1+fHHH014eLi58847zcaNG8306dNNcHCw+eijj3xteJ/Urw8++MDcd999Zt68eUaSmT9/vt/8Rx55xMTExJi3337brFu3zvz+9783qampprCw0Ndm4MCBpmvXruarr74yX3zxhUlLSzPDhw/3zc/JyTHNmjUz11xzjdmwYYOZPXu2cTqd5plnnvG1WbZsmQkODjb/+Mc/zMaNG83f//53Exoaar799ts61YLK1XScR4wYYQYOHOj3+T5w4IBfG45zwzdgwAAzc+ZMs2HDBrN27Vpz0UUXmZYtW5q8vDxfm4b0t7qmWlC52hznc88919x4441+n+mcnBzffI5zw/fuu++a999/3/zwww9m8+bN5m9/+5sJDQ01GzZsMMacmJ9lAlU96NmzpxkzZozvd4/HY5KSkszUqVMDWBXKTZo0yXTt2rXSednZ2SY0NNS8+eabvmnff/+9kWSWL19ujCnr0AUFBZk9e/b42jz99NMmOjraFBcXG2OM+etf/2o6duzot+yhQ4eaAQMG+H7nfXLsHNnR9nq9pnnz5uaf//ynb1p2drZxOBxm9uzZxhhjNm7caCSZlStX+tp8+OGHxmazmV9++cUYY8xTTz1l4uLifMfZGGPuvvtu07ZtW9/vV111lRk8eLBfPb169TI333xzrWtB7VQVqC699NIqX8Nxbpz27t1rJJnPP//cGNOw/lbXphbUzpHH2ZiyQHX77bdX+RqOc+MUFxdnnn/++RP2s8wlf0fJ7Xbrm2++Uf/+/X3TgoKC1L9/fy1fvjyAleFwW7ZsUVJSklq3bq1rrrlGO3bskCR98803Kikp8Tt+7dq1U8uWLX3Hb/ny5ercubOaNWvmazNgwAC5XC599913vjaHL6O8TfkyeJ8cX5mZmdqzZ4/f/o6JiVGvXr38jmtsbKx69Ojha9O/f38FBQXp66+/9rXJyMiQ3W73tRkwYIA2b96sgwcP+tpUd+xrUwuOzmeffaamTZuqbdu2uvXWW7V//37fPI5z45STkyNJatKkiaSG9be6NrWgdo48zuVmzZqlhIQEderUSffee68KCgp88zjOjYvH49Hrr7+u/Px8nX322SfsZzmkTq1RQVZWljwej99Bl6RmzZpp06ZNAaoKh+vVq5deeukltW3bVrt379aUKVPUt29fbdiwQXv27JHdbldsbKzfa5o1a6Y9e/ZIkvbs2VPp8S2fV10bl8ulwsJCHTx4kPfJcVR+XCrb34cfs6ZNm/rNDwkJUZMmTfzapKamVlhG+by4uLgqj/3hy6ipFlg3cOBAXXHFFUpNTdW2bdv0t7/9TYMGDdLy5csVHBzMcW6EvF6v7rjjDvXu3VudOnWSpAb1t7o2taBmlR1nSbr66quVkpKipKQkrV+/Xnfffbc2b96sefPmSeI4Nxbffvutzj77bBUVFSkyMlLz589Xhw4dtHbt2hPys0ygwglv0KBBvn936dJFvXr1UkpKit544w05nc4AVgbgaA0bNsz3786dO6tLly5q06aNPvvsM/Xr1y+AlcGqMWPGaMOGDVq6dGmgS8ExVNVxvummm3z/7ty5s0455RT169dP27ZtU5s2bY53mbCobdu2Wrt2rXJycvTWW29pxIgR+vzzzwNd1jHDJX9HKSEhQcHBwRVGBPn111/VvHnzAFWF6sTGxuq0007T1q1b1bx5c7ndbmVnZ/u1Ofz4NW/evNLjWz6vujbR0dFyOp28T46z8n1a3f5u3ry59u7d6ze/tLRUBw4cqJdjf/j8mmpB/WndurUSEhK0detWSRznxmbs2LFasGCBPv30U7Vo0cI3vSH9ra5NLaheVce5Mr169ZIkv880x7nhs9vtSktL0xlnnKGpU6eqa9eu+s9//nPCfpYJVEfJbrfrjDPO0KJFi3zTvF6vFi1apLPPPjuAlaEqeXl52rZtm0455RSdccYZCg0N9Tt+mzdv1o4dO3zH7+yzz9a3337r1ylbuHChoqOj1aFDB1+bw5dR3qZ8GbxPjq/U1FQ1b97cb3+7XC59/fXXfsc1Oztb33zzja/N4sWL5fV6ff8DP/vss7VkyRKVlJT42ixcuFBt27ZVXFycr011x742taD+/Pzzz9q/f79OOeUUSRznxsIYo7Fjx2r+/PlavHhxhUswG9Lf6trUgsrVdJwrs3btWkny+0xznBsfr9er4uLiE/ezXKchLFCp119/3TgcDvPSSy+ZjRs3mptuusnExsb6jU6CwPnLX/5iPvvsM5OZmWmWLVtm+vfvbxISEszevXuNMWVDZrZs2dIsXrzYrFq1ypx99tnm7LPP9r2+fPjOCy+80Kxdu9Z89NFHJjExsdLhO8ePH2++//578+STT1Y6fCfvk/qTm5tr1qxZY9asWWMkmccee8ysWbPG/PTTT8aYsiGsY2NjzTvvvGPWr19vLr300kqHTe/evbv5+uuvzdKlS016errfcNrZ2dmmWbNm5o9//KPZsGGDef311014eHiF4bRDQkLMo48+ar7//nszadKkSofTrqkWVK6645ybm2vuuusus3z5cpOZmWk++eQTc/rpp5v09HRTVFTkWwbHueG79dZbTUxMjPnss8/8hssuKCjwtWlIf6trqgWVq+k4b9261dx///1m1apVJjMz07zzzjumdevWJiMjw7cMjnPDd88995jPP//cZGZmmvXr15t77rnH2Gw28/HHHxtjTszPMoGqnkyfPt20bNnS2O1207NnT/PVV18FuiQcMnToUHPKKacYu91uTj31VDN06FCzdetW3/zCwkLzpz/9ycTFxZnw8HBz+eWXm927d/stY/v27WbQoEHG6XSahIQE85e//MWUlJT4tfn0009Nt27djN1uN61btzYzZ86sUAvvk/rz6aefGkkVfkaMGGGMKRvGesKECaZZs2bG4XCYfv36mc2bN/stY//+/Wb48OEmMjLSREdHm1GjRpnc3Fy/NuvWrTN9+vQxDofDnHrqqeaRRx6pUMsbb7xhTjvtNGO3203Hjh3N+++/7ze/NrWgctUd54KCAnPhhReaxMREExoaalJSUsyNN95Y4UsKjnPDV9kxluT3d7Qh/a2uTS2oqKbjvGPHDpORkWGaNGliHA6HSUtLM+PHj/d7DpUxHOeGbvTo0SYlJcXY7XaTmJho+vXr5wtTxpyYn2WbMcbU7ZwWAAAAAEDiHioAAAAAsIxABQAAAAAWEagAAAAAwCICFQAAAABYRKACAAAAAIsIVAAAAABgEYEKAAAAACwiUAEAAACARQQqAECjZLPZ9Pbbb9f7clu1aqXHH3+83pcLADgxEagAANVavny5goODNXjw4Dq/NpDhZOTIkbLZbLLZbLLb7UpLS9P999+v0tLSal+3cuVK3XTTTcepSgBAY0egAgBU64UXXtBtt92mJUuWaNeuXYEup04GDhyo3bt3a8uWLfrLX/6iyZMn65///Gelbd1utyQpMTFR4eHhx7NMAEAjRqACAFQpLy9Pc+bM0a233qrBgwfrpZdeqtDmvffe05lnnqmwsDAlJCTo8ssvlySdd955+umnn/TnP//Zd6ZIkiZPnqxu3br5LePxxx9Xq1atfL+vXLlSv/vd75SQkKCYmBide+65Wr16dZ3rdzgcat68uVJSUnTrrbeqf//+evfddyWVncG67LLL9NBDDykpKUlt27aVVPGsWnZ2tm6++WY1a9ZMYWFh6tSpkxYsWOCbv3TpUvXt21dOp1PJyckaN26c8vPzffOfeuoppaenKywsTM2aNdOVV15Z5+0AADRcBCoAQJXeeOMNtWvXTm3bttW1116rF198UcYY3/z3339fl19+uS666CKtWbNGixYtUs+ePSVJ8+bNU4sWLXT//fdr9+7d2r17d63Xm5ubqxEjRmjp0qX66quvlJ6erosuuki5ublHtT1Op9N3JkqSFi1apM2bN2vhwoV+Iamc1+vVoEGDtGzZMr366qvauHGjHnnkEQUHB0uStm3bpoEDB2rIkCFav3695syZo6VLl2rs2LGSpFWrVmncuHG6//77tXnzZn300UfKyMg4qm0AADQsIYEuAADQcL3wwgu69tprJZVdPpeTk6PPP/9c5513niTpoYce0rBhwzRlyhTfa7p27SpJatKkiYKDgxUVFaXmzZvXab0XXHCB3+/PPvusYmNj9fnnn+viiy+u83YYY7Ro0SL973//02233eabHhERoeeff152u73S133yySdasWKFvv/+e5122mmSpNatW/vmT506Vddcc43uuOMOSVJ6err++9//6txzz9XTTz+tHTt2KCIiQhdffLGioqKUkpKi7t2717l+AEDDxRkqAEClNm/erBUrVmj48OGSpJCQEA0dOlQvvPCCr83atWvVr1+/el/3r7/+qhtvvFHp6emKiYlRdHS08vLytGPHjjotZ8GCBYqMjFRYWJgGDRqkoUOHavLkyb75nTt3rjJMSWXb16JFC1+YOtK6dev00ksvKTIy0vczYMAAeb1eZWZm6ne/+51SUlLUunVr/fGPf9SsWbNUUFBQp20AADRsnKECAFTqhRdeUGlpqZKSknzTjDFyOBx64oknFBMTI6fTWeflBgUF+V02KEklJSV+v48YMUL79+/Xf/7zH6WkpMjhcOjss8/2u1yvNs4//3w9/fTTstvtSkpKUkiI///2IiIiqn19TduXl5enm2++WePGjaswr2XLlrLb7Vq9erU+++wzffzxx5o4caImT56slStXKjY2tk7bAgBomDhDBQCooLS0VK+88or+9a9/ae3atb6fdevWKSkpSbNnz5YkdenSRYsWLapyOXa7XR6Px29aYmKi9uzZ4xeq1q5d69dm2bJlGjdunC666CJ17NhRDodDWVlZdd6OiIgIpaWlqWXLlhXCVG106dJFP//8s3744YdK559++unauHGj0tLSKvyUn/kKCQlR//799Y9//EPr16/X9u3btXjx4jrXAgBomDhDBQCoYMGCBTp48KCuv/56xcTE+M0bMmSIXnjhBd1yyy2aNGmS+vXrpzZt2mjYsGEqLS3VBx98oLvvvltS2Yh5S5Ys0bBhw+RwOJSQkKDzzjtP+/bt0z/+8Q9deeWV+uijj/Thhx8qOjrat4709HT93//9n3r06CGXy6Xx48dbOht2tM4991xlZGRoyJAheuyxx5SWlqZNmzbJZrNp4MCBuvvuu3XWWWdp7NixuuGGGxQREaGNGzdq4cKFeuKJJ7RgwQL9+OOPysjIUFxcnD744AN5vV7fiIIAgMaPM1QAgApeeOEF9e/fv0KYksoC1apVq7R+/Xqdd955evPNN/Xuu++qW7duuuCCC7RixQpf2/vvv1/bt29XmzZtlJiYKElq3769nnrqKT355JPq2rWrVqxYobvuuqvC+g8ePKjTTz9df/zjHzVu3Dg1bdr02G50FebOnaszzzxTw4cPV4cOHfTXv/7Vd9atS5cu+vzzz/XDDz+ob9++6t69uyZOnOi7TDI2Nlbz5s3TBRdcoPbt22vGjBmaPXu2OnbsGJBtAQDUP5s58kJ2AAAAAECtcIYKAAAAACwiUAEAAACARQQqAAAAALCIQAUAAAAAFhGoAAAAAMAiAhUAAAAAWESgAgAAAACLCFQAAAAAYBGBCgAAAAAsIlABAAAAgEUEKgAAAACw6P8BjODgZfDjylkAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiQAAAHHCAYAAACPy0PBAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABQBElEQVR4nO3deVhUZf8G8HuGZUB2RBhwQdxBzbUQd5NURMUtM30LzbQM3HClN/cUwx030rfUDM2yNLM0SVJSERXFLcVdNAVUBGQbljm/P/w5OYEd0DkcHO/Pe811xXOeOed75p3o5vucM6MQBEEAERERkYyUchdARERExEBCREREsmMgISIiItkxkBAREZHsGEiIiIhIdgwkREREJDsGEiIiIpIdAwkRERHJjoGEiIiIZMdAQiShS5cuoVu3brCzs4NCocCOHTsMuv/r169DoVBgw4YNBt3vi6xz587o3Lmz3GUQUTkxkJDRu3LlCj744APUqVMHFhYWsLW1Rbt27bB8+XLk5eVJeuzAwECcOXMG8+bNw6ZNm9C6dWtJj1eRhg0bBoVCAVtb21Jfx0uXLkGhUEChUGDRokXl3v/t27cxa9YsJCYmGqBaIqrsTOUugEhKP//8M958802oVCq8++67aNKkCQoKCnDw4EFMnjwZ586dw9q1ayU5dl5eHuLi4vDf//4XwcHBkhzD3d0deXl5MDMzk2T/YkxNTZGbm4uffvoJgwYN0tsWFRUFCwsL5OfnP9O+b9++jdmzZ6N27dpo3rx5mZ+3d+/eZzoeEcmLgYSM1rVr1zB48GC4u7sjJiYGrq6uum1BQUG4fPkyfv75Z8mOf/fuXQCAvb29ZMdQKBSwsLCQbP9iVCoV2rVrhy1btpQIJJs3b4a/vz++//77CqklNzcXVapUgbm5eYUcj4gMi0s2ZLTCw8ORnZ2NL774Qi+MPFavXj2MGzdO93NRURHmzp2LunXrQqVSoXbt2vj444+h0Wj0nle7dm306tULBw8exGuvvQYLCwvUqVMHX331lW7OrFmz4O7uDgCYPHkyFAoFateuDeDRUsfjf37SrFmzoFAo9Maio6PRvn172Nvbw9raGg0bNsTHH3+s2/60a0hiYmLQoUMHWFlZwd7eHgEBATh//nypx7t8+TKGDRsGe3t72NnZYfjw4cjNzX36C/sPQ4YMwe7du5GRkaEbO3bsGC5duoQhQ4aUmJ+eno5JkyahadOmsLa2hq2tLfz8/HDq1CndnP379+PVV18FAAwfPly39PP4PDt37owmTZogISEBHTt2RJUqVXSvyz+vIQkMDISFhUWJ8+/evTscHBxw+/btMp8rEUmHgYSM1k8//YQ6deqgbdu2ZZr//vvvY8aMGWjZsiWWLl2KTp06ISwsDIMHDy4x9/Llyxg4cCDeeOMNLF68GA4ODhg2bBjOnTsHAOjfvz+WLl0KAHj77bexadMmLFu2rFz1nzt3Dr169YJGo8GcOXOwePFi9OnTB4cOHfrX5/3222/o3r070tLSMGvWLISEhODw4cNo164drl+/XmL+oEGD8PDhQ4SFhWHQoEHYsGEDZs+eXeY6+/fvD4VCgR9++EE3tnnzZjRq1AgtW7YsMf/q1avYsWMHevXqhSVLlmDy5Mk4c+YMOnXqpAsHnp6emDNnDgBg1KhR2LRpEzZt2oSOHTvq9nP//n34+fmhefPmWLZsGbp06VJqfcuXL0e1atUQGBiI4uJiAMDnn3+OvXv3YsWKFXBzcyvzuRKRhAQiI5SZmSkAEAICAso0PzExUQAgvP/++3rjkyZNEgAIMTExujF3d3cBgBAbG6sbS0tLE1QqlTBx4kTd2LVr1wQAwsKFC/X2GRgYKLi7u5eoYebMmcKT/0ouXbpUACDcvXv3qXU/Psb69et1Y82bNxecnZ2F+/fv68ZOnTolKJVK4d133y1xvPfee09vn/369ROqVq361GM+eR5WVlaCIAjCwIEDha5duwqCIAjFxcWCWq0WZs+eXeprkJ+fLxQXF5c4D5VKJcyZM0c3duzYsRLn9linTp0EAEJkZGSp2zp16qQ39uuvvwoAhE8//VS4evWqYG1tLfTt21f0HImo4rBDQkYpKysLAGBjY1Om+b/88gsAICQkRG984sSJAFDiWhMvLy906NBB93O1atXQsGFDXL169Zlr/qfH1578+OOP0Gq1ZXrOnTt3kJiYiGHDhsHR0VE3/sorr+CNN97QneeTPvzwQ72fO3TogPv37+tew7IYMmQI9u/fj5SUFMTExCAlJaXU5Rrg0XUnSuWjXz3FxcW4f/++bjnqxIkTZT6mSqXC8OHDyzS3W7du+OCDDzBnzhz0798fFhYW+Pzzz8t8LCKSHgMJGSVbW1sAwMOHD8s0/8aNG1AqlahXr57euFqthr29PW7cuKE3XqtWrRL7cHBwwIMHD56x4pLeeusttGvXDu+//z5cXFwwePBgfPvtt/8aTh7X2bBhwxLbPD09ce/ePeTk5OiN//NcHBwcAKBc59KzZ0/Y2Nhg69atiIqKwquvvlritXxMq9Vi6dKlqF+/PlQqFZycnFCtWjWcPn0amZmZZT5m9erVy3UB66JFi+Do6IjExERERETA2dm5zM8lIukxkJBRsrW1hZubG86ePVuu5/3zotKnMTExKXVcEIRnPsbj6xses7S0RGxsLH777Te88847OH36NN566y288cYbJeY+j+c5l8dUKhX69++PjRs3Yvv27U/tjgDA/PnzERISgo4dO+Lrr7/Gr7/+iujoaDRu3LjMnSDg0etTHidPnkRaWhoA4MyZM+V6LhFJj4GEjFavXr1w5coVxMXFic51d3eHVqvFpUuX9MZTU1ORkZGhu2PGEBwcHPTuSHnsn10YAFAqlejatSuWLFmCP//8E/PmzUNMTAx+//33Uvf9uM6kpKQS2y5cuAAnJydYWVk93wk8xZAhQ3Dy5Ek8fPiw1AuBH9u2bRu6dOmCL774AoMHD0a3bt3g6+tb4jUpazgsi5ycHAwfPhxeXl4YNWoUwsPDcezYMYPtn4ieHwMJGa0pU6bAysoK77//PlJTU0tsv3LlCpYvXw7g0ZIDgBJ3wixZsgQA4O/vb7C66tati8zMTJw+fVo3dufOHWzfvl1vXnp6eonnPv6AsH/eivyYq6srmjdvjo0bN+r9B/7s2bPYu3ev7jyl0KVLF8ydOxcrV66EWq1+6jwTE5MS3ZfvvvsOf/31l97Y4+BUWngrr6lTpyI5ORkbN27EkiVLULt2bQQGBj71dSSiiscPRiOjVbduXWzevBlvvfUWPD099T6p9fDhw/juu+8wbNgwAECzZs0QGBiItWvXIiMjA506dcLRo0exceNG9O3b96m3lD6LwYMHY+rUqejXrx/Gjh2L3NxcrFmzBg0aNNC7qHPOnDmIjY2Fv78/3N3dkZaWhtWrV6NGjRpo3779U/e/cOFC+Pn5wcfHByNGjEBeXh5WrFgBOzs7zJo1y2Dn8U9KpRKffPKJ6LxevXphzpw5GD58ONq2bYszZ84gKioKderU0ZtXt25d2NvbIzIyEjY2NrCysoK3tzc8PDzKVVdMTAxWr16NmTNn6m5DXr9+PTp37ozp06cjPDy8XPsjIonIfJcPkeQuXrwojBw5Uqhdu7Zgbm4u2NjYCO3atRNWrFgh5Ofn6+YVFhYKs2fPFjw8PAQzMzOhZs2aQmhoqN4cQXh026+/v3+J4/zzdtOn3fYrCIKwd+9eoUmTJoK5ubnQsGFD4euvvy5x2+++ffuEgIAAwc3NTTA3Nxfc3NyEt99+W7h48WKJY/zz1tjffvtNaNeunWBpaSnY2toKvXv3Fv7880+9OY+P98/bitevXy8AEK5du/bU11QQ9G/7fZqn3fY7ceJEwdXVVbC0tBTatWsnxMXFlXq77o8//ih4eXkJpqameufZqVMnoXHjxqUe88n9ZGVlCe7u7kLLli2FwsJCvXkTJkwQlEqlEBcX96/nQEQVQyEI5bhyjYiIiEgCvIaEiIiIZMdAQkRERLJjICEiIiLZMZAQERGR7BhIiIiISHYMJERERCQ7BhIiIiKSnVF+UuuwLafFJ9FLZZ5fI7lLoErExIDfk0MvPrWdmeTHsGwRbJD95J1caZD9VEbskBAREZHsjLJDQkREVKko+Pe/GAYSIiIiqXGZUBQDCRERkdTYIRHFV4iIiIhkxw4JERGR1LhkI4qBhIiISGpcshHFV4iIiIhkxw4JERGR1LhkI4qBhIiISGpcshHFV4iIiIhkxw4JERGR1LhkI4qBhIiISGpcshHFV4iIiIhkxw4JERGR1LhkI4qBhIiISGpcshHFQEJERCQ1dkhEMbIRERGR7NghISIikhqXbEQxkBAREUmNgUQUXyEiIiIjFRsbi969e8PNzQ0KhQI7duzQbSssLMTUqVPRtGlTWFlZwc3NDe+++y5u376tt4/09HQMHToUtra2sLe3x4gRI5Cdna035/Tp0+jQoQMsLCxQs2ZNhIeHl7tWBhIiIiKpKRWGeZRTTk4OmjVrhlWrVpXYlpubixMnTmD69Ok4ceIEfvjhByQlJaFPnz5684YOHYpz584hOjoau3btQmxsLEaNGqXbnpWVhW7dusHd3R0JCQlYuHAhZs2ahbVr15arVi7ZEBERSU2mJRs/Pz/4+fmVus3Ozg7R0dF6YytXrsRrr72G5ORk1KpVC+fPn8eePXtw7NgxtG7dGgCwYsUK9OzZE4sWLYKbmxuioqJQUFCAL7/8Eubm5mjcuDESExOxZMkSveAihh0SIiKiF4RGo0FWVpbeQ6PRGGz/mZmZUCgUsLe3BwDExcXB3t5eF0YAwNfXF0qlEvHx8bo5HTt2hLm5uW5O9+7dkZSUhAcPHpT52AwkREREUlMoDPIICwuDnZ2d3iMsLMwgJebn52Pq1Kl4++23YWtrCwBISUmBs7Oz3jxTU1M4OjoiJSVFN8fFxUVvzuOfH88pCy7ZEBERSc1ASzahoaEICQnRG1OpVM+938LCQgwaNAiCIGDNmjXPvb9nwUBCRET0glCpVAYJIE96HEZu3LiBmJgYXXcEANRqNdLS0vTmFxUVIT09HWq1WjcnNTVVb87jnx/PKQsu2RAREUnNQEs2hvY4jFy6dAm//fYbqlatqrfdx8cHGRkZSEhI0I3FxMRAq9XC29tbNyc2NhaFhYW6OdHR0WjYsCEcHBzKXAsDCRERkdQUSsM8yik7OxuJiYlITEwEAFy7dg2JiYlITk5GYWEhBg4ciOPHjyMqKgrFxcVISUlBSkoKCgoKAACenp7o0aMHRo4ciaNHj+LQoUMIDg7G4MGD4ebmBgAYMmQIzM3NMWLECJw7dw5bt27F8uXLSywtieGSDRERkdRk+nK948ePo0uXLrqfH4eEwMBAzJo1Czt37gQANG/eXO95v//+Ozp37gwAiIqKQnBwMLp27QqlUokBAwYgIiJCN9fOzg579+5FUFAQWrVqBScnJ8yYMaNct/wCDCRERERGq3PnzhAE4anb/23bY46Ojti8efO/znnllVfwxx9/lLu+JzGQEBERSY3fZSOKgYSIiEhqMi3ZvEgY2YiIiEh27JAQERFJjUs2ohhIiIiIpMYlG1GMbERERCQ7dkiIiIikxiUbUQwkREREUmMgEcVXiIiIiGTHDgkREZHUeFGrKAYSIiIiqXHJRhQDCRERkdTYIRHFyEZERESyY4eEiIhIalyyEcVAQkREJDUu2YhiZCMiIiLZsUNCREQkMQU7JKIYSIiIiCTGQCKOSzZEREQkO3ZIiIiIpMYGiSgGEiIiIolxyUYcl2yIiIhIduyQEBERSYwdEnEMJERERBJjIBHHQPICWdS7EZyszUuM77t4Dz+cSUW/pi5orLZB1SpmeKgpwolbWfjhTAryCrV689t7OKB7IyeobVTIK9TiWHIGNiXcrqjTIAM6dfI4tn69AZcu/In79+5iTvgytO/UVbc9/f49rFu1FMfj45D98CFeadEKYyaGokYtd92cv27dRGTEIpw9dRKFBQV41acdxkwMhWNVJzlOiZ7DqRPHseXr9bj4/++HT8OXo0Pnv98Pubm5WLtqKQ4eiEFmZgZc3apjwKChCBjwFgAgKzMTX65dhePxh5Gaegf29g5o3+l1jPhwDKytbeQ6LaPAQCKOgeQFMnvvJSifeFNXt7PAlNfr4NjNTNhbmsLe0gxbT97GX1kaOFmZIbB1DdhbmmLVoWTdc7o3dEKPRtWwNfEOrtzPhcpUCSerkiGHXgz5eXmoW78B/Hr3w8yp4/W2CYKAGVPGwcTUFHMXRqCKlRW2bf4Kk8aMxPpvdsDSsgry8nIxZewo1K3fEItX/Q8AsP7zlfjvpDFY9UUUlEpeZvYiycvPQ736DdGzdz9M/8f7AQBWLQvHyePx+O/sMKhdq+NY/GEsC/8UTtWc0a5jF9y7l4b799Iwetwk1Paog9Q7d7B4wZxHYXfB0oo/IXqpMJC8QB5qivV+9veyQepDDS6k5QAAVh68odt2N7sA359OwSifmlAqAK0AVDEzQf9X1FgWex3nU7N1c29l5FfMCZDBebftAO+2HUrdduvmDfx59jS+2LIdHnXqAQDGT52OgT27IGbvbvgHDMDZU4lIvXMba7/6DlbW1gCAqTPnIcC3HU4ej0er13wq7Fzo+bVp2wFtnvJ+AIBzpxPR3T8ALVq9BgDo0+9N/LT9O5w/dwbtOnZBnbr1MfezZbr51WvUwvujx2LezGkoKiqCqSn/k/HM2CARJeufP/fu3UN4eDj69esHHx8f+Pj4oF+/fli4cCHu3r0rZ2mVnolSAZ/aDvjjavpT51iamSCvUAut8OjnxmprKBWAg6Up5vdsgCUBjfBRu1pwrGJWQVVTRSosKAAAmJurdGNKpRJmZmY4e+rEozmFBYBCATPzv7tk5uYqKJRKnDl1smILJsk1fqU5DsX+jrtpqRAEASeOH8XN5Ot41bvtU5+Tk/0QVaysGUaek0KhMMjDmMkWSI4dO4YGDRogIiICdnZ26NixIzp27Ag7OztERESgUaNGOH78uFzlVXotq9uiipkJDl57UOp2a3MT9GnijANX7uvGnK3NoQDQu7EzNp+4jVUHk2FlboLJXTxgojTuN/rLqFZtDzirXfG/1cvwMCsThYWF2PLVF7iblor79+4BALyavAJLC0usXbkU+fl5yMvLRWTEImiLi5F+j38UGJtxkz5GbY+6GNirK7q2bYEp4z7A+Mn/RbOWrUudn5HxAF99+Tl69x1YwZXSy0i2yDtmzBi8+eabiIyMLJH6BEHAhx9+iDFjxiAuLu5f96PRaKDRaPTGigsLYGJm3NdFdKzriDN3HiIjr6jENgtTJSZ08sDtzHzsOJOqG1coAFMTJb5OuI1zKY+WbCIPJ2N5Xy94OlvhbEp2iX3Ri8vU1AxzFizFwnkzEfBGeyhNTNDq1TZ4zac9gEdtM3sHR8yYvxjLwudi+7dRUCiVeP0NP9Rv6AkFrx8xOj98G4U/z57G/MUroVa74tTJBCxbOA9O1ZzR+h/LcznZ2Zg24SO4e9TF8FEfyVSx8TD27oYhyBZITp06hQ0bNpT6f5JCocCECRPQokUL0f2EhYVh9uzZemPN+n+I5gNHG6zWyqZqFTM0drHGiieuGXnMwlSJiZ09kF9UjBV/3ECx8Pe2x+HldubfAe6hphgPC4pQlRe2GqUGno2x7uttyM5+iKLCQtg7OOKj94agYSMv3ZxX27RF1A+7kZnxACYmJrC2scUAv85wdashY+VkaJr8fKxbvRyfhi+HT/tOAIC69Rvi8sUL2Pr1Br1AkpuTg8njPkCVKlb4NHw5TE25rPu8GEjEyfYnkFqtxtGjR5+6/ejRo3BxcRHdT2hoKDIzM/UeTQNGGLLUSqdDHUdkaYpw6naW3riFqRKTunigWCtgeex1FGoFve2X7j26+FVt+/c1BVbmJrAxN8W9nALpCyfZWFvbwN7BEbeSb+Di+XNo2/H1EnPs7B1gbWOLE8fjkfEgHW07dq74QkkyRUVFKCoqKtH5UpqYQCv8/dEAOdnZmDhmFMzMzDB/8QqoVKp/7opIErJ1SCZNmoRRo0YhISEBXbt21YWP1NRU7Nu3D+vWrcOiRYtE96NSqUr8C2PMyzUKAO3rOODQtQd4Mm9YmCoxuYsHzE2V+DzuBizNTGD5/3/UZGmKIAhA6sMCnLiViaEt3bDh2C3kFRbjzWauuPNQgwupXK55EeXl5uKvW3/f1n3n9l+4fPECbGzt4KJ2xf59v8Le3hHOajWuXb6ElUs/Q7uOr+PVNn9fxLj7p+1wr10Hdg6O+PNMIlYt+QwD334Htdw95Dgleg65pbwfLl28ANv/fz80b9kakRGLoVKpoFa7IfHkcfz6y04EjZsM4FEYmTR2FPLz8/DJnOXIyc5BTvajP2TsHRxgYmIiy3kZA3ZIxCkEQRDEp0lj69atWLp0KRISElBc/OiWVhMTE7Rq1QohISEYNGjQM+132JbThiyzUmmstsbkLnUwddcFpD78u6vRyNkK07rWLfU5k3aex72cQgCPgsuQlm5oVdMWggBcSMvB5hO3kZ5bWCH1y2WeXyO5S5BEYsIxhHz0Xonx7v59MHXGPPywNQpbv16PB+n34ehUDd38euOdER/CzOzvFvzaVUvx664f8TArE2rX6ujd/00MfPtdo/4FamKk53Yy4SjGjy75fujhH4DQmfNw/949rF29DMfjDyMrKxNqtRt69R2IQUMe/f/9tOcDwDc7foWrW3WpT0EWajvpl6SqBm4xyH7ub3zbIPupjGQNJI8VFhbi3v9f9e/k5KT3y/JZGHMgoWdjrIGEno2xBhJ6NgwklUOluLHczMwMrq6ucpdBREQkCWPuOBpKpQgkRERExoyBRBwDCRERkcQYSMTxk4+IiIhIduyQEBERSY0NElEMJERERBLjko04LtkQERGR7NghISIikhg7JOIYSIiIiCTGQCKOSzZEREQkO3ZIiIiIJMYOiTgGEiIiIqkxj4jikg0RERHJjh0SIiIiiXHJRhwDCRERkcQYSMQxkBAREUmMgUQcryEhIiIyUrGxsejduzfc3NygUCiwY8cOve2CIGDGjBlwdXWFpaUlfH19cenSJb056enpGDp0KGxtbWFvb48RI0YgOztbb87p06fRoUMHWFhYoGbNmggPDy93rQwkREREUlMY6FFOOTk5aNasGVatWlXq9vDwcERERCAyMhLx8fGwsrJC9+7dkZ+fr5szdOhQnDt3DtHR0di1axdiY2MxatQo3fasrCx069YN7u7uSEhIwMKFCzFr1iysXbu2XLVyyYaIiEhici3Z+Pn5wc/Pr9RtgiBg2bJl+OSTTxAQEAAA+Oqrr+Di4oIdO3Zg8ODBOH/+PPbs2YNjx46hdevWAIAVK1agZ8+eWLRoEdzc3BAVFYWCggJ8+eWXMDc3R+PGjZGYmIglS5boBRcx7JAQERG9IDQaDbKysvQeGo3mmfZ17do1pKSkwNfXVzdmZ2cHb29vxMXFAQDi4uJgb2+vCyMA4OvrC6VSifj4eN2cjh07wtzcXDene/fuSEpKwoMHD8pcDwMJERGRxBQKhUEeYWFhsLOz03uEhYU9U00pKSkAABcXF71xFxcX3baUlBQ4OzvrbTc1NYWjo6PenNL28eQxyoJLNkRERBIz1JJNaGgoQkJC9MZUKpVB9i03BhIiIqIXhEqlMlgAUavVAIDU1FS4urrqxlNTU9G8eXPdnLS0NL3nFRUVIT09Xfd8tVqN1NRUvTmPf348pyy4ZENERCQxQy3ZGJKHhwfUajX27dunG8vKykJ8fDx8fHwAAD4+PsjIyEBCQoJuTkxMDLRaLby9vXVzYmNjUVhYqJsTHR2Nhg0bwsHBocz1MJAQERFJTabbfrOzs5GYmIjExEQAjy5kTUxMRHJyMhQKBcaPH49PP/0UO3fuxJkzZ/Duu+/Czc0Nffv2BQB4enqiR48eGDlyJI4ePYpDhw4hODgYgwcPhpubGwBgyJAhMDc3x4gRI3Du3Dls3boVy5cvL7G0JIZLNkREREbq+PHj6NKli+7nxyEhMDAQGzZswJQpU5CTk4NRo0YhIyMD7du3x549e2BhYaF7TlRUFIKDg9G1a1colUoMGDAAERERuu12dnbYu3cvgoKC0KpVKzg5OWHGjBnluuUXABSCIAjPeb6VzrAtp+UugSqZeX6N5C6BKhETfow3PUFtZyb5MeqE/GKQ/Vxd0tMg+6mM2CEhIiKSGL/LRhwDCRERkcSYR8TxolYiIiKSHTskREREEuOSjTgGEiIiIokxj4jjkg0RERHJjh0SIiIiiXHJRhwDCRERkcSYR8RxyYaIiIhkxw4JERGRxJRKtkjEMJAQERFJjEs24rhkQ0RERLJjh4SIiEhivMtGHAMJERGRxJhHxDGQEBERSYwdEnG8hoSIiIhkxw4JERGRxNghEcdAQkREJDHmEXFcsiEiIiLZsUNCREQkMS7ZiGMgISIikhjziDgu2RAREZHs2CEhIiKSGJdsxDGQEBERSYx5RByXbIiIiEh27JAQERFJjEs24hhIiIiIJMY8Io6BhIiISGLskIjjNSREREQkO6PskHzStb7cJVAlM//3K3KXQJVIsHctuUugSkRtZyb5MdggEWeUgYSIiKgy4ZKNOC7ZEBERkezYISEiIpIYGyTiGEiIiIgkxiUbcVyyISIiItmxQ0JERCQxNkjEMZAQERFJjEs24rhkQ0RERLJjh4SIiEhi7JCIYyAhIiKSGPOIOAYSIiIiibFDIo7XkBAREZHs2CEhIiKSGBsk4hhIiIiIJMYlG3FcsiEiIiLZsUNCREQkMTZIxDGQEBERSUzJRCKKSzZEREQkO3ZIiIiIJMYGiTgGEiIiIonxLhtxXLIhIiKSmFJhmEd5FBcXY/r06fDw8IClpSXq1q2LuXPnQhAE3RxBEDBjxgy4urrC0tISvr6+uHTpkt5+0tPTMXToUNja2sLe3h4jRoxAdna2IV4WPQwkRERERuizzz7DmjVrsHLlSpw/fx6fffYZwsPDsWLFCt2c8PBwREREIDIyEvHx8bCyskL37t2Rn5+vmzN06FCcO3cO0dHR2LVrF2JjYzFq1CiD18slGyIiIonJsWRz+PBhBAQEwN/fHwBQu3ZtbNmyBUePHgXwqDuybNkyfPLJJwgICAAAfPXVV3BxccGOHTswePBgnD9/Hnv27MGxY8fQunVrAMCKFSvQs2dPLFq0CG5ubgarlx0SIiIiiSkUhnmUR9u2bbFv3z5cvHgRAHDq1CkcPHgQfn5+AIBr164hJSUFvr6+uufY2dnB29sbcXFxAIC4uDjY29vrwggA+Pr6QqlUIj4+/jlfFX3skBAREb0gNBoNNBqN3phKpYJKpSoxd9q0acjKykKjRo1gYmKC4uJizJs3D0OHDgUApKSkAABcXFz0nufi4qLblpKSAmdnZ73tpqamcHR01M0xFHZIiIiIJKYw0P/CwsJgZ2en9wgLCyv1mN9++y2ioqKwefNmnDhxAhs3bsSiRYuwcePGCj77smGHhIiISGLlvUPmaUJDQxESEqI3Vlp3BAAmT56MadOmYfDgwQCApk2b4saNGwgLC0NgYCDUajUAIDU1Fa6urrrnpaamonnz5gAAtVqNtLQ0vf0WFRUhPT1d93xDYYeEiIjoBaFSqWBra6v3eFogyc3NhVKp/595ExMTaLVaAICHhwfUajX27dun256VlYX4+Hj4+PgAAHx8fJCRkYGEhATdnJiYGGi1Wnh7exv03NghISIikpgcd9n07t0b8+bNQ61atdC4cWOcPHkSS5YswXvvvaerafz48fj0009Rv359eHh4YPr06XBzc0Pfvn0BAJ6enujRowdGjhyJyMhIFBYWIjg4GIMHDzboHTYAAwkREZHk5Pig1hUrVmD69On46KOPkJaWBjc3N3zwwQeYMWOGbs6UKVOQk5ODUaNGISMjA+3bt8eePXtgYWGhmxMVFYXg4GB07doVSqUSAwYMQEREhMHrVQhPfmSbkbiclid3CVTJLD10Xe4SqBIJ9q4ldwlUiXi6WUl+jL7/O26Q/ex4v7X4pBcUOyREREQSU/K7bEQxkBAREUmMeUQcAwkREZHE+G2/4njbLxEREcmOHRIiIiKJsUEijoGEiIhIYryoVRyXbIiIiEh27JAQERFJjP0RcQwkREREEuNdNuK4ZENERESyY4eEiIhIYko2SESVKZDs3LmzzDvs06fPMxdDRERkjLhkI65MgeTx1xCLUSgUKC4ufp56iIiI6CVUpkCi1WqlroOIiMhosUEijteQEBERSYxLNuKeKZDk5OTgwIEDSE5ORkFBgd62sWPHGqQwIiIiY8GLWsWVO5CcPHkSPXv2RG5uLnJycuDo6Ih79+6hSpUqcHZ2ZiAhIiKiciv355BMmDABvXv3xoMHD2BpaYkjR47gxo0baNWqFRYtWiRFjURERC80hUJhkIcxK3cgSUxMxMSJE6FUKmFiYgKNRoOaNWsiPDwcH3/8sRQ1EhERvdAUBnoYs3IHEjMzMyiVj57m7OyM5ORkAICdnR1u3rxp2OqIiIjopVDua0hatGiBY8eOoX79+ujUqRNmzJiBe/fuYdOmTWjSpIkUNRIREb3QlEa+3GII5e6QzJ8/H66urgCAefPmwcHBAaNHj8bdu3exdu1agxdIRET0olMoDPMwZuXukLRu3Vr3z87OztizZ49BCyIiIqKXDz8YjYiISGLGfoeMIZQ7kHh4ePzrC3v16tXnKoie7ttNX+Bw7D7cunEd5ioVPJs0w/DR41GjVm3dnGljRuBMYoLe8/wCBiJ40icAgKzMDCyc8zGuX7mErKwM2Ds4ok37zggcNQZVrKwr8nTIAOwsTNG3sTO81FYwN1HibnYBvj5xB8kZ+QAAlYkCAY2d8YqbDazMTXA/pxD7r6Tj4PWMUvf3kU9NNFZb4/MjN3H6TnYFngkZwraoL3HkjxjcSr4OlUqFho2bIXDUWFR/4nfEg/R72BC5DKeOxyMvLwfVa9bGwKEj0LZTV719HY/7A1u/WocbVy/BzNwcjZu1wsefLqngMzIezCPiyh1Ixo8fr/dzYWEhTp48iT179mDy5MmGqotKcSYxAf793kIDz8YoLi7Gxs9X4JOQ0Yjc9AMsLC1187r37o//jPhI97OFhYXunxVKJdq074x3RwbBzt4Bt2/dxJqlYXiYlYkpMxdU6PnQ87E0U2JiR3dcvJeL1YdvIltTjGrW5sgt/PsLLvs3dUHDalbYePw27ucWwtPZCm81UyMzvwhnUvQDR5e6jhV9CmRg504lwK/vINRv+Oh3xNf/W4lZUz7CivXf635HLAubgdzsh/h43lLY2tkjdt8eLJozFYsiv0ad+o0AAIcP7MPqxXPxn/eD0bTFq9AWF+PGtctynhq9BModSMaNG1fq+KpVq3D8+PHnLoiebu7i1Xo/h3w8B0P6vI7LSX+iSfNWunELCws4VnUqdR82Nrbw7zdI97Oz2g3+/Qbh+y0bpSmaJNOtQVU8yCvC1yfu6Mbu5xbqzalT1RJHkjNx6V4uAODQ9Qy0r20PdwdLvUBSw06FrvUdEf77NYT1bFAxJ0AGNzN8ld7PY6fNRmC/rrhy8U80bvbod0TS2VP4YEIoGng+uity0Dvv46dtUbhy8Tzq1G+E4uIifLFyIQI/GI83/Pvq9lWzdp0KOw9jxLtsxJX7Lpun8fPzw/fff2+o3VEZ5OQ8+g+Kta2d3vjve3fj7V6d8dG7A7AhMgL5+XlP3cf9e2k4fGAfmjRr9dQ5VDk1VdsgOSMPI16rjgU962NaFw+0rW2vN+fq/Ty84moNO4tHf3vUd6oCZ2tzXEj7O4yYmSgwrHV1fHsqBVmaYpDxyM15CED/d0TDJs1w6Pe9eJiVCa1Wiz9ifkVBgUb3R82Vixdw/14alEoFJox8G8MHdMOcqcHskDwn3mUjzmAXtW7btg2Ojmz5VhStVou1EQvh1bQ5ateppxvv9IYfnF3cUNWpGq5duYj1kctx6+Z1fDJPf+33s1nTEH9wPzSafLzWrhPGTZ1Z0adAz8nJygwdPBwQczkdvybdg7uDJd58xQXFWgHxyZkAgO9Op+LtFmrM96uPYq0ArSBg88kUXL7/d0gd2NQFV9PzeM2IkdFqtfhi5SJ4NmkOd4+/f0dMnvkZFs2eincCusDExBQqCwtMm7MYrtVrAQBS7/wFAPhm4+cYPnoinNWu+PHbr/HJ+FFYvWk7bP7xBxCVDS9qFfdMH4z25AsrCAJSUlJw9+5drF69+l+eWX43b97EzJkz8eWXXz51jkajgUaj+ceYFiqVyqC1VDZrloThxrXLWLhqg964X5+Bun+uXbc+HKtWw8fjR+HOXzfhWr2mbtvIMZMwZPgH+OvmDWz8PALrVi5C0MT/VlT5ZAAKhQLJD/Kw88+7AIBbmRq42arQ3sNeF0g61XGAh4Ml1sTdRHpuIeo7VcFbzVyQmV+IpLu5aKq2RoNqVlgQw4vRjc3a5Qtw49oVhK3Q//25+cvVyMnOxuxFa2Br54D4Q79j4eypmB/xBWrXqQ+tVgsAehe6jp06CyMG9cDh/dHo/sTvGCJDKncgCQgI0AskSqUS1apVQ+fOndGoUSODFpeeno6NGzf+ayAJCwvD7Nmz9cbGTPoYYyd/YtBaKpM1S8NwNC4Wn634Ek7OLv86t6FXUwDA7Vv6gcSxqhMcqzqhprsHbGztMCVoON4OHAVHp2qS1k6Gk5VfhDsPC/TGUh5q0NzNBgBgplSgT2NnrD1yC+dSH3U/bmdpUN3OAr71qyLpbi4aVLOCk5UZFvZqqLefkd41cPleLpYfTK6YkyGDWrt8AY7F/YH5y/8Hp2p//46489dN/LJ9KyK+/A61POoCADzqNcCfp09i945vMTrkv7rrz568ZsTM3BwurjVwNy2lYk/EiBjs+ggjVu5AMmvWLIMdfOfOnf+6vSy3EIeGhiIkJERv7Gam9rnqqqwEQUDksgWIi41BWMT/oHarLvqcq5cuAMBTL3IFAOH//yIqLCx46hyqfK7cz4WLtbnemLO1OdL//8JWE6UCpkoFBAh6cwRB0H1JV/TFezj8j1uAP/Gtg+9Pp5a4C4cqP0EQsC7iMxw5+Ds+XboOLq76vyM0mke3gyuU+ssHSqVS1xmp28ATZmbm+Cv5BryatgAAFBUVIi31Nqq5uFbAWRgnLtmIK3cgMTExwZ07d+Ds7Kw3fv/+fTg7O6O4uOwXxfXt2xcKhQKCIDx1jtj/iSqVqsTyjOpfLuJ8ka1eMh8HftuN6fOXwbKKFdLv3wMAWFlbQ6WywJ2/bmJ/9G609mkPW1s7XLtyCetWLEKTZq3gUe/RnRPH4v5ARvp91PdsAktLS9y4dgVfrl4Gr6bNS/zyosot5nI6JnWqje4NquLEX1lwd7BEu9oO2HLy0V03+UVaXLybg35NnFFYnKpbsnmtlh1+OJMKAMjSFJd6IWt6XmGJO3ao8vt82QLE7tuNjz9dCssqVfAg/dHviCpWj35H1KhVG67Va2LNknkY9uEE2NjaIf7QfpxKiMd/5y/Xze3eZwC+2RAJJ2cXOLu4YvvWrwAA7Tq/Idu5kfFTCP+WBkqhVCqRkpJSIpDcvn0bdevWRV5e2cNA9erVsXr1agQEBJS6PTExEa1atSpXyAGAy2nGGUj8OzQvdXx86Gy80TMAd1NTsGjuf3Hj2mXk5+ehmrMLfDq8jsGBI3UfenbqxDF8tW4Fbl6/isKCQjg5u6Btp654c+hwWNvYVuDZVKylh67LXYIkmqit0cerGpytzXE/txD7LqfrdTxsVSbo09gZns5WqGJugvTcQhy6noGYy+lP3eeqfp5G/8Fowd615C5BEn27tCx1fMzUWejaow8A4PatZHy1NgLnzyYiPy8Xrm41EfDWO+jSrZduflFRITatW4n90T+jQKNBA88mGBE0SbfMY2w83awkP8b4Hy8YZD/LAgx7aURlUuZAEhERAQCYMGEC5s6dC2vrvz/Vs7i4GLGxsbh+/TpOnjxZ5oP36dMHzZs3x5w5c0rdfurUKbRo0ULXSiwrYw0k9OyMNZDQszHWQELPpiICSchOwwSSJX2MN5CUeclm6dKlAP7/OobISJiYmOi2mZubo3bt2oiMjCzXwSdPnoycnJynbq9Xrx5+//33cu2TiIiIXjxlDiTXrl0DAHTp0gU//PADHBwcnvvgHTp0+NftVlZW6NSp03Mfh4iISE68qFVcuS9qZceCiIiofJTMI6LKfWv0gAED8Nlnn5UYDw8Px5tvvmmQooiIiOjlUu5AEhsbi549e5YY9/PzQ2xsrEGKIiIiMib8Lhtx5V6yyc7Ohrm5eYlxMzMzZGVlGaQoIiIiY8Jv+xVX7g5J06ZNsXXr1hLj33zzDby8vAxSFBERkTFRGuhhzMrdIZk+fTr69++PK1eu4PXXXwcA7Nu3D5s3b8a2bdsMXiAREREZv3IHkt69e2PHjh2YP38+tm3bBktLSzRr1gwxMTFwdHSUokYiIqIXGldsxJU7kACAv78//P39AQBZWVnYsmULJk2ahISEhHJ/zDsREZGx4zUk4p55SSo2NhaBgYFwc3PD4sWL8frrr+PIkSOGrI2IiIheEuXqkKSkpGDDhg344osvkJWVhUGDBkGj0WDHjh28oJWIiOgp2CARV+YOSe/evdGwYUOcPn0ay5Ytw+3bt7FixQopayMiIjIKSoVhHsaszB2S3bt3Y+zYsRg9ejTq168vZU1ERET0kilzh+TgwYN4+PAhWrVqBW9vb6xcuRL37t2TsjYiIiKjoFQoDPIwZmUOJG3atMG6detw584dfPDBB/jmm2/g5uYGrVaL6OhoPHz4UMo6iYiIXlj86Hhx5b7LxsrKCu+99x4OHjyIM2fOYOLEiViwYAGcnZ3Rp08fKWokIiKiZ/DXX3/hP//5D6pWrQpLS0s0bdoUx48f120XBAEzZsyAq6srLC0t4evri0uXLuntIz09HUOHDoWtrS3s7e0xYsQIZGdnG7zW5/ok2oYNGyI8PBy3bt3Cli1bDFUTERGRUZHjotYHDx6gXbt2MDMzw+7du/Hnn39i8eLFcHBw0M0JDw9HREQEIiMjER8fDysrK3Tv3h35+fm6OUOHDsW5c+cQHR2NXbt2ITY2FqNGjTLUS6OjEARBMPheZXY5LU/uEqiSWXroutwlUCUS7F1L7hKoEvF0s5L8GPP3XTHIfj7uWrfMc6dNm4ZDhw7hjz/+KHW7IAhwc3PDxIkTMWnSJABAZmYmXFxcsGHDBgwePBjnz5+Hl5cXjh07htatWwMA9uzZg549e+LWrVtwc3N7/pP6f8b+XT1ERESyM1SHRKPRICsrS++h0WhKPebOnTvRunVrvPnmm3B2dkaLFi2wbt063fZr164hJSUFvr6+ujE7Ozt4e3sjLi4OABAXFwd7e3tdGAEAX19fKJVKxMfHG/Y1MujeiIiISDJhYWGws7PTe4SFhZU69+rVq1izZg3q16+PX3/9FaNHj8bYsWOxceNGAI8+7BQAXFxc9J7n4uKi25aSkgJnZ2e97aampnB0dNTNMZRn+i4bIiIiKjtDfahZaGgoQkJC9MZUKlWpc7VaLVq3bo358+cDAFq0aIGzZ88iMjISgYGBhinIgNghISIikphCoTDIQ6VSwdbWVu/xtEDi6upa4mtdPD09kZycDABQq9UAgNTUVL05qampum1qtRppaWl624uKipCenq6bYygMJEREREaoXbt2SEpK0hu7ePEi3N3dAQAeHh5Qq9XYt2+fbntWVhbi4+Ph4+MDAPDx8UFGRgYSEhJ0c2JiYqDVauHt7W3QerlkQ0REJDE5vodmwoQJaNu2LebPn49Bgwbh6NGjWLt2LdauXQvgUddm/Pjx+PTTT1G/fn14eHhg+vTpcHNzQ9++fQE86qj06NEDI0eORGRkJAoLCxEcHIzBgwcb9A4bgIGEiIhIcnJ8yuqrr76K7du3IzQ0FHPmzIGHhweWLVuGoUOH6uZMmTIFOTk5GDVqFDIyMtC+fXvs2bMHFhYWujlRUVEIDg5G165doVQqMWDAAERERBi8Xn4OCb0U+Dkk9CR+Dgk9qSI+h2RJ7FWD7CekYx2D7KcyYoeEiIhIYsb+xXiGwEBCREQkMTmuIXnR8C4bIiIikh07JERERBLjio04BhIiIiKJKcFEIoaBhIiISGLskIjjNSREREQkO3ZIiIiIJMa7bMQxkBAREUmMn0Mijks2REREJDt2SIiIiCTGBok4BhIiIiKJcclGHJdsiIiISHbskBAREUmMDRJxDCREREQS43KEOL5GREREJDt2SIiIiCSm4JqNKAYSIiIiiTGOiGMgISIikhhv+xXHa0iIiIhIduyQEBERSYz9EXEMJERERBLjio04LtkQERGR7NghISIikhhv+xXHQEJERCQxLkeI42tEREREsmOHhIiISGJcshHHQEJERCQxxhFxXLIhIiIi2bFDQkREJDEu2YgzykBSw9FS7hKokpn9Rn25S6BKpGaH8XKXQJVI3smVkh+DyxHijDKQEBERVSbskIhjaCMiIiLZsUNCREQkMfZHxDGQEBERSYwrNuK4ZENERESyY4eEiIhIYkou2ohiICEiIpIYl2zEccmGiIiIZMcOCRERkcQUXLIRxUBCREQkMS7ZiOOSDREREcmOHRIiIiKJ8S4bcQwkREREEuOSjTgGEiIiIokxkIjjNSREREQkO3ZIiIiIJMbbfsUxkBAREUlMyTwiiks2REREJDt2SIiIiCTGJRtxDCREREQS41024rhkQ0RE9BJYsGABFAoFxo8frxvLz89HUFAQqlatCmtrawwYMACpqal6z0tOToa/vz+qVKkCZ2dnTJ48GUVFRQavj4GEiIhIYgoD/e9ZHTt2DJ9//jleeeUVvfEJEybgp59+wnfffYcDBw7g9u3b6N+/v257cXEx/P39UVBQgMOHD2Pjxo3YsGEDZsyY8cy1PA0DCRERkcSUCsM8nkV2djaGDh2KdevWwcHBQTeemZmJL774AkuWLMHrr7+OVq1aYf369Th8+DCOHDkCANi7dy/+/PNPfP3112jevDn8/Pwwd+5crFq1CgUFBYZ4aXQYSIiIiF4QGo0GWVlZeg+NRvOvzwkKCoK/vz98fX31xhMSElBYWKg33qhRI9SqVQtxcXEAgLi4ODRt2hQuLi66Od27d0dWVhbOnTtnwDNjICEiIpKcoZZswsLCYGdnp/cICwt76nG/+eYbnDhxotQ5KSkpMDc3h729vd64i4sLUlJSdHOeDCOPtz/eZki8y4aIiEhihrrLJjQ0FCEhIXpjKpWq1Lk3b97EuHHjEB0dDQsLC8MUICF2SIiIiCSmMNBDpVLB1tZW7/G0QJKQkIC0tDS0bNkSpqamMDU1xYEDBxAREQFTU1O4uLigoKAAGRkZes9LTU2FWq0GAKjV6hJ33Tz++fEcQ2EgISIiMkJdu3bFmTNnkJiYqHu0bt0aQ4cO1f2zmZkZ9u3bp3tOUlISkpOT4ePjAwDw8fHBmTNnkJaWppsTHR0NW1tbeHl5GbReLtkQERFJTCnDJ6PZ2NigSZMmemNWVlaoWrWqbnzEiBEICQmBo6MjbG1tMWbMGPj4+KBNmzYAgG7dusHLywvvvPMOwsPDkZKSgk8++QRBQUFP7cw8KwYSIiIiiVXWD2pdunQplEolBgwYAI1Gg+7du2P16tW67SYmJti1axdGjx4NHx8fWFlZITAwEHPmzDF4LQpBEASD71Vm+Yb/ADl6wWXzTUFPqNlhvNwlUCWSd3Kl5Mc4cjnDIPtpU8/eIPupjNghISIiklplbZFUIgwkREREEuO3/YrjXTZEREQkO3ZIiIiIJCbDTTYvHAYSIiIiiTGPiOOSDREREcmOHRIiIiKpsUUiioGEiIhIYrzLRhwDCRERkcR4Uas4XkNCREREsmOHhIiISGJskIhjICEiIpIaE4koLtkQERGR7NghISIikhjvshHHQEJERCQx3mUjjks2REREJDt2SIiIiCTGBok4BhIiIiKpMZGI4pINERERyY4dEiIiIonxLhtxDCREREQS41024hhIiIiIJMY8Io7XkBAREZHs2CF5wRUXF2PNqhX4eddO3L93D9WcndEnoB9GffgRFP/fI1yzagX27P4ZKSkpMDMzg5dXYwSPm4BXXmkmc/X0vBJPHMfmr77EhfN/4v69uwhbFIGOXbrqtn8682Ps3vWj3nO8fdphycq1JfZVUFCAkYGDcfliEtZv3oYGDT0lr5+eT7uWdTHhXV+09KoF12p2GDRhLX7afxoAYGqqxKyPeqN7+8bwqFEVWdn5iIm/gOkRO3HnbqZuH/VqOWP+hL7waVYH5mYmOHvpNmav3oXY45d0cxZPGYg2zeqgcT1XXLiWijaDF1T4ub7w2CIRxQ7JC279F+vw3dYtCP3vDGz/6ReMnzAJG778HzZHbdLNcXevjdD/zsD323/Chk2b4Va9OkaPfA/p6ekyVk6GkJeXh3oNGmLi1E+eOqdN2/bY+et+3WPW/IWlzlu9fDGcqjlLVSpJwMpShTMX/8L4sK0ltlWxMEdzz5pYsG43fN7+DIMnrkMDdxd8t+wDvXk/RHwIUxMl/D6IQNuh4Th98S/8EPEhXKra6M376scj2Lb3hKTnY8wUBvqfMWOH5AWXmHgSnV/vio6dOgMAqlevgd2//IyzZ07r5vTs1VvvOZOmhGL799tw6WISvNv4VGS5ZGA+7TrAp12Hf51jZmaOqk7V/nVO3KE/cPTIYcxbuBRHDv1hyBJJQnsP/Ym9h/4sdVtWdj56jV6pNzZhwbc4GDUFNdUOuJnyAFXtrVDf3RmjZ0fh7KXbAIDpET/iw7c6wqueG1LvJwEAJoZvAwA4OfREk/rVJTwjepmxQ/KCa968BY4eOYLr168BAJIuXMDJkwlo36FjqfMLCwrw/XdbYWNjgwYNG1ZkqSSTkwnH4O/bAYP7+2Ph/DnIzMjQ255+/x4++3Qmps8Ng4WFpTxFUoWwtbGEVqtFxsM8AMD9jBwkXUvBkF6voYqFOUxMlHh/QHuk3s/CyT+TZa7WuCgUhnkYM3ZIXnDvvT8K2dnZ6NvLDyYmJiguLsaYcRPg36uP3rwD+3/H1EkhyM/Pg1O1aohc9yUcHBxlqpoqSpu27dHpdV+4udXAX7du4vNVyzBx7Af4fP1mmJiYQBAEzJv1X/QdMAieXk1w5/ZfcpdMElGZm+LTsQH4dk8CHubk68b9P1yJrUtH4e6hRdBqBdx9kI2AoNW60EKGYeRZwiBkDyR5eXlISEiAo6MjvLy89Lbl5+fj22+/xbvvvvvU52s0Gmg0Gr0xwUQFlUolSb2Vza97duOXn39CWPhi1KtXDxcunMfCBWGoVs0Zffr208179TVvfPv9DmRkPMD3277F5Inj8fWW71C1alUZqyep+XbvqfvnuvUboG79BhgU0AMnE46h9WttsO2bKOTm5OCd4SNlrJKkZmqqxNfhI6BQKDB2vv71JktDB+Fu+kP4vrcMeZoCDOvXFt8v/wDt/7MQKfeyZKqYXkayLtlcvHgRnp6e6NixI5o2bYpOnTrhzp07uu2ZmZkYPnz4v+4jLCwMdnZ2eo+Fn4VJXXqlsXRxON4bMQp+Pf1Rv0FD9O7TF/95NxBf/O9zvXlVqlRBLXd3vNKsOWbPnQ9TE1Ps+GGbTFWTXKrXqAl7ewfcuvmoHZ9wLB5nz5xCF58W6PjaK3irrx8A4P133sLcGaFylkoGYmqqRNRnI1DL1QG9Rq/U6450fq0BenZognenrUfcqatIvHAL48O+RZ6mEP/p7S1j1UZIYaCHEZO1QzJ16lQ0adIEx48fR0ZGBsaPH4927dph//79qFWrVpn2ERoaipCQEL0xweTl6I4AQH5ePpRK/XepiYkJtFrhX5+nFbQoKCiQsjSqhNJSU5CZmYGqTk4AgPGTQzHqo7G67XfvpiEkeBRmhy1C4yavyFUmGcjjMFK3VjX0GBWB9Mwcve1VLMwBAFqtVm9cqxV0HxtAhmHsd8gYgqyB5PDhw/jtt9/g5OQEJycn/PTTT/joo4/QoUMH/P7777CyshLdh0pVcnkmv0iqiiufTp27YN3aSKhd3VC3Xj1cOH8emzauR0C/AQCA3Nxc/G9tJDp3eR1O1aoh48EDfLMlCmmpqXijew+Zq6fnlZubo+t2AMDt27dwMek8bG3tYGtnhy/XrkHnrm+galUn/HXrJlYvX4waNWvB26c9AEDt6qa3P8sqVQA86qQ4u6gr7kTomVhZmqNuzb/voKpdvSpeaVAdD7JycedeJjYvfB8tGtVE/3GRMFEqdLfypmfmorCoGPGnr+FBVi7+N/ddzF+7G3n5hXivf1vUrl4Vew6e0+23Tk0nWFuq4OJkC0uVGV5p8OhOm/NXU1BYVFyxJ01GSyEIwr//KS0hW1tbxMfHw9NT/wOYgoOD8eOPP2Lz5s3o3LkziovL94Z/mQJJTk42VkUsR8y+35Cefh/VnJ3h5+ePD0YHwczcHBqNBtOmTMSZ06eQ8eAB7O3t0bhJU4z8YDSaNH15/gLONtI3xYnjRzHmg5LLmn69AjA5dAamTRyDi0kXkP0wC07VnPFam7YYOXoMHKs6lbq/O7f/wsDe3Yz+g9FqdhgvdwkG0aFVfez937gS45t2HsGnkb8g6Zc5pT6v2/vL8UfCow8+a+lVC7OCeqOlVy2YmSpx/moK5q/drXc78a/rxqFj6/ol9tOw5wwk33nxP88o7+RK8UnPKSkl1yD7aaiuYpD9VEayBpLXXnsNY8aMwTvvvFNiW3BwMKKiopCVlcVAQs/NWAMJPRtjCSRkGBURSC4aKJA0MOJAIutFrf369cOWLVtK3bZy5Uq8/fbbkDEvERERGQYvahUla4dEKvxjmP6JHRJ6Ejsk9KQK6ZCkGqhD4mK8HRLZP4eEiIjI2PEuG3EMJERERBLjXdTi+F02REREJDt2SIiIiCTGBok4BhIiIiKpMZGI4pINERERyY4dEiIiIonxLhtxDCREREQS41024rhkQ0RERLJjh4SIiEhibJCIYyAhIiKSGhOJKAYSIiIiifGiVnG8hoSIiIhkxw4JERGRxHiXjTh2SIiIiCSmMNCjPMLCwvDqq6/CxsYGzs7O6Nu3L5KSkvTm5OfnIygoCFWrVoW1tTUGDBiA1NRUvTnJycnw9/dHlSpV4OzsjMmTJ6OoqKic1YhjICEiIjJCBw4cQFBQEI4cOYLo6GgUFhaiW7duyMnJ0c2ZMGECfvrpJ3z33Xc4cOAAbt++jf79++u2FxcXw9/fHwUFBTh8+DA2btyIDRs2YMaMGQavVyEIgmDwvcos3/DBjV5w2XxT0BNqdhgvdwlUieSdXCn5MW490BhkPzUcVM/83Lt378LZ2RkHDhxAx44dkZmZiWrVqmHz5s0YOHAgAODChQvw9PREXFwc2rRpg927d6NXr164ffs2XFxcAACRkZGYOnUq7t69C3Nzc4OcF8AOCRERUQWQY9FGX2ZmJgDA0dERAJCQkIDCwkL4+vrq5jRq1Ai1atVCXFwcACAuLg5NmzbVhREA6N69O7KysnDu3LnnquefeFErERHRC0Kj0UCj0e+2qFQqqFT/3jnRarUYP3482rVrhyZNmgAAUlJSYG5uDnt7e725Li4uSElJ0c15Mow83v54myGxQ0JERCQxhcIwj7CwMNjZ2ek9wsLCRI8fFBSEs2fP4ptvvqmAs3027JAQERFJzFB3/YaGhiIkJERvTKw7EhwcjF27diE2NhY1atTQjavVahQUFCAjI0OvS5Kamgq1Wq2bc/ToUb39Pb4L5/EcQ2GHhIiI6AWhUqlga2ur93haIBEEAcHBwdi+fTtiYmLg4eGht71Vq1YwMzPDvn37dGNJSUlITk6Gj48PAMDHxwdnzpxBWlqabk50dDRsbW3h5eVl0HNjh4SIiEhicnwwWlBQEDZv3owff/wRNjY2ums+7OzsYGlpCTs7O4wYMQIhISFwdHSEra0txowZAx8fH7Rp0wYA0K1bN3h5eeGdd95BeHg4UlJS8MknnyAoKEi0M1NevO2XXgq87ZeexNt+6UkVcdtvSmahQfajtjMr81zFU1LQ+vXrMWzYMACPPhht4sSJ2LJlCzQaDbp3747Vq1frLcfcuHEDo0ePxv79+2FlZYXAwEAsWLAApqaG7WkwkNBLgYGEnsRAQk+qkECSZaBAYlv2QPKi4TUkREREJDteQ0JERCQxfreeOAYSIiIiifHbfsVxyYaIiIhkxw4JERGRxBRctBHFQEJERCQ15hFRXLIhIiIi2bFDQkREJDE2SMQxkBAREUmMd9mI45INERERyY4dEiIiIonxLhtxDCREREQS45KNOC7ZEBERkewYSIiIiEh2XLIhIiKSGJdsxDGQEBERSYwXtYrjkg0RERHJjh0SIiIiiXHJRhwDCRERkcSYR8RxyYaIiIhkxw4JERGR1NgiEcVAQkREJDHeZSOOSzZEREQkO3ZIiIiIJMa7bMQxkBAREUmMeUQcAwkREZHUmEhE8RoSIiIikh07JERERBLjXTbiGEiIiIgkxotaxXHJhoiIiGSnEARBkLsIMjyNRoOwsDCEhoZCpVLJXQ5VAnxP0JP4fqDKhoHESGVlZcHOzg6ZmZmwtbWVuxyqBPieoCfx/UCVDZdsiIiISHYMJERERCQ7BhIiIiKSHQOJkVKpVJg5cyYvViMdvifoSXw/UGXDi1qJiIhIduyQEBERkewYSIiIiEh2DCREREQkOwYSIiIikh0DiZFatWoVateuDQsLC3h7e+Po0aNyl0QyiY2NRe/eveHm5gaFQoEdO3bIXRLJKCwsDK+++ipsbGzg7OyMvn37IikpSe6yiBhIjNHWrVsREhKCmTNn4sSJE2jWrBm6d++OtLQ0uUsjGeTk5KBZs2ZYtWqV3KVQJXDgwAEEBQXhyJEjiI6ORmFhIbp164acnBy5S6OXHG/7NULe3t549dVXsXLlSgCAVqtFzZo1MWbMGEybNk3m6khOCoUC27dvR9++feUuhSqJu3fvwtnZGQcOHEDHjh3lLodeYuyQGJmCggIkJCTA19dXN6ZUKuHr64u4uDgZKyOiyigzMxMA4OjoKHMl9LJjIDEy9+7dQ3FxMVxcXPTGXVxckJKSIlNVRFQZabVajB8/Hu3atUOTJk3kLodecqZyF0BERPIICgrC2bNncfDgQblLIWIgMTZOTk4wMTFBamqq3nhqairUarVMVRFRZRMcHIxdu3YhNjYWNWrUkLscIi7ZGBtzc3O0atUK+/bt041ptVrs27cPPj4+MlZGRJWBIAgIDg7G9u3bERMTAw8PD7lLIgLADolRCgkJQWBgIFq3bo3XXnsNy5YtQ05ODoYPHy53aSSD7OxsXL58WffztWvXkJiYCEdHR9SqVUvGykgOQUFB2Lx5M3788UfY2Njori2zs7ODpaWlzNXRy4y3/RqplStXYuHChUhJSUHz5s0REREBb29vucsiGezfvx9dunQpMR4YGIgNGzZUfEEkK4VCUer4+vXrMWzYsIothugJDCREREQkO15DQkRERLJjICEiIiLZMZAQERGR7BhIiIiISHYMJERERCQ7BhIiIiKSHQMJERERyY6BhMgIDRs2DH379tX93LlzZ4wfP77C69i/fz8UCgUyMjIq/NhE9GJhICGqQMOGDYNCoYBCoYC5uTnq1auHOXPmoKioSNLj/vDDD5g7d26Z5jJEEJEc+F02RBWsR48eWL9+PTQaDX755RcEBQXBzMwMoaGhevMKCgpgbm5ukGM6OjoaZD9ERFJhh4SogqlUKqjVari7u2P06NHw9fXFzp07dcss8+bNg5ubGxo2bAgAuHnzJgYNGgR7e3s4OjoiICAA169f1+2vuLgYISEhsLe3R9WqVTFlyhT88xsh/rlko9FoMHXqVNSsWRMqlQr16tXDF198gevXr+u+98bBwQEKhUL3/SZarRZhYWHw8PCApaUlmjVrhm3btukd55dffkGDBg1gaWmJLl266NVJRPRvGEiIZGZpaYmCggIAwL59+5CUlITo6Gjs2rULhYWF6N69O2xsbPDHH3/g0KFDsLa2Ro8ePXTPWbx4MTZs2IAvv/wSBw8eRHp6OrZv3/6vx3z33XexZcsWRERE4Pz58/j8889hbW2NmjVr4vvvvwcAJCUl4c6dO1i+fDkAICwsDF999RUiIyNx7tw5TJgwAf/5z39w4MABAI+CU//+/dG7d28kJibi/fffx7Rp06R62YjI2AhEVGECAwOFgIAAQRAEQavVCtHR0YJKpRImTZokBAYGCi4uLoJGo9HN37Rpk9CwYUNBq9XqxjQajWBpaSn8+uuvgiAIgqurqxAeHq7bXlhYKNSoUUN3HEEQhE6dOgnjxo0TBEEQkpKSBABCdHR0qTX+/vvvAgDhwYMHurH8/HyhSpUqwuHDh/XmjhgxQnj77bcFQRCE0NBQwcvLS2/71KlTS+yLiKg0vIaEqILt2rUL1tbWKCwshFarxZAhQzBr1iwEBQWhadOmeteNnDp1CpcvX4aNjY3ePvLz83HlyhVkZmbizp078Pb21m0zNTVF69atSyzbPJaYmAgTExN06tSpzDVfvnwZubm5eOONN/TGCwoK0KJFCwDA+fPn9eoAAB8fnzIfg4hebgwkRBWsS5cuWLNmDczNzeHm5gZT07//NbSystKbm52djVatWiEqKqrEfqpVq/ZMx7e0tCz3c7KzswEAP//8M6pXr663TaVSPVMdRERPYiAhqmBWVlaoV69emea2bNkSW7duhbOzM2xtbUud4+rqivj4eHTs2BEAUFRUhISEBLRs2bLU+U2bNoVWq8WBAwfg6+tbYvvjDk1xcbFuzMvLCyqVCsnJyU/trHh6emLnzp16Y0eOHBE/SSIi8KJWokpt6NChcHJyQkBAAP744w9cu3YN+/fvx9ixY3Hr1i0AwLhx47BgwQLs2LEDFy5cwEcfffSvnyFSu3ZtBAYG4r333sOOHTt0+/z2228BAO7u7lAoFNi1axfu3r2L7Oxs2NjYYNKkSZgwYQI2btyIK1eu4MSJE1ixYgU2btwIAPjwww9x6dIlTJ48GUlJSdi8eTM2bNgg9UtEREaCgYSoEqtSpQpiY2NRq1Yt9O/fH56enhgxYgTy8/N1HZOJEyfinXfeQWBgIHx8fGBjY4N+/fr9637XrFmDgQMH4qOPPkKjRo0wcuRI5OTkAACqV6+O2bNnY9q0aXBxcUFwcDAAYO7cuZg+fTrCwsLg6emJHj164Oeff4aHhwcAoFatWvj++++xY8cONGvWDJGRkZg/f76Erw4RGROF8LQr34iIiIgqCDskREREJDsGEiIiIpIdAwkRERHJjoGEiIiIZMdAQkRERLJjICEiIiLZMZAQERGR7BhIiIiISHYMJERERCQ7BhIiIiKSHQMJERERyY6BhIiIiGT3fzgiHmADx5XhAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Визуализация результатов для задачи регрессии\n", + "plt.figure(figsize=(10, 6))\n", + "sns.scatterplot(x=y_test_reg, y=y_pred_reg)\n", + "plt.xlabel('Actual Prices')\n", + "plt.ylabel('Predicted Prices')\n", + "plt.title('Actual vs Predicted Prices')\n", + "plt.show()\n", + "\n", + "# Визуализация результатов для задачи классификации\n", + "conf_matrix = confusion_matrix(y_test_class, y_pred_class)\n", + "sns.heatmap(conf_matrix, annot=True, fmt='d', cmap='Blues')\n", + "plt.xlabel('Predicted')\n", + "plt.ylabel('Actual')\n", + "plt.title('Confusion Matrix')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "1) Плохое качество предсказаний в первой диаграмме: \n", + "Модель регрессии плохо предсказывает цены автомобилей, так как точки на диаграмме рассеяния распределены хаотично и далеко от диагонали. Значительные ошибки: Ошибки предсказаний значительны, что указывает на то, что модель не может точно предсказать цены автомобилей. Необходимость улучшения модели: Для улучшения качества предсказаний стоит рассмотреть другие модели, такие как градиентный бустинг или нейронные сети, а также улучшить предобработку данных.\n", + "\n", + "2) Выводы по второй диаграмме:\n", + "Хорошее качество классификации: Матрица ошибок показывает высокие значения на диагонали и низкие значения вне диагонали, что указывает на хорошее качество классификации.\n", + "Правильные предсказания: Большинство предсказаний модели являются правильными, что говорит о ее способности хорошо различать классы.\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.12.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}