{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Лабораторная работа 3"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>1. Определить две бизнес-цели</b><br><br> \n",
    "Во-первых, у нас есть в датасете есть столбец NumWebPurchases — количество покупок через интернет.<br>Ставим первую бизнес цель: Увеличение продаж через интернет-магазин. А еще у нас имеется столбец Response — отклик на текущую кампанию. Ставим вторую бизнес цель: Анализ отклика на предыдущие кампании для повышения их эффективности."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>2. Определить цели технического проекта </b><br><br>\n",
    "\n",
    "<b>Для увеличения интернет-продаж:</b>\n",
    "\n",
    "Разработать модели сегментации клиентов на основе их характеристик (доход, покупки).\n",
    "Создать прогнозные модели для определения вероятности веб-покупок.\n",
    "\n",
    "<b>Для оптимизации кампаний:</b>\n",
    "\n",
    "Провести анализ данных об откликах клиентов на прошлые кампании.\n",
    "Сформировать рекомендации по улучшению таргетирования на основе анализа успешных кампаний."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>4. Выполнить разбиение каждого набора данных</b> \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "((1329, 16), (443, 16), (444, 16))"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn.model_selection import train_test_split\n",
    "import pandas as pd\n",
    "dataset = pd.read_csv(\".//datasetlab1//marketing_campaign.csv\", sep=\"\\t\")\n",
    "\n",
    "# Удаление неинформативных столбцов и выбор целевых данных для бизнес-целей\n",
    "columns_to_use = [\n",
    "    \"Income\", \"Kidhome\", \"Teenhome\", \"NumWebPurchases\", \"MntWines\", \n",
    "    \"MntFruits\", \"MntMeatProducts\", \"MntFishProducts\", \"MntSweetProducts\",\n",
    "    \"MntGoldProds\", \"AcceptedCmp1\", \"AcceptedCmp2\", \"AcceptedCmp3\", \n",
    "    \"AcceptedCmp4\", \"AcceptedCmp5\", \"Response\", \"Recency\"\n",
    "]\n",
    "\n",
    "# Очистка данных от пропусков и выбор только необходимых столбцов\n",
    "filtered_data = dataset[columns_to_use].dropna()\n",
    "\n",
    "# Разделение данных на признаки (X) и целевую переменную (y) для оптимизации кампаний\n",
    "X = filtered_data.drop(columns=[\"Response\"])\n",
    "y = filtered_data[\"Response\"]\n",
    "\n",
    "# Разбиение на обучающую (60%), контрольную (20%) и тестовую (20%) выборки\n",
    "X_train, X_temp, y_train, y_temp = train_test_split(X, y, test_size=0.4, random_state=42, stratify=y)\n",
    "X_val, X_test, y_val, y_test = train_test_split(X_temp, y_temp, test_size=0.5, random_state=42, stratify=y_temp)\n",
    "\n",
    "# Проверка размера выборок\n",
    "X_train.shape, X_val.shape, X_test.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>5. Оценить сбалансированность выборок </b><br><br>\n",
    "\n",
    "За 0 берем не отклик, за 1 - отклик клиента на рекламу."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 27860 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 28012 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 27236 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Распределение классов в обучающей выборке (в процентах):\n",
      "Response\n",
      "0    84.951091\n",
      "1    15.048909\n",
      "Name: proportion, dtype: float64\n"
     ]
    }
   ],
   "source": [
    "# Импорт необходимых библиотек\n",
    "import seaborn as sns\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# Функция для визуализации распределения классов\n",
    "def plot_class_distribution(y, title):\n",
    "    sns.countplot(x=y_train, color='orange')\n",
    "    plt.title(title)\n",
    "    plt.xlabel(\"Response (Целевой признак)\")\n",
    "    plt.ylabel(\"Количество записей\")\n",
    "    plt.show()\n",
    "\n",
    "# Оценка сбалансированности классов в выборках\n",
    "plot_class_distribution(y_train, \"Распределение классов в обучающей выборке\")\n",
    "plot_class_distribution(y_val, \"Распределение классов в контрольной выборке\")\n",
    "plot_class_distribution(y_test, \"Распределение классов в тестовой выборке\")\n",
    "\n",
    "# Проверка пропорций классов в обучающей выборке\n",
    "class_distribution_train = y_train.value_counts(normalize=True) * 100\n",
    "print(\"Распределение классов в обучающей выборке (в процентах):\")\n",
    "print(class_distribution_train)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>Для второй бизнес цели</b>\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Размеры выборок для второй цели:\n",
      "Обучающая: (1329, 15), Контрольная: (443, 15), Тестовая: (444, 15)\n"
     ]
    }
   ],
   "source": [
    "from sklearn.model_selection import train_test_split\n",
    "\n",
    "# Целевой признак для второй бизнес-цели\n",
    "target_col_2 = 'NumWebPurchases'\n",
    "\n",
    "# Разделение данных на обучающую, контрольную и тестовую выборки\n",
    "X_train_2, X_temp_2, y_train_2, y_temp_2 = train_test_split(\n",
    "    X.drop(columns=[target_col_2]),  # Все признаки, кроме целевого\n",
    "    X[target_col_2],                # Целевой признак\n",
    "    test_size=0.4,                  # 40% на контрольную и тестовую выборки\n",
    "    random_state=42\n",
    ")\n",
    "\n",
    "X_val_2, X_test_2, y_val_2, y_test_2 = train_test_split(\n",
    "    X_temp_2,\n",
    "    y_temp_2,\n",
    "    test_size=0.5,  # 50% от оставшихся данных для тестовой выборки\n",
    "    random_state=42\n",
    ")\n",
    "\n",
    "# Проверим размеры выборок\n",
    "print(\"Размеры выборок для второй цели:\")\n",
    "print(f\"Обучающая: {X_train_2.shape}, Контрольная: {X_val_2.shape}, Тестовая: {X_test_2.shape}\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Оценка:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 33188 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 31660 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "[encoded data, 28932 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Распределение классов в обучающей выборке (в процентах):\n",
      "NumWebPurchases\n",
      "1     15.876599\n",
      "2     15.575621\n",
      "3     14.672686\n",
      "4     13.167795\n",
      "5     10.233258\n",
      "6      8.577878\n",
      "7      6.471031\n",
      "8      4.966140\n",
      "9      3.837472\n",
      "11     2.558315\n",
      "0      2.257336\n",
      "10     1.655380\n",
      "23     0.075245\n",
      "27     0.075245\n",
      "Name: proportion, dtype: float64\n"
     ]
    }
   ],
   "source": [
    "# Функция для визуализации распределения классов\n",
    "def plot_class_distribution(y, title):\n",
    "    sns.countplot(x=y, color='orange')\n",
    "    plt.title(title)\n",
    "    plt.xlabel(\"NumWebPurchases (Целевой признак)\")\n",
    "    plt.ylabel(\"Количество записей\")\n",
    "    plt.show()\n",
    "\n",
    "# Оценка сбалансированности классов в выборках\n",
    "plot_class_distribution(y_train_2, \"Распределение классов в обучающей выборке\")\n",
    "plot_class_distribution(y_val_2, \"Распределение классов в контрольной выборке\")\n",
    "plot_class_distribution(y_test_2, \"Распределение классов в тестовой выборке\")\n",
    "\n",
    "# Проверка пропорций классов в обучающей выборке\n",
    "class_distribution_train_2 = y_train_2.value_counts(normalize=True) * 100\n",
    "print(\"Распределение классов в обучающей выборке (в процентах):\")\n",
    "print(class_distribution_train_2)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>6.</b><br><br> \n",
    "\n",
    "Наблюдаем несбалансированность, для Второй бизнес цели выполним Upsampling (увеличение выборки для редких классов). Делаем покупки больше."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 32048 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Распределение классов после SMOTE (в процентах):\n",
      "Response\n",
      "0    50.0\n",
      "1    50.0\n",
      "Name: proportion, dtype: float64\n"
     ]
    }
   ],
   "source": [
    "from imblearn.over_sampling import SMOTE\n",
    "\n",
    "# Применение SMOTE к обучающей выборке\n",
    "smote = SMOTE(random_state=42)\n",
    "X_train_balanced, y_train_balanced = smote.fit_resample(X_train, y_train)\n",
    "\n",
    "# Проверим распределение после аугментации\n",
    "plot_class_distribution(y_train_balanced, \"Распределение классов после SMOTE (обучающая выборка)\")\n",
    "\n",
    "# Проверим процентное распределение\n",
    "balanced_distribution = y_train_balanced.value_counts(normalize=True) * 100\n",
    "print(\"Распределение классов после SMOTE (в процентах):\")\n",
    "print(balanced_distribution)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>Для первой бизнес цели:</b>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Размерность выборки после RandomOverSampler:\n",
      "X_train_res: (2954, 15)\n",
      "y_train_res: (2954,)\n",
      "\n",
      "Распределение классов после балансировки (в процентах):\n",
      "NumWebPurchases\n",
      "2     7.142857\n",
      "5     7.142857\n",
      "1     7.142857\n",
      "8     7.142857\n",
      "9     7.142857\n",
      "3     7.142857\n",
      "11    7.142857\n",
      "7     7.142857\n",
      "6     7.142857\n",
      "4     7.142857\n",
      "0     7.142857\n",
      "10    7.142857\n",
      "23    7.142857\n",
      "27    7.142857\n",
      "Name: proportion, dtype: float64\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 31360 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from imblearn.over_sampling import RandomOverSampler\n",
    "import pandas as pd\n",
    "\n",
    "# Применение RandomOverSampler для балансировки классов\n",
    "ros = RandomOverSampler(random_state=42)\n",
    "X_train_res, y_train_res = ros.fit_resample(X_train_2, y_train_2)\n",
    "\n",
    "# Выводим новые размеры выборки\n",
    "print(f\"Размерность выборки после RandomOverSampler:\")\n",
    "print(f\"X_train_res: {X_train_res.shape}\")\n",
    "print(f\"y_train_res: {y_train_res.shape}\")\n",
    "\n",
    "# Распределение классов в обучающей выборке после балансировки\n",
    "class_distribution_res = pd.Series(y_train_res).value_counts(normalize=True) * 100\n",
    "print(\"\\nРаспределение классов после балансировки (в процентах):\")\n",
    "print(class_distribution_res)\n",
    "\n",
    "# Для визуализации можно использовать график\n",
    "import seaborn as sns\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# Функция для визуализации распределения классов\n",
    "def plot_class_distribution(y, title):\n",
    "    sns.countplot(x=y, color=\"orange\")\n",
    "    plt.title(title)\n",
    "    plt.xlabel(\"Response (Целевой признак)\")\n",
    "    plt.ylabel(\"Количество записей\")\n",
    "    plt.show()\n",
    "\n",
    "# Построение графика распределения классов\n",
    "plot_class_distribution(y_train_res, \"Распределение классов после балансировки\")\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>7-8. Делаем конструирование признаков</b>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "               Income  Kidhome  Teenhome  MntWines  MntFruits  \\\n",
      "customer_id                                                     \n",
      "0           -0.263557        1         1        68          0   \n",
      "1           -1.102440        1         0        18          3   \n",
      "2            0.633408        0         1       225        162   \n",
      "3            1.135917        1         0       739        107   \n",
      "4            1.299116        0         0       395        183   \n",
      "\n",
      "             MntMeatProducts  MntFishProducts  MntSweetProducts  MntGoldProds  \\\n",
      "customer_id                                                                     \n",
      "0                         16                0                 0             8   \n",
      "1                         19                3                 3             6   \n",
      "2                        387              106                36            29   \n",
      "3                        309              140                80            35   \n",
      "4                        565              166               141            28   \n",
      "\n",
      "             AcceptedCmp1  AcceptedCmp2  AcceptedCmp3  AcceptedCmp4  \\\n",
      "customer_id                                                           \n",
      "0                       0             0             0             0   \n",
      "1                       0             0             0             0   \n",
      "2                       0             0             0             0   \n",
      "3                       0             0             0             0   \n",
      "4                       0             0             0             0   \n",
      "\n",
      "             AcceptedCmp5  Recency  Income_binned  \n",
      "customer_id                                        \n",
      "0                       0        6            1.0  \n",
      "1                       0       67            0.0  \n",
      "2                       0       77            1.0  \n",
      "3                       0        2            2.0  \n",
      "4                       0       19            2.0  \n",
      "Размерность выборки после RandomOverSampler:\n",
      "X_train_res: (2954, 17)\n",
      "y_train_res: (2954,)\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "d:\\study\\3_course\\aim\\aimenv\\Lib\\site-packages\\featuretools\\entityset\\entityset.py:1733: UserWarning: index customer_id not found in dataframe, creating new integer column\n",
      "  warnings.warn(\n",
      "d:\\study\\3_course\\aim\\aimenv\\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"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "from sklearn.preprocessing import KBinsDiscretizer, MinMaxScaler, StandardScaler\n",
    "import featuretools as ft\n",
    "from imblearn.over_sampling import RandomOverSampler\n",
    "\n",
    "\n",
    "# 1. One-hot encoding для категориальных признаков\n",
    "X_train_2 = pd.get_dummies(X_train_2, drop_first=True)\n",
    "X_test_2 = pd.get_dummies(X_test_2, drop_first=True)\n",
    "\n",
    "# 2. Дискретизация числовых признаков\n",
    "discretizer = KBinsDiscretizer(n_bins=5, encode='ordinal', strategy='uniform')\n",
    "X_train_2['Income_binned'] = discretizer.fit_transform(X_train_2[['Income']])\n",
    "X_test_2['Income_binned'] = discretizer.transform(X_test_2[['Income']])\n",
    "\n",
    "# 3. Масштабирование признаков\n",
    "scaler_minmax = MinMaxScaler()\n",
    "X_train_2[['Income']] = scaler_minmax.fit_transform(X_train_2[['Income']])\n",
    "X_test_2[['Income']] = scaler_minmax.transform(X_test_2[['Income']])\n",
    "\n",
    "# Стандартизация признаков\n",
    "scaler_standard = StandardScaler()\n",
    "X_train_2[['Income']] = scaler_standard.fit_transform(X_train_2[['Income']])\n",
    "X_test_2[['Income']] = scaler_standard.transform(X_test_2[['Income']])\n",
    "\n",
    "# 4. Применение Featuretools для создания признаков\n",
    "es = ft.EntitySet(id=\"data\")\n",
    "\n",
    "# Мы добавляем данные в EntitySet с помощью метода add_dataframe\n",
    "es = es.add_dataframe(\n",
    "    dataframe_name=\"customer_data\",\n",
    "    dataframe=X_train_2,\n",
    "    index=\"customer_id\" \n",
    ")\n",
    "\n",
    "# Применяем Featuretools для создания признаков\n",
    "# Изменения: теперь указываем `target_dataframe_name` вместо `target_entity`\n",
    "features, feature_names = ft.dfs(entityset=es, target_dataframe_name=\"customer_data\")\n",
    "\n",
    "print(features.head())\n",
    "\n",
    "# 5. Балансировка выборки с помощью RandomOverSampler\n",
    "ros = RandomOverSampler(random_state=42)\n",
    "X_train_res, y_train_res = ros.fit_resample(X_train_2, y_train_2)\n",
    "\n",
    "print(f\"Размерность выборки после RandomOverSampler:\")\n",
    "print(f\"X_train_res: {X_train_res.shape}\")\n",
    "print(f\"y_train_res: {y_train_res.shape}\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Прилетает ошибка - UserWarning: Only one dataframe in entityset, changing max_depth to 1 since deeper features cannot be created\n",
    "  warnings.warn. Она значит, что EntitySet состоит из одного DataFrame. Т.е. только одна сущность.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>Следующая бизнес-цель</b>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "               Income  Kidhome  Teenhome  NumWebPurchases  MntWines  \\\n",
      "customer_id                                                           \n",
      "0            0.739837        0         1                6       522   \n",
      "1           -0.203068        1         1                1        22   \n",
      "2            0.160233        0         1                7       479   \n",
      "3            1.049812        0         0                4       594   \n",
      "4            0.119182        1         2                6       416   \n",
      "\n",
      "             MntFruits  MntMeatProducts  MntFishProducts  MntSweetProducts  \\\n",
      "customer_id                                                                  \n",
      "0                    0              522              227               120   \n",
      "1                    2               10                6                 4   \n",
      "2                    5               82                7                17   \n",
      "3                   51              631               72                55   \n",
      "4                    0               26                0                 0   \n",
      "\n",
      "             MntGoldProds  AcceptedCmp1  AcceptedCmp2  AcceptedCmp3  \\\n",
      "customer_id                                                           \n",
      "0                     134             0             0             0   \n",
      "1                      34             0             0             0   \n",
      "2                     171             0             0             1   \n",
      "3                      32             0             0             0   \n",
      "4                       4             0             0             0   \n",
      "\n",
      "             AcceptedCmp4  AcceptedCmp5  Recency  Income_binned  \n",
      "customer_id                                                      \n",
      "0                       0             0       28            0.0  \n",
      "1                       0             0       84            0.0  \n",
      "2                       0             0       30            0.0  \n",
      "3                       0             0       42            0.0  \n",
      "4                       1             0       11            0.0  \n",
      "Размерность выборки после RandomOverSampler для первой бизнес-цели:\n",
      "X_train_res_1: (2258, 18)\n",
      "y_train_res_1: (2258,)\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "d:\\study\\3_course\\aim\\aimenv\\Lib\\site-packages\\featuretools\\entityset\\entityset.py:1733: UserWarning: index customer_id not found in dataframe, creating new integer column\n",
      "  warnings.warn(\n",
      "d:\\study\\3_course\\aim\\aimenv\\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"
     ]
    }
   ],
   "source": [
    "# 1. One-hot encoding для категориальных признаков\n",
    "X_train = pd.get_dummies(X_train, drop_first=True)\n",
    "X_test = pd.get_dummies(X_test, drop_first=True)\n",
    "\n",
    "# 2. Дискретизация числовых признаков\n",
    "discretizer = KBinsDiscretizer(n_bins=5, encode='ordinal', strategy='uniform')\n",
    "X_train['Income_binned'] = discretizer.fit_transform(X_train[['Income']])\n",
    "X_test['Income_binned'] = discretizer.transform(X_test[['Income']])\n",
    "\n",
    "# 3. Масштабирование признаков\n",
    "scaler_minmax = MinMaxScaler()\n",
    "X_train[['Income']] = scaler_minmax.fit_transform(X_train[['Income']])\n",
    "X_test[['Income']] = scaler_minmax.transform(X_test[['Income']])\n",
    "\n",
    "# Стандартизация признаков\n",
    "scaler_standard = StandardScaler()\n",
    "X_train[['Income']] = scaler_standard.fit_transform(X_train[['Income']])\n",
    "X_test[['Income']] = scaler_standard.transform(X_test[['Income']])\n",
    "\n",
    "# 4. Применение Featuretools для создания признаков\n",
    "es = ft.EntitySet(id=\"data\")\n",
    "es = es.add_dataframe(dataframe_name=\"customer_data\", dataframe=X_train, index=\"customer_id\")\n",
    "\n",
    "# Применяем deep feature synthesis для создания новых признаков\n",
    "features, feature_names = ft.dfs(entityset=es, target_dataframe_name=\"customer_data\", max_depth=2)\n",
    "\n",
    "\n",
    "print(features.head())\n",
    "\n",
    "# 5. Балансировка выборки с помощью RandomOverSampler\n",
    "ros = RandomOverSampler(random_state=42)\n",
    "X_train_res_1, y_train_res_1 = ros.fit_resample(X_train, y_train)\n",
    "\n",
    "print(f\"Размерность выборки после RandomOverSampler для первой бизнес-цели:\")\n",
    "print(f\"X_train_res_1: {X_train_res_1.shape}\")\n",
    "print(f\"y_train_res_1: {y_train_res_1.shape}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>9. Оценить качество каждого набора признаков</b><br><br>Настраиваем модель"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "X_train columns: Index(['Income', 'Kidhome', 'Teenhome', 'NumWebPurchases', 'MntWines',\n",
      "       'MntFruits', 'MntMeatProducts', 'MntFishProducts', 'MntSweetProducts',\n",
      "       'MntGoldProds', 'AcceptedCmp1', 'AcceptedCmp2', 'AcceptedCmp3',\n",
      "       'AcceptedCmp4', 'AcceptedCmp5', 'Recency', 'Income_binned'],\n",
      "      dtype='object')\n",
      "X_test columns: Index(['Income', 'Kidhome', 'Teenhome', 'NumWebPurchases', 'MntWines',\n",
      "       'MntFruits', 'MntMeatProducts', 'MntFishProducts', 'MntSweetProducts',\n",
      "       'MntGoldProds', 'AcceptedCmp1', 'AcceptedCmp2', 'AcceptedCmp3',\n",
      "       'AcceptedCmp4', 'AcceptedCmp5', 'Recency', 'Income_binned'],\n",
      "      dtype='object')\n"
     ]
    }
   ],
   "source": [
    "X_train = X_train.drop(columns=['customer_id'], errors='ignore')\n",
    "print(\"X_train columns:\", X_train.columns)\n",
    "print(\"X_test columns:\", X_test.columns)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy: 0.8761261261261262\n",
      "ROC-AUC: 0.8519339641315966\n",
      "Время обучения модели: 0.2374 секунд\n",
      "Время предсказания: 0.0086 секунд\n",
      "Средняя точность по кросс-валидации: 0.8736\n",
      "Корреляция признаков с целевой переменной:\n",
      "Response            1.000000\n",
      "AcceptedCmp5        0.323374\n",
      "AcceptedCmp1        0.297345\n",
      "AcceptedCmp3        0.254005\n",
      "MntWines            0.246299\n",
      "MntMeatProducts     0.237746\n",
      "AcceptedCmp4        0.180205\n",
      "AcceptedCmp2        0.169294\n",
      "NumWebPurchases     0.151431\n",
      "MntGoldProds        0.140332\n",
      "Income              0.133047\n",
      "MntFruits           0.122443\n",
      "MntSweetProducts    0.116170\n",
      "MntFishProducts     0.108145\n",
      "Kidhome            -0.077909\n",
      "Teenhome           -0.153901\n",
      "Recency            -0.199766\n",
      "Name: Response, dtype: float64\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 302352 characters]",
      "text/plain": [
       "<Figure size 1000x800 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "              precision    recall  f1-score   support\n",
      "\n",
      "           0       0.89      0.98      0.93       377\n",
      "           1       0.70      0.31      0.43        67\n",
      "\n",
      "    accuracy                           0.88       444\n",
      "   macro avg       0.79      0.64      0.68       444\n",
      "weighted avg       0.86      0.88      0.86       444\n",
      "\n"
     ]
    }
   ],
   "source": [
    "import time\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "from sklearn.model_selection import train_test_split, cross_val_score\n",
    "from sklearn.metrics import accuracy_score, roc_auc_score, classification_report\n",
    "from sklearn.ensemble import RandomForestClassifier\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "\n",
    "# 1. Оценка предсказательной способности (Accuracy и ROC-AUC для бинарной классификации)\n",
    "model = RandomForestClassifier(random_state=42)\n",
    "\n",
    "start_time = time.perf_counter()\n",
    "model.fit(X_train, y_train)\n",
    "end_time = time.perf_counter()\n",
    "\n",
    "train_time = end_time - start_time\n",
    "\n",
    "y_pred = model.predict(X_test)\n",
    "accuracy = accuracy_score(y_test, y_pred)\n",
    "roc_auc = roc_auc_score(y_test, model.predict_proba(X_test)[:, 1])\n",
    "\n",
    "print(f\"Accuracy: {accuracy}\")\n",
    "print(f\"ROC-AUC: {roc_auc}\")\n",
    "print(f\"Время обучения модели: {train_time:.4f} секунд\")\n",
    "\n",
    "# 2. Оценка скорости вычисления (время предсказания)\n",
    "start_time = time.perf_counter()\n",
    "y_pred = model.predict(X_test)\n",
    "end_time = time.perf_counter()\n",
    "predict_time = end_time - start_time\n",
    "\n",
    "print(f\"Время предсказания: {predict_time:.4f} секунд\")\n",
    "\n",
    "# 3. Оценка надежности модели с помощью перекрестной проверки\n",
    "cv_scores = cross_val_score(model, X, y, cv=5, scoring='accuracy')\n",
    "mean_cv_score = np.mean(cv_scores)\n",
    "print(f\"Средняя точность по кросс-валидации: {mean_cv_score:.4f}\")\n",
    "\n",
    "# 4. Оценка корреляции признаков с целевой переменной\n",
    "correlation_matrix = pd.concat([X, y], axis=1).corr()\n",
    "correlation_with_target = correlation_matrix['Response'].sort_values(ascending=False)\n",
    "print(\"Корреляция признаков с целевой переменной:\")\n",
    "print(correlation_with_target)\n",
    "\n",
    "# Визуализация корреляции\n",
    "plt.figure(figsize=(10, 8))\n",
    "sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', fmt='.2f')\n",
    "plt.title('Корреляционная матрица признаков')\n",
    "plt.show()\n",
    "\n",
    "# Дополнительная информация о модели\n",
    "print(classification_report(y_test, y_pred))\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "aimenv",
   "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.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
