diff --git a/lab_3/lab3.ipynb b/lab_3/lab3.ipynb new file mode 100644 index 0000000..d98dc6a --- /dev/null +++ b/lab_3/lab3.ipynb @@ -0,0 +1,1546 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Лабораторная 3\n", + "\n", + "Датасет: Информация об онлайн обучении учеников" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Index(['Education Level', 'Institution Type', 'Gender', 'Age', 'Device',\n", + " 'IT Student', 'Location', 'Financial Condition', 'Internet Type',\n", + " 'Network Type', 'Flexibility Level'],\n", + " dtype='object')\n" + ] + } + ], + "source": [ + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import seaborn as sns\n", + "import featuretools as ft\n", + "import time\n", + "import math\n", + "from imblearn.over_sampling import RandomOverSampler\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score\n", + "from sklearn.ensemble import RandomForestClassifier\n", + "from sklearn.model_selection import cross_val_score\n", + "from sklearn.metrics import r2_score, mean_absolute_error, mean_squared_error\n", + "\n", + "df = pd.read_csv(\"..\\\\static\\\\csv\\\\students_adaptability_level_online_education.csv\")\n", + "print(df.columns)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Столбцы:\n", + "\n", + "Education Level - уровень образования\\\n", + "Institution Type - тип учреждения\\\n", + "Gender - пол\\\n", + "Age - возраст\\\n", + "Device - устройство\\\n", + "IT Student - ученик IT направления или нет\\\n", + "Location - локация\\\n", + "Financial Condition - финансовое состояние\\\n", + "Internet Type - тип доступа к сети\\\n", + "Network Type - уровень сети\\\n", + "Flexibility Level - уровень приспособления" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "RangeIndex: 1205 entries, 0 to 1204\n", + "Data columns (total 11 columns):\n", + " # Column Non-Null Count Dtype \n", + "--- ------ -------------- ----- \n", + " 0 Education Level 1205 non-null object\n", + " 1 Institution Type 1205 non-null object\n", + " 2 Gender 1205 non-null object\n", + " 3 Age 1205 non-null int64 \n", + " 4 Device 1205 non-null object\n", + " 5 IT Student 1205 non-null object\n", + " 6 Location 1205 non-null object\n", + " 7 Financial Condition 1205 non-null object\n", + " 8 Internet Type 1205 non-null object\n", + " 9 Network Type 1205 non-null object\n", + " 10 Flexibility Level 1205 non-null object\n", + "dtypes: int64(1), object(10)\n", + "memory usage: 103.7+ KB\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Education LevelInstitution TypeGenderAgeDeviceIT StudentLocationFinancial ConditionInternet TypeNetwork TypeFlexibility Level
0UniversityPrivateMale23TabNoTownMidWifi4GModerate
1UniversityPrivateFemale23MobileNoTownMidMobile Data4GModerate
2CollegePublicFemale18MobileNoTownMidWifi4GModerate
3SchoolPrivateFemale11MobileNoTownMidMobile Data4GModerate
4SchoolPrivateFemale18MobileNoTownPoorMobile Data3GLow
\n", + "
" + ], + "text/plain": [ + " Education Level Institution Type Gender Age Device IT Student Location \\\n", + "0 University Private Male 23 Tab No Town \n", + "1 University Private Female 23 Mobile No Town \n", + "2 College Public Female 18 Mobile No Town \n", + "3 School Private Female 11 Mobile No Town \n", + "4 School Private Female 18 Mobile No Town \n", + "\n", + " Financial Condition Internet Type Network Type Flexibility Level \n", + "0 Mid Wifi 4G Moderate \n", + "1 Mid Mobile Data 4G Moderate \n", + "2 Mid Wifi 4G Moderate \n", + "3 Mid Mobile Data 4G Moderate \n", + "4 Poor Mobile Data 3G Low " + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.info()\n", + "df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Примеры бизнес-целей для датасета:\n", + "1. Улучшение доступа к онлайн-образованию для учеников с низким уровнем финансового обеспечения.\n", + "2. Повышение удовлетворенности учеников онлайн-обучением на основе их устройств, типу соединения, местоположения." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Цели технического проекта:\n", + "\n", + "1. Провести анализ зависимости учеников от уровня интернет-соединения и устройств\n", + "2. Провести анализ влияния различных факторов (тип устройства, интернет-соединение, финансовое положение) на уровень приспособленности." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Проверяем на выбросы." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Пустые значения по столбцам:\n", + "Education Level 0\n", + "Institution Type 0\n", + "Gender 0\n", + "Age 0\n", + "Device 0\n", + "IT Student 0\n", + "Location 0\n", + "Financial Condition 0\n", + "Internet Type 0\n", + "Network Type 0\n", + "Flexibility Level 0\n", + "dtype: int64\n", + "\n", + "Количество дубликатов: 980\n", + "\n", + "Статистический обзор данных:\n", + "\n", + "Коэффициент асимметрии для столбца 'Age': 0.024342017300169792\n" + ] + } + ], + "source": [ + "null_values = df.isnull().sum()\n", + "print(\"Пустые значения по столбцам:\")\n", + "print(null_values)\n", + "\n", + "duplicates = df.duplicated().sum()\n", + "print(f\"\\nКоличество дубликатов: {duplicates}\")\n", + "\n", + "print(\"\\nСтатистический обзор данных:\")\n", + "df.describe()\n", + "\n", + "for column in df.select_dtypes(include=[np.number]).columns:\n", + " skewness = df[column].skew()\n", + " print(f\"\\nКоэффициент асимметрии для столбца '{column}': {skewness}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Выбросы незначительны, дубликаты есть. Удаляем дубликаты и очищаем от шумов." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Шумы в датасете:\n", + "Empty DataFrame\n", + "Columns: [Education Level, Institution Type, Gender, Age, Device, IT Student, Location, Financial Condition, Internet Type, Network Type, Flexibility Level]\n", + "Index: []\n" + ] + } + ], + "source": [ + "cleaned_df = df.drop_duplicates()\n", + "\n", + "Q1 = df[\"Age\"].quantile(0.25)\n", + "Q3 = df[\"Age\"].quantile(0.75)\n", + "\n", + "IQR = Q3 - Q1\n", + "\n", + "threshold = 1.5 * IQR\n", + "lower_bound = Q1 - threshold\n", + "upper_bound = Q3 + threshold\n", + "\n", + "outliers = (df[\"Age\"] < lower_bound) | (df[\"Age\"] > upper_bound)\n", + "\n", + "print(\"Шумы в датасете:\")\n", + "print(df[outliers])\n", + "\n", + "median_score = df[\"Age\"].median()\n", + "df.loc[outliers, \"Age\"] = median_score" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Преобразуем строковые значение в столбце \"Уровень приспособления\" в числовые значения. Это понадобится для расчёта качества набора признаков." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "map_flexibility_to_int = {'Low': 0, 'Moderate': 1, 'High': 2}\n", + "\n", + "df['Flexibility Level'] = df['Flexibility Level'].map(map_flexibility_to_int).astype('int32')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Шумов в датасете нет. Разбиваем датасет на три выборки: обучающую, контрольную и тестовую." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Размер обучающей выборки: (723, 10)\n", + "Размер контрольной выборки: (241, 10)\n", + "Размер тестовой выборки: (241, 10)\n" + ] + } + ], + "source": [ + "X = df.drop(columns=['Flexibility Level'])\n", + "Y = df['Flexibility Level']\n", + "\n", + "X_train_df, X_test_df, Y_train_df, Y_test_df = train_test_split(X, Y, test_size=0.2, random_state=42)\n", + "\n", + "X_train_df, X_val_df, Y_train_df, Y_val_df = train_test_split(X_train_df, Y_train_df, test_size=0.25, random_state=42)\n", + "\n", + "print(\"Размер обучающей выборки:\", X_train_df.shape)\n", + "print(\"Размер контрольной выборки:\",X_val_df.shape)\n", + "print(\"Размер тестовой выборки:\", X_test_df.shape)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Проверка сбалансированности данных." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Распределение классов в обучающей выборке:\n", + "Flexibility Level\n", + "1 0.531120\n", + "0 0.385892\n", + "2 0.082988\n", + "Name: proportion, dtype: float64\n", + "\n", + "Распределение классов в контрольной выборке:\n", + "Flexibility Level\n", + "1 0.522822\n", + "0 0.406639\n", + "2 0.070539\n", + "Name: proportion, dtype: float64\n", + "\n", + "Распределение классов в тестовой выборке:\n", + "Flexibility Level\n", + "1 0.477178\n", + "0 0.427386\n", + "2 0.095436\n", + "Name: proportion, dtype: float64\n" + ] + }, + { + "data": { + "image/png": "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Nzc3/fDDDw5npma1TUk6cuSIpEtngOa0zRIlSmj27NlZ3n5lAN2gQQO99tprDssmTZqkr7/+Osv1d+zYoY8++kizZs3Kcq5vm82mu+66S2PHjs1y/ZCQkGxrz1SzZk298847kqSjR4/q3XffVbNmzbRx48Ycjz23Zs2apR49eqhDhw4aMmSISpQoIQ8PD8XFxdnnj7/cxIkTlZKSou3btysuLk5PPfWUZs2a5TDmyJEjWQbL2XnxxRcVFRWlFi1aOP3opCRNmTJF7du3V6NGja66rfbt2zv9IOXLL79sf75crnfv3urUqZMyMjK0Y8cOjRgxQh06dNC2bduy3f6xY8e0fv16SdL27dtls9kcPqjKSatWrTRkyBBJl85QHz16tJo3b67169c7nPF8LXVdvp6rrF69Wq+//rrWrVunQYMGqXXr1g7fOFixYoXatWunJk2a6L333lPJkiVVsGBBxcfH69NPP3Xa3vXcxwAAAPkNQTcAALhtzZ8/X82bN3c6K/Wff/5xCI/Kly+vNWvW6MKFCzfkBxUzZZ6xnckYoz///FM1a9a071eSChcurMjIyKtu7/fff9eFCxdyDPczt2uMUbly5exnjuZk+/btcnNzy/IM1cu3uWTJEjVu3DhXgWBAQIDTMeX0g5FDhw5V7dq19eijj2a7/99//1333XdfnqeTueOOOxxqatasmUqVKqX4+Phsf1A00+HDh5WamupwVvcff/whSQoLC5N06fl255136ssvv3SoMfOM4ivVq1dPknT//ferRIkS6t69u1566SVVrVpV0qWpVv7880+1bt06V8e3YMECJSQkZDlNSqb69etr79692rx5s06fPi1Jmjlzpj755BOnsWXKlHF6DMePH59l0F2xYkX72KioKJ09e1YvvfRSjj/02a9fP50+fVpxcXEaOnSoxo8fr8GDB+fqWEuWLOlQW+XKldWoUSMtWLBAXbt2zVNdmWfd79q1y+EMbJvNpt27d6tOnTqS/ndG+65du+xT52TatWuX0wcTNptNe/fudfi/eOVzJ1PPnj01bNgwHT58WNWqVdOgQYMcHpsvvvhC3t7e+vHHHx2mtImPj8/yfrqe+xgAACC/4eN6AABw2/Lw8HCal3fevHk6dOiQw7KHH35YKSkpmjRpktM2cjuvb1ZmzpxpDxOlS0Ho33//rfvvv1+SFB4ervLl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jPz8/PTss8867fPgwYPy8PBQXFycJKlHjx5Zfp3Wzc1NI0aMsF//66+/1LdvX1WuXFk+Pj4qXry4OnXqpH379jmst3z5crm5uWn58uX2ZevWrVPLli1VqFAh+fn5qVmzZlqxYoXDeh999JHc3Ny0fv16+7KUlBSnOiSpbdu2TjWvWLFCnTp1UtmyZeXl5aWQkBANGjRI586dczq2+fPnq27duipUqJDc3Nzsl7fffttpbFY1Zl58fX1111136YMPPnAY16NHD/n7++e4rSuPKzePa6bk5GQ98cQTCgoKkre3t2rVqqWPP/7YYcy+ffvsxzRu3DiFhobKx8dHTZs21datW53qvfL+nDVrltzd3fXmm2/al23evFk9evTQnXfeKW9vbwUHB6tnz546duxYjscKAFa2adMmtW/fXiVLltSPP/6YZcg9b948hYeHy8fHRwEBAfrPf/6jQ4cOOYzJrjfMnz/foW82a9bModdkdcnk5uam/v37a/bs2apcubK8vb0VHh6uX375xWk/v/32m+6//34VLlxY/v7+uu+++7R69eosjzm7Gj766COHMTVq1Ljq/ZdZ45Wy6uVvv/22GjVqpOLFi8vHx0fh4eGaP3++07pnzpzRc889pzvvvFMFCxZ0qDElJSXHeq48toCAALVp08apN2ZXd6bM1wSZr4PWrVsnm82m9PR01a1bV97e3ipevLi6du2q/fv3O63/008/KSIiQn5+fipatKjat2+vHTt2OIwZMWKE3NzctHPnTnXu3FmFCxdW8eLF9eyzz+r8+fNO9V7+uuLixYt64IEHVKxYMW3fvt2+PD4+Xi1atFCJEiXk5eWlatWq6f3338/xPgMAXJKWlqbY2FhVqFDB/p7zhRdeUFpamtPYWbNmqX79+vL19dUdd9yhJk2aaNGiRZKksLCwHPv85f0xNTVVzz33nEJCQuTl5aXKlSvr7bffdgrjL1/fw8NDpUuXVu/evfXPP//Yx6Snp2v48OEKDw9XkSJF5Ofnp4iICC1btsyp/sz3nGXLlpWHh4d921d7n3vl8bm7uys4OFiPPvqoQz+8/P1qdjL7YKbVq1fL29tbe/bsUfXq1eXl5aXg4GD16dNHx48fd1r/Wl6f7d27V1FRUfLz81OpUqU0atQoh/s4s97LXwudPn1a4eHhKleunP7++2/78ty+ngGywtQlsLRvvvlGYWFhioiIyPL2Jk2aKCwsTN9995192bFjxzRt2jT5+/trwIABCgwM1KxZs9SxY0fNnj1bXbt2lb+/vx566CHNnTtXY8eOdfh69WeffSZjjLp163ZNta5bt06//vqrunTpojJlymjfvn16//331axZM23fvl2+vr5Zrvfnn3+qWbNm8vX11ZAhQ+Tr66vp06crMjJSixcvVpMmTa6pjuzMmzdPZ8+e1dNPP63ixYtr7dq1mjhxog4ePKh58+bZxyUkJKhz586qVauW3nzzTRUpUkQpKSkaNGhQrvc1btw4BQQE6NSpU5oxY4Z69eqlsLAwRUZG5rn+3DyuknTu3Dk1a9ZMf/75p/r3769y5cpp3rx56tGjh/755x+nDzdmzpyp06dPq1+/fjp//rwmTJigFi1aaMuWLQoKCsqylkWLFqlnz57q37+/wzQqixcv1t69exUTE6Pg4GBt27ZN06ZN07Zt27R69epcz3EHAFaxZ88etW7dWl5eXvrxxx9VsmRJpzGZZ4DXq1dPcXFxSkpK0oQJE7Rq1Sr99ttvKlq06DXt86WXXtKTTz4pSfb+1Lt372xfK/z888+aO3euBgwYIC8vL7333ntq3bq11q5daw+it23bpoiICBUuXFgvvPCCChYsqKlTp6pZs2b6+eef1aBBA6ftVqlSRS+99JJDHTfbhAkT1K5dO3Xr1k3p6emaM2eOOnXqpG+//VZt2rSxjxsyZIimTJmiJ554Qo0bN1bBggX15Zdf6quvvsrVfjKPzRijPXv2aOzYsXrggQeyDKRzK/ND3/79+ys8PFxvvvmmjh49qnfffVcrV67Ub7/9poCAAEnSkiVLdP/99+vOO+/UiBEjdO7cOU2cOFGNGzfWxo0bnT4A6Ny5s8LCwhQXF6fVq1fr3Xff1YkTJzRz5sxs63nyySe1fPlyLV68WNWqVbMvf//991W9enW1a9dOBQoU0DfffKO+ffvKZrOpX79+eT5+APi3s9lsateunVauXKnevXuratWq2rJli8aNG6c//vjD4QSlkSNHasSIEWrUqJFGjRolT09PrVmzRj/99JNatWql8ePH68yZM5KkHTt26I033tCwYcPsU6RkhsnGGLVr107Lli3TE088odq1a+vHH3/UkCFDdOjQIY0bN86hxoceekgdO3bUxYsXlZCQoGnTpuncuXP2qVhOnTql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Nzc3denSJcuznN5++21VrFgxy7OJbrSMjAy1bNlSx48f14svvqgqVarIz89Phw4dUo8ePRzq69KlizZu3KiJEydq2rRpedrfrFmzFBQUpPPnz+unn35Sv3795O3trR49etjHeHt765tvvpF06cOKGTNmaODAgSpZsqQ6d+7stM1reVxvhpSUFPn5+embb75Rhw4dFBcXp9jYWIcxnTt31q+//qohQ4aodu3a8vf3l81mU+vWrXN9phsAWMWYMWPsHwxPmzZN99xzj4YOHar33nsvz9u8vDdkWrFiRbbzP7rKkSNHFBUVddVxYWFhmj59uqRL82a+++67evzxx3XnnXfav/EjSe3bt3f6YceXX35ZR44csV9fsWKF2rVrpyZNmui9995TyZIlVbBgQcXHxzuF59OmTVPXrl0dPri/FjVr1rS/Sc2cR7tZs2bauHGjgoODneo2xigxMVGjRo1S27Zts3wDfiv7eHZnBK5du1a9evWSn5+fXnvtNXXq1MnhTf6ePXt03333qUqVKho7dqxCQkLk6emp77//XuPGjaOXA0AObDab7rrrLo0dOzbL20NCQm5xRc4ef/xxde/eXTabTXv37tWrr76qtm3basmSJXJzc9OsWbPUo0cPdejQQUOGDFGJEiXk4eGhuLg47dmzx2Fbc+fOVbdu3ZxeD/j5+eWqllatWmnIkCGSpIMHD2r06NFq3ry51q9f79Aze/furU6dOikjI0M7duzQiBEj1KFDB23bts1pm65+zyxd+kHM119/XevWrdOgQYPUunVrh2+EXcvrGSArBN2wtLZt22r69OlauXKl7r33XqfbV6xYoX379qlPnz72ZeXKldOuXbucxu7cuVOSHH7AqEaNGqpTp45mz56tMmXKaP/+/Zo4caLTuh9++KGGDx+uPXv22N/ktGzZ0mHM/PnzFR0dbX9jKF36Su/lv+J8ufDwcDVt2lT+/v65rjevtmzZoj/++EMff/yxunfvbl++ePFip7Hu7u56++23tWXLFiUmJuq9995TUlKSw3QuV9O4cWN73W3bttW2bdsUFxfnEHR7eHg4/DhlmzZtVKxYMS1cuDDLoDu3j2toaKg2b94sm83mcFZ35rjQ0FCH9bN6M/7HH3843e++vr5auHChqlSpokGDBumNN95Q586d7WcLnDhxQkuXLtXIkSM1fPjwHLcPAP8Gl/9Ycr169dSvXz9NnjxZ3bt3t4e4mX9zd+3aZf/qcqZdu3Y5/U2+sjdIyraP5lZ2f+d9fX0VGBgo6dLf+Ox6jLu7u8Ob84MHD+r06dP2v/858fPzczieiIgIlS5dWosWLXIIusuUKeN03OPHj3cIur/44gt5e3vrxx9/dJg2JT4+3mm/YWFhmjVrlu666y717NlTHTp00MyZM+0/tnU1d9xxh0M9zZo1U6lSpRQfH6+hQ4dmW7e/v7+6devmMCVapsxvOGX1XNi5c6dDH88cd6WdO3cqICDAKUTYvXu3ffvSpR/6ttlsTr28ZcuWev/993X+/HktWLBAvXv31vLly+3B+DfffKO0tDT93//9n8qWLWtfL/Pr9gCA7JUvX94+FUhOU5CUL19eNptN27dvd/hxx7wIDQ3VkiVLdPr0aYezurN773fnnXc69K0iRYroscce0+rVq9WwYUPNnz9fd955p7788kuHY7jyBCdJqlOnjqZPn66IiAiNGjVK99xzj8aMGaNVq1blqvaSJUs61FK5cmU1atTIfhJepooVK9rHRUVF6ezZs3rppZey/IHoy3vt5Wdg22w27d69W3Xq1HG4X3L7+izzg4HMs7ilS6+lJOe8omfPnho2bJgOHz6satWqadCgQQ6vP67l9QyQFaYugaUNGTJEPj4+6tOnj44dO+Zw2/Hjx/XUU0/J19fX/kmoJD3wwANau3atfv31V/uy8+fP6/3331dwcLDDPJ3SpU91Fy1apPHjx6t48eK6//77s6wlNDRULVq0UGRkpNObUenSm/Mr58yaOHGiMjIysj0+Nzc3tWrVSj/++KN27NjhcGwff/yx6tatq6CgoGzXz63M+bkur88Yk+1UIRMnTtRPP/2k2bNnKzIyUo0bN76u/Z87d+6qX+PKrO3yucQul9vH9YEHHtCRI0c0d+5c+7iLFy9q4sSJ8vf3d5orfMGCBTp06JD9+tq1a7VmzRqn50FgYKD9K2CjRo1SmTJl1KtXL6e6r3wOjB8/PsfjBoB/i9dff10lS5ZU7969dfHiRUlS3bp1VaJECU2ZMsWhD/zwww/asWOH2rRpc9PrSkhIcJjz8cCBA/r666/VqlUreXh4yMPDQ61atdLXX3/t8PXbpKQkffrpp7r33nvt3xqTLn3VWJLTG8PcyPywPLtelxMPDw+5ubk5vK7Yt2+fFixY4DT24sWL6tatm6pXr65x48YpMjLS6SvH1+LcuXOSdNVentPx1alTR8HBwU7PhRUrVmj9+vVq27atpEtv/GvXrq2PP/7Y4UOOrVu3atGiRXrggQectj158mSH65knLVzZyxs1aiQPDw/5+flpypQp+uWXX+xn3F9e9+W9/OTJk7z5BoBc6Ny5sw4dOuTwdzXTuXPn7NNOdejQQe7u7ho1apTTN2VyOwd1pgceeEAZGRmaNGmSw/Jx48bJzc0t2/f2l9cl/a+/ZdUH1qxZo4SEBKd1T506pccff1zt2rXTyy+/rMjISJUsWfKa6s+pluzk1Gvvu+8+eXl56d1333W4b2fPnq2kpCR7r83L67PL72NjjCZNmqSCBQs6zSseEREhSSpVqpRGjx6tWbNmOUzHdi2vZ4CscEY3LK1ixYr6+OOP1a1bN91111164oknVK5cOe3bt08ffvihUlJS9Nlnn6l8+fL2dV544QXNnj1b999/vwYMGKCAgADNmjVL27dv1+zZs1WggON/i8cee0wvvPCCvvrqKz399NMqWLBgnmpt27atPvnkExUpUkTVqlVTQkKClixZctUfqHj11Vf1448/qmnTpnrmmWfk6+ur6dOn659//tH8+fOdxickJNjnCM/8caw///xTCxcutI85evSozp07p4ULF6p169aqUqWKypcvr+eff16HDh1S4cKF9cUXX2Q5Z9a2bdv0wgsvaMSIEapXr16e7osFCxYoICDAPnXJihUrNHDgQIcxGRkZ9ppPnz6t+Ph4paamqkOHDlluM7ePa+/evTV16lT7j3mGhYVp/vz5WrVqlcaPH+80f1uFChV077336umnn1ZaWpr9A48XXngh2+Pz8fHRtGnTFBkZqffff199+/ZV4cKF1aRJE7311lu6cOGC/Yy9xMTEPN2HAGA1hQoV0sSJE9WxY0e98847evHFF1WwYEGNHj1aMTExatq0qbp27aqkpCRNmDBBYWFhGjRo0E2vq0aNGoqKitKAAQPk5eVln1pl5MiR9jGvvfaaFi9erHvvvVd9+/ZVgQIFNHXqVKWlpemtt96SdCn4jo2N1QcffKAuXbpkOdf0lc6cOWPvdcePH9e7776rggUL5ingb9OmjcaOHavWrVvrscceU3JysiZPnqwKFSo4TfM2cuRIbdmyRb/99lueXtckJSVp1qxZki5N3TV16lQVKFDA/gY50/79+7Vw4UL71CWvv/66QkNDVadOHacz6QsUKKC33npL3bt3V0REhLp162afFqVMmTJ68cUX7WPHjBmj+++/Xw0bNtQTTzyhc+fOaeLEiSpSpIhGjBjhVG9iYqLatWun1q1bKyEhQbNmzdJjjz2mWrVqZXuMUVFR+s9//qMXXnhBDz74oEqWLKlWrVrJ09NTDz74oPr06aMzZ85o+vTpKlGihP7+++9rvh8B4Hby+OOP6/PPP9dTTz2lZcuWqXHjxsrIyNDOnTv1+eef68cff1TdunVVoUIFvfTSS3r11VcVERGhjh07ysvLS+vWrVOpUqUUFxeX630++OCDat68uV566SXt27dPtWrV0qJFi/T1119r4MCBDjmBdGna01mzZskYoz179th7UN26dSVdek//5Zdf6qGHHlKbNm2UmJioKVOmqFq1ajpz5ozDtvr166dz585lOa92buzdu9feaw8dOqRJkyapcOHCTsHxrl27tHDhQvtZ8GPGjFG9evVUunRpp20WK1ZML7/8sl555RVFRUWpffv22rt3ryZNmqRatWrpySeflKRrfn3m7e2thQsXKjo6Wg0aNNAPP/yg7777TsOGDbN/Oy4rvXv31qeffqqnnnpKW7dutc8xntvXM0CWDPAvsHnzZtO1a1dTsmRJU7BgQRMcHGy6du1qtmzZkuX4PXv2mEceecQUKVLEeHt7m3r16pkFCxZku/0HHnjASDK//vprrmuSZGJjY+3XT5w4YWJiYkxAQIDx9/c3UVFRZufOnSY0NNRER0fbxy1btsxIMsuWLbMv27Bhg2nVqpXx9/c3vr6+pkmTJubnn3922F98fLyRdM2XTNu3bzeRkZHG39/fBAQEmF69epnff//dSDLx8fHGGGPOnz9vatasae69915z8eJF+7qJiYlGkhkzZkyO98mVNXp6epoKFSqY4cOHm/Pnz9vHRUdHO4zz9/c3d999t/nkk0+yvX+Nyf3jmpSUZH8sPD09zV133WU/xqyO6Z133jEhISHGy8vLREREmN9//91hbHR0tAkNDXXaT0xMjClcuLA5ePCgMcaYgwcPmoceesgULVrUFClSxHTq1MkcPnw4y2MBAKvK/Fu/bt26LG9v37698fX1NXv37rUvmzt3rqlTp47x8vIyxYoVM926dbP/7cwUHR1t/Pz8nLY3b948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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "\n", + "def analyze_balance(y_train, y_val, y_test, y_name):\n", + " print(\"Распределение классов в обучающей выборке:\")\n", + " print(y_train.value_counts(normalize=True))\n", + " \n", + " print(\"\\nРаспределение классов в контрольной выборке:\")\n", + " print(y_val.value_counts(normalize=True))\n", + " \n", + " print(\"\\nРаспределение классов в тестовой выборке:\")\n", + " print(y_test.value_counts(normalize=True))\n", + "\n", + " fig, axes = plt.subplots(1, 3, figsize=(18, 5), sharey=True)\n", + " fig.suptitle('Распределение в различных выборках')\n", + "\n", + " sns.barplot(x=y_train.value_counts().index, y=y_train.value_counts(normalize=True), ax=axes[0])\n", + " axes[0].set_title('Обучающая выборка')\n", + " axes[0].set_xlabel(y_name)\n", + " axes[0].set_ylabel('Доля')\n", + "\n", + " sns.barplot(x=y_val.value_counts().index, y=y_val.value_counts(normalize=True), ax=axes[1])\n", + " axes[1].set_title('Контрольная выборка')\n", + " axes[1].set_xlabel(y_name)\n", + "\n", + " sns.barplot(x=y_test.value_counts().index, y=y_test.value_counts(normalize=True), ax=axes[2])\n", + " axes[2].set_title('Тестовая выборка')\n", + " axes[2].set_xlabel(y_name)\n", + "\n", + " plt.show()\n", + "\n", + "analyze_balance(Y_train_df, Y_val_df, Y_test_df, 'Flexibility Level')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Выполним оверсемплинг для балансировки." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Распределение классов в обучающей выборке:\n", + "Flexibility Level\n", + "2 0.333333\n", + "0 0.333333\n", + "1 0.333333\n", + "Name: proportion, dtype: float64\n", + "\n", + "Распределение классов в контрольной выборке:\n", + "Flexibility Level\n", + "1 0.333333\n", + "0 0.333333\n", + "2 0.333333\n", + "Name: proportion, dtype: float64\n", + "\n", + "Распределение классов в тестовой выборке:\n", + "Flexibility Level\n", + "1 0.477178\n", + "0 0.427386\n", + "2 0.095436\n", + "Name: proportion, dtype: float64\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABboAAAHyCAYAAAAtJXgGAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABt6klEQVR4nO3deXhMZ//H8U8SsltKSCyRqH2ppbEUjTVEG0W1lHoqokWLKlrtQ1tBl1S1StFaWulCS2mrv25qKS0ae9WuaqeViF2QkLl/f7gyjzFJRITJqffruua6zJn7nPM9MyPfmc+cucfNGGMEAAAAAAAAAIBFubu6AAAAAAAAAAAAbgRBNwAAAAAAAADA0gi6AQAAAAAAAACWRtANAAAAAAAAALA0gm4AAAAAAAAAgKURdAMAAAAAAAAALI2gGwAAAAAAAABgaQTdAAAAAAAAAABLI+gGAAAAgFyw2WxKTk7Wnj17XF0KAADAbY+gGwAAAABy6MiRIxo0aJBCQkLk6empEiVKqHr16jp9+rSrSwMAALitFXB1AQAAAHnto48+UkxMjP26l5eXypUrpzZt2ujll19WYGCgC6sDYFV//fWXWrRooYsXL2rgwIG6++67VaBAAfn4+MjPz8/V5QEAANzWCLoBAMC/1ujRo1W+fHlduHBBK1as0Pvvv68ffvhBW7Zska+vr6vLA2Axffv2laenp1atWqUyZcq4uhwAAABcgaAbAAD8a913332qV6+eJOmJJ55Q8eLFNW7cOH3zzTfq1q2bi6sDYCXr16/Xzz//rIULFxJyAwAA5EPM0Q0AAG4bLVu2lCTt3btXknT8+HE999xzuuuuu+Tv76/ChQvrvvvu0x9//OG07oULFzRy5EhVrlxZ3t7eKlWqlDp16qTdu3dLkvbt2yc3N7csL82bN7dva9myZXJzc9OcOXM0fPhwBQUFyc/PT+3bt9fBgwed9r169Wq1bdtWRYoUka+vr5o1a6aVK1dmeozNmzfPdP8jR450Gjtz5kyFhYXJx8dHxYoVU9euXTPdf3bHdiWbzabx48erRo0a8vb2VmBgoPr27asTJ044jAsNDVW7du2c9jNgwACnbWZW+9ixY53uU0lKTU1VbGysKlasKC8vLwUHB+v5559XampqpvfVla6+3wICAhQVFaUtW7bkaN2aNWtq/fr1aty4sXx8fFS+fHlNmTLFYVxaWppGjBihsLAwFSlSRH5+fgoPD9fSpUsdxu3cuVMtW7ZUUFCQ/TiefPJJHT9+3GnfPXv2vObj3bNnT4WGhjqsd/DgQfn4+MjNzU379u2T9L/H+aOPPnIYO3LkyEwflwEDBjjV065dO4d9ZWzzrbfeyuLec95+fHy83NzcNGPGDIdxr7/+utzc3PTDDz9kuS3p8vMr435wd3dXUFCQHnnkER04cOCG6lq1apW8vb21e/du1ahRQ15eXgoKClLfvn0zfWzmzp1r//8VEBCg//znPzp8+LDDmJ49e8rf31979uxRZGSk/Pz8VLp0aY0ePVrGGKd6r3xszpw5o7CwMJUvX17//POPfflbb72lxo0bq3jx4vLx8VFYWJjmzZvnsN8bvY8BAADyI87oBgAAt42MULp48eKSpD179mj+/Pnq3Lmzypcvr8TERE2dOlXNmjXTtm3bVLp0aUlSenq62rVrpyVLlqhr16565plndObMGS1atEhbtmxRhQoV7Pvo1q2b7r//fof9Dhs2LNN6XnvtNbm5uemFF15QUlKSxo8fr4iICG3cuFE+Pj6SpJ9//ln33XefwsLCFBsbK3d3d8XHx6tly5Zavny5GjRo4LTdsmXLKi4uTpJ09uxZPfXUU5nu++WXX1aXLl30xBNP6OjRo5o4caKaNm2q33//XUWLFnVap0+fPgoPD5ckffXVV/r6668dbu/bt699fvSBAwdq7969mjRpkn7//XetXLlSBQsWzPR+uB4nT560H9uVbDab2rdvrxUrVqhPnz6qVq2aNm/erHfeeUd//vmn5s+ff81tV61aVS+++KKMMdq9e7fGjRun+++/3yEgzcqJEyd0//33q0uXLurWrZu++OILPfXUU/L09FSvXr0kSadPn9YHH3ygbt26qXfv3jpz5ow+/PBDRUZGas2aNapTp44kKSUlRWXLltUDDzygwoULa8uWLZo8ebIOHz6sb7/91mnfAQEBeuedd+zXH3vssWvWO2LECF24cOGa41whJiZGX331lYYMGaLWrVsrODhYmzdv1qhRo/T44487/f/KTHh4uPr06SObzaYtW7Zo/Pjx+vvvv7V8+fJc13Xs2DFduHBBTz31lFq2bKknn3xSu3fv1uTJk7V69WqtXr1aXl5ekv73OwH169dXXFycEhMTNWHCBK1cudLp/1d6erratm2r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xx8dzkzNbJuSdOTIEUmXzwDNbpslS5bUrFmzMr396gC6YcOGevXVVx2WTZo0Sd98802m62/fvl0fffSRZs6cmelc3zabTXfddZfGjRuX6frBwcFZ1p6hVq1aevvttyVJR48e1bvvvqvmzZtrw4YN2R57Ts2cOVM9e/ZUx44dNXToUJUsWVIeHh6Ki4uzzx9/pYkTJyo5OVnbtm1TXFycnnzySc2cOdNhzJEjRzINlrPywgsvKDIyUi1btnT60UlJmjJlijp06KDGjRtfc1sdOnRw+kHKl156yf58uVKfPn3UuXNnpaena/v27Ro5cqQ6duyorVu3Zrn9Y8eOad26dZKkbdu2yWazOXxQlZ02bdpo6NChki6foT5mzBi1aNFC69atczjj+XrqunI9V1m1apVee+01rV27VoMHD1bbtm0dvnGwfPlytW/fXk2bNtV7772nUqVKqWDBgoqPj9dnn33mtL0buY8BAADyG4JuAABw25o3b55atGjhdFbqyZMnHcKjChUqaPXq1bp48WKe/KBihowztjMYY/TXX3+pVq1a9v1KUuHChRUREXHN7f3xxx+6ePFituF+xnaNMSpfvrz9zNHsbNu2TW5ubpmeoXrlNhcvXqwmTZrkKBAMCAhwOqbsfjBy2LBhqlOnjh555JEs9//HH3+oVatWuZ5O5o477nCoqXnz5ipdurTi4+Oz/EHRDH///bdSUlIczur+888/JUmhoaGSLj/f7rzzTn311VcONWacUXy1+vXrS5Luu+8+lSxZUj169NCLL76oatWqSbo81cpff/2ltm3b5uj45s+fr4SEhEynScnQoEED7dmzR5s2bdKZM2ckSZ988ok+/fRTp7Fly5Z1egzHjx+fadBdqVIl+9jIyEidO3dOL774YrY/9Nm/f3+dOXNGcXFxGjZsmMaPH68hQ4bk6FhLlSrlUFuVKlXUuHFjzZ8/X926dctVXRln3e/cudPhDGybzaZdu3apbt26kv53RvvOnTvtU+dk2Llzp9MHEzabTXv27HH4v3j1cydDr169NHz4cP3999+qXr26Bg8e7PDYfPnll/L29tZPP/3kMKVNfHx8pvfTjdzHAAAA+Q0f1wMAgNuWh4eH07y8c+fO1eHDhx2WPfTQQ0pOTtakSZOctpHTeX0z88knn9jDROlyEPrPP//ovvvukySFhYWpQoUKeuut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FR4enuntTZs2VWhoqL7//nv7smPHjmnatGny9/fXwIEDVaJECc2cOVOdOnXSrFmz1K1bN/n7++vBBx/UnDlzNG7cOIevV3/++ecyxqh79+7XVevatWv122+/qWvXripbtqz27dun999/X82bN9e2bdvk6+ub6Xp//fWXmjdvLl9fXw0dOlS+vr6aPn26IiIitGjRIjVt2vS66sjK3Llzde7cOT311FMqXry41qxZo4kTJ+rQoUOaO3eufVxCQoK6dOmi2rVr64033lCRIkWUnJyswYMH53hf77zzjgICAnT69GnNmDFDvXv3VmhoqCIiInJdf04eV0k6f/68mjdvrr/++ksDBgxQ+fLlNXfuXPXs2VMnT550+nDjk08+0ZkzZ9S/f39duHBBEyZMUMuWLbV582YFBgZmWsvChQvVq1cvDRgwwGEalUWLFmnPnj2KiYlRUFCQtm7dqmnTpmnr1q1atWpVjue4AwCr2L17t9q2bSsvLy/99NNPKlWqlNOYjDPA69evr7i4OCUmJmrChAlauXKlfv/9dxUtWvS69vniiy/qiSeekCR7f+rTp0+WrxV++eUXzZkzRwMHDpSXl5fee+89tW3bVmvWrLEH0Vu3blV4eLgKFy6s559/XgULFtTUqVPVvHlz/fLLL2rYsKHTdqtWraoXX3zRoY6bbcKECWrfvr26d++utLQ0zZ49W507d9Z3332nqKgo+7ihQ4dqypQpevzxx9WkSRMVLFhQX331lb7++usc7Sfj2Iwx2r17t8aNG6f7778/00A6pzI+9B0wYIDCwsL0xhtv6OjRo3r33Xe1YsUK/f777woICJAkLV68WPfdd5/uvPNOjRw5UufPn9fEiRPVpEkTbdiwwekDgC5duig0NFRxcXFatWqV3n33XZ04cUKffPJJlvU88cQTWrZsmRYtWqTq1avbl7///vuqUaOG2rdvrwIFCujbb79Vv379ZLPZ1L9//1wfPwD829lsNrVv314rVqxQnz59VK1aNW3evFnvvPOO/vzzT4cTlEaNGqWRI0eqcePGGj16tDw9PbV69Wr9/PPPatOmjcaPH6+zZ89KkrZv367XX39dw4cPt0+RkhEmG2PUvn17LV26VI8//rjq1Kmjn376SUOHDtXhw4f1zjvvONT44IMPqlOnTrp06ZISEhI0bdo0nT9/3j4Vy+nTp/XBBx+o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6tq1a6ZnOb311luqVKlSpmcT5bX09HS1bt1ax48f1wsvvKCqVavKz89Phw8fVs+ePR3q69q1qzZs2KCJEydq2rRpudrfzJkzFRgYqAsXLujnn39W//795e3trZ49e9rHeHt769tvv5V0+cOKGTNmaNCgQSpVqpS6dOnitM3reVxvhuTkZPn5+enbb79Vx44dFRcXp9jYWIcxXbp00W+//aahQ4eqTp068vf3l81mU9u2bXN8phsAWMXYsWPtHwxPmzZN99xzj4YNG6b33nsv19u8sjdkWL58eZbzP7rKkSNHFBkZec1xoaGhmj59uqTL82a+++67euyxx3TnnXfav/EjSR06dHD6YceXXnpJR44csV9fvny52rdvr6ZNm+q9995TqVKlVLBgQcXHxzuF59OmTVO3bt0cPri/HrVq1bK/Sc2YR7t58+basGGDgoKCnOo2xmjv3r0aPXq02rVrl+kb8FvZx7M6I3DNmjXq3bu3/Pz89Oqrr6pz584Ob/J3796tVq1aqWrVqho3bpyCg4Pl6empH374Qe+88w69HACyYbPZdNddd2ncuHGZ3h4cHHyLK3L22GOPqUePHrLZbNqzZ49eeeUVtWvXTosXL5abm5tmzpypnj17qmPHjho6dKhKliwpDw8PxcXFaffu3Q7bmjNnjrp37+70esDPzy9HtbRp00ZDhw6VJB06dEhjxoxRixYttG7dOoee2adPH3Xu3Fnp6enavn27Ro4cqY4dO2rr1q1O23T1e2bp8g9ivvbaa1q7dq0GDx6stm3bOnwj7HpezwCZIeiGpbVr107Tp0/XihUrdO+99zrdvnz5cu3bt099+/a1Lytfvrx27tzpNHbHjh2S5PADRjVr1lTdunU1a9YslS1bVgcOHNDEiROd1v3www81YsQI7d692/4mp3Xr1g5j5s2bp+joaPsbQ+nyV3qv/BXnK4WFhalZs2by9/fPcb25tXnzZv3555/6+OOP1aNHD/vyRYsWOY11d3fXW2+9pc2bN2vv3r167733lJiY6DCdy7U0adLEXne7du20detWxcXFOQTdHh4eDj9OGRUVpWLFimnBggWZBt05fVxDQkK0adMm2Ww2h7O6M8aFhIQ4rJ/Zm/E///zT6X739fXVggULVLVqVQ0ePFivv/66unTpYj9b4MSJE1qyZIlGjRqlESNGZLt9APg3uPLHkuvXr6/+/ftr8uTJ6tGjhz3Ezfibu3PnTvtXlzPs3LnT6W/y1b1BUpZ9NKey+jvv6+urEiVKSLr8Nz6rHuPu7u7w5vzQoUM6c+aM/e9/dvz8/ByOJzw8XGXKlNHChQsdgu6yZcs6Hff48eMdgu4vv/xS3t7e+umnnxymTYmPj3fab2hoqGbOnKm77rpLvXr1UseOHfXJJ5/Yf2zrWu644w6Hepo3b67SpUsrPj5ew4YNy7Juf39/de/e3WFKtAwZ33DK7LmwY8cOhz6eMe5qO3bsUEBAgFOIsGvXLvv2pcs/9G2z2Zx6eevWrfX+++/rwoULmj9/vvr06aNly5bZg/Fvv/1Wqamp+r//+z+VK1fOvl7G1+0BAFmrUKGCfSqQ7KYgqVChgmw2m7Zt2+bw4465ERISosWLF+vMmTMOZ3Vn9d7vzjvvdOhbRYoU0aOPPqpVq1apUaNGmjdvnu6880599dVXDsdw9QlOklS3bl1Nnz5d4eHhGj16tO655x6NHTtWK1euzFHtpUqVcqilSpUqaty4sf0kvAyVKlWyj4uMjNS5c+f04osvZvoD0Vf22ivPwLbZbNq1a5fq1q3rcL/k9PVZxgcDGWdxS5dfS0nOeUWvXr00fPhw/f3336pevboGDx7s8Prjel7PAJlh6hJY2tChQ+Xj46O+ffvq2LFjDrcdP35cTz75pHx9fe2fhErS/fffrzVr1ui3336zL7tw4YLef/99BQUFOczTKV3+VHfhwoUaP368ihcvrvvuuy/TWkJCQtSyZUtFREQ4vRmVLr85v3rOrIkTJyo9PT3L43Nzc1ObNm30008/afv27Q7H9vHHH6tevXoKDAzMcv2cypif68r6jDFZThUyceJE/fzzz5o1a5YiIiLUpEmTG9r/+fPnr/k1rozarpxL7Eo5fVzvv/9+HTlyRHPmzLGPu3TpkiZOnCh/f3+nucLnz5+vw4cP26+vWbNGq1evdnoelChRwv4VsNGjR6ts2bLq3bu3U91XPwfGjx+f7XEDwL/Fa6+9plKlSqlPnz66dOmSJKlevXoqWbKkpkyZ4tAHfvzxR23fvl1RUVE3va6EhASHOR8PHjyob775Rm3atJGHh4c8PDzUpk0bffPNNw5fv01MTNRnn32me++91/6tMenyV40lOb0xzImMD8uz6nXZ8fDwkJubm8Prin379mn+/PlOYy9duqTu3burRo0aeueddxQREeH0lePrcf78eUm6Zi/P7vjq1q2roKAgp+fC8uXLtW7dOrVr107S5Tf+derU0ccff+zwIceWLVu0cOFC3X///U7bnjx5ssP1jJMWru7ljRs3loeHh/z8/DRlyhT9+uuv9jPur6z7yl5+6tQp3nwDQA506dJFhw8fdvi7muH8+fP2aac6duwod3d3jR492umbMjmdgzrD/fffr/T0dE2aNMlh+TvvvCM3N7cs39tfWZf0v/6WWR9YvXq1EhISnNY9ffq0HnvsMbVv314vvfSSIiIiVKpUqeuqP7taspJdr23VqpW8vLz07rvvOty3s2bNUmJior3X5ub12ZX3sTFGkyZNUsGCBZ3mFQ8PD5cklS5dWmPGjNHMmTMdpmO7ntczQGY4oxuWVqlSJX388cfq3r277rrrLj3++OMqX7689u3bpw8//FDJycn6/PPPVaFCBfs6zz//vGbNmqX77rtPAwcOVEBAgGbOnKlt27Zp1qxZKlDA8b/Fo48+queff15ff/21nnrqKRUsWDBXtbZr106ffvqpihQpourVqyshIUGLFy++5g9UvPLKK/rpp5/UrFkzPf300/L19dX06dN18uRJzZs3z2l8QkKCfY7wjB/H+uuvv7RgwQL7mKNHj+r8+fNasGCB2rZtq6pVq6pChQp67rnndPjwYRUuXFhffvllpnNmbd26Vc8//7xGjhyp+vXr5+q+mD9/vgICAuxTlyxfvlyDBg1yGJOenm6v+cyZM4qPj1dKSoo6duyY6TZz+rj26dNHU6dOtf+YZ2hoqObNm6eVK1dq/PjxTvO3VaxYUffee6+eeuoppaam2j/weP7557M8Ph8fH02bNk0RERF6//331a9fPxUuXFhNmzbVm2++qYsXL9rP2Nu7d2+u7kMAsJpChQpp4sSJ6tSpk95++2298MILKliwoMaMGaOYmBg1a9ZM3bp1U2JioiZMmKDQ0FANHjz4ptdVs2ZNRUZGauDAgfLy8rJPrTJq1Cj7mFdffVWLFi3Svffeq379+qlAgQKaOnWqUlNT9eabb0q6HHzHxsbqgw8+UNeuXTOda/pqZ8+etfe648eP691331XBggVzFfBHRUVp3Lhxatu2rR599FElJSVp8uTJqlixotM0b6NGjdLmzZv1+++/5+p1TWJiombOnCnp8tRdU6dOVYECBexvkDMcOHBACxYssE9d8tprrykkJER169Z1OpO+QIECevPNN9WjRw+Fh4ere/fu9mlRypYtqxdeeME+duzYsbrvvvvUqFEjPf744zp//rwmTpyoIkWKaOTIkU717t27V+3bt1fbtm2VkJCgmTNn6tFHH1Xt2rWzPMbIyEj95z//0fPPP68HHnhApUqVUps2beTp6akHHnhAffv21dmzZzV9+nSVLFlS//zzz3XfjwBwO3nsscf0xRdf6Mknn9TSpUvVpEkTpaena8eOHfriiy/0008/qV69eqpYsaJefPFFvfLKKwoPD1enTp3k5eWltWvXqnTp0oqLi8vxPh944AG1aNFCL774ovbt26fatWtr4cKF+uabbzRo0CCHnEC6PO3pzJkzZYzR7t277T2oXr16ki6/p//qq6/04IMPKioqSnv37tWUKVNUvXp1nT171mFb/fv31/nz5zOdVzsn9uzZY++1hw8f1qRJk1S4cGGn4Hjnzp1asGCB/Sz4sWPHqn79+ipTpozTNosVK6aXXnpJL7/8siIjI9WhQwft2bNHkyZNUu3atfXEE09I0nW/PvP29taCBQsUHR2thg0b6scff9T333+v4cOH278dl5k+ffros88+05NPPqktW7bY5xjP6esZIFMG+BfYtGmT6datmylVqpQpWLCgCQoKMt26dTObN2/OdPzu3bvNww8/bIoUKWK8vb1N/fr1zfz587Pc/v33328kmd9++y3HNUkysbGx9usnTpwwMTExJiAgwPj7+5vIyEizY8cOExISYqKjo+3jli5daiSZpUuX2petX7/etGnTxvj7+xtfX1/TtGlT88svvzjsLz4+3ki67kuGbdu2mYiICOPv728CAgJM7969zR9//GEkmfj4eGOMMRcuXDC1atUy9957r7l06ZJ93b179xpJZuzYsdneJ1fX6OnpaSpWrGhGjBhhLly4YB8XHR3tMM7f39/cfffd5tNPP83y/jUm549rYmKi/bHw9PQ0d911l/0YMzumt99+2wQHBxsvLy8THh5u/vjjD4ex0dHRJiQkxGk/MTExpnDhwubQoUPGGGMOHTpkHnzwQVO0aFFTpEgR07lzZ/P3339neiwAYFUZf+vXrl2b6e0dOnQwvr6+Zs+ePfZlc+bMMXXr1jVeXl6mWLFipnv37va/nRmio6ONn5+f0/bmzp3r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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "ros = RandomOverSampler(random_state=42)\n", + "\n", + "X_train_resampled, Y_train_resampled = ros.fit_resample(X_train_df, Y_train_df)\n", + "X_val_resampled, Y_val_resampled = ros.fit_resample(X_val_df, Y_val_df)\n", + "\n", + "analyze_balance(Y_train_resampled, Y_val_resampled, Y_test_df, 'Flexibility Level')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Конструирование признаков. Для начала применим унитарное кодирование категориальных признаков (one-hot encoding), переведя их в бинарные вектора." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
AgeEducation Level_SchoolEducation Level_UniversityInstitution Type_PublicGender_MaleDevice_MobileDevice_TabIT Student_YesLocation_TownFinancial Condition_PoorFinancial Condition_RichInternet Type_WifiNetwork Type_3GNetwork Type_4G
010TrueFalseFalseTrueTrueFalseFalseTrueFalseTrueTrueFalseTrue
118FalseFalseFalseFalseTrueFalseFalseTrueFalseFalseTrueFalseTrue
223FalseTrueFalseTrueTrueFalseFalseTrueFalseFalseTrueFalseTrue
318TrueFalseTrueTrueTrueFalseFalseTrueFalseTrueFalseFalseTrue
423FalseTrueFalseFalseTrueFalseFalseFalseFalseFalseTrueFalseTrue
\n", + "
" + ], + "text/plain": [ + " Age Education Level_School Education Level_University \\\n", + "0 10 True False \n", + "1 18 False False \n", + "2 23 False True \n", + "3 18 True False \n", + "4 23 False True \n", + "\n", + " Institution Type_Public Gender_Male Device_Mobile Device_Tab \\\n", + "0 False True True False \n", + "1 False False True False \n", + "2 False True True False \n", + "3 True True True False \n", + "4 False False True False \n", + "\n", + " IT Student_Yes Location_Town Financial Condition_Poor \\\n", + "0 False True False \n", + "1 False True False \n", + "2 False True False \n", + "3 False True False \n", + "4 False False False \n", + "\n", + " Financial Condition_Rich Internet Type_Wifi Network Type_3G \\\n", + "0 True True False \n", + "1 False True False \n", + "2 False True False \n", + "3 True False False \n", + "4 False True False \n", + "\n", + " Network Type_4G \n", + "0 True \n", + "1 True \n", + "2 True \n", + "3 True \n", + "4 True " + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cat_features = ['Education Level', 'Institution Type', 'Gender', 'Device', 'IT Student', 'Location', 'Financial Condition', 'Internet Type', 'Network Type']\n", + "\n", + "train_encoded = pd.get_dummies(X_train_resampled, columns=cat_features, drop_first=True)\n", + "val_encoded = pd.get_dummies(X_val_resampled, columns=cat_features, drop_first=True)\n", + "test_encoded = pd.get_dummies(X_test_df, columns=cat_features, drop_first=True)\n", + "\n", + "train_encoded.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Применим дискретизацию к числовым признакам." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Education Level_SchoolEducation Level_UniversityInstitution Type_PublicGender_MaleDevice_MobileDevice_TabIT Student_YesLocation_TownFinancial Condition_PoorFinancial Condition_RichInternet Type_WifiNetwork Type_3GNetwork Type_4GAge_Bin
0TrueFalseFalseTrueTrueFalseFalseTrueFalseTrueTrueFalseTrueyoung
1FalseFalseFalseFalseTrueFalseFalseTrueFalseFalseTrueFalseTrueyoung
2FalseTrueFalseTrueTrueFalseFalseTrueFalseFalseTrueFalseTrueyoung
3TrueFalseTrueTrueTrueFalseFalseTrueFalseTrueFalseFalseTrueyoung
4FalseTrueFalseFalseTrueFalseFalseFalseFalseFalseTrueFalseTrueyoung
\n", + "
" + ], + "text/plain": [ + " Education Level_School Education Level_University \\\n", + "0 True False \n", + "1 False False \n", + "2 False True \n", + "3 True False \n", + "4 False True \n", + "\n", + " Institution Type_Public Gender_Male Device_Mobile Device_Tab \\\n", + "0 False True True False \n", + "1 False False True False \n", + "2 False True True False \n", + "3 True True True False \n", + "4 False False True False \n", + "\n", + " IT Student_Yes Location_Town Financial Condition_Poor \\\n", + "0 False True False \n", + "1 False True False \n", + "2 False True False \n", + "3 False True False \n", + "4 False False False \n", + "\n", + " Financial Condition_Rich Internet Type_Wifi Network Type_3G \\\n", + "0 True True False \n", + "1 False True False \n", + "2 False True False \n", + "3 True False False \n", + "4 False True False \n", + "\n", + " Network Type_4G Age_Bin \n", + "0 True young \n", + "1 True young \n", + "2 True young \n", + "3 True young \n", + "4 True young " + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "num_features = ['Age']\n", + "\n", + "def discretize_features(df, features, bins, labels):\n", + " for feature in features:\n", + " df[f'{feature}_Bin'] = pd.cut(df[feature], bins=bins, labels=labels)\n", + " df.drop(columns=[feature], inplace=True)\n", + " return df\n", + "\n", + "age_bins = [0, 25, 55, 100]\n", + "age_labels = [\"young\", \"middle-aged\", \"old\"]\n", + "\n", + "train_encoded = discretize_features(train_encoded, num_features, bins=age_bins, labels=age_labels)\n", + "val_encoded = discretize_features(val_encoded, num_features, bins=age_bins, labels=age_labels)\n", + "test_encoded = discretize_features(test_encoded, num_features, bins=age_bins, labels=age_labels)\n", + "\n", + "train_encoded.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Применим ручной синтез признаков. К примеру, для этого датасета, сделаем признак \"соотвествие устройства для обучения\". Мобильные устройства часто менее удобны для учебы по сравнению с планшетами." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Education Level_SchoolEducation Level_UniversityInstitution Type_PublicGender_MaleDevice_MobileDevice_TabIT Student_YesLocation_TownFinancial Condition_PoorFinancial Condition_RichInternet Type_WifiNetwork Type_3GNetwork Type_4GAge_BinDevice Suitability
0TrueFalseFalseTrueTrueFalseFalseTrueFalseTrueTrueFalseTrueyoungLow
1FalseFalseFalseFalseTrueFalseFalseTrueFalseFalseTrueFalseTrueyoungLow
2FalseTrueFalseTrueTrueFalseFalseTrueFalseFalseTrueFalseTrueyoungLow
3TrueFalseTrueTrueTrueFalseFalseTrueFalseTrueFalseFalseTrueyoungLow
4FalseTrueFalseFalseTrueFalseFalseFalseFalseFalseTrueFalseTrueyoungLow
\n", + "
" + ], + "text/plain": [ + " Education Level_School Education Level_University \\\n", + "0 True False \n", + "1 False False \n", + "2 False True \n", + "3 True False \n", + "4 False True \n", + "\n", + " Institution Type_Public Gender_Male Device_Mobile Device_Tab \\\n", + "0 False True True False \n", + "1 False False True False \n", + "2 False True True False \n", + "3 True True True False \n", + "4 False False True False \n", + "\n", + " IT Student_Yes Location_Town Financial Condition_Poor \\\n", + "0 False True False \n", + "1 False True False \n", + "2 False True False \n", + "3 False True False \n", + "4 False False False \n", + "\n", + " Financial Condition_Rich Internet Type_Wifi Network Type_3G \\\n", + "0 True True False \n", + "1 False True False \n", + "2 False True False \n", + "3 True False False \n", + "4 False True False \n", + "\n", + " Network Type_4G Age_Bin Device Suitability \n", + "0 True young Low \n", + "1 True young Low \n", + "2 True young Low \n", + "3 True young Low \n", + "4 True young Low " + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "train_encoded['Device Suitability'] = train_encoded['Device_Tab'].apply(lambda x: \"High\" if x == True else \"Low\")\n", + "val_encoded['Device Suitability'] = val_encoded['Device_Tab'].apply(lambda x: \"High\" if x == True else \"Low\")\n", + "test_encoded['Device Suitability'] = test_encoded['Device_Tab'].apply(lambda x: \"High\" if x == True else \"Low\")\n", + "\n", + "train_encoded.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Конструирование признаков с помощью фреймворка Featuretools." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "d:\\ulstu\\cr3\\sem1\\MAI\\AIM-PIbd-31-Makarov-DV\\.venv\\Lib\\site-packages\\woodwork\\type_sys\\utils.py:33: UserWarning: Could not infer format, so each element will be parsed individually, falling back to `dateutil`. To ensure parsing is consistent and as-expected, please specify a format.\n", + " pd.to_datetime(\n", + "d:\\ulstu\\cr3\\sem1\\MAI\\AIM-PIbd-31-Makarov-DV\\.venv\\Lib\\site-packages\\woodwork\\type_sys\\utils.py:33: UserWarning: Could not infer format, so each element will be parsed individually, falling back to `dateutil`. To ensure parsing is consistent and as-expected, please specify a format.\n", + " pd.to_datetime(\n", + "d:\\ulstu\\cr3\\sem1\\MAI\\AIM-PIbd-31-Makarov-DV\\.venv\\Lib\\site-packages\\woodwork\\type_sys\\utils.py:33: UserWarning: Could not infer format, so each element will be parsed individually, falling back to `dateutil`. To ensure parsing is consistent and as-expected, please specify a format.\n", + " pd.to_datetime(\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Education Level_SchoolEducation Level_UniversityInstitution Type_PublicGender_MaleDevice_MobileDevice_TabIT Student_YesLocation_TownFinancial Condition_PoorFinancial Condition_RichInternet Type_WifiNetwork Type_3GNetwork Type_4GAge_BinDevice Suitability
id
0TrueFalseFalseTrueTrueFalseFalseTrueFalseTrueTrueFalseTrueyoungLow
1FalseFalseFalseFalseTrueFalseFalseTrueFalseFalseTrueFalseTrueyoungLow
2FalseTrueFalseTrueTrueFalseFalseTrueFalseFalseTrueFalseTrueyoungLow
3TrueFalseTrueTrueTrueFalseFalseTrueFalseTrueFalseFalseTrueyoungLow
4FalseTrueFalseFalseTrueFalseFalseFalseFalseFalseTrueFalseTrueyoungLow
\n", + "
" + ], + "text/plain": [ + " Education Level_School Education Level_University \\\n", + "id \n", + "0 True False \n", + "1 False False \n", + "2 False True \n", + "3 True False \n", + "4 False True \n", + "\n", + " Institution Type_Public Gender_Male Device_Mobile Device_Tab \\\n", + "id \n", + "0 False True True False \n", + "1 False False True False \n", + "2 False True True False \n", + "3 True True True False \n", + "4 False False True False \n", + "\n", + " IT Student_Yes Location_Town Financial Condition_Poor \\\n", + "id \n", + "0 False True False \n", + "1 False True False \n", + "2 False True False \n", + "3 False True False \n", + "4 False False False \n", + "\n", + " Financial Condition_Rich Internet Type_Wifi Network Type_3G \\\n", + "id \n", + "0 True True False \n", + "1 False True False \n", + "2 False True False \n", + "3 True False False \n", + "4 False True False \n", + "\n", + " Network Type_4G Age_Bin Device Suitability \n", + "id \n", + "0 True young Low \n", + "1 True young Low \n", + "2 True young Low \n", + "3 True young Low \n", + "4 True young Low " + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ft_data = train_encoded.copy()\n", + "\n", + "es = ft.EntitySet(id=\"students\")\n", + "es = es.add_dataframe(dataframe_name=\"students_data\", dataframe=ft_data, index=\"id\", make_index=True)\n", + "\n", + "feature_matrix, feature_defs = ft.dfs(\n", + " entityset=es, \n", + " target_dataframe_name=\"students_data\",\n", + " max_depth=1\n", + ")\n", + "\n", + "feature_matrix.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Featuretools не смог сделать новые признаки.\n", + "\n", + "Оценка качества набора признаков." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Время обучения модели: 0.11 секунд\n" + ] + } + ], + "source": [ + "train_encoded = pd.get_dummies(train_encoded, drop_first=True)\n", + "val_encoded = pd.get_dummies(val_encoded, drop_first=True)\n", + "test_encoded = pd.get_dummies(test_encoded, drop_first=True)\n", + "\n", + "cols = train_encoded.columns\n", + "\n", + "train_encoded = train_encoded.reindex(columns=cols, fill_value=0)\n", + "val_encoded = val_encoded.reindex(columns=cols, fill_value=0)\n", + "test_encoded = test_encoded.reindex(columns=cols, fill_value=0)\n", + "\n", + "model = RandomForestClassifier(n_estimators=100, random_state=42)\n", + "\n", + "start = time.time()\n", + "model.fit(train_encoded, Y_train_resampled)\n", + "train_time = time.time() - start\n", + "\n", + "print(f'Время обучения модели: {train_time:.2f} секунд')" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Feature Importance:\n", + " feature importance\n", + "9 Financial Condition_Rich 0.184028\n", + "3 Gender_Male 0.108992\n", + "8 Financial Condition_Poor 0.107030\n", + "2 Institution Type_Public 0.095663\n", + "10 Internet Type_Wifi 0.089925\n", + "7 Location_Town 0.078658\n", + "0 Education Level_School 0.061961\n", + "6 IT Student_Yes 0.055048\n", + "1 Education Level_University 0.049695\n", + "12 Network Type_4G 0.044837\n", + "4 Device_Mobile 0.042086\n", + "11 Network Type_3G 0.038541\n", + "13 Age_Bin_middle-aged 0.034876\n", + "15 Device Suitability_Low 0.004611\n", + "5 Device_Tab 0.004049\n", + "14 Age_Bin_old 0.000000\n" + ] + } + ], + "source": [ + "# Получение важности признаков\n", + "importances = model.feature_importances_\n", + "feature_names = train_encoded.columns\n", + "\n", + "# Сортировка признаков по важности\n", + "feature_importance = pd.DataFrame({'feature': feature_names, 'importance': importances})\n", + "feature_importance = feature_importance.sort_values(by='importance', ascending=False)\n", + "\n", + "print(\"Feature Importance:\")\n", + "print(feature_importance)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "d:\\ulstu\\cr3\\sem1\\MAI\\AIM-PIbd-31-Makarov-DV\\.venv\\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": [ + "\n", + "RMSE: 0.5652451456569942\n", + "R²: 0.22569473420679287\n", + "MAE: 0.2697095435684647 \n", + "\n", + "Кросс-валидация RMSE: 0.5705060311373475 \n", + "\n", + "Train RMSE: 0.5237418787490223\n", + "Train R²: 0.5885416666666667\n", + "Train MAE: 0.19791666666666666\n", + "\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "d:\\ulstu\\cr3\\sem1\\MAI\\AIM-PIbd-31-Makarov-DV\\.venv\\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" + ] + } + ], + "source": [ + "y_pred = model.predict(test_encoded)\n", + "\n", + "# Анализ важности признаков\n", + "feature_importances = model.feature_importances_\n", + "feature_names = train_encoded.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", + "rmse = mean_squared_error(Y_test_df, y_pred, squared=False)\n", + "r2 = r2_score(Y_test_df, y_pred)\n", + "mae = mean_absolute_error(Y_test_df, y_pred)\n", + "\n", + "print()\n", + "print(f\"RMSE: {rmse}\")\n", + "print(f\"R²: {r2}\")\n", + "print(f\"MAE: {mae} \\n\")\n", + "\n", + "# Кросс-валидация\n", + "scores = cross_val_score(model, train_encoded, Y_train_resampled, cv=5, scoring='neg_mean_squared_error')\n", + "rmse_cv = math.sqrt((-scores.mean()))\n", + "print(f\"Кросс-валидация RMSE: {rmse_cv} \\n\")\n", + "\n", + "# Проверка на переобучение\n", + "y_train_pred = model.predict(train_encoded)\n", + "\n", + "rmse_train = mean_squared_error(Y_train_resampled, y_train_pred, squared=False)\n", + "r2_train = r2_score(Y_train_resampled, y_train_pred)\n", + "mae_train = mean_absolute_error(Y_train_resampled, 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", + "print()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/lab_3/requirements.txt b/lab_3/requirements.txt new file mode 100644 index 0000000..f9e243b Binary files /dev/null and b/lab_3/requirements.txt differ