{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "ea8251c3",
   "metadata": {},
   "source": [
    "\n",
    "# Регрессия нейросетями и эволюционный поиск архитектуры\n",
    "\n",
    "В работе автоматически выбирается ключевая зависимая переменная, строится базовая нейросеть по всем признакам, затем определяется важность признаков и формируется сокращённый набор переменных. После этого по выбранным признакам обучается вторая нейросеть, архитектура которой подбирается методом эволюционного поиска. В конце выводятся все метрики и таблицы, необходимые для краткого итогового вывода.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "4a61905f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Используемый файл: Mental_Health_Lifestyle_Dataset(1).csv\n",
      "Форма датасета: (3000, 12)\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Country</th>\n",
       "      <th>Age</th>\n",
       "      <th>Gender</th>\n",
       "      <th>Exercise Level</th>\n",
       "      <th>Diet Type</th>\n",
       "      <th>Sleep Hours</th>\n",
       "      <th>Stress Level</th>\n",
       "      <th>Mental Health Condition</th>\n",
       "      <th>Work Hours per Week</th>\n",
       "      <th>Screen Time per Day (Hours)</th>\n",
       "      <th>Social Interaction Score</th>\n",
       "      <th>Happiness Score</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Brazil</td>\n",
       "      <td>48</td>\n",
       "      <td>Male</td>\n",
       "      <td>Low</td>\n",
       "      <td>Vegetarian</td>\n",
       "      <td>6.3</td>\n",
       "      <td>Low</td>\n",
       "      <td>NaN</td>\n",
       "      <td>21</td>\n",
       "      <td>4.0</td>\n",
       "      <td>7.8</td>\n",
       "      <td>6.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Australia</td>\n",
       "      <td>31</td>\n",
       "      <td>Male</td>\n",
       "      <td>Moderate</td>\n",
       "      <td>Vegan</td>\n",
       "      <td>4.9</td>\n",
       "      <td>Low</td>\n",
       "      <td>PTSD</td>\n",
       "      <td>48</td>\n",
       "      <td>5.2</td>\n",
       "      <td>8.2</td>\n",
       "      <td>6.8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Japan</td>\n",
       "      <td>37</td>\n",
       "      <td>Female</td>\n",
       "      <td>Low</td>\n",
       "      <td>Vegetarian</td>\n",
       "      <td>7.2</td>\n",
       "      <td>High</td>\n",
       "      <td>NaN</td>\n",
       "      <td>43</td>\n",
       "      <td>4.7</td>\n",
       "      <td>9.6</td>\n",
       "      <td>9.7</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>Brazil</td>\n",
       "      <td>35</td>\n",
       "      <td>Male</td>\n",
       "      <td>Low</td>\n",
       "      <td>Vegan</td>\n",
       "      <td>7.2</td>\n",
       "      <td>Low</td>\n",
       "      <td>Depression</td>\n",
       "      <td>43</td>\n",
       "      <td>2.2</td>\n",
       "      <td>8.2</td>\n",
       "      <td>6.6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>Germany</td>\n",
       "      <td>46</td>\n",
       "      <td>Male</td>\n",
       "      <td>Low</td>\n",
       "      <td>Balanced</td>\n",
       "      <td>7.3</td>\n",
       "      <td>Low</td>\n",
       "      <td>Anxiety</td>\n",
       "      <td>35</td>\n",
       "      <td>3.6</td>\n",
       "      <td>4.7</td>\n",
       "      <td>4.4</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     Country  Age  Gender Exercise Level   Diet Type  Sleep Hours  \\\n",
       "0     Brazil   48    Male            Low  Vegetarian          6.3   \n",
       "1  Australia   31    Male       Moderate       Vegan          4.9   \n",
       "2      Japan   37  Female            Low  Vegetarian          7.2   \n",
       "3     Brazil   35    Male            Low       Vegan          7.2   \n",
       "4    Germany   46    Male            Low    Balanced          7.3   \n",
       "\n",
       "  Stress Level Mental Health Condition  Work Hours per Week  \\\n",
       "0          Low                     NaN                   21   \n",
       "1          Low                    PTSD                   48   \n",
       "2         High                     NaN                   43   \n",
       "3          Low              Depression                   43   \n",
       "4          Low                 Anxiety                   35   \n",
       "\n",
       "   Screen Time per Day (Hours)  Social Interaction Score  Happiness Score  \n",
       "0                          4.0                       7.8              6.5  \n",
       "1                          5.2                       8.2              6.8  \n",
       "2                          4.7                       9.6              9.7  \n",
       "3                          2.2                       8.2              6.6  \n",
       "4                          3.6                       4.7              4.4  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>original_name</th>\n",
       "      <th>normalized_name</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Country</td>\n",
       "      <td>country</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Age</td>\n",
       "      <td>age</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Gender</td>\n",
       "      <td>gender</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>Exercise Level</td>\n",
       "      <td>exercise_level</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>Diet Type</td>\n",
       "      <td>diet_type</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>Sleep Hours</td>\n",
       "      <td>sleep_hours</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>Stress Level</td>\n",
       "      <td>stress_level</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>Mental Health Condition</td>\n",
       "      <td>mental_health_condition</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>Work Hours per Week</td>\n",
       "      <td>work_hours_per_week</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>Screen Time per Day (Hours)</td>\n",
       "      <td>screen_time_per_day_hours</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>Social Interaction Score</td>\n",
       "      <td>social_interaction_score</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>Happiness Score</td>\n",
       "      <td>happiness_score</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                  original_name            normalized_name\n",
       "0                       Country                    country\n",
       "1                           Age                        age\n",
       "2                        Gender                     gender\n",
       "3                Exercise Level             exercise_level\n",
       "4                     Diet Type                  diet_type\n",
       "5                   Sleep Hours                sleep_hours\n",
       "6                  Stress Level               stress_level\n",
       "7       Mental Health Condition    mental_health_condition\n",
       "8           Work Hours per Week        work_hours_per_week\n",
       "9   Screen Time per Day (Hours)  screen_time_per_day_hours\n",
       "10     Social Interaction Score   social_interaction_score\n",
       "11              Happiness Score            happiness_score"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Типы данных:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>country</th>\n",
       "      <th>age</th>\n",
       "      <th>gender</th>\n",
       "      <th>exercise_level</th>\n",
       "      <th>diet_type</th>\n",
       "      <th>sleep_hours</th>\n",
       "      <th>stress_level</th>\n",
       "      <th>mental_health_condition</th>\n",
       "      <th>work_hours_per_week</th>\n",
       "      <th>screen_time_per_day_hours</th>\n",
       "      <th>social_interaction_score</th>\n",
       "      <th>happiness_score</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>dtype</th>\n",
       "      <td>object</td>\n",
       "      <td>int64</td>\n",
       "      <td>object</td>\n",
       "      <td>object</td>\n",
       "      <td>object</td>\n",
       "      <td>float64</td>\n",
       "      <td>object</td>\n",
       "      <td>object</td>\n",
       "      <td>int64</td>\n",
       "      <td>float64</td>\n",
       "      <td>float64</td>\n",
       "      <td>float64</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      country    age  gender exercise_level diet_type sleep_hours  \\\n",
       "dtype  object  int64  object         object    object     float64   \n",
       "\n",
       "      stress_level mental_health_condition work_hours_per_week  \\\n",
       "dtype       object                  object               int64   \n",
       "\n",
       "      screen_time_per_day_hours social_interaction_score happiness_score  \n",
       "dtype                   float64                  float64         float64  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "import os\n",
    "import re\n",
    "import math\n",
    "import json\n",
    "import warnings\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.compose import ColumnTransformer\n",
    "from sklearn.pipeline import Pipeline\n",
    "from sklearn.impute import SimpleImputer\n",
    "from sklearn.preprocessing import OneHotEncoder, StandardScaler\n",
    "from sklearn.neural_network import MLPRegressor\n",
    "from sklearn.inspection import permutation_importance\n",
    "from sklearn.metrics import r2_score, mean_squared_error, mean_absolute_error\n",
    "\n",
    "warnings.filterwarnings(\"ignore\")\n",
    "RANDOM_STATE = 42\n",
    "np.random.seed(RANDOM_STATE)\n",
    "\n",
    "def find_file(candidates):\n",
    "    for path in candidates:\n",
    "        if os.path.exists(path):\n",
    "            return path\n",
    "    data_dir = \"/mnt/data\"\n",
    "    if os.path.isdir(data_dir):\n",
    "        files = os.listdir(data_dir)\n",
    "        for name in files:\n",
    "            low = name.lower()\n",
    "            if \"mental\" in low and \"lifestyle\" in low and low.endswith(\".csv\"):\n",
    "                return os.path.join(data_dir, name)\n",
    "            if \"anxiety\" in low and low.endswith(\".csv\"):\n",
    "                return os.path.join(data_dir, name)\n",
    "    raise FileNotFoundError(\"CSV-файл не найден. Поместите его рядом с ноутбуком или укажите корректное имя.\")\n",
    "\n",
    "file_candidates = [\n",
    "    \"Mental_Health_Lifestyle_Dataset(1).csv\",\n",
    "    \"Mental_Health_Lifestyle_Dataset.csv\",\n",
    "    \"mental_health_lifestyle_dataset.csv\",\n",
    "    \"mental_health_lifestyle.csv\",\n",
    "    \"/mnt/data/Mental_Health_Lifestyle_Dataset(1).csv\",\n",
    "    \"/mnt/data/Mental_Health_Lifestyle_Dataset.csv\",\n",
    "    \"/mnt/data/mental_health_lifestyle_dataset.csv\",\n",
    "]\n",
    "file_path = find_file(file_candidates)\n",
    "print(\"Используемый файл:\", file_path)\n",
    "\n",
    "df = pd.read_csv(file_path)\n",
    "print(\"Форма датасета:\", df.shape)\n",
    "display(df.head())\n",
    "\n",
    "def normalize_col(col):\n",
    "    col = str(col).strip().lower()\n",
    "    col = col.replace(\"%\", \" pct \")\n",
    "    col = re.sub(r\"[^a-zа-я0-9]+\", \"_\", col)\n",
    "    col = re.sub(r\"_+\", \"_\", col).strip(\"_\")\n",
    "    return col\n",
    "\n",
    "orig_cols = df.columns.tolist()\n",
    "df.columns = [normalize_col(c) for c in df.columns]\n",
    "display(pd.DataFrame({\"original_name\": orig_cols, \"normalized_name\": df.columns}))\n",
    "\n",
    "print(\"Типы данных:\")\n",
    "display(df.dtypes.to_frame(\"dtype\").T)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "0cfbe798",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Выбранная зависимая переменная: happiness_score\n",
      "Найденные идентификаторы / потенциально несодержательные поля: []\n",
      "Число объектов после удаления пропусков по целевой переменной: 3000\n",
      "Число исходных признаков: 11\n",
      "Числовые признаки: ['age', 'sleep_hours', 'work_hours_per_week', 'screen_time_per_day_hours', 'social_interaction_score']\n",
      "Категориальные признаки: ['country', 'gender', 'exercise_level', 'diet_type', 'stress_level', 'mental_health_condition']\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>country</th>\n",
       "      <th>age</th>\n",
       "      <th>gender</th>\n",
       "      <th>exercise_level</th>\n",
       "      <th>diet_type</th>\n",
       "      <th>sleep_hours</th>\n",
       "      <th>stress_level</th>\n",
       "      <th>mental_health_condition</th>\n",
       "      <th>work_hours_per_week</th>\n",
       "      <th>screen_time_per_day_hours</th>\n",
       "      <th>social_interaction_score</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Brazil</td>\n",
       "      <td>48</td>\n",
       "      <td>Male</td>\n",
       "      <td>Low</td>\n",
       "      <td>Vegetarian</td>\n",
       "      <td>6.3</td>\n",
       "      <td>Low</td>\n",
       "      <td>NaN</td>\n",
       "      <td>21</td>\n",
       "      <td>4.0</td>\n",
       "      <td>7.8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Australia</td>\n",
       "      <td>31</td>\n",
       "      <td>Male</td>\n",
       "      <td>Moderate</td>\n",
       "      <td>Vegan</td>\n",
       "      <td>4.9</td>\n",
       "      <td>Low</td>\n",
       "      <td>PTSD</td>\n",
       "      <td>48</td>\n",
       "      <td>5.2</td>\n",
       "      <td>8.2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Japan</td>\n",
       "      <td>37</td>\n",
       "      <td>Female</td>\n",
       "      <td>Low</td>\n",
       "      <td>Vegetarian</td>\n",
       "      <td>7.2</td>\n",
       "      <td>High</td>\n",
       "      <td>NaN</td>\n",
       "      <td>43</td>\n",
       "      <td>4.7</td>\n",
       "      <td>9.6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>Brazil</td>\n",
       "      <td>35</td>\n",
       "      <td>Male</td>\n",
       "      <td>Low</td>\n",
       "      <td>Vegan</td>\n",
       "      <td>7.2</td>\n",
       "      <td>Low</td>\n",
       "      <td>Depression</td>\n",
       "      <td>43</td>\n",
       "      <td>2.2</td>\n",
       "      <td>8.2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>Germany</td>\n",
       "      <td>46</td>\n",
       "      <td>Male</td>\n",
       "      <td>Low</td>\n",
       "      <td>Balanced</td>\n",
       "      <td>7.3</td>\n",
       "      <td>Low</td>\n",
       "      <td>Anxiety</td>\n",
       "      <td>35</td>\n",
       "      <td>3.6</td>\n",
       "      <td>4.7</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     country  age  gender exercise_level   diet_type  sleep_hours  \\\n",
       "0     Brazil   48    Male            Low  Vegetarian          6.3   \n",
       "1  Australia   31    Male       Moderate       Vegan          4.9   \n",
       "2      Japan   37  Female            Low  Vegetarian          7.2   \n",
       "3     Brazil   35    Male            Low       Vegan          7.2   \n",
       "4    Germany   46    Male            Low    Balanced          7.3   \n",
       "\n",
       "  stress_level mental_health_condition  work_hours_per_week  \\\n",
       "0          Low                     NaN                   21   \n",
       "1          Low                    PTSD                   48   \n",
       "2         High                     NaN                   43   \n",
       "3          Low              Depression                   43   \n",
       "4          Low                 Anxiety                   35   \n",
       "\n",
       "   screen_time_per_day_hours  social_interaction_score  \n",
       "0                        4.0                       7.8  \n",
       "1                        5.2                       8.2  \n",
       "2                        4.7                       9.6  \n",
       "3                        2.2                       8.2  \n",
       "4                        3.6                       4.7  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "def choose_target(dataframe):\n",
    "    cols = list(dataframe.columns)\n",
    "    preferred = [\n",
    "        \"happiness_score\",\n",
    "        \"score\",\n",
    "        \"target\",\n",
    "        \"price\",\n",
    "        \"amount\",\n",
    "        \"depression_score\",\n",
    "        \"sales\",\n",
    "        \"profit\",\n",
    "    ]\n",
    "    for col in preferred:\n",
    "        if col in cols:\n",
    "            ser = pd.to_numeric(dataframe[col], errors=\"coerce\")\n",
    "            if ser.notna().mean() >= 0.7:\n",
    "                return col\n",
    "\n",
    "    numeric_candidates = []\n",
    "    for col in cols:\n",
    "        ser = pd.to_numeric(dataframe[col], errors=\"coerce\")\n",
    "        nunique = ser.nunique(dropna=True)\n",
    "        if ser.notna().mean() >= 0.7 and nunique > 10:\n",
    "            numeric_candidates.append((col, nunique))\n",
    "    if numeric_candidates:\n",
    "        return numeric_candidates[-1][0]\n",
    "    raise ValueError(\"Не удалось автоматически определить числовую зависимую переменную.\")\n",
    "\n",
    "target_col = choose_target(df)\n",
    "print(\"Выбранная зависимая переменная:\", target_col)\n",
    "\n",
    "id_like_cols = [c for c in df.columns if any(tok in c for tok in [\"id\", \"name\"]) and c != target_col]\n",
    "print(\"Найденные идентификаторы / потенциально несодержательные поля:\", id_like_cols)\n",
    "\n",
    "y = pd.to_numeric(df[target_col], errors=\"coerce\")\n",
    "X = df.drop(columns=[target_col] + id_like_cols).copy()\n",
    "\n",
    "# приведение числовых столбцов\n",
    "for col in X.columns:\n",
    "    converted = pd.to_numeric(X[col], errors=\"ignore\")\n",
    "    X[col] = converted\n",
    "\n",
    "# удаляем строки без цели\n",
    "mask = y.notna()\n",
    "X = X.loc[mask].reset_index(drop=True)\n",
    "y = y.loc[mask].reset_index(drop=True)\n",
    "\n",
    "print(\"Число объектов после удаления пропусков по целевой переменной:\", len(y))\n",
    "print(\"Число исходных признаков:\", X.shape[1])\n",
    "\n",
    "numeric_features = X.select_dtypes(include=[np.number]).columns.tolist()\n",
    "categorical_features = [c for c in X.columns if c not in numeric_features]\n",
    "\n",
    "print(\"Числовые признаки:\", numeric_features)\n",
    "print(\"Категориальные признаки:\", categorical_features)\n",
    "\n",
    "display(X.head())\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "7807e1b0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Размеры выборок:\n",
      "train: (1800, 11) (1800,)\n",
      "val: (600, 11) (600,)\n",
      "test: (600, 11) (600,)\n",
      "Число признаков после кодирования: 30\n",
      "Первые 20 преобразованных признаков:\n",
      "['num__age', 'num__sleep_hours', 'num__work_hours_per_week', 'num__screen_time_per_day_hours', 'num__social_interaction_score', 'cat__country_Australia', 'cat__country_Brazil', 'cat__country_Canada', 'cat__country_Germany', 'cat__country_India', 'cat__country_Japan', 'cat__country_USA', 'cat__gender_Female', 'cat__gender_Male', 'cat__gender_Other', 'cat__exercise_level_High', 'cat__exercise_level_Low', 'cat__exercise_level_Moderate', 'cat__diet_type_Balanced', 'cat__diet_type_Junk Food']\n"
     ]
    }
   ],
   "source": [
    "\n",
    "X_trainval, X_test, y_trainval, y_test = train_test_split(\n",
    "    X, y, test_size=0.2, random_state=RANDOM_STATE\n",
    ")\n",
    "X_train, X_val, y_train, y_val = train_test_split(\n",
    "    X_trainval, y_trainval, test_size=0.25, random_state=RANDOM_STATE\n",
    ")\n",
    "\n",
    "print(\"Размеры выборок:\")\n",
    "print(\"train:\", X_train.shape, y_train.shape)\n",
    "print(\"val:\", X_val.shape, y_val.shape)\n",
    "print(\"test:\", X_test.shape, y_test.shape)\n",
    "\n",
    "def make_ohe():\n",
    "    try:\n",
    "        return OneHotEncoder(handle_unknown=\"ignore\", sparse_output=False)\n",
    "    except TypeError:\n",
    "        return OneHotEncoder(handle_unknown=\"ignore\", sparse=False)\n",
    "\n",
    "preprocessor = ColumnTransformer(\n",
    "    transformers=[\n",
    "        (\"num\", Pipeline([\n",
    "            (\"imputer\", SimpleImputer(strategy=\"median\")),\n",
    "            (\"scaler\", StandardScaler()),\n",
    "        ]), numeric_features),\n",
    "        (\"cat\", Pipeline([\n",
    "            (\"imputer\", SimpleImputer(strategy=\"most_frequent\")),\n",
    "            (\"ohe\", make_ohe()),\n",
    "        ]), categorical_features),\n",
    "    ],\n",
    "    remainder=\"drop\"\n",
    ")\n",
    "\n",
    "X_train_proc = preprocessor.fit_transform(X_train)\n",
    "X_val_proc = preprocessor.transform(X_val)\n",
    "X_test_proc = preprocessor.transform(X_test)\n",
    "X_trainval_proc = preprocessor.fit_transform(X_trainval)\n",
    "X_test_from_trainval_proc = preprocessor.transform(X_test)\n",
    "\n",
    "try:\n",
    "    feature_names = preprocessor.get_feature_names_out()\n",
    "except Exception:\n",
    "    feature_names = [f\"feature_{i}\" for i in range(X_train_proc.shape[1])]\n",
    "\n",
    "print(\"Число признаков после кодирования:\", len(feature_names))\n",
    "print(\"Первые 20 преобразованных признаков:\")\n",
    "print(list(feature_names[:20]))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "8f4120a2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Метрики базовой нейросети:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>split</th>\n",
       "      <th>r2</th>\n",
       "      <th>rmse</th>\n",
       "      <th>mae</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>train</td>\n",
       "      <td>0.051686</td>\n",
       "      <td>2.467446</td>\n",
       "      <td>2.120161</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>validation</td>\n",
       "      <td>-0.071769</td>\n",
       "      <td>2.672584</td>\n",
       "      <td>2.290122</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>test</td>\n",
       "      <td>-0.025478</td>\n",
       "      <td>2.634732</td>\n",
       "      <td>2.256196</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        split        r2      rmse       mae\n",
       "0       train  0.051686  2.467446  2.120161\n",
       "1  validation -0.071769  2.672584  2.290122\n",
       "2        test -0.025478  2.634732  2.256196"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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ka+32rVrF6pVq4bq1aujffv2KCgowJo1a+Rwdf78eWg0GtStW9fmdiEhIQgICLC7P6t58+YhNzcXkyZNumefitq0aZPd8/fJJ5/Y7HPq1CkIIVCvXj27fY8fP273mrBatWoVjh49infeeafE49/5XAGW/+s5OTm4du0arl27hpycnBL/z5jNZnne7ZkzZ2ymzhSnrK/vsijtzyEipXDOK9F9evfddzFgwAAAwLJly/DQQw9h4sSJWLRo0X3f9yeffIJz585h48aNd90vPj4egGVUde3atXjyySfxww8/oGvXrjCZTOjatStu3LiB119/HQ0bNoSPjw8uXbqEIUOG2ISnf/zjHzhw4ADmz5+PZcuW3Xf9xSk6Mngv3bt3R40aNfD555/j4Ycfxueff46QkBDExcXJ+9SoUQPz58/H8OHD5V/UVtaADljmvD7wwAOYN29esccqGvYBoG/fvnYf2vr3v/+NK1euFHv7TZs24ZdffsHu3buLvT4yMhLLly/HqFGj8OCDD9pcd69AYO3ZvdZzTUtLQ+fOneHv74+33noL0dHR8PT0xIEDB/D666/bBeXevXujbt26SElJwZIlS/DUU09hx44dpfpQ1J2aNWuGuXPnAgCuXbuGjz76CLGxsThw4ABCQkLk/cqyJm1qaireffddTJw4EUFBQWWqp23btpg+fbrNtgULFsjLXAGW14QkSfjpp5+KXcnA19fXblt+fj4mT56M//u//7N7vamprK/vsijtzyEipTC8Et2nhx9+WP6+devWGD58OBYuXIjnnnvO5k/3AJCcnIzs7Gyb0deTJ08CgF1gyMnJwbRp0zBs2DB5NKwkRcNc37598fvvv+O9995D165dcfjwYZw8eRIrV67Ec889J+9nDbxFaTQavPfeezh8+DCSkpKwaNEiXL16VR65u5vIyEicOHHCbrv1T9XWxxAVFYVNmzYhMzMTfn5+8n4nT56E2Wy26YNWq8XAgQOxYsUKzJ49G+vXr8dLL71kFzRefPFF9O/fH0eOHEF+fj6A23+OtoqOjsahQ4fQpUuXUgWoWrVq2fQVAD744INiw6sQAhMmTMDjjz9u95wXNWjQIFy4cAHTpk3DZ599hsDAwFL1NioqCmazGadOnZJHsgEgIyMDly9flkd6t27diuvXr+Pbb7+1eV0mJSUVe781a9ZEzZo1AQD9+/dH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OzsbGzZswJYtW3D48GGbJY6IiKjyYnglIqd07do1DBw4EAEBAZg0aRL69OmjdklEROQEOOeViIiIiFwG57wSERERkctgeCUiIiIil+H2c17NZjOSk5Ph5+fn0FPmEREREZFjCCGQmZmJsLAw+aQ2JXH78JqcnCyfH5qIiIiInNfFixdRq1atu+7j9uHVz88PgKUZ1vNEVySj0YhNmzahW7dudqf7JMdir5XDXiuHvVYOe60c9lo5rtrrjIwMhIeHy7ntbtw+vFqnCvj7+ysWXr29veHv7+9SLxpXxF4rh71WDnutHPZaOey1cly916WZ4skPbBERERGRy1A1vG7fvh29e/dGWFgYJEnC+vXrba7PysrCiBEjUKtWLXh5eaFx48ZYsmSJOsUSERERkepUDa/Z2dmIiYnBwoULi71+7Nix+Pnnn/H555/j+PHjGD16NEaMGIENGzYoXCkREREROQNV57z26NEDPXr0KPH6Xbt2YfDgwYiNjQUADB06FEuXLsXevXt5qkgiIiKiSsipP7DVvn17bNiwAS+88ALCwsKwdetWnDx5Eu+//36Jt8nLy0NeXp58OSMjA4BlArPRaKzwmq3HUOJYlR17rRz2WjnstXLYa+Ww18px1V6XpV5JCCEqsJZSkyQJ69atQ79+/eRteXl5GDp0KD799FPodDpoNBp8/PHHeO6550q8n6lTp2LatGl221evXg1vb++KKJ2IiIiI7kNOTg4GDhyI9PT0e64O5dQjr/Pnz8eePXuwYcMGREZGYvv27Rg+fDjCwsIQFxdX7G0mTpyIsWPHypet64Z169ZNsaWy4uPj0bVrV5dcosKVsNfKYa+Vw14rh71WDnutHFfttfUv5aXhtOH11q1bmDRpEtatW4devXoBAJo1a4bExES89957JYZXg8EAg8Fgt12v1yv6JCp9vMqMvVYOe60c9lo57LVy2GvluFqvy1Kr067zap2jeuf5bbVaLcxms0pVEREREZGaVB15zcrKwunTp+XLSUlJSExMRFBQECIiItC5c2e89tpr8PLyQmRkJLZt24ZPP/0U8+bNU7Hquzt4MQ17UiR0yi1AkAu94yEiIiJyBaqG14SEBDzyyCPyZetc1cGDB2PFihX48ssvMXHiRAwaNAg3btxAZGQkZsyYgVdeeUWtku9p5JeHcCVDi75XM/GQn5fa5RARERG5FVXDa2xsLO622EFISAiWL1+uYEX3L7qaL65k5OHMtWw8VFftaoiIiIjci9POeXVV0dV8AABnU7NVroSIiIjI/TC8Opg1vJ6+xvBKRERE5GgMrw5mDa9nGF6JiIiIHI7h1cHqFobXS2m3kGs0qVwNERERkXtheHWwIB8PeOsEhADOXMtSuxwiIiIit8Lw6mCSJKFG4QpZp1MYXomIiIgcieG1AtTwsiz/dYbhlYiIiMihGF4rgDW8nua0ASIiIiKHYnitAJw2QERERFQxGF4rQEjhyOu51BwUmMwqV0NERETkPhheK0CgAfDUa5BvMuPizVtql0NERETkNhheK4BGAqKqFp5pi1MHiIiIiByG4bWCyKeJZXglIiIichiG1wrC8EpERETkeAyvFUQOr1wui4iIiMhhGF4riDW8nknJghBC5WqIiIiI3APDawWJrOoDjQRk5RXgakae2uUQERERuQWG1wpi0GkQyRUHiIiIiByK4bUCRVfzBQCc4bxXIiIiIodgeK1AdatbwitHXomIiIgcg+G1AjG8EhERETkWw2sFksMrpw0QEREROQTDawWyLpd1LTMP6beMKldDRERE5PoYXiuQn6ceIf6eADh1gIiIiMgRGF4rmHXqwBmGVyIiIqL7xvBawXiaWCIiIiLHYXitYFxxgIiIiMhxVA2v27dvR+/evREWFgZJkrB+/Xq7fY4fP44+ffqgSpUq8PHxQevWrXHhwgXliy2n6Oo8UQERERGRo6gaXrOzsxETE4OFCxcWe/2ZM2fQsWNHNGzYEFu3bsUff/yByZMnw9PTU+FKy8868nrxRg5yjSaVqyEiIiJybTo1D96jRw/06NGjxOvfeOMN9OzZE3PmzJG3RUdHK1Gaw1TzNcDfU4eM3AIkpWajUai/2iURERERuSxVw+vdmM1m/O9//8P48ePRvXt3HDx4EFFRUZg4cSL69etX4u3y8vKQl5cnX87IyAAAGI1GGI0Vv9aq9RhFjxVdzQcHL6bjxOV01A32qvAaKoviek0Vg71WDnutHPZaOey1cly112WpVxJCiAqspdQkScK6devkYHrlyhWEhobC29sb06dPxyOPPIKff/4ZkyZNwpYtW9C5c+di72fq1KmYNm2a3fbVq1fD29u7Ih9CiVaf1uD3axo8WsuMHuFmVWogIiIiclY5OTkYOHAg0tPT4e9/979SO214TU5ORs2aNfH0009j9erV8n59+vSBj48Pvvjii2Lvp7iR1/DwcKSmpt6zGY5gNBoRHx+Prl27Qq/XAwD+s+McZm88iZ5Na+DDp2IqvIbKorheU8Vgr5XDXiuHvVYOe60cV+11RkYGgoODSxVenXbaQHBwMHQ6HRo3bmyzvVGjRtixY0eJtzMYDDAYDHbb9Xq9ok9i0eM1KJznejY1x6VeSK5C6ee2MmOvlcNeK4e9Vg57rRxX63VZanXadV49PDzQunVrnDhxwmb7yZMnERkZqVJV5RNdzbLiwNnUbJjMTjHQTUREROSSVB15zcrKwunTp+XLSUlJSExMRFBQECIiIvDaa6/hqaeewsMPPyzPef3++++xdetW9Youh1qB3vDQaZBfYMbFGzmoHeyjdklERERELknVkdeEhAS0aNECLVq0AACMHTsWLVq0wJQpUwAAjz/+OJYsWYI5c+bggQcewH/+8x+sXbsWHTt2VLPsMtNqJNQpDKw8WQERERFR+ak68hobG4t7fV7shRdewAsvvKBQRRWnbnVf/HklE6dTstClUQ21yyEiIiJySU4759XdWM+0dTqFI69ERERE5cXwqhA5vHLaABEREVG5MbwqpOjIq5MsrUtERETkchheFRIV7AONBGTmFuBaZt69b0BEREREdhheFWLQaRERZDk9Lee9EhEREZUPw6uCrCcr4LxXIiIiovJheFUQVxwgIiIiuj8MrwqKLgyvPFEBERERUfkwvCqII69ERERE94fhVUHW8Ho1Iw8ZuUaVqyEiIiJyPQyvCvL31KO6nwEAcIajr0RERERlxvCqME4dICIiIio/hleF8TSxREREROXH8Kowa3jltAEiIiKismN4VVjdapw2QERERFReDK8Ks671euFGDnKNJpWrISIiInItDK8Kq+5ngJ9BB7MAzl/PUbscIiIiIpfC8KowSZLk0VdOHSAiIiIqG4ZXFURX42liiYiIiMqD4VUF0dV9AABnGV6JiIiIyoThVQV1gq0jr9kqV0JERETkWhheVVC3yMirEELlaoiIiIhcB8OrCiKCfKDVSMjON+FqRp7a5RARERG5DIZXFXjoNIgI8gbAea9EREREZcHwqpI6wZapA1xxgIiIiKj0GF5VYl3rlR/aIiIiIio9hleVcOSViIiIqOxUDa/bt29H7969ERYWBkmSsH79+hL3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A1tERERE5D448kpERERELoPhlYiIiIhcBsMrEREREbkMhlciIiIichkMrw62cOFC1K5dG56enmjbti327t2rdkkub/v27ejduzfCwsIgSRLWr19vc70QAlOmTEFoaCi8vLwQFxeHU6dOqVOsC5s5cyZat24NPz8/VK9eHf369cOJEyds9snNzcXw4cNRtWpV+Pr64oknnsDVq1dVqth1LV68GM2aNZMXEW/Xrh1++ukn+Xr2ueLMmjULkiRh9OjR8jb22zGmTp0KSZJsvho2bChfzz471qVLl/DMM8+gatWq8PLywgMPPICEhAT5enf+3cjw6kBfffUVxo4dizfffBMHDhxATEwMunfvjpSUFLVLc2nZ2dmIiYnBwoULi71+zpw5+Oijj7BkyRL8/vvv8PHxQffu3ZGbm6twpa5t27ZtGD58OPbs2YP4+HgYjUZ069YN2dnZ8j5jxozB999/jzVr1mDbtm1ITk5G//79VazaNdWqVQuzZs3C/v37kZCQgL/97W/o27cvjh49CoB9rij79u3D0qVL0axZM5vt7LfjNGnSBJcvX5a/duzYIV/HPjvOzZs30aFDB+j1evz00084duwY5s6di8DAQHkft/7dKMhh2rRpI4YPHy5fNplMIiwsTMycOVPFqtwLALFu3Tr5stlsFiEhIeLdd9+Vt6WlpQmDwSC++OILFSp0HykpKQKA2LZtmxDC0le9Xi/WrFkj73P8+HEBQOzevVutMt1GYGCg+M9//sM+V5DMzExRr149ER8fLzp37ixGjRolhODr2pHefPNNERMTU+x17LNjvf7666Jjx44lXu/uvxs58uog+fn52L9/P+Li4uRtGo0GcXFx2L17t4qVubekpCRcuXLFpu9VqlRB27Zt2ff7lJ6eDgAICgoCAOzfvx9Go9Gm1w0bNkRERAR7fR9MJhO+/PJLZGdno127duxzBRk+fDh69epl01eAr2tHO3XqFMLCwlCnTh0MGjQIFy5cAMA+O9qGDRvQqlUrDBgwANWrV0eLFi3w8ccfy9e7++9GhlcHSU1NhclkQo0aNWy216hRA1euXFGpKvdn7S377lhmsxmjR49Ghw4d0LRpUwCWXnt4eCAgIMBmX/a6fA4fPgxfX18YDAa88sorWLduHRo3bsw+V4Avv/wSBw4cwMyZM+2uY78dp23btlixYgV+/vlnLF68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",
      "text/plain": [
       "<Figure size 800x400 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "def regression_metrics(y_true, y_pred):\n",
    "    return {\n",
    "        \"r2\": float(r2_score(y_true, y_pred)),\n",
    "        \"rmse\": float(np.sqrt(mean_squared_error(y_true, y_pred))),\n",
    "        \"mae\": float(mean_absolute_error(y_true, y_pred)),\n",
    "    }\n",
    "\n",
    "baseline_hidden = (64, 32)\n",
    "baseline_model = MLPRegressor(\n",
    "    hidden_layer_sizes=baseline_hidden,\n",
    "    activation=\"relu\",\n",
    "    solver=\"adam\",\n",
    "    alpha=1e-4,\n",
    "    learning_rate_init=1e-3,\n",
    "    max_iter=400,\n",
    "    early_stopping=True,\n",
    "    validation_fraction=0.15,\n",
    "    n_iter_no_change=20,\n",
    "    random_state=RANDOM_STATE\n",
    ")\n",
    "baseline_model.fit(X_train_proc, y_train)\n",
    "\n",
    "pred_train_baseline = baseline_model.predict(X_train_proc)\n",
    "pred_val_baseline = baseline_model.predict(X_val_proc)\n",
    "pred_test_baseline = baseline_model.predict(X_test_proc)\n",
    "\n",
    "baseline_metrics = pd.DataFrame([\n",
    "    {\"split\": \"train\", **regression_metrics(y_train, pred_train_baseline)},\n",
    "    {\"split\": \"validation\", **regression_metrics(y_val, pred_val_baseline)},\n",
    "    {\"split\": \"test\", **regression_metrics(y_test, pred_test_baseline)},\n",
    "])\n",
    "\n",
    "print(\"Метрики базовой нейросети:\")\n",
    "display(baseline_metrics)\n",
    "\n",
    "plt.figure(figsize=(8, 4))\n",
    "plt.plot(baseline_model.loss_curve_)\n",
    "plt.title(\"Кривая обучения базовой нейросети\")\n",
    "plt.xlabel(\"Итерация\")\n",
    "plt.ylabel(\"Loss\")\n",
    "plt.grid(True)\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "c0c544b1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Топ-10 признаков по перестановочной важности:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>feature</th>\n",
       "      <th>permutation_importance_mean</th>\n",
       "      <th>permutation_importance_std</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>exercise_level</td>\n",
       "      <td>0.022801</td>\n",
       "      <td>0.011556</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>stress_level</td>\n",
       "      <td>0.021812</td>\n",
       "      <td>0.014420</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>diet_type</td>\n",
       "      <td>0.019173</td>\n",
       "      <td>0.008693</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>mental_health_condition</td>\n",
       "      <td>0.010748</td>\n",
       "      <td>0.005653</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>gender</td>\n",
       "      <td>0.007888</td>\n",
       "      <td>0.005160</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>country</td>\n",
       "      <td>0.007468</td>\n",
       "      <td>0.007103</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>work_hours_per_week</td>\n",
       "      <td>0.006936</td>\n",
       "      <td>0.006448</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>age</td>\n",
       "      <td>-0.012904</td>\n",
       "      <td>0.008048</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>sleep_hours</td>\n",
       "      <td>-0.013075</td>\n",
       "      <td>0.008175</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>social_interaction_score</td>\n",
       "      <td>-0.016482</td>\n",
       "      <td>0.006457</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                    feature  permutation_importance_mean  \\\n",
       "0            exercise_level                     0.022801   \n",
       "1              stress_level                     0.021812   \n",
       "2                 diet_type                     0.019173   \n",
       "3   mental_health_condition                     0.010748   \n",
       "4                    gender                     0.007888   \n",
       "5                   country                     0.007468   \n",
       "6       work_hours_per_week                     0.006936   \n",
       "7                       age                    -0.012904   \n",
       "8               sleep_hours                    -0.013075   \n",
       "9  social_interaction_score                    -0.016482   \n",
       "\n",
       "   permutation_importance_std  \n",
       "0                    0.011556  \n",
       "1                    0.014420  \n",
       "2                    0.008693  \n",
       "3                    0.005653  \n",
       "4                    0.005160  \n",
       "5                    0.007103  \n",
       "6                    0.006448  \n",
       "7                    0.008048  \n",
       "8                    0.008175  \n",
       "9                    0.006457  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Отобранные признаки:\n",
      "['exercise_level', 'stress_level', 'diet_type', 'mental_health_condition', 'gender', 'country', 'work_hours_per_week']\n",
      "Число отобранных признаков: 7\n"
     ]
    }
   ],
   "source": [
    "\n",
    "# Важность признаков по перестановочному подходу на валидационной выборке\n",
    "perm = permutation_importance(\n",
    "    estimator=baseline_model,\n",
    "    X=X_val_proc,\n",
    "    y=y_val,\n",
    "    scoring=\"neg_root_mean_squared_error\",\n",
    "    n_repeats=10,\n",
    "    random_state=RANDOM_STATE,\n",
    ")\n",
    "\n",
    "# Нужно агрегировать важности по исходным признакам\n",
    "proc_feature_names = np.array(feature_names)\n",
    "agg_rows = []\n",
    "for original_feature in X.columns:\n",
    "    mask = np.array([name.startswith(f\"num__{original_feature}\") or name.startswith(f\"cat__{original_feature}_\") for name in proc_feature_names])\n",
    "    if mask.sum() == 0:\n",
    "        continue\n",
    "    agg_rows.append({\n",
    "        \"feature\": original_feature,\n",
    "        \"permutation_importance_mean\": float(np.mean(perm.importances_mean[mask])),\n",
    "        \"permutation_importance_std\": float(np.sqrt(np.mean(np.square(perm.importances_std[mask])))),\n",
    "    })\n",
    "\n",
    "perm_df = pd.DataFrame(agg_rows).sort_values(\"permutation_importance_mean\", ascending=False).reset_index(drop=True)\n",
    "print(\"Топ-10 признаков по перестановочной важности:\")\n",
    "display(perm_df.head(10))\n",
    "\n",
    "positive_features = perm_df.loc[perm_df[\"permutation_importance_mean\"] > 0, \"feature\"].tolist()\n",
    "if len(positive_features) >= 4:\n",
    "    selected_features = positive_features[:min(8, len(positive_features))]\n",
    "else:\n",
    "    selected_features = perm_df[\"feature\"].head(min(6, len(perm_df))).tolist()\n",
    "\n",
    "print(\"Отобранные признаки:\")\n",
    "print(selected_features)\n",
    "print(\"Число отобранных признаков:\", len(selected_features))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "aa552126",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Число признаков после кодирования для второй модели: 26\n"
     ]
    }
   ],
   "source": [
    "\n",
    "X_sel = X[selected_features].copy()\n",
    "\n",
    "numeric_features_sel = X_sel.select_dtypes(include=[np.number]).columns.tolist()\n",
    "categorical_features_sel = [c for c in X_sel.columns if c not in numeric_features_sel]\n",
    "\n",
    "preprocessor_sel = ColumnTransformer(\n",
    "    transformers=[\n",
    "        (\"num\", Pipeline([\n",
    "            (\"imputer\", SimpleImputer(strategy=\"median\")),\n",
    "            (\"scaler\", StandardScaler()),\n",
    "        ]), numeric_features_sel),\n",
    "        (\"cat\", Pipeline([\n",
    "            (\"imputer\", SimpleImputer(strategy=\"most_frequent\")),\n",
    "            (\"ohe\", make_ohe()),\n",
    "        ]), categorical_features_sel),\n",
    "    ],\n",
    "    remainder=\"drop\"\n",
    ")\n",
    "\n",
    "X_sel_trainval = X_trainval[selected_features].copy()\n",
    "X_sel_test = X_test[selected_features].copy()\n",
    "X_sel_train = X_train[selected_features].copy()\n",
    "X_sel_val = X_val[selected_features].copy()\n",
    "\n",
    "X_sel_train_proc = preprocessor_sel.fit_transform(X_sel_train)\n",
    "X_sel_val_proc = preprocessor_sel.transform(X_sel_val)\n",
    "X_sel_trainval_proc = preprocessor_sel.fit_transform(X_sel_trainval)\n",
    "X_sel_test_proc = preprocessor_sel.transform(X_sel_test)\n",
    "\n",
    "try:\n",
    "    feature_names_sel = preprocessor_sel.get_feature_names_out()\n",
    "except Exception:\n",
    "    feature_names_sel = [f\"feature_{i}\" for i in range(X_sel_train_proc.shape[1])]\n",
    "\n",
    "print(\"Число признаков после кодирования для второй модели:\", len(feature_names_sel))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "ddd683b4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Топ-10 конфигураций эволюционного поиска:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>hidden_layers</th>\n",
       "      <th>alpha</th>\n",
       "      <th>learning_rate_init</th>\n",
       "      <th>rmse_val</th>\n",
       "      <th>mae_val</th>\n",
       "      <th>r2_val</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>(56,)</td>\n",
       "      <td>0.000081</td>\n",
       "      <td>0.000660</td>\n",
       "      <td>2.577821</td>\n",
       "      <td>2.220958</td>\n",
       "      <td>0.002888</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>(96,)</td>\n",
       "      <td>0.000006</td>\n",
       "      <td>0.001274</td>\n",
       "      <td>2.580910</td>\n",
       "      <td>2.221198</td>\n",
       "      <td>0.000497</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>(58, 29)</td>\n",
       "      <td>0.000145</td>\n",
       "      <td>0.003917</td>\n",
       "      <td>2.580938</td>\n",
       "      <td>2.227231</td>\n",
       "      <td>0.000475</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>(54, 27)</td>\n",
       "      <td>0.000003</td>\n",
       "      <td>0.001958</td>\n",
       "      <td>2.580952</td>\n",
       "      <td>2.217738</td>\n",
       "      <td>0.000464</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>(104, 52, 26)</td>\n",
       "      <td>0.001017</td>\n",
       "      <td>0.000160</td>\n",
       "      <td>2.585507</td>\n",
       "      <td>2.228321</td>\n",
       "      <td>-0.003067</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>(93,)</td>\n",
       "      <td>0.000185</td>\n",
       "      <td>0.000349</td>\n",
       "      <td>2.585920</td>\n",
       "      <td>2.224106</td>\n",
       "      <td>-0.003387</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>(126, 63, 32, 16)</td>\n",
       "      <td>0.004860</td>\n",
       "      <td>0.001904</td>\n",
       "      <td>2.586628</td>\n",
       "      <td>2.233122</td>\n",
       "      <td>-0.003937</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>(104, 52, 26)</td>\n",
       "      <td>0.000002</td>\n",
       "      <td>0.000396</td>\n",
       "      <td>2.587182</td>\n",
       "      <td>2.227062</td>\n",
       "      <td>-0.004367</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>(105, 52, 26)</td>\n",
       "      <td>0.001684</td>\n",
       "      <td>0.000143</td>\n",
       "      <td>2.587307</td>\n",
       "      <td>2.224707</td>\n",
       "      <td>-0.004464</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>(29, 14, 8)</td>\n",
       "      <td>0.000916</td>\n",
       "      <td>0.001446</td>\n",
       "      <td>2.587984</td>\n",
       "      <td>2.223008</td>\n",
       "      <td>-0.004990</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       hidden_layers     alpha  learning_rate_init  rmse_val   mae_val  \\\n",
       "0              (56,)  0.000081            0.000660  2.577821  2.220958   \n",
       "1              (96,)  0.000006            0.001274  2.580910  2.221198   \n",
       "2           (58, 29)  0.000145            0.003917  2.580938  2.227231   \n",
       "3           (54, 27)  0.000003            0.001958  2.580952  2.217738   \n",
       "4      (104, 52, 26)  0.001017            0.000160  2.585507  2.228321   \n",
       "5              (93,)  0.000185            0.000349  2.585920  2.224106   \n",
       "6  (126, 63, 32, 16)  0.004860            0.001904  2.586628  2.233122   \n",
       "7      (104, 52, 26)  0.000002            0.000396  2.587182  2.227062   \n",
       "8      (105, 52, 26)  0.001684            0.000143  2.587307  2.224707   \n",
       "9        (29, 14, 8)  0.000916            0.001446  2.587984  2.223008   \n",
       "\n",
       "     r2_val  \n",
       "0  0.002888  \n",
       "1  0.000497  \n",
       "2  0.000475  \n",
       "3  0.000464  \n",
       "4 -0.003067  \n",
       "5 -0.003387  \n",
       "6 -0.003937  \n",
       "7 -0.004367  \n",
       "8 -0.004464  \n",
       "9 -0.004990  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Лучшая архитектура, найденная эволюционным поиском: (56,)\n",
      "alpha: 8.067758731492677e-05\n",
      "learning_rate_init: 0.0006600577523657266\n"
     ]
    }
   ],
   "source": [
    "\n",
    "search_results = []\n",
    "\n",
    "def decode_candidate(vec):\n",
    "    # [layers_raw, units_raw, alpha_raw, lr_raw]\n",
    "    layers = int(np.clip(round(vec[0]), 1, 4))\n",
    "    base_units = int(np.clip(round(vec[1]), 16, 128))\n",
    "    alpha = float(10 ** np.clip(vec[2], -6, -2))\n",
    "    lr = float(10 ** np.clip(vec[3], -4, -2))\n",
    "\n",
    "    arch = []\n",
    "    units = base_units\n",
    "    for _ in range(layers):\n",
    "        arch.append(max(8, int(round(units))))\n",
    "        units = max(8, units / 2)\n",
    "    return tuple(arch), alpha, lr\n",
    "\n",
    "_eval_cache = {}\n",
    "\n",
    "def evaluate_candidate(vec):\n",
    "    arch, alpha, lr = decode_candidate(vec)\n",
    "    key = (arch, round(alpha, 8), round(lr, 8))\n",
    "    if key in _eval_cache:\n",
    "        return _eval_cache[key]\n",
    "\n",
    "    model = MLPRegressor(\n",
    "        hidden_layer_sizes=arch,\n",
    "        activation=\"relu\",\n",
    "        solver=\"adam\",\n",
    "        alpha=alpha,\n",
    "        learning_rate_init=lr,\n",
    "        max_iter=250,\n",
    "        early_stopping=True,\n",
    "        validation_fraction=0.15,\n",
    "        n_iter_no_change=15,\n",
    "        random_state=RANDOM_STATE\n",
    "    )\n",
    "    model.fit(X_sel_train_proc, y_train)\n",
    "    pred_val = model.predict(X_sel_val_proc)\n",
    "    val_rmse = float(np.sqrt(mean_squared_error(y_val, pred_val)))\n",
    "    val_mae = float(mean_absolute_error(y_val, pred_val))\n",
    "    val_r2 = float(r2_score(y_val, pred_val))\n",
    "\n",
    "    row = {\n",
    "        \"hidden_layers\": arch,\n",
    "        \"alpha\": alpha,\n",
    "        \"learning_rate_init\": lr,\n",
    "        \"rmse_val\": val_rmse,\n",
    "        \"mae_val\": val_mae,\n",
    "        \"r2_val\": val_r2,\n",
    "    }\n",
    "    search_results.append(row)\n",
    "    _eval_cache[key] = val_rmse\n",
    "    return val_rmse\n",
    "\n",
    "use_scipy = True\n",
    "try:\n",
    "    from scipy.optimize import differential_evolution\n",
    "except Exception:\n",
    "    use_scipy = False\n",
    "\n",
    "bounds = [\n",
    "    (1, 4),      # число слоёв\n",
    "    (16, 128),   # базовое число нейронов\n",
    "    (-6, -2),    # log10(alpha)\n",
    "    (-4, -2),    # log10(lr)\n",
    "]\n",
    "\n",
    "if use_scipy:\n",
    "    result = differential_evolution(\n",
    "        func=evaluate_candidate,\n",
    "        bounds=bounds,\n",
    "        strategy=\"best1bin\",\n",
    "        maxiter=6,\n",
    "        popsize=6,\n",
    "        tol=0.01,\n",
    "        polish=False,\n",
    "        seed=RANDOM_STATE,\n",
    "        updating=\"deferred\",\n",
    "        workers=1,\n",
    "    )\n",
    "    best_arch, best_alpha, best_lr = decode_candidate(result.x)\n",
    "else:\n",
    "    # упрощённый эволюционный поиск без scipy\n",
    "    population = [np.array([\n",
    "        np.random.uniform(1, 4),\n",
    "        np.random.uniform(16, 128),\n",
    "        np.random.uniform(-6, -2),\n",
    "        np.random.uniform(-4, -2)\n",
    "    ]) for _ in range(18)]\n",
    "\n",
    "    for gen in range(8):\n",
    "        scores = np.array([evaluate_candidate(ind) for ind in population])\n",
    "        order = np.argsort(scores)\n",
    "        population = [population[i] for i in order[:9]]\n",
    "        new_population = population.copy()\n",
    "        while len(new_population) < 18:\n",
    "            a, b = np.random.choice(len(population), 2, replace=False)\n",
    "            child = 0.5 * population[a] + 0.5 * population[b]\n",
    "            child = child + np.random.normal(0, [0.4, 8, 0.4, 0.3], size=4)\n",
    "            child[0] = np.clip(child[0], 1, 4)\n",
    "            child[1] = np.clip(child[1], 16, 128)\n",
    "            child[2] = np.clip(child[2], -6, -2)\n",
    "            child[3] = np.clip(child[3], -4, -2)\n",
    "            new_population.append(child)\n",
    "        population = new_population\n",
    "    best_vec = min(population, key=evaluate_candidate)\n",
    "    best_arch, best_alpha, best_lr = decode_candidate(best_vec)\n",
    "\n",
    "search_df = pd.DataFrame(search_results).sort_values([\"rmse_val\", \"mae_val\"]).drop_duplicates().reset_index(drop=True)\n",
    "print(\"Топ-10 конфигураций эволюционного поиска:\")\n",
    "display(search_df.head(10))\n",
    "\n",
    "print(\"Лучшая архитектура, найденная эволюционным поиском:\", best_arch)\n",
    "print(\"alpha:\", best_alpha)\n",
    "print(\"learning_rate_init:\", best_lr)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "687ddc75",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Метрики второй модели (по выбранным признакам):\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>split</th>\n",
       "      <th>r2</th>\n",
       "      <th>rmse</th>\n",
       "      <th>mae</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>trainval</td>\n",
       "      <td>0.008197</td>\n",
       "      <td>2.53543</td>\n",
       "      <td>2.192504</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>test</td>\n",
       "      <td>-0.011536</td>\n",
       "      <td>2.61676</td>\n",
       "      <td>2.264249</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      split        r2     rmse       mae\n",
       "0  trainval  0.008197  2.53543  2.192504\n",
       "1      test -0.011536  2.61676  2.264249"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 800x400 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "best_model = MLPRegressor(\n",
    "    hidden_layer_sizes=best_arch,\n",
    "    activation=\"relu\",\n",
    "    solver=\"adam\",\n",
    "    alpha=best_alpha,\n",
    "    learning_rate_init=best_lr,\n",
    "    max_iter=500,\n",
    "    early_stopping=True,\n",
    "    validation_fraction=0.15,\n",
    "    n_iter_no_change=20,\n",
    "    random_state=RANDOM_STATE\n",
    ")\n",
    "best_model.fit(X_sel_trainval_proc, y_trainval)\n",
    "\n",
    "pred_trainval_best = best_model.predict(X_sel_trainval_proc)\n",
    "pred_test_best = best_model.predict(X_sel_test_proc)\n",
    "\n",
    "best_metrics = pd.DataFrame([\n",
    "    {\"split\": \"trainval\", **regression_metrics(y_trainval, pred_trainval_best)},\n",
    "    {\"split\": \"test\", **regression_metrics(y_test, pred_test_best)},\n",
    "])\n",
    "\n",
    "print(\"Метрики второй модели (по выбранным признакам):\")\n",
    "display(best_metrics)\n",
    "\n",
    "plt.figure(figsize=(8, 4))\n",
    "plt.plot(best_model.loss_curve_)\n",
    "plt.title(\"Кривая обучения второй нейросети\")\n",
    "plt.xlabel(\"Итерация\")\n",
    "plt.ylabel(\"Loss\")\n",
    "plt.grid(True)\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "63502f80",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Сравнение моделей:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>model</th>\n",
       "      <th>r2_test</th>\n",
       "      <th>rmse_test</th>\n",
       "      <th>mae_test</th>\n",
       "      <th>r2_val</th>\n",
       "      <th>rmse_val</th>\n",
       "      <th>mae_val</th>\n",
       "      <th>n_original_features</th>\n",
       "      <th>n_processed_features</th>\n",
       "      <th>hidden_layers</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Нейросеть по отобранным признакам + эволюционн...</td>\n",
       "      <td>-0.011536</td>\n",
       "      <td>2.616760</td>\n",
       "      <td>2.264249</td>\n",
       "      <td>0.010686</td>\n",
       "      <td>2.567721</td>\n",
       "      <td>2.214208</td>\n",
       "      <td>7</td>\n",
       "      <td>26</td>\n",
       "      <td>(56,)</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Базовая нейросеть по всем признакам</td>\n",
       "      <td>-0.025478</td>\n",
       "      <td>2.634732</td>\n",
       "      <td>2.256196</td>\n",
       "      <td>-0.071769</td>\n",
       "      <td>2.672584</td>\n",
       "      <td>2.290122</td>\n",
       "      <td>11</td>\n",
       "      <td>30</td>\n",
       "      <td>(64, 32)</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                               model   r2_test  rmse_test  \\\n",
       "0  Нейросеть по отобранным признакам + эволюционн... -0.011536   2.616760   \n",
       "1                Базовая нейросеть по всем признакам -0.025478   2.634732   \n",
       "\n",
       "   mae_test    r2_val  rmse_val   mae_val  n_original_features  \\\n",
       "0  2.264249  0.010686  2.567721  2.214208                    7   \n",
       "1  2.256196 -0.071769  2.672584  2.290122                   11   \n",
       "\n",
       "   n_processed_features hidden_layers  \n",
       "0                    26         (56,)  \n",
       "1                    30      (64, 32)  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "comparison_df = pd.DataFrame([\n",
    "    {\n",
    "        \"model\": \"Базовая нейросеть по всем признакам\",\n",
    "        \"r2_test\": regression_metrics(y_test, pred_test_baseline)[\"r2\"],\n",
    "        \"rmse_test\": regression_metrics(y_test, pred_test_baseline)[\"rmse\"],\n",
    "        \"mae_test\": regression_metrics(y_test, pred_test_baseline)[\"mae\"],\n",
    "        \"r2_val\": regression_metrics(y_val, pred_val_baseline)[\"r2\"],\n",
    "        \"rmse_val\": regression_metrics(y_val, pred_val_baseline)[\"rmse\"],\n",
    "        \"mae_val\": regression_metrics(y_val, pred_val_baseline)[\"mae\"],\n",
    "        \"n_original_features\": X.shape[1],\n",
    "        \"n_processed_features\": len(feature_names),\n",
    "        \"hidden_layers\": str(baseline_hidden),\n",
    "    },\n",
    "    {\n",
    "        \"model\": \"Нейросеть по отобранным признакам + эволюционный поиск архитектуры\",\n",
    "        \"r2_test\": regression_metrics(y_test, pred_test_best)[\"r2\"],\n",
    "        \"rmse_test\": regression_metrics(y_test, pred_test_best)[\"rmse\"],\n",
    "        \"mae_test\": regression_metrics(y_test, pred_test_best)[\"mae\"],\n",
    "        \"r2_val\": regression_metrics(y_val, best_model.predict(X_sel_val_proc))[\"r2\"],\n",
    "        \"rmse_val\": regression_metrics(y_val, best_model.predict(X_sel_val_proc))[\"rmse\"],\n",
    "        \"mae_val\": regression_metrics(y_val, best_model.predict(X_sel_val_proc))[\"mae\"],\n",
    "        \"n_original_features\": len(selected_features),\n",
    "        \"n_processed_features\": len(feature_names_sel),\n",
    "        \"hidden_layers\": str(best_arch),\n",
    "    },\n",
    "]).sort_values([\"rmse_test\", \"mae_test\"]).reset_index(drop=True)\n",
    "\n",
    "print(\"Сравнение моделей:\")\n",
    "display(comparison_df)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "662ca5d8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "=== КЛЮЧЕВАЯ ИНФОРМАЦИЯ ДЛЯ ВЫВОДА ===\n",
      "Зависимая переменная: happiness_score\n",
      "\n",
      "Число исходных признаков: 11\n",
      "Число признаков после кодирования (все признаки): 30\n",
      "Число отобранных исходных признаков: 7\n",
      "Число признаков после кодирования (отобранные признаки): 26\n",
      "Фиксированная архитектура первой модели: (64, 32)\n",
      "Архитектура, найденная эволюционным поиском: (56,)\n",
      "alpha найденной модели: 8.067758731492677e-05\n",
      "learning_rate_init найденной модели: 0.0006600577523657266\n",
      "\n",
      "Отобранные признаки:\n",
      "['exercise_level', 'stress_level', 'diet_type', 'mental_health_condition', 'gender', 'country', 'work_hours_per_week']\n",
      "\n",
      "Метрики моделей на тестовой выборке:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>model</th>\n",
       "      <th>r2_test</th>\n",
       "      <th>rmse_test</th>\n",
       "      <th>mae_test</th>\n",
       "      <th>r2_val</th>\n",
       "      <th>rmse_val</th>\n",
       "      <th>mae_val</th>\n",
       "      <th>n_original_features</th>\n",
       "      <th>n_processed_features</th>\n",
       "      <th>hidden_layers</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Нейросеть по отобранным признакам + эволюционн...</td>\n",
       "      <td>-0.011536</td>\n",
       "      <td>2.616760</td>\n",
       "      <td>2.264249</td>\n",
       "      <td>0.010686</td>\n",
       "      <td>2.567721</td>\n",
       "      <td>2.214208</td>\n",
       "      <td>7</td>\n",
       "      <td>26</td>\n",
       "      <td>(56,)</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Базовая нейросеть по всем признакам</td>\n",
       "      <td>-0.025478</td>\n",
       "      <td>2.634732</td>\n",
       "      <td>2.256196</td>\n",
       "      <td>-0.071769</td>\n",
       "      <td>2.672584</td>\n",
       "      <td>2.290122</td>\n",
       "      <td>11</td>\n",
       "      <td>30</td>\n",
       "      <td>(64, 32)</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                               model   r2_test  rmse_test  \\\n",
       "0  Нейросеть по отобранным признакам + эволюционн... -0.011536   2.616760   \n",
       "1                Базовая нейросеть по всем признакам -0.025478   2.634732   \n",
       "\n",
       "   mae_test    r2_val  rmse_val   mae_val  n_original_features  \\\n",
       "0  2.264249  0.010686  2.567721  2.214208                    7   \n",
       "1  2.256196 -0.071769  2.672584  2.290122                   11   \n",
       "\n",
       "   n_processed_features hidden_layers  \n",
       "0                    26         (56,)  \n",
       "1                    30      (64, 32)  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Лучшая модель:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>model</th>\n",
       "      <th>r2_test</th>\n",
       "      <th>rmse_test</th>\n",
       "      <th>mae_test</th>\n",
       "      <th>r2_val</th>\n",
       "      <th>rmse_val</th>\n",
       "      <th>mae_val</th>\n",
       "      <th>n_original_features</th>\n",
       "      <th>n_processed_features</th>\n",
       "      <th>hidden_layers</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Нейросеть по отобранным признакам + эволюционн...</td>\n",
       "      <td>-0.011536</td>\n",
       "      <td>2.61676</td>\n",
       "      <td>2.264249</td>\n",
       "      <td>0.010686</td>\n",
       "      <td>2.567721</td>\n",
       "      <td>2.214208</td>\n",
       "      <td>7</td>\n",
       "      <td>26</td>\n",
       "      <td>(56,)</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                               model   r2_test  rmse_test  \\\n",
       "0  Нейросеть по отобранным признакам + эволюционн... -0.011536    2.61676   \n",
       "\n",
       "   mae_test    r2_val  rmse_val   mae_val  n_original_features  \\\n",
       "0  2.264249  0.010686  2.567721  2.214208                    7   \n",
       "\n",
       "   n_processed_features hidden_layers  \n",
       "0                    26         (56,)  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Топ-10 признаков по важности:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>feature</th>\n",
       "      <th>permutation_importance_mean</th>\n",
       "      <th>permutation_importance_std</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>exercise_level</td>\n",
       "      <td>0.022801</td>\n",
       "      <td>0.011556</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>stress_level</td>\n",
       "      <td>0.021812</td>\n",
       "      <td>0.014420</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>diet_type</td>\n",
       "      <td>0.019173</td>\n",
       "      <td>0.008693</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>mental_health_condition</td>\n",
       "      <td>0.010748</td>\n",
       "      <td>0.005653</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>gender</td>\n",
       "      <td>0.007888</td>\n",
       "      <td>0.005160</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>country</td>\n",
       "      <td>0.007468</td>\n",
       "      <td>0.007103</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>work_hours_per_week</td>\n",
       "      <td>0.006936</td>\n",
       "      <td>0.006448</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>age</td>\n",
       "      <td>-0.012904</td>\n",
       "      <td>0.008048</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>sleep_hours</td>\n",
       "      <td>-0.013075</td>\n",
       "      <td>0.008175</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>social_interaction_score</td>\n",
       "      <td>-0.016482</td>\n",
       "      <td>0.006457</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                    feature  permutation_importance_mean  \\\n",
       "0            exercise_level                     0.022801   \n",
       "1              stress_level                     0.021812   \n",
       "2                 diet_type                     0.019173   \n",
       "3   mental_health_condition                     0.010748   \n",
       "4                    gender                     0.007888   \n",
       "5                   country                     0.007468   \n",
       "6       work_hours_per_week                     0.006936   \n",
       "7                       age                    -0.012904   \n",
       "8               sleep_hours                    -0.013075   \n",
       "9  social_interaction_score                    -0.016482   \n",
       "\n",
       "   permutation_importance_std  \n",
       "0                    0.011556  \n",
       "1                    0.014420  \n",
       "2                    0.008693  \n",
       "3                    0.005653  \n",
       "4                    0.005160  \n",
       "5                    0.007103  \n",
       "6                    0.006448  \n",
       "7                    0.008048  \n",
       "8                    0.008175  \n",
       "9                    0.006457  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Топ-10 конфигураций эволюционного поиска:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>hidden_layers</th>\n",
       "      <th>alpha</th>\n",
       "      <th>learning_rate_init</th>\n",
       "      <th>rmse_val</th>\n",
       "      <th>mae_val</th>\n",
       "      <th>r2_val</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>(56,)</td>\n",
       "      <td>0.000081</td>\n",
       "      <td>0.000660</td>\n",
       "      <td>2.577821</td>\n",
       "      <td>2.220958</td>\n",
       "      <td>0.002888</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>(96,)</td>\n",
       "      <td>0.000006</td>\n",
       "      <td>0.001274</td>\n",
       "      <td>2.580910</td>\n",
       "      <td>2.221198</td>\n",
       "      <td>0.000497</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>(58, 29)</td>\n",
       "      <td>0.000145</td>\n",
       "      <td>0.003917</td>\n",
       "      <td>2.580938</td>\n",
       "      <td>2.227231</td>\n",
       "      <td>0.000475</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>(54, 27)</td>\n",
       "      <td>0.000003</td>\n",
       "      <td>0.001958</td>\n",
       "      <td>2.580952</td>\n",
       "      <td>2.217738</td>\n",
       "      <td>0.000464</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>(104, 52, 26)</td>\n",
       "      <td>0.001017</td>\n",
       "      <td>0.000160</td>\n",
       "      <td>2.585507</td>\n",
       "      <td>2.228321</td>\n",
       "      <td>-0.003067</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>(93,)</td>\n",
       "      <td>0.000185</td>\n",
       "      <td>0.000349</td>\n",
       "      <td>2.585920</td>\n",
       "      <td>2.224106</td>\n",
       "      <td>-0.003387</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>(126, 63, 32, 16)</td>\n",
       "      <td>0.004860</td>\n",
       "      <td>0.001904</td>\n",
       "      <td>2.586628</td>\n",
       "      <td>2.233122</td>\n",
       "      <td>-0.003937</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>(104, 52, 26)</td>\n",
       "      <td>0.000002</td>\n",
       "      <td>0.000396</td>\n",
       "      <td>2.587182</td>\n",
       "      <td>2.227062</td>\n",
       "      <td>-0.004367</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>(105, 52, 26)</td>\n",
       "      <td>0.001684</td>\n",
       "      <td>0.000143</td>\n",
       "      <td>2.587307</td>\n",
       "      <td>2.224707</td>\n",
       "      <td>-0.004464</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>(29, 14, 8)</td>\n",
       "      <td>0.000916</td>\n",
       "      <td>0.001446</td>\n",
       "      <td>2.587984</td>\n",
       "      <td>2.223008</td>\n",
       "      <td>-0.004990</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       hidden_layers     alpha  learning_rate_init  rmse_val   mae_val  \\\n",
       "0              (56,)  0.000081            0.000660  2.577821  2.220958   \n",
       "1              (96,)  0.000006            0.001274  2.580910  2.221198   \n",
       "2           (58, 29)  0.000145            0.003917  2.580938  2.227231   \n",
       "3           (54, 27)  0.000003            0.001958  2.580952  2.217738   \n",
       "4      (104, 52, 26)  0.001017            0.000160  2.585507  2.228321   \n",
       "5              (93,)  0.000185            0.000349  2.585920  2.224106   \n",
       "6  (126, 63, 32, 16)  0.004860            0.001904  2.586628  2.233122   \n",
       "7      (104, 52, 26)  0.000002            0.000396  2.587182  2.227062   \n",
       "8      (105, 52, 26)  0.001684            0.000143  2.587307  2.224707   \n",
       "9        (29, 14, 8)  0.000916            0.001446  2.587984  2.223008   \n",
       "\n",
       "     r2_val  \n",
       "0  0.002888  \n",
       "1  0.000497  \n",
       "2  0.000475  \n",
       "3  0.000464  \n",
       "4 -0.003067  \n",
       "5 -0.003387  \n",
       "6 -0.003937  \n",
       "7 -0.004367  \n",
       "8 -0.004464  \n",
       "9 -0.004990  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Последние эпохи обучения базовой нейросети:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>epoch</th>\n",
       "      <th>train_loss</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>53</th>\n",
       "      <td>54</td>\n",
       "      <td>2.892276</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>54</th>\n",
       "      <td>55</td>\n",
       "      <td>2.885353</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>55</th>\n",
       "      <td>56</td>\n",
       "      <td>2.878268</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>56</th>\n",
       "      <td>57</td>\n",
       "      <td>2.873679</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>57</th>\n",
       "      <td>58</td>\n",
       "      <td>2.862408</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>58</th>\n",
       "      <td>59</td>\n",
       "      <td>2.860602</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>59</th>\n",
       "      <td>60</td>\n",
       "      <td>2.849065</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>60</th>\n",
       "      <td>61</td>\n",
       "      <td>2.841779</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>61</th>\n",
       "      <td>62</td>\n",
       "      <td>2.832322</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>62</th>\n",
       "      <td>63</td>\n",
       "      <td>2.824808</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    epoch  train_loss\n",
       "53     54    2.892276\n",
       "54     55    2.885353\n",
       "55     56    2.878268\n",
       "56     57    2.873679\n",
       "57     58    2.862408\n",
       "58     59    2.860602\n",
       "59     60    2.849065\n",
       "60     61    2.841779\n",
       "61     62    2.832322\n",
       "62     63    2.824808"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Последние эпохи обучения модели с найденной архитектурой:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>epoch</th>\n",
       "      <th>train_loss</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>61</th>\n",
       "      <td>62</td>\n",
       "      <td>3.156066</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>62</th>\n",
       "      <td>63</td>\n",
       "      <td>3.156377</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>63</th>\n",
       "      <td>64</td>\n",
       "      <td>3.154805</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>64</th>\n",
       "      <td>65</td>\n",
       "      <td>3.154852</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>65</th>\n",
       "      <td>66</td>\n",
       "      <td>3.153527</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>66</th>\n",
       "      <td>67</td>\n",
       "      <td>3.154119</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>67</th>\n",
       "      <td>68</td>\n",
       "      <td>3.153056</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>68</th>\n",
       "      <td>69</td>\n",
       "      <td>3.152203</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>69</th>\n",
       "      <td>70</td>\n",
       "      <td>3.151758</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>70</th>\n",
       "      <td>71</td>\n",
       "      <td>3.151723</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    epoch  train_loss\n",
       "61     62    3.156066\n",
       "62     63    3.156377\n",
       "63     64    3.154805\n",
       "64     65    3.154852\n",
       "65     66    3.153527\n",
       "66     67    3.154119\n",
       "67     68    3.153056\n",
       "68     69    3.152203\n",
       "69     70    3.151758\n",
       "70     71    3.151723"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Первые 10 фактических и предсказанных значений на тесте:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>y_true</th>\n",
       "      <th>y_pred_baseline</th>\n",
       "      <th>y_pred_selected_evolution</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>5.6</td>\n",
       "      <td>4.828311</td>\n",
       "      <td>5.289400</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>9.8</td>\n",
       "      <td>5.699056</td>\n",
       "      <td>5.482407</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>6.0</td>\n",
       "      <td>4.619857</td>\n",
       "      <td>5.499895</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>8.6</td>\n",
       "      <td>5.055970</td>\n",
       "      <td>4.970277</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>2.8</td>\n",
       "      <td>6.008471</td>\n",
       "      <td>5.316428</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>5.3</td>\n",
       "      <td>5.479088</td>\n",
       "      <td>5.267063</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>2.2</td>\n",
       "      <td>5.314668</td>\n",
       "      <td>5.545767</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>4.5</td>\n",
       "      <td>5.269071</td>\n",
       "      <td>5.413516</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>5.1</td>\n",
       "      <td>5.503009</td>\n",
       "      <td>5.547910</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>4.3</td>\n",
       "      <td>4.846507</td>\n",
       "      <td>5.304741</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   y_true  y_pred_baseline  y_pred_selected_evolution\n",
       "0     5.6         4.828311                   5.289400\n",
       "1     9.8         5.699056                   5.482407\n",
       "2     6.0         4.619857                   5.499895\n",
       "3     8.6         5.055970                   4.970277\n",
       "4     2.8         6.008471                   5.316428\n",
       "5     5.3         5.479088                   5.267063\n",
       "6     2.2         5.314668                   5.545767\n",
       "7     4.5         5.269071                   5.413516\n",
       "8     5.1         5.503009                   5.547910\n",
       "9     4.3         4.846507                   5.304741"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "print(\"=== КЛЮЧЕВАЯ ИНФОРМАЦИЯ ДЛЯ ВЫВОДА ===\")\n",
    "print(f\"Зависимая переменная: {target_col}\")\n",
    "print()\n",
    "print(f\"Число исходных признаков: {X.shape[1]}\")\n",
    "print(f\"Число признаков после кодирования (все признаки): {len(feature_names)}\")\n",
    "print(f\"Число отобранных исходных признаков: {len(selected_features)}\")\n",
    "print(f\"Число признаков после кодирования (отобранные признаки): {len(feature_names_sel)}\")\n",
    "print(f\"Фиксированная архитектура первой модели: {baseline_hidden}\")\n",
    "print(f\"Архитектура, найденная эволюционным поиском: {best_arch}\")\n",
    "print(f\"alpha найденной модели: {best_alpha}\")\n",
    "print(f\"learning_rate_init найденной модели: {best_lr}\")\n",
    "print()\n",
    "\n",
    "print(\"Отобранные признаки:\")\n",
    "print(selected_features)\n",
    "print()\n",
    "\n",
    "print(\"Метрики моделей на тестовой выборке:\")\n",
    "display(comparison_df)\n",
    "\n",
    "print(\"Лучшая модель:\")\n",
    "best_row = comparison_df.sort_values([\"rmse_test\", \"mae_test\", \"r2_test\"], ascending=[True, True, False]).head(1)\n",
    "display(best_row)\n",
    "\n",
    "print(\"Топ-10 признаков по важности:\")\n",
    "display(perm_df.head(10))\n",
    "\n",
    "print(\"Топ-10 конфигураций эволюционного поиска:\")\n",
    "display(search_df.head(10))\n",
    "\n",
    "print(\"Последние эпохи обучения базовой нейросети:\")\n",
    "display(pd.DataFrame({\n",
    "    \"epoch\": np.arange(1, len(baseline_model.loss_curve_) + 1),\n",
    "    \"train_loss\": baseline_model.loss_curve_,\n",
    "}).tail(10))\n",
    "\n",
    "print(\"Последние эпохи обучения модели с найденной архитектурой:\")\n",
    "display(pd.DataFrame({\n",
    "    \"epoch\": np.arange(1, len(best_model.loss_curve_) + 1),\n",
    "    \"train_loss\": best_model.loss_curve_,\n",
    "}).tail(10))\n",
    "\n",
    "pred_example_df = pd.DataFrame({\n",
    "    \"y_true\": y_test.reset_index(drop=True).head(10),\n",
    "    \"y_pred_baseline\": pd.Series(pred_test_baseline).head(10),\n",
    "    \"y_pred_selected_evolution\": pd.Series(pred_test_best).head(10),\n",
    "})\n",
    "print(\"Первые 10 фактических и предсказанных значений на тесте:\")\n",
    "display(pred_example_df)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e6a08f26",
   "metadata": {},
   "source": [
    "Итог\n",
    "\n",
    "Зависимой переменной выбрана happiness_score. Для прогноза были построены две нейросети: базовая модель по всем признакам и модель по 7 отобранным признакам с архитектурой, найденной эволюционным поиском.\n",
    "\n",
    "По тестовым метрикам обе модели показали неприемлемое качество: у обеих R² < 0, а предсказания слабо отражают реальную вариацию целевой переменной. Это означает, что модели фактически не дают полезного регрессионного описания данных.\n",
    "\n",
    "Наиболее важными признаками по permutation importance оказались exercise_level, stress_level, diet_type, mental_health_condition, gender, country, work_hours_per_week, однако даже их использование не привело к практически пригодному результату.\n",
    "\n",
    "Следовательно, все построенные модели в данной постановке задачи неудовлетворительны и не представляют практической ценности для использования."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
