{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "bea21d70",
   "metadata": {},
   "source": [
    "# Регрессия по датасету вина: нейросети, отбор признаков и эволюционный поиск архитектуры\n",
    "\n",
    "В работе:\n",
    "- автоматически определяется зависимая переменная;\n",
    "- строится базовая нейросеть по всем признакам;\n",
    "- оценивается важность признаков;\n",
    "- отбираются наиболее важные признаки;\n",
    "- по ним строится вторая нейросеть с архитектурой, найденной методом эволюционного поиска;\n",
    "- модели сравниваются на валидационной и тестовой выборках.\n",
    "\n",
    "Финальный текстовый вывод в ноутбуке отсутствует. В конце есть отдельная ячейка, печатающая всю информацию для вывода."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "84d40ef3",
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "import warnings\n",
    "warnings.filterwarnings(\"ignore\")\n",
    "\n",
    "import os\n",
    "import re\n",
    "import glob\n",
    "import math\n",
    "import random\n",
    "from pathlib import Path\n",
    "\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "from sklearn.compose import ColumnTransformer\n",
    "from sklearn.base import BaseEstimator, RegressorMixin\n",
    "from sklearn.impute import SimpleImputer\n",
    "from sklearn.inspection import permutation_importance\n",
    "from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.neural_network import MLPRegressor\n",
    "from sklearn.pipeline import Pipeline\n",
    "from sklearn.preprocessing import OneHotEncoder, StandardScaler"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "688e4ac8",
   "metadata": {},
   "source": [
    "## Загрузка и первичный просмотр данных"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "4a6b74ba",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Используемый файл: cleaned_red_wine.csv\n",
      "Форма датасета: (1359, 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>fixed acidity</th>\n",
       "      <th>volatile acidity</th>\n",
       "      <th>citric acid</th>\n",
       "      <th>residual sugar</th>\n",
       "      <th>chlorides</th>\n",
       "      <th>free sulfur dioxide</th>\n",
       "      <th>total sulfur dioxide</th>\n",
       "      <th>density</th>\n",
       "      <th>pH</th>\n",
       "      <th>sulphates</th>\n",
       "      <th>alcohol</th>\n",
       "      <th>quality</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>7.4</td>\n",
       "      <td>0.70</td>\n",
       "      <td>0.00</td>\n",
       "      <td>1.9</td>\n",
       "      <td>0.076</td>\n",
       "      <td>11.0</td>\n",
       "      <td>34.0</td>\n",
       "      <td>0.9978</td>\n",
       "      <td>3.51</td>\n",
       "      <td>0.56</td>\n",
       "      <td>9.4</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>7.8</td>\n",
       "      <td>0.88</td>\n",
       "      <td>0.00</td>\n",
       "      <td>2.6</td>\n",
       "      <td>0.098</td>\n",
       "      <td>25.0</td>\n",
       "      <td>67.0</td>\n",
       "      <td>0.9968</td>\n",
       "      <td>3.20</td>\n",
       "      <td>0.68</td>\n",
       "      <td>9.8</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>7.8</td>\n",
       "      <td>0.76</td>\n",
       "      <td>0.04</td>\n",
       "      <td>2.3</td>\n",
       "      <td>0.092</td>\n",
       "      <td>15.0</td>\n",
       "      <td>54.0</td>\n",
       "      <td>0.9970</td>\n",
       "      <td>3.26</td>\n",
       "      <td>0.65</td>\n",
       "      <td>9.8</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>11.2</td>\n",
       "      <td>0.28</td>\n",
       "      <td>0.56</td>\n",
       "      <td>1.9</td>\n",
       "      <td>0.075</td>\n",
       "      <td>17.0</td>\n",
       "      <td>60.0</td>\n",
       "      <td>0.9980</td>\n",
       "      <td>3.16</td>\n",
       "      <td>0.58</td>\n",
       "      <td>9.8</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>7.4</td>\n",
       "      <td>0.66</td>\n",
       "      <td>0.00</td>\n",
       "      <td>1.8</td>\n",
       "      <td>0.075</td>\n",
       "      <td>13.0</td>\n",
       "      <td>40.0</td>\n",
       "      <td>0.9978</td>\n",
       "      <td>3.51</td>\n",
       "      <td>0.56</td>\n",
       "      <td>9.4</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   fixed acidity  volatile acidity  citric acid  residual sugar  chlorides  \\\n",
       "0            7.4              0.70         0.00             1.9      0.076   \n",
       "1            7.8              0.88         0.00             2.6      0.098   \n",
       "2            7.8              0.76         0.04             2.3      0.092   \n",
       "3           11.2              0.28         0.56             1.9      0.075   \n",
       "4            7.4              0.66         0.00             1.8      0.075   \n",
       "\n",
       "   free sulfur dioxide  total sulfur dioxide  density    pH  sulphates  \\\n",
       "0                 11.0                  34.0   0.9978  3.51       0.56   \n",
       "1                 25.0                  67.0   0.9968  3.20       0.68   \n",
       "2                 15.0                  54.0   0.9970  3.26       0.65   \n",
       "3                 17.0                  60.0   0.9980  3.16       0.58   \n",
       "4                 13.0                  40.0   0.9978  3.51       0.56   \n",
       "\n",
       "   alcohol  quality  \n",
       "0      9.4        5  \n",
       "1      9.8        5  \n",
       "2      9.8        5  \n",
       "3      9.8        6  \n",
       "4      9.4        5  "
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\n",
    "def find_csv():\n",
    "    candidate_names = [\n",
    "        \"cleaned_red_wine.csv\",\n",
    "        \"cleaned_white_wine.csv\",\n",
    "        \"winequality-white.csv\",\n",
    "        \"winequality-red.csv\",\n",
    "        \"cleaned-white-dataset.csv\",\n",
    "        \"cleaned_red_wine_dataset.csv\",\n",
    "    ]\n",
    "    search_dirs = [\n",
    "        Path(\".\"),\n",
    "        Path(\"/mnt/data\"),\n",
    "        Path.home(),\n",
    "    ]\n",
    "\n",
    "    for d in search_dirs:\n",
    "        for name in candidate_names:\n",
    "            p = d / name\n",
    "            if p.exists():\n",
    "                return p\n",
    "\n",
    "    patterns = [\n",
    "        \"*wine*.csv\",\n",
    "        \"*Wine*.csv\",\n",
    "        \"*cleaned*.csv\",\n",
    "        \"*red*.csv\",\n",
    "        \"*white*.csv\",\n",
    "    ]\n",
    "    found = []\n",
    "    for d in search_dirs:\n",
    "        if d.exists():\n",
    "            for pattern in patterns:\n",
    "                found.extend(glob.glob(str(d / pattern)))\n",
    "    found = [Path(x) for x in found if Path(x).is_file()]\n",
    "\n",
    "    if not found:\n",
    "        raise FileNotFoundError(\"CSV-файл не найден. Поместите файл cleaned_red_wine.csv рядом с ноутбуком.\")\n",
    "\n",
    "    # приоритет: файлы, в которых есть слова cleaned/red/wine\n",
    "    found_sorted = sorted(\n",
    "        found,\n",
    "        key=lambda p: (\n",
    "            \"cleaned\" not in p.name.lower(),\n",
    "            \"red\" not in p.name.lower(),\n",
    "            \"wine\" not in p.name.lower(),\n",
    "            len(p.name)\n",
    "        )\n",
    "    )\n",
    "    return found_sorted[0]\n",
    "\n",
    "csv_path = find_csv()\n",
    "print(\"Используемый файл:\", csv_path)\n",
    "\n",
    "df_raw = pd.read_csv(csv_path)\n",
    "print(\"Форма датасета:\", df_raw.shape)\n",
    "df_raw.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "52698ca6",
   "metadata": {},
   "outputs": [
    {
     "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>fixed acidity</td>\n",
       "      <td>fixed_acidity</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>volatile acidity</td>\n",
       "      <td>volatile_acidity</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>citric acid</td>\n",
       "      <td>citric_acid</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>residual sugar</td>\n",
       "      <td>residual_sugar</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>chlorides</td>\n",
       "      <td>chlorides</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>free sulfur dioxide</td>\n",
       "      <td>free_sulfur_dioxide</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>total sulfur dioxide</td>\n",
       "      <td>total_sulfur_dioxide</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>density</td>\n",
       "      <td>density</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>pH</td>\n",
       "      <td>ph</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>sulphates</td>\n",
       "      <td>sulphates</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>alcohol</td>\n",
       "      <td>alcohol</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>quality</td>\n",
       "      <td>quality</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "           original_name       normalized_name\n",
       "0          fixed acidity         fixed_acidity\n",
       "1       volatile acidity      volatile_acidity\n",
       "2            citric acid           citric_acid\n",
       "3         residual sugar        residual_sugar\n",
       "4              chlorides             chlorides\n",
       "5    free sulfur dioxide   free_sulfur_dioxide\n",
       "6   total sulfur dioxide  total_sulfur_dioxide\n",
       "7                density               density\n",
       "8                     pH                    ph\n",
       "9              sulphates             sulphates\n",
       "10               alcohol               alcohol\n",
       "11               quality               quality"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\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>fixed_acidity</th>\n",
       "      <th>volatile_acidity</th>\n",
       "      <th>citric_acid</th>\n",
       "      <th>residual_sugar</th>\n",
       "      <th>chlorides</th>\n",
       "      <th>free_sulfur_dioxide</th>\n",
       "      <th>total_sulfur_dioxide</th>\n",
       "      <th>density</th>\n",
       "      <th>ph</th>\n",
       "      <th>sulphates</th>\n",
       "      <th>alcohol</th>\n",
       "      <th>quality</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>dtype</th>\n",
       "      <td>float64</td>\n",
       "      <td>float64</td>\n",
       "      <td>float64</td>\n",
       "      <td>float64</td>\n",
       "      <td>float64</td>\n",
       "      <td>float64</td>\n",
       "      <td>float64</td>\n",
       "      <td>float64</td>\n",
       "      <td>float64</td>\n",
       "      <td>float64</td>\n",
       "      <td>float64</td>\n",
       "      <td>int64</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      fixed_acidity volatile_acidity citric_acid residual_sugar chlorides  \\\n",
       "dtype       float64          float64     float64        float64   float64   \n",
       "\n",
       "      free_sulfur_dioxide total_sulfur_dioxide  density       ph sulphates  \\\n",
       "dtype             float64              float64  float64  float64   float64   \n",
       "\n",
       "       alcohol quality  \n",
       "dtype  float64   int64  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "def normalize_col(name):\n",
    "    name = str(name).strip().lower()\n",
    "    name = name.replace(\"%\", \"pct\")\n",
    "    name = re.sub(r\"[^a-z0-9]+\", \"_\", name)\n",
    "    name = re.sub(r\"_+\", \"_\", name).strip(\"_\")\n",
    "    return name\n",
    "\n",
    "original_cols = list(df_raw.columns)\n",
    "normalized_cols = [normalize_col(c) for c in original_cols]\n",
    "\n",
    "mapping_df = pd.DataFrame({\n",
    "    \"original_name\": original_cols,\n",
    "    \"normalized_name\": normalized_cols\n",
    "})\n",
    "display(mapping_df)\n",
    "\n",
    "df = df_raw.copy()\n",
    "df.columns = normalized_cols\n",
    "print(\"\\nТипы данных:\")\n",
    "display(df.dtypes.to_frame(\"dtype\").T)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "97f26e03",
   "metadata": {},
   "source": [
    "## Выбор зависимой переменной и подготовка признаков"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "c6037fbf",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Выбранная зависимая переменная: quality\n",
      "Найденные идентификаторы / служебные поля: ['citric_acid']\n",
      "Число исходных признаков: 10\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>feature</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>fixed_acidity</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>volatile_acidity</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>residual_sugar</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>chlorides</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>free_sulfur_dioxide</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>total_sulfur_dioxide</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>density</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>ph</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>sulphates</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>alcohol</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                feature\n",
       "0         fixed_acidity\n",
       "1      volatile_acidity\n",
       "2        residual_sugar\n",
       "3             chlorides\n",
       "4   free_sulfur_dioxide\n",
       "5  total_sulfur_dioxide\n",
       "6               density\n",
       "7                    ph\n",
       "8             sulphates\n",
       "9               alcohol"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "def choose_target(dataframe):\n",
    "    cols = list(dataframe.columns)\n",
    "    numeric_cols = dataframe.select_dtypes(include=[np.number]).columns.tolist()\n",
    "\n",
    "    preferred = [\"quality\", \"price\", \"target\", \"y\", \"score\"]\n",
    "    for c in preferred:\n",
    "        if c in cols:\n",
    "            return c\n",
    "\n",
    "    # если есть последний числовой столбец — используем его\n",
    "    if numeric_cols:\n",
    "        return numeric_cols[-1]\n",
    "\n",
    "    raise ValueError(\"Не удалось автоматически определить зависимую переменную.\")\n",
    "\n",
    "target_col = choose_target(df)\n",
    "print(\"Выбранная зависимая переменная:\", target_col)\n",
    "\n",
    "id_like = [c for c in df.columns if c.endswith(\"id\") or c in {\"id\"}]\n",
    "feature_cols = [c for c in df.columns if c != target_col and c not in id_like]\n",
    "\n",
    "print(\"Найденные идентификаторы / служебные поля:\", id_like)\n",
    "print(\"Число исходных признаков:\", len(feature_cols))\n",
    "print(\"Список признаков:\")\n",
    "display(pd.DataFrame({\"feature\": feature_cols}))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "0cddfa05",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Числовые признаки: ['fixed_acidity', 'volatile_acidity', 'residual_sugar', 'chlorides', 'free_sulfur_dioxide', 'total_sulfur_dioxide', 'density', 'ph', 'sulphates', 'alcohol']\n",
      "Категориальные признаки: []\n",
      "Количество пропусков в X до обработки: 0\n",
      "Количество пропусков в y: 0\n"
     ]
    }
   ],
   "source": [
    "\n",
    "X = df[feature_cols].copy()\n",
    "y = pd.to_numeric(df[target_col], errors=\"coerce\")\n",
    "\n",
    "valid_mask = y.notna()\n",
    "X = X.loc[valid_mask].reset_index(drop=True)\n",
    "y = y.loc[valid_mask].reset_index(drop=True)\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",
    "print(\"Количество пропусков в X до обработки:\", int(X.isna().sum().sum()))\n",
    "print(\"Количество пропусков в y:\", int(y.isna().sum()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "916bbd77",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Размеры выборок:\n",
      "train: (815, 10) (815,)\n",
      "validation: (272, 10) (272,)\n",
      "test: (272, 10) (272,)\n"
     ]
    }
   ],
   "source": [
    "\n",
    "X_trainval, X_test, y_trainval, y_test = train_test_split(\n",
    "    X, y, test_size=0.2, random_state=42\n",
    ")\n",
    "X_train, X_val, y_train, y_val = train_test_split(\n",
    "    X_trainval, y_trainval, test_size=0.25, random_state=42\n",
    ")\n",
    "\n",
    "print(\"Размеры выборок:\")\n",
    "print(\"train:\", X_train.shape, y_train.shape)\n",
    "print(\"validation:\", X_val.shape, y_val.shape)\n",
    "print(\"test:\", X_test.shape, y_test.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "4817229d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Число признаков после кодирования: 10\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>processed_feature</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>num__fixed_acidity</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>num__volatile_acidity</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>num__residual_sugar</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>num__chlorides</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>num__free_sulfur_dioxide</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>num__total_sulfur_dioxide</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>num__density</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>num__ph</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>num__sulphates</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>num__alcohol</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "           processed_feature\n",
       "0         num__fixed_acidity\n",
       "1      num__volatile_acidity\n",
       "2        num__residual_sugar\n",
       "3             num__chlorides\n",
       "4   num__free_sulfur_dioxide\n",
       "5  num__total_sulfur_dioxide\n",
       "6               num__density\n",
       "7                    num__ph\n",
       "8             num__sulphates\n",
       "9               num__alcohol"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "def make_preprocessor(num_cols, cat_cols):\n",
    "    transformers = []\n",
    "    if num_cols:\n",
    "        transformers.append((\n",
    "            \"num\",\n",
    "            Pipeline([\n",
    "                (\"imputer\", SimpleImputer(strategy=\"median\")),\n",
    "                (\"scaler\", StandardScaler())\n",
    "            ]),\n",
    "            num_cols\n",
    "        ))\n",
    "    if cat_cols:\n",
    "        transformers.append((\n",
    "            \"cat\",\n",
    "            Pipeline([\n",
    "                (\"imputer\", SimpleImputer(strategy=\"most_frequent\")),\n",
    "                (\"onehot\", OneHotEncoder(handle_unknown=\"ignore\"))\n",
    "            ]),\n",
    "            cat_cols\n",
    "        ))\n",
    "    return ColumnTransformer(transformers=transformers)\n",
    "\n",
    "preprocessor_all = make_preprocessor(numeric_features, categorical_features)\n",
    "\n",
    "X_train_proc = preprocessor_all.fit_transform(X_train)\n",
    "X_val_proc = preprocessor_all.transform(X_val)\n",
    "X_test_proc = preprocessor_all.transform(X_test)\n",
    "X_trainval_proc = preprocessor_all.transform(X_trainval)\n",
    "\n",
    "feature_names_all = preprocessor_all.get_feature_names_out()\n",
    "print(\"Число признаков после кодирования:\", len(feature_names_all))\n",
    "print(\"Первые признаки после преобразования:\")\n",
    "display(pd.DataFrame({\"processed_feature\": feature_names_all[:20]}))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d1b8493f",
   "metadata": {},
   "source": [
    "## Вспомогательные функции"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "bd96e4d9",
   "metadata": {},
   "outputs": [],
   "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",
    "def fit_eval_mlp(\n",
    "    Xtr, ytr, Xv, yv, Xte, yte,\n",
    "    hidden_layers=(64, 32),\n",
    "    alpha=1e-4,\n",
    "    learning_rate_init=1e-3,\n",
    "    max_iter=400,\n",
    "    random_state=42\n",
    "):\n",
    "    y_scaler = StandardScaler()\n",
    "    ytr_s = y_scaler.fit_transform(np.asarray(ytr).reshape(-1, 1)).ravel()\n",
    "\n",
    "    model = MLPRegressor(\n",
    "        hidden_layer_sizes=hidden_layers,\n",
    "        activation=\"relu\",\n",
    "        solver=\"adam\",\n",
    "        alpha=alpha,\n",
    "        learning_rate_init=learning_rate_init,\n",
    "        max_iter=max_iter,\n",
    "        random_state=random_state,\n",
    "        early_stopping=False\n",
    "    )\n",
    "    model.fit(Xtr, ytr_s)\n",
    "\n",
    "    pred_train = y_scaler.inverse_transform(model.predict(Xtr).reshape(-1, 1)).ravel()\n",
    "    pred_val = y_scaler.inverse_transform(model.predict(Xv).reshape(-1, 1)).ravel()\n",
    "    pred_test = y_scaler.inverse_transform(model.predict(Xte).reshape(-1, 1)).ravel()\n",
    "\n",
    "    losses_df = pd.DataFrame({\n",
    "        \"epoch\": np.arange(1, len(model.loss_curve_) + 1),\n",
    "        \"train_loss\": model.loss_curve_\n",
    "    })\n",
    "\n",
    "    return {\n",
    "        \"model\": model,\n",
    "        \"y_scaler\": y_scaler,\n",
    "        \"pred_train\": pred_train,\n",
    "        \"pred_val\": pred_val,\n",
    "        \"pred_test\": pred_test,\n",
    "        \"metrics_train\": regression_metrics(ytr, pred_train),\n",
    "        \"metrics_val\": regression_metrics(yv, pred_val),\n",
    "        \"metrics_test\": regression_metrics(yte, pred_test),\n",
    "        \"losses\": losses_df\n",
    "    }\n",
    "\n",
    "def decode_vector(vec):\n",
    "    n_layers = int(np.clip(np.round(vec[0]), 1, 3))\n",
    "    raw_units = [vec[1], vec[2], vec[3]]\n",
    "    units = [int(np.clip(np.round(v / 8) * 8, 8, 128)) for v in raw_units][:n_layers]\n",
    "    hidden_layers = tuple(units)\n",
    "    alpha = 10 ** float(np.clip(vec[4], -6, -1))\n",
    "    learning_rate_init = 10 ** float(np.clip(vec[5], -4, -1))\n",
    "    return hidden_layers, alpha, learning_rate_init"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4daf7724",
   "metadata": {},
   "source": [
    "## Базовая нейросеть по всем признакам"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "ef23f956",
   "metadata": {},
   "outputs": [
    {
     "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.343546</td>\n",
       "      <td>0.681911</td>\n",
       "      <td>0.528839</td>\n",
       "      <td>0.239206</td>\n",
       "      <td>0.7413</td>\n",
       "      <td>0.563845</td>\n",
       "      <td>10</td>\n",
       "      <td>10</td>\n",
       "      <td>(64, 32)</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                 model   r2_test  rmse_test  mae_test  \\\n",
       "0  Базовая нейросеть по всем признакам  0.343546   0.681911  0.528839   \n",
       "\n",
       "     r2_val  rmse_val   mae_val  n_original_features  n_processed_features  \\\n",
       "0  0.239206    0.7413  0.563845                   10                    10   \n",
       "\n",
       "  hidden_layers  \n",
       "0      (64, 32)  "
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\n",
    "baseline_result = fit_eval_mlp(\n",
    "    X_train_proc, y_train,\n",
    "    X_val_proc, y_val,\n",
    "    X_test_proc, y_test,\n",
    "    hidden_layers=(64, 32),\n",
    "    alpha=1e-4,\n",
    "    learning_rate_init=1e-3,\n",
    "    max_iter=500,\n",
    "    random_state=42\n",
    ")\n",
    "\n",
    "baseline_metrics_row = {\n",
    "    \"model\": \"Базовая нейросеть по всем признакам\",\n",
    "    \"r2_test\": baseline_result[\"metrics_test\"][\"r2\"],\n",
    "    \"rmse_test\": baseline_result[\"metrics_test\"][\"rmse\"],\n",
    "    \"mae_test\": baseline_result[\"metrics_test\"][\"mae\"],\n",
    "    \"r2_val\": baseline_result[\"metrics_val\"][\"r2\"],\n",
    "    \"rmse_val\": baseline_result[\"metrics_val\"][\"rmse\"],\n",
    "    \"mae_val\": baseline_result[\"metrics_val\"][\"mae\"],\n",
    "    \"n_original_features\": len(feature_cols),\n",
    "    \"n_processed_features\": len(feature_names_all),\n",
    "    \"hidden_layers\": str((64, 32)),\n",
    "}\n",
    "pd.DataFrame([baseline_metrics_row])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4198b6a8",
   "metadata": {},
   "source": [
    "## Определение важности признаков\n",
    "\n",
    "Используется перестановочная важность на валидационной выборке."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "f751cd36",
   "metadata": {},
   "outputs": [
    {
     "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>alcohol</td>\n",
       "      <td>0.197726</td>\n",
       "      <td>0.025297</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>sulphates</td>\n",
       "      <td>0.111403</td>\n",
       "      <td>0.026000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>total_sulfur_dioxide</td>\n",
       "      <td>0.087461</td>\n",
       "      <td>0.018176</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>fixed_acidity</td>\n",
       "      <td>0.074592</td>\n",
       "      <td>0.022738</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>ph</td>\n",
       "      <td>0.073306</td>\n",
       "      <td>0.017507</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>volatile_acidity</td>\n",
       "      <td>0.064309</td>\n",
       "      <td>0.024947</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>density</td>\n",
       "      <td>0.054816</td>\n",
       "      <td>0.013859</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>free_sulfur_dioxide</td>\n",
       "      <td>0.035482</td>\n",
       "      <td>0.016148</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>residual_sugar</td>\n",
       "      <td>0.028441</td>\n",
       "      <td>0.006704</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>chlorides</td>\n",
       "      <td>0.005736</td>\n",
       "      <td>0.013181</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                feature  permutation_importance_mean  \\\n",
       "0               alcohol                     0.197726   \n",
       "1             sulphates                     0.111403   \n",
       "2  total_sulfur_dioxide                     0.087461   \n",
       "3         fixed_acidity                     0.074592   \n",
       "4                    ph                     0.073306   \n",
       "5      volatile_acidity                     0.064309   \n",
       "6               density                     0.054816   \n",
       "7   free_sulfur_dioxide                     0.035482   \n",
       "8        residual_sugar                     0.028441   \n",
       "9             chlorides                     0.005736   \n",
       "\n",
       "   permutation_importance_std  \n",
       "0                    0.025297  \n",
       "1                    0.026000  \n",
       "2                    0.018176  \n",
       "3                    0.022738  \n",
       "4                    0.017507  \n",
       "5                    0.024947  \n",
       "6                    0.013859  \n",
       "7                    0.016148  \n",
       "8                    0.006704  \n",
       "9                    0.013181  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "class InverseScaledRegressorWrapper(RegressorMixin, BaseEstimator):\n",
    "    def __init__(self, fitted_model, y_scaler):\n",
    "        self.fitted_model = fitted_model\n",
    "        self.y_scaler = y_scaler\n",
    "\n",
    "    def fit(self, X, y=None):\n",
    "        return self\n",
    "\n",
    "    def predict(self, X):\n",
    "        pred_scaled = self.fitted_model.predict(X)\n",
    "        return self.y_scaler.inverse_transform(np.asarray(pred_scaled).reshape(-1, 1)).ravel()\n",
    "\n",
    "wrapped_baseline = InverseScaledRegressorWrapper(\n",
    "    baseline_result[\"model\"],\n",
    "    baseline_result[\"y_scaler\"]\n",
    ")\n",
    "\n",
    "perm = permutation_importance(\n",
    "    estimator=wrapped_baseline,\n",
    "    X=X_val_proc,\n",
    "    y=y_val,\n",
    "    scoring=\"neg_root_mean_squared_error\",\n",
    "    n_repeats=10,\n",
    "    random_state=42\n",
    ")\n",
    "\n",
    "perm_df = pd.DataFrame({\n",
    "    \"processed_feature\": feature_names_all,\n",
    "    \"permutation_importance_mean\": perm.importances_mean,\n",
    "    \"permutation_importance_std\": perm.importances_std\n",
    "})\n",
    "\n",
    "def processed_to_original(name):\n",
    "    if \"__\" in name:\n",
    "        return name.split(\"__\", 1)[1].split(\"_\", 1)[0] if name.startswith(\"cat__\") else name.split(\"__\", 1)[1]\n",
    "    return name\n",
    "\n",
    "# Для числовых признаков имена вида num__fixed_acidity, для категориальных - cat__country_France\n",
    "original_name_map = []\n",
    "for processed_name in feature_names_all:\n",
    "    if processed_name.startswith(\"num__\"):\n",
    "        original_name_map.append(processed_name.replace(\"num__\", \"\", 1))\n",
    "    elif processed_name.startswith(\"cat__\"):\n",
    "        tail = processed_name.replace(\"cat__\", \"\", 1)\n",
    "        # исходное имя — до первого one-hot значения\n",
    "        matched = None\n",
    "        for c in categorical_features:\n",
    "            prefix = c + \"_\"\n",
    "            if tail.startswith(prefix):\n",
    "                matched = c\n",
    "                break\n",
    "        original_name_map.append(matched if matched is not None else tail)\n",
    "    else:\n",
    "        original_name_map.append(processed_name)\n",
    "\n",
    "perm_df[\"feature\"] = original_name_map\n",
    "\n",
    "feature_importance_df = (\n",
    "    perm_df.groupby(\"feature\", as_index=False)\n",
    "    .agg(\n",
    "        permutation_importance_mean=(\"permutation_importance_mean\", \"sum\"),\n",
    "        permutation_importance_std=(\"permutation_importance_std\", \"mean\")\n",
    "    )\n",
    "    .sort_values(\"permutation_importance_mean\", ascending=False)\n",
    "    .reset_index(drop=True)\n",
    ")\n",
    "\n",
    "display(feature_importance_df.head(10))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "f08ee023",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Отобранные признаки:\n",
      "['alcohol', 'sulphates', 'total_sulfur_dioxide', 'fixed_acidity', 'ph', 'volatile_acidity']\n",
      "Число отобранных исходных признаков: 6\n"
     ]
    }
   ],
   "source": [
    "\n",
    "# отбор признаков: берём top-k, но не меньше 5 признаков\n",
    "top_k = min(max(5, int(np.ceil(len(feature_cols) * 0.6))), len(feature_cols))\n",
    "selected_features = feature_importance_df.head(top_k)[\"feature\"].tolist()\n",
    "\n",
    "# если важности совсем слабы, всё равно оставляем top_k\n",
    "print(\"Отобранные признаки:\")\n",
    "print(selected_features)\n",
    "print(\"Число отобранных исходных признаков:\", len(selected_features))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "29c2561d",
   "metadata": {},
   "source": [
    "## Подготовка данных по отобранным признакам"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "60e4b793",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Число признаков после кодирования (отобранные признаки): 6\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>processed_feature</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>num__alcohol</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>num__sulphates</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>num__total_sulfur_dioxide</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>num__fixed_acidity</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>num__ph</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>num__volatile_acidity</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "           processed_feature\n",
       "0               num__alcohol\n",
       "1             num__sulphates\n",
       "2  num__total_sulfur_dioxide\n",
       "3         num__fixed_acidity\n",
       "4                    num__ph\n",
       "5      num__volatile_acidity"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "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 = make_preprocessor(numeric_features_sel, categorical_features_sel)\n",
    "\n",
    "X_train_sel = X_train[selected_features].copy()\n",
    "X_val_sel = X_val[selected_features].copy()\n",
    "X_test_sel = X_test[selected_features].copy()\n",
    "\n",
    "X_train_sel_proc = preprocessor_sel.fit_transform(X_train_sel)\n",
    "X_val_sel_proc = preprocessor_sel.transform(X_val_sel)\n",
    "X_test_sel_proc = preprocessor_sel.transform(X_test_sel)\n",
    "\n",
    "feature_names_sel = preprocessor_sel.get_feature_names_out()\n",
    "\n",
    "print(\"Число признаков после кодирования (отобранные признаки):\", len(feature_names_sel))\n",
    "display(pd.DataFrame({\"processed_feature\": feature_names_sel[:20]}))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bcf3a1b4",
   "metadata": {},
   "source": [
    "## Эволюционный поиск архитектуры второй нейросети\n",
    "\n",
    "Используется упрощённый дифференциальный эволюционный поиск по:\n",
    "- числу скрытых слоёв;\n",
    "- размерностям скрытых слоёв;\n",
    "- коэффициенту регуляризации `alpha`;\n",
    "- начальному шагу обучения `learning_rate_init`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "e8529a29",
   "metadata": {},
   "outputs": [
    {
     "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>generation</th>\n",
       "      <th>best_hidden_layers</th>\n",
       "      <th>best_alpha</th>\n",
       "      <th>best_learning_rate_init</th>\n",
       "      <th>best_val_rmse</th>\n",
       "      <th>best_val_mae</th>\n",
       "      <th>best_val_r2</th>\n",
       "      <th>mean_val_rmse</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>(32, 72)</td>\n",
       "      <td>0.000006</td>\n",
       "      <td>0.000108</td>\n",
       "      <td>0.666126</td>\n",
       "      <td>0.515317</td>\n",
       "      <td>0.385684</td>\n",
       "      <td>0.684986</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2</td>\n",
       "      <td>(32,)</td>\n",
       "      <td>0.004625</td>\n",
       "      <td>0.047211</td>\n",
       "      <td>0.663136</td>\n",
       "      <td>0.516006</td>\n",
       "      <td>0.391185</td>\n",
       "      <td>0.676327</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>3</td>\n",
       "      <td>(32,)</td>\n",
       "      <td>0.004625</td>\n",
       "      <td>0.047211</td>\n",
       "      <td>0.663136</td>\n",
       "      <td>0.516006</td>\n",
       "      <td>0.391185</td>\n",
       "      <td>0.675348</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>4</td>\n",
       "      <td>(96, 8)</td>\n",
       "      <td>0.000002</td>\n",
       "      <td>0.000100</td>\n",
       "      <td>0.659703</td>\n",
       "      <td>0.518266</td>\n",
       "      <td>0.397474</td>\n",
       "      <td>0.672381</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5</td>\n",
       "      <td>(96, 8)</td>\n",
       "      <td>0.000002</td>\n",
       "      <td>0.000100</td>\n",
       "      <td>0.659703</td>\n",
       "      <td>0.518266</td>\n",
       "      <td>0.397474</td>\n",
       "      <td>0.670662</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>6</td>\n",
       "      <td>(96, 8)</td>\n",
       "      <td>0.000002</td>\n",
       "      <td>0.000100</td>\n",
       "      <td>0.659703</td>\n",
       "      <td>0.518266</td>\n",
       "      <td>0.397474</td>\n",
       "      <td>0.667770</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>7</td>\n",
       "      <td>(96, 8)</td>\n",
       "      <td>0.000002</td>\n",
       "      <td>0.000100</td>\n",
       "      <td>0.659703</td>\n",
       "      <td>0.518266</td>\n",
       "      <td>0.397474</td>\n",
       "      <td>0.667318</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>8</td>\n",
       "      <td>(96, 8)</td>\n",
       "      <td>0.000002</td>\n",
       "      <td>0.000100</td>\n",
       "      <td>0.659703</td>\n",
       "      <td>0.518266</td>\n",
       "      <td>0.397474</td>\n",
       "      <td>0.665663</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   generation best_hidden_layers  best_alpha  best_learning_rate_init  \\\n",
       "0           1           (32, 72)    0.000006                 0.000108   \n",
       "1           2              (32,)    0.004625                 0.047211   \n",
       "2           3              (32,)    0.004625                 0.047211   \n",
       "3           4            (96, 8)    0.000002                 0.000100   \n",
       "4           5            (96, 8)    0.000002                 0.000100   \n",
       "5           6            (96, 8)    0.000002                 0.000100   \n",
       "6           7            (96, 8)    0.000002                 0.000100   \n",
       "7           8            (96, 8)    0.000002                 0.000100   \n",
       "\n",
       "   best_val_rmse  best_val_mae  best_val_r2  mean_val_rmse  \n",
       "0       0.666126      0.515317     0.385684       0.684986  \n",
       "1       0.663136      0.516006     0.391185       0.676327  \n",
       "2       0.663136      0.516006     0.391185       0.675348  \n",
       "3       0.659703      0.518266     0.397474       0.672381  \n",
       "4       0.659703      0.518266     0.397474       0.670662  \n",
       "5       0.659703      0.518266     0.397474       0.667770  \n",
       "6       0.659703      0.518266     0.397474       0.667318  \n",
       "7       0.659703      0.518266     0.397474       0.665663  "
      ]
     },
     "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>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",
       "      <th>rmse_test</th>\n",
       "      <th>mae_test</th>\n",
       "      <th>r2_test</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>(96, 8)</td>\n",
       "      <td>0.000002</td>\n",
       "      <td>0.000100</td>\n",
       "      <td>0.659703</td>\n",
       "      <td>0.518266</td>\n",
       "      <td>0.397474</td>\n",
       "      <td>0.645034</td>\n",
       "      <td>0.501347</td>\n",
       "      <td>0.412627</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>(104, 8)</td>\n",
       "      <td>0.000034</td>\n",
       "      <td>0.000100</td>\n",
       "      <td>0.660456</td>\n",
       "      <td>0.513696</td>\n",
       "      <td>0.396098</td>\n",
       "      <td>0.644013</td>\n",
       "      <td>0.494874</td>\n",
       "      <td>0.414486</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>(128, 8, 8)</td>\n",
       "      <td>0.000001</td>\n",
       "      <td>0.000100</td>\n",
       "      <td>0.660986</td>\n",
       "      <td>0.513248</td>\n",
       "      <td>0.395127</td>\n",
       "      <td>0.629693</td>\n",
       "      <td>0.481430</td>\n",
       "      <td>0.440234</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>(80, 8, 48)</td>\n",
       "      <td>0.000001</td>\n",
       "      <td>0.000100</td>\n",
       "      <td>0.661431</td>\n",
       "      <td>0.518035</td>\n",
       "      <td>0.394313</td>\n",
       "      <td>0.626088</td>\n",
       "      <td>0.485662</td>\n",
       "      <td>0.446625</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>(104, 8, 32)</td>\n",
       "      <td>0.000001</td>\n",
       "      <td>0.000100</td>\n",
       "      <td>0.664654</td>\n",
       "      <td>0.513201</td>\n",
       "      <td>0.388396</td>\n",
       "      <td>0.642104</td>\n",
       "      <td>0.492726</td>\n",
       "      <td>0.417952</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>(104, 8, 32)</td>\n",
       "      <td>0.000001</td>\n",
       "      <td>0.000100</td>\n",
       "      <td>0.664654</td>\n",
       "      <td>0.513201</td>\n",
       "      <td>0.388396</td>\n",
       "      <td>0.642104</td>\n",
       "      <td>0.492726</td>\n",
       "      <td>0.417952</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>(128, 8)</td>\n",
       "      <td>0.000153</td>\n",
       "      <td>0.000100</td>\n",
       "      <td>0.665050</td>\n",
       "      <td>0.516224</td>\n",
       "      <td>0.387666</td>\n",
       "      <td>0.629876</td>\n",
       "      <td>0.487524</td>\n",
       "      <td>0.439909</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>(112, 8)</td>\n",
       "      <td>0.000001</td>\n",
       "      <td>0.000100</td>\n",
       "      <td>0.665161</td>\n",
       "      <td>0.517248</td>\n",
       "      <td>0.387461</td>\n",
       "      <td>0.634953</td>\n",
       "      <td>0.485301</td>\n",
       "      <td>0.430843</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>(72,)</td>\n",
       "      <td>0.100000</td>\n",
       "      <td>0.000419</td>\n",
       "      <td>0.668271</td>\n",
       "      <td>0.520894</td>\n",
       "      <td>0.381720</td>\n",
       "      <td>0.640291</td>\n",
       "      <td>0.493402</td>\n",
       "      <td>0.421233</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>(40, 40, 32)</td>\n",
       "      <td>0.000001</td>\n",
       "      <td>0.000259</td>\n",
       "      <td>0.686265</td>\n",
       "      <td>0.520748</td>\n",
       "      <td>0.347977</td>\n",
       "      <td>0.643131</td>\n",
       "      <td>0.490765</td>\n",
       "      <td>0.416088</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  hidden_layers     alpha  learning_rate_init  rmse_val   mae_val    r2_val  \\\n",
       "0       (96, 8)  0.000002            0.000100  0.659703  0.518266  0.397474   \n",
       "1      (104, 8)  0.000034            0.000100  0.660456  0.513696  0.396098   \n",
       "2   (128, 8, 8)  0.000001            0.000100  0.660986  0.513248  0.395127   \n",
       "3   (80, 8, 48)  0.000001            0.000100  0.661431  0.518035  0.394313   \n",
       "4  (104, 8, 32)  0.000001            0.000100  0.664654  0.513201  0.388396   \n",
       "5  (104, 8, 32)  0.000001            0.000100  0.664654  0.513201  0.388396   \n",
       "6      (128, 8)  0.000153            0.000100  0.665050  0.516224  0.387666   \n",
       "7      (112, 8)  0.000001            0.000100  0.665161  0.517248  0.387461   \n",
       "8         (72,)  0.100000            0.000419  0.668271  0.520894  0.381720   \n",
       "9  (40, 40, 32)  0.000001            0.000259  0.686265  0.520748  0.347977   \n",
       "\n",
       "   rmse_test  mae_test   r2_test  \n",
       "0   0.645034  0.501347  0.412627  \n",
       "1   0.644013  0.494874  0.414486  \n",
       "2   0.629693  0.481430  0.440234  \n",
       "3   0.626088  0.485662  0.446625  \n",
       "4   0.642104  0.492726  0.417952  \n",
       "5   0.642104  0.492726  0.417952  \n",
       "6   0.629876  0.487524  0.439909  \n",
       "7   0.634953  0.485301  0.430843  \n",
       "8   0.640291  0.493402  0.421233  \n",
       "9   0.643131  0.490765  0.416088  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "rng = np.random.default_rng(42)\n",
    "\n",
    "bounds = np.array([\n",
    "    [1, 3],      # число слоёв\n",
    "    [8, 128],    # units1\n",
    "    [8, 128],    # units2\n",
    "    [8, 128],    # units3\n",
    "    [-6, -1],    # log10(alpha)\n",
    "    [-4, -1],    # log10(lr)\n",
    "], dtype=float)\n",
    "\n",
    "def random_vector():\n",
    "    return np.array([rng.uniform(low, high) for low, high in bounds], dtype=float)\n",
    "\n",
    "cache = {}\n",
    "\n",
    "def evaluate_vector(vec, seed=42):\n",
    "    hidden_layers, alpha, learning_rate_init = decode_vector(vec)\n",
    "    key = (hidden_layers, round(alpha, 8), round(learning_rate_init, 8))\n",
    "    if key in cache:\n",
    "        return cache[key]\n",
    "\n",
    "    result = fit_eval_mlp(\n",
    "        X_train_sel_proc, y_train,\n",
    "        X_val_sel_proc, y_val,\n",
    "        X_test_sel_proc, y_test,\n",
    "        hidden_layers=hidden_layers,\n",
    "        alpha=alpha,\n",
    "        learning_rate_init=learning_rate_init,\n",
    "        max_iter=300,\n",
    "        random_state=seed\n",
    "    )\n",
    "    row = {\n",
    "        \"hidden_layers\": str(hidden_layers),\n",
    "        \"alpha\": alpha,\n",
    "        \"learning_rate_init\": learning_rate_init,\n",
    "        \"rmse_val\": result[\"metrics_val\"][\"rmse\"],\n",
    "        \"mae_val\": result[\"metrics_val\"][\"mae\"],\n",
    "        \"r2_val\": result[\"metrics_val\"][\"r2\"],\n",
    "        \"rmse_test\": result[\"metrics_test\"][\"rmse\"],\n",
    "        \"mae_test\": result[\"metrics_test\"][\"mae\"],\n",
    "        \"r2_test\": result[\"metrics_test\"][\"r2\"],\n",
    "        \"result\": result,\n",
    "    }\n",
    "    cache[key] = row\n",
    "    return row\n",
    "\n",
    "pop_size = 10\n",
    "generations = 8\n",
    "F = 0.7\n",
    "CR = 0.8\n",
    "\n",
    "population = [random_vector() for _ in range(pop_size)]\n",
    "scores = [evaluate_vector(vec) for vec in population]\n",
    "\n",
    "evolution_log = []\n",
    "\n",
    "for gen in range(generations):\n",
    "    new_population = []\n",
    "    new_scores = []\n",
    "\n",
    "    for i in range(pop_size):\n",
    "        idxs = [j for j in range(pop_size) if j != i]\n",
    "        a_idx, b_idx, c_idx = rng.choice(idxs, size=3, replace=False)\n",
    "        a_vec, b_vec, c_vec = population[a_idx], population[b_idx], population[c_idx]\n",
    "\n",
    "        mutant = a_vec + F * (b_vec - c_vec)\n",
    "        mutant = np.clip(mutant, bounds[:, 0], bounds[:, 1])\n",
    "\n",
    "        trial = population[i].copy()\n",
    "        j_rand = rng.integers(0, len(bounds))\n",
    "        for j in range(len(bounds)):\n",
    "            if rng.random() < CR or j == j_rand:\n",
    "                trial[j] = mutant[j]\n",
    "\n",
    "        trial_score = evaluate_vector(trial, seed=42 + gen + i)\n",
    "        current_score = scores[i]\n",
    "\n",
    "        if trial_score[\"rmse_val\"] <= current_score[\"rmse_val\"]:\n",
    "            new_population.append(trial)\n",
    "            new_scores.append(trial_score)\n",
    "        else:\n",
    "            new_population.append(population[i])\n",
    "            new_scores.append(current_score)\n",
    "\n",
    "    population = new_population\n",
    "    scores = new_scores\n",
    "\n",
    "    best_idx = int(np.argmin([s[\"rmse_val\"] for s in scores]))\n",
    "    best = scores[best_idx]\n",
    "    evolution_log.append({\n",
    "        \"generation\": gen + 1,\n",
    "        \"best_hidden_layers\": best[\"hidden_layers\"],\n",
    "        \"best_alpha\": best[\"alpha\"],\n",
    "        \"best_learning_rate_init\": best[\"learning_rate_init\"],\n",
    "        \"best_val_rmse\": best[\"rmse_val\"],\n",
    "        \"best_val_mae\": best[\"mae_val\"],\n",
    "        \"best_val_r2\": best[\"r2_val\"],\n",
    "        \"mean_val_rmse\": float(np.mean([s[\"rmse_val\"] for s in scores])),\n",
    "    })\n",
    "\n",
    "evolution_log_df = pd.DataFrame(evolution_log)\n",
    "top_configs_df = (\n",
    "    pd.DataFrame([{k: v for k, v in s.items() if k != \"result\"} for s in scores])\n",
    "    .sort_values([\"rmse_val\", \"mae_val\"], ascending=[True, True])\n",
    "    .reset_index(drop=True)\n",
    ")\n",
    "\n",
    "display(evolution_log_df.tail(10))\n",
    "display(top_configs_df.head(10))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c825fa1f",
   "metadata": {},
   "source": [
    "## Обучение лучшей второй модели по отобранным признакам"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "ffae8410",
   "metadata": {},
   "outputs": [
    {
     "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.412627</td>\n",
       "      <td>0.645034</td>\n",
       "      <td>0.501347</td>\n",
       "      <td>0.397474</td>\n",
       "      <td>0.659703</td>\n",
       "      <td>0.518266</td>\n",
       "      <td>6</td>\n",
       "      <td>6</td>\n",
       "      <td>(96, 8)</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Базовая нейросеть по всем признакам</td>\n",
       "      <td>0.343546</td>\n",
       "      <td>0.681911</td>\n",
       "      <td>0.528839</td>\n",
       "      <td>0.239206</td>\n",
       "      <td>0.741300</td>\n",
       "      <td>0.563845</td>\n",
       "      <td>10</td>\n",
       "      <td>10</td>\n",
       "      <td>(64, 32)</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                               model   r2_test  rmse_test  \\\n",
       "0  Нейросеть по отобранным признакам + эволюционн...  0.412627   0.645034   \n",
       "1                Базовая нейросеть по всем признакам  0.343546   0.681911   \n",
       "\n",
       "   mae_test    r2_val  rmse_val   mae_val  n_original_features  \\\n",
       "0  0.501347  0.397474  0.659703  0.518266                    6   \n",
       "1  0.528839  0.239206  0.741300  0.563845                   10   \n",
       "\n",
       "   n_processed_features hidden_layers  \n",
       "0                     6       (96, 8)  \n",
       "1                    10      (64, 32)  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "best_idx = int(np.argmin([s[\"rmse_val\"] for s in scores]))\n",
    "best_row = scores[best_idx]\n",
    "best_result = best_row[\"result\"]\n",
    "\n",
    "selected_metrics_row = {\n",
    "    \"model\": \"Нейросеть по отобранным признакам + эволюционный поиск\",\n",
    "    \"r2_test\": best_result[\"metrics_test\"][\"r2\"],\n",
    "    \"rmse_test\": best_result[\"metrics_test\"][\"rmse\"],\n",
    "    \"mae_test\": best_result[\"metrics_test\"][\"mae\"],\n",
    "    \"r2_val\": best_result[\"metrics_val\"][\"r2\"],\n",
    "    \"rmse_val\": best_result[\"metrics_val\"][\"rmse\"],\n",
    "    \"mae_val\": best_result[\"metrics_val\"][\"mae\"],\n",
    "    \"n_original_features\": len(selected_features),\n",
    "    \"n_processed_features\": len(feature_names_sel),\n",
    "    \"hidden_layers\": best_row[\"hidden_layers\"],\n",
    "}\n",
    "\n",
    "results_df = pd.DataFrame([baseline_metrics_row, selected_metrics_row]).sort_values(\n",
    "    [\"r2_test\", \"rmse_test\"], ascending=[False, True]\n",
    ").reset_index(drop=True)\n",
    "\n",
    "display(results_df)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b163d3fb",
   "metadata": {},
   "source": [
    "## Визуализация"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "74bce991",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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UMJWROQx1K9fP86fP0+TJk0IDAy0dTgiIiIiIiIikkbUw1ZEREREREREREQkk1APWxEREREREREREZFMQglbERERERERERERkUxCCVsRERERERERERGRTOKpW3QsPj6ef//9F09PT0wmk63DEREREclQhmFw48YN8uTJg52d/nYvGUv34iIiIvK0Ss19+FOXsP3333/x8/OzdRgiIiIiNnXmzBny5ctn6zDkKaN7cREREXnapeQ+/KlL2Hp6egLmN8fLy8vG0YiIiIhkrPDwcPz8/Cz3RCIZSffiIiIi8rRKzX34U5ewTfjqlZeXl24SRURE5Kmlr6OLLeheXERERJ52KbkPV+MyERERERERERERkUxCCVsRERERERERERGRTEIJWxEREREREREREZFM4qnrYSsiIk82wzCIjY0lLi7O1qGI2IS9vT0ODg7qUSsiIiIi8phSwlZERJ4Y0dHRhIWFcfPmTVuHImJTbm5u+Pr64uTkZOtQREREREQklZSwFRGRJ0J8fDwnT57E3t6ePHny4OTkpApDeeoYhkF0dDQXL17k5MmTFClSBDs7dcASEREREXmcKGErIiJPhOjoaOLj4/Hz88PNzc3W4YjYjKurK46Ojpw6dYro6GhcXFxsHZKIiIiIiKSCSi5EROSJompCEf13ICIiIiLyONPdvIiIiIiIiIiIiEgmoYStiIiIPPYOHDhA48aNiY6OZv/+/VSuXNnWIYmIiIiIiDwUJWxFRERsKCAgAJPJlGjLly+frUN7rJQqVQpHR0fc3d2pXLkyAwcOtHVIIiIiIiIiD0WLjomIiNhYo0aNmDt3rtU+e3t7G0XzeDKZTPz0009cuHABDw8PLTwnIiIiIiKPLVXYioiI2JizszO5c+e22nLmzGk1ZujQoRQtWhQ3NzcKFizIyJEjiYmJsbw+depUnnnmGZydnfHx8aF79+7cvHnT8vqBAweoW7curq6uZM+enZ49exIREWF5/e5KXycnJ4oVK8Y333xjeT0kJIQWLVrg4+ODh4cHlSpVYsOGDVYxhoWF0apVK7Jnz25VLXzt2rUkrzs0NBSTyURQUJDVfn9/f6ZMmWJ5fu3aNbp3707OnDnx8vKibt267Nu3z/L6mDFjKFeuHAC5cuXCwcGBwoULW5173rx5ZMmShRUrVlCkSBFcXFxo2LAhZ86csTr3zJkzKVSo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UeFw+Jc0jExEREREREREREQyIyVs01FChS08ZFsEOzso2978OOi7NIpKREREREREREREMislbNORg/1/CduY+PiHmyQhYXtiE4SHpUFUIiIiIiIiIiIiklkpYZuOHO3+e3tjH6YlAkD2QuD3PBjxsH9RGkUmIiIiIiIiIiIimZEStunIzs6E6U6RbezDVtgClHvV/DPoO3iYxctERERERERERETksaCEbTpLqLJ96ApbgJItwcEFLh2Bf/emTWAiIiIiIiIiIiKS6Shhm84c7/SxjYl7hApbF28o9pL5cdD3aRCViIiIiIiIiIiIZEaZImE7Y8YM/P39cXFxoUqVKuzcuTPZsfPmzcNkMlltLi4uGRht6jg72gMQFfsICVv4ry3CgR8gNuoRoxIREREREREREZHMyOYJ20WLFjFw4EBGjx7N3r17KVu2LA0bNuTChQvJHuPl5UVYWJhlO3XqVAZGnDouDua3+HZM3KNNVLA2eOaB29fg6JpHjktERETkcRAQEEDLli0z5Fz+/v5MmTLF8vzcuXO8+OKLuLu7kyVLlgyJIcGYMWMoV66c5Xlavw/z5s174DXdG4OIiIiIZAybJ2wnTZpEjx496Nq1KyVKlODzzz/Hzc2NOXPmJHuMyWQid+7cls3HxycDI06dNKuwtbOHMm3Nj4O+e8SoRERERB5e7dq1GTBgQLofY2uTJ08mLCyMoKAgjh49atNYpk6dyrx589Jsvnbt2tn8mkREREQkaTZN2EZHR7Nnzx7q169v2WdnZ0f9+vXZtm1bssdFRESQP39+/Pz8aNGiBX///XeyY6OioggPD7faMpJzWlXYApTraP55bB1c/+fR5xMRERGRZIWEhFCxYkWKFClCrly5HmoOwzCIjY195Fi8vb3TtMrX1dX1oa9JRERERNKXTRO2ly5dIi4uLlGFrI+PD+fOnUvymGeffZY5c+bw448/8u233xIfH0+1atU4e/ZskuM/+ugjvL29LZufn1+aX8f9uNypsL0d84gVtgA5i0L+6mDEw96vH30+ERERkVQKCAjgt99+Y+rUqZb1BEJDQ/ntt9+oXLkyzs7O+Pr68s4771gSlckdExcXR7du3ShQoACurq48++yzTJ069aFjW7JkCaVLl8bV1ZXs2bNTv359IiMjgaQrfFu2bElAQECSc/n7+7N06VK+/vprTCYTAQEBhIaGYjKZCAoKsoy7du0aJpOJzZs3A7B582ZMJhOrV6+mYsWKODs7s2XLlgfGPm7cOHx8fPD09KRbt27cvn3b6vV7WyJERUXx5ptvkitXLlxcXHjhhRfYtWsXALdv36ZkyZL07NnTMj4kJARPT0/Lt9iSaonwoBgAvvzyS4oXL46LiwvFihXjs88+e+C1iYiIiEjq2LwlQmpVrVqVzp07U65cOWrVqsWyZcvImTMnX3zxRZLjhw0bxvXr1y3bmTNnMjTeNK2wBXjudfPPvfMhLiZt5hQRERFJoalTp1K1alV69OhhWU/A0dGRJk2aUKlSJfbt28fMmTP56quveP/995M9xs/Pj/j4ePLly8cPP/zAoUOHGDVqFO+++y6LFy9OdVxhYWF06NCB119/neDgYDZv3kyrVq0wDOOhrnPXrl00atSItm3bEhYWlupE8jvvvMO4ceMIDg6mTJky9x27ePFixowZw4cffsju3bvx9fV9YCL07bffZunSpcyfP5+9e/dSuHBhGjZsyJUrV3BxcWHBggXMnz+fH3/8kbi4OF577TVefPFFXn/99YeOYcGCBYwaNYoPPviA4OBgPvzwQ0aOHMn8+fOTjdPW33YTEREReRw52PLkOXLkwN7envPnz1vtP3/+PLlz507RHI6OjpQvX57jx48n+bqzszPOzs6PHOvDckmrHrYJijcH95xwI8y8+FjxZmkzr4iIiEgKeHt74+TkhJubm+V+bfjw4fj5+TF9+nRMJhPFihXj33//ZejQoYwaNSrJYwDs7e0JDAy0PC9QoADbtm1j8eLFtG3bNlVxhYWFERsbS6tWrcifPz8ApUuXfujrzJkzJ87Ozri6ulpivnr1aoqPHzt2LC+++GKKxk6ZMoVu3brRrVs3AN5//302bNiQZIUrQGRkJDNnzmTevHk0btwYgNmzZ7N+/Xq++uorhgwZQrly5Xj//ffp3r077du359SpU6xcufKRYhg9ejQTJ06kVatWgPn3dejQIb744gu6dOmS5LwfffSR1e9YRERERB7MphW2Tk5OVKxYkY0bN1r2xcfHs3HjRqpWrZqiOeLi4jhw4AC+vr7pFeYjcXFM4wpbByco38n8eNdXaTOniIiIyCMIDg6matWqmEwmy77q1asTERGRbNuqBDNmzKBixYrkzJkTDw8PZs2axenTp1MdQ9myZalXrx6lS5emTZs2zJ49O1UJ1rT23HPPpXhscHAwVapUsdp3v3vhkJAQYmJiqF69umWfo6MjlStXJjg42LJv0KBBFC1alOnTpzNnzhyyZ8/+0DFERkYSEhJCt27d8PDwsGzvv/8+ISEhyc5r62+7iYiIiDyObN4SYeDAgcyePZv58+cTHBzMG2+8QWRkJF27dgWgc+fODBs2zDJ+7NixrFu3jhMnTrB3715ee+01Tp06Rffu3W11Cff1Xw/bNErYAlQMAExwYhNcTv4GWURERCQzW7hwIYMHD6Zbt26sW7eOoKAgunbtSnR0dKrnsre3Z/369axevZoSJUrw6aef8uyzz3Ly5EnAvLDtve0RYmJS117Kzs5863z3PMnN4e7unqq508OFCxc4evQo9vb2HDt27JHmioiIAMyVvEFBQZbt4MGDbN++PdnjnJ2d8fLystpERERE5P5snrBt164dEyZMYNSoUZQrV46goCDWrFljWYjs9OnThIWFWcZfvXqVHj16ULx4cZo0aUJ4eDh//vknJUqUsNUl3FdCD9s0a4kAkDU/FLnzFbs9c9NuXhEREZEUcHJyIi7uvz9GFy9enG3btlklMrdu3Yqnpyf58uVL8piEMdWqVaN3796UL1+ewoUL37da80FMJhPVq1cnMDCQv/76CycnJ5YvXw6YWxzcfU8ZFxfHwYMHUzV/zpw5AazmuXsBsodVvHhxduzYYbXvfknQQoUK4eTkxNatWy37YmJi2LVrl9U98euvv07p0qWZP38+Q4cOtaq+TW0MPj4+5MmThxMnTlC4cGGrrUCBAim+VhERERF5MJv2sE3Qt29f+vbtm+RrCSvuJpg8eTKTJ0/OgKjShqWHbVpW2AI81w2OrYO/voXa74KTW9rOLyIiIpIMf39/duzYQWhoKB4eHvTu3ZspU6bQr18/+vbty5EjRxg9ejQDBw60VKXee0y2bNkoUqQIX3/9NWvXrqVAgQJ888037Nq166ESgDt27GDjxo00aNCAXLlysWPHDi5evEjx4sUBqFu3LgMHDuSXX36hUKFCTJo0iWvXrqXqHK6urjz//POMGzeOAgUKcOHCBUaMGJHqWO/Vv39/AgICeO6556hevToLFizg77//pmDBgkmOd3d354033mDIkCFky5aNZ555hk8++YSbN29aetDOmDGDbdu2sX//fvz8/Pjll1/o2LEj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SqXw9va+39tqUAcPHsSjjz4KAKiqqsKxY8dUa+y2a9cOf/31l1r7RUVFwcTEBK1atbprvbq6ujXaJyoqCuPGjcNTTz0FoDq5mpqaWq94/fz88P333+Pq1au1zrLt1KkTEhMTa+1/RNQ4+NAxIqK7SEtLQ8eOHfHDDz8gKSkJ58+fx88//4whQ4agZ8+emDJlSp3q8fLywpAhQzBhwgTs378fsbGxeP755+Hk5IQhQ4YAAE6cOIF58+bh+++/R48ePfDZZ5/hrbfewvnz51V1pKWlYc2aNUhOTsYXX3yB9evXN9atExEREdFDoE2bNhg9ejTGjBmDdevWISUlBYcPH8bixYuxefPmBr9e7969ceXKFXzyySdITk7GV199ha1bt6qVcXNzw8mTJ5GYmIicnBxUVlbWaSzr5uaGlJQUxMTEICcnB+Xl5TWuP3r0aOjr62Ps2LGIi4vDnj178MYbb+CFF15QLYegaV999RXWr1+PhIQETJo0CdeuXcOLL74IAHj99ddx8eJFvPHGG0hISMCGDRswf/58TJ06VW35hdq4ublh165dyMzMxLVr1wBUf0ZYt24dYmJiEBsbi+eee67eM35HjRoFe3t7DB06FFFRUTh//jz++usvREdHAwDmzZuHn376CQsXLsTp06cRHx+PNWvW4L333ruP1iGiumDClojoLjp06ID58+cjIiIC3bp1Q/v27fHJJ59g8uTJ+PfffyGXy+tcV3h4OAIDA/HEE08gODgYQghs2bIFurq6KCsrw/PPP49x48bhySefBAC88sor6NOnD1544QUoFAoMHjwYb7/9NiZPnoyOHTviwIEDmDt3bmPdOhERERE9JMLDwzFmzBi888478Pb2xtChQ3HkyBHVeqgNqV27dvjf//6Hr776Cv7+/jh8+DCmTZumVmbChAnw9vZG586dYWNjg6ioqDqNZYcPH44BAwagT58+sLGxwW+//Vbj+oaGhti+fTuuXr2KLl264Omnn0a/fv2wYsWKBr/X+xUWFoawsDD4+/tj//792LhxI6ytrQEATk5O2LJlCw4fPgx/f39MnDgRL730Up2Sn59++il27NgBZ2dnBAQEAAA+++wzWFhYoHv37njyyScRGhqKTp061SteuVyOf//9F7a2tnj88cfh6+uLsLAw1RIboaGh2LRpE/7991906dIF3bp1w7Jly2pdNo6IGoZE3L74DBERERERERER1Utqaipat26NEydOoGPHjpoOh4geYpxhS0RERERERERERKQlmLAlIiIiIiIiIiIi0hJcEoGIiIiIiIiIiIhIS3CGLREREREREREREZGWYMKWiIiIiIiIiIiISEswYUtERERERERERESkJZiwJSIiIiIiIiIiItISTNgSERERERERERERaQkmbImIiIiIiIiIiIi0BBO2RERERERERERERFqCCVsiIiIiIiIiIiIiLcGELREREREREREREZGW+D9Dm9SnDIir9AAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 1400x500 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "fig, axes = plt.subplots(1, 2, figsize=(14, 5))\n",
    "\n",
    "axes[0].plot(baseline_result[\"losses\"][\"epoch\"], baseline_result[\"losses\"][\"train_loss\"], label=\"Базовая нейросеть\")\n",
    "axes[0].plot(best_result[\"losses\"][\"epoch\"], best_result[\"losses\"][\"train_loss\"], label=\"Эволюционная сеть\")\n",
    "axes[0].set_title(\"Кривые обучения\")\n",
    "axes[0].set_xlabel(\"Эпоха\")\n",
    "axes[0].set_ylabel(\"Train loss\")\n",
    "axes[0].legend()\n",
    "\n",
    "top_plot = feature_importance_df.head(10).sort_values(\"permutation_importance_mean\")\n",
    "axes[1].barh(top_plot[\"feature\"], top_plot[\"permutation_importance_mean\"])\n",
    "axes[1].set_title(\"Топ-10 признаков по важности\")\n",
    "axes[1].set_xlabel(\"Permutation importance\")\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f1fa8f72",
   "metadata": {},
   "source": [
    "## Финальная ячейка для вывода\n",
    "\n",
    "Эта ячейка печатает всю информацию, необходимую для написания итогового вывода по реальным результатам."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "e1dfeb45",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "=== КЛЮЧЕВАЯ ИНФОРМАЦИЯ ДЛЯ ВЫВОДА ===\n",
      "Зависимая переменная: quality\n",
      "\n",
      "Число исходных признаков: 10\n",
      "Число признаков после кодирования (все признаки): 10\n",
      "Число отобранных исходных признаков: 6\n",
      "Число признаков после кодирования (отобранные признаки): 6\n",
      "Фиксированная архитектура первой модели: (64, 32)\n",
      "Архитектура, найденная эволюционным поиском: (96, 8)\n",
      "alpha найденной модели: 1.8988086655790854e-06\n",
      "learning_rate_init найденной модели: 0.0001\n",
      "\n",
      "Отобранные признаки:\n",
      "['alcohol', 'sulphates', 'total_sulfur_dioxide', 'fixed_acidity', 'ph', 'volatile_acidity']\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.412627</td>\n",
       "      <td>0.645034</td>\n",
       "      <td>0.501347</td>\n",
       "      <td>0.397474</td>\n",
       "      <td>0.659703</td>\n",
       "      <td>0.518266</td>\n",
       "      <td>6</td>\n",
       "      <td>6</td>\n",
       "      <td>(96, 8)</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Базовая нейросеть по всем признакам</td>\n",
       "      <td>0.343546</td>\n",
       "      <td>0.681911</td>\n",
       "      <td>0.528839</td>\n",
       "      <td>0.239206</td>\n",
       "      <td>0.741300</td>\n",
       "      <td>0.563845</td>\n",
       "      <td>10</td>\n",
       "      <td>10</td>\n",
       "      <td>(64, 32)</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                               model   r2_test  rmse_test  \\\n",
       "0  Нейросеть по отобранным признакам + эволюционн...  0.412627   0.645034   \n",
       "1                Базовая нейросеть по всем признакам  0.343546   0.681911   \n",
       "\n",
       "   mae_test    r2_val  rmse_val   mae_val  n_original_features  \\\n",
       "0  0.501347  0.397474  0.659703  0.518266                    6   \n",
       "1  0.528839  0.239206  0.741300  0.563845                   10   \n",
       "\n",
       "   n_processed_features hidden_layers  \n",
       "0                     6       (96, 8)  \n",
       "1                    10      (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.412627</td>\n",
       "      <td>0.645034</td>\n",
       "      <td>0.501347</td>\n",
       "      <td>0.397474</td>\n",
       "      <td>0.659703</td>\n",
       "      <td>0.518266</td>\n",
       "      <td>6</td>\n",
       "      <td>6</td>\n",
       "      <td>(96, 8)</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                               model   r2_test  rmse_test  \\\n",
       "0  Нейросеть по отобранным признакам + эволюционн...  0.412627   0.645034   \n",
       "\n",
       "   mae_test    r2_val  rmse_val   mae_val  n_original_features  \\\n",
       "0  0.501347  0.397474  0.659703  0.518266                    6   \n",
       "\n",
       "   n_processed_features hidden_layers  \n",
       "0                     6       (96, 8)  "
      ]
     },
     "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>alcohol</td>\n",
       "      <td>0.197726</td>\n",
       "      <td>0.025297</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>sulphates</td>\n",
       "      <td>0.111403</td>\n",
       "      <td>0.026000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>total_sulfur_dioxide</td>\n",
       "      <td>0.087461</td>\n",
       "      <td>0.018176</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>fixed_acidity</td>\n",
       "      <td>0.074592</td>\n",
       "      <td>0.022738</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>ph</td>\n",
       "      <td>0.073306</td>\n",
       "      <td>0.017507</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>volatile_acidity</td>\n",
       "      <td>0.064309</td>\n",
       "      <td>0.024947</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>density</td>\n",
       "      <td>0.054816</td>\n",
       "      <td>0.013859</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>free_sulfur_dioxide</td>\n",
       "      <td>0.035482</td>\n",
       "      <td>0.016148</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>residual_sugar</td>\n",
       "      <td>0.028441</td>\n",
       "      <td>0.006704</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>chlorides</td>\n",
       "      <td>0.005736</td>\n",
       "      <td>0.013181</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                feature  permutation_importance_mean  \\\n",
       "0               alcohol                     0.197726   \n",
       "1             sulphates                     0.111403   \n",
       "2  total_sulfur_dioxide                     0.087461   \n",
       "3         fixed_acidity                     0.074592   \n",
       "4                    ph                     0.073306   \n",
       "5      volatile_acidity                     0.064309   \n",
       "6               density                     0.054816   \n",
       "7   free_sulfur_dioxide                     0.035482   \n",
       "8        residual_sugar                     0.028441   \n",
       "9             chlorides                     0.005736   \n",
       "\n",
       "   permutation_importance_std  \n",
       "0                    0.025297  \n",
       "1                    0.026000  \n",
       "2                    0.018176  \n",
       "3                    0.022738  \n",
       "4                    0.017507  \n",
       "5                    0.024947  \n",
       "6                    0.013859  \n",
       "7                    0.016148  \n",
       "8                    0.006704  \n",
       "9                    0.013181  "
      ]
     },
     "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",
       "      <th>rmse_test</th>\n",
       "      <th>mae_test</th>\n",
       "      <th>r2_test</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>(96, 8)</td>\n",
       "      <td>0.000002</td>\n",
       "      <td>0.000100</td>\n",
       "      <td>0.659703</td>\n",
       "      <td>0.518266</td>\n",
       "      <td>0.397474</td>\n",
       "      <td>0.645034</td>\n",
       "      <td>0.501347</td>\n",
       "      <td>0.412627</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>(104, 8)</td>\n",
       "      <td>0.000034</td>\n",
       "      <td>0.000100</td>\n",
       "      <td>0.660456</td>\n",
       "      <td>0.513696</td>\n",
       "      <td>0.396098</td>\n",
       "      <td>0.644013</td>\n",
       "      <td>0.494874</td>\n",
       "      <td>0.414486</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>(128, 8, 8)</td>\n",
       "      <td>0.000001</td>\n",
       "      <td>0.000100</td>\n",
       "      <td>0.660986</td>\n",
       "      <td>0.513248</td>\n",
       "      <td>0.395127</td>\n",
       "      <td>0.629693</td>\n",
       "      <td>0.481430</td>\n",
       "      <td>0.440234</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>(80, 8, 48)</td>\n",
       "      <td>0.000001</td>\n",
       "      <td>0.000100</td>\n",
       "      <td>0.661431</td>\n",
       "      <td>0.518035</td>\n",
       "      <td>0.394313</td>\n",
       "      <td>0.626088</td>\n",
       "      <td>0.485662</td>\n",
       "      <td>0.446625</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>(104, 8, 32)</td>\n",
       "      <td>0.000001</td>\n",
       "      <td>0.000100</td>\n",
       "      <td>0.664654</td>\n",
       "      <td>0.513201</td>\n",
       "      <td>0.388396</td>\n",
       "      <td>0.642104</td>\n",
       "      <td>0.492726</td>\n",
       "      <td>0.417952</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>(104, 8, 32)</td>\n",
       "      <td>0.000001</td>\n",
       "      <td>0.000100</td>\n",
       "      <td>0.664654</td>\n",
       "      <td>0.513201</td>\n",
       "      <td>0.388396</td>\n",
       "      <td>0.642104</td>\n",
       "      <td>0.492726</td>\n",
       "      <td>0.417952</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>(128, 8)</td>\n",
       "      <td>0.000153</td>\n",
       "      <td>0.000100</td>\n",
       "      <td>0.665050</td>\n",
       "      <td>0.516224</td>\n",
       "      <td>0.387666</td>\n",
       "      <td>0.629876</td>\n",
       "      <td>0.487524</td>\n",
       "      <td>0.439909</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>(112, 8)</td>\n",
       "      <td>0.000001</td>\n",
       "      <td>0.000100</td>\n",
       "      <td>0.665161</td>\n",
       "      <td>0.517248</td>\n",
       "      <td>0.387461</td>\n",
       "      <td>0.634953</td>\n",
       "      <td>0.485301</td>\n",
       "      <td>0.430843</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>(72,)</td>\n",
       "      <td>0.100000</td>\n",
       "      <td>0.000419</td>\n",
       "      <td>0.668271</td>\n",
       "      <td>0.520894</td>\n",
       "      <td>0.381720</td>\n",
       "      <td>0.640291</td>\n",
       "      <td>0.493402</td>\n",
       "      <td>0.421233</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>(40, 40, 32)</td>\n",
       "      <td>0.000001</td>\n",
       "      <td>0.000259</td>\n",
       "      <td>0.686265</td>\n",
       "      <td>0.520748</td>\n",
       "      <td>0.347977</td>\n",
       "      <td>0.643131</td>\n",
       "      <td>0.490765</td>\n",
       "      <td>0.416088</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  hidden_layers     alpha  learning_rate_init  rmse_val   mae_val    r2_val  \\\n",
       "0       (96, 8)  0.000002            0.000100  0.659703  0.518266  0.397474   \n",
       "1      (104, 8)  0.000034            0.000100  0.660456  0.513696  0.396098   \n",
       "2   (128, 8, 8)  0.000001            0.000100  0.660986  0.513248  0.395127   \n",
       "3   (80, 8, 48)  0.000001            0.000100  0.661431  0.518035  0.394313   \n",
       "4  (104, 8, 32)  0.000001            0.000100  0.664654  0.513201  0.388396   \n",
       "5  (104, 8, 32)  0.000001            0.000100  0.664654  0.513201  0.388396   \n",
       "6      (128, 8)  0.000153            0.000100  0.665050  0.516224  0.387666   \n",
       "7      (112, 8)  0.000001            0.000100  0.665161  0.517248  0.387461   \n",
       "8         (72,)  0.100000            0.000419  0.668271  0.520894  0.381720   \n",
       "9  (40, 40, 32)  0.000001            0.000259  0.686265  0.520748  0.347977   \n",
       "\n",
       "   rmse_test  mae_test   r2_test  \n",
       "0   0.645034  0.501347  0.412627  \n",
       "1   0.644013  0.494874  0.414486  \n",
       "2   0.629693  0.481430  0.440234  \n",
       "3   0.626088  0.485662  0.446625  \n",
       "4   0.642104  0.492726  0.417952  \n",
       "5   0.642104  0.492726  0.417952  \n",
       "6   0.629876  0.487524  0.439909  \n",
       "7   0.634953  0.485301  0.430843  \n",
       "8   0.640291  0.493402  0.421233  \n",
       "9   0.643131  0.490765  0.416088  "
      ]
     },
     "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>337</th>\n",
       "      <td>338</td>\n",
       "      <td>0.128392</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>338</th>\n",
       "      <td>339</td>\n",
       "      <td>0.129904</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>339</th>\n",
       "      <td>340</td>\n",
       "      <td>0.124444</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>340</th>\n",
       "      <td>341</td>\n",
       "      <td>0.127064</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>341</th>\n",
       "      <td>342</td>\n",
       "      <td>0.127914</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>342</th>\n",
       "      <td>343</td>\n",
       "      <td>0.124983</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>343</th>\n",
       "      <td>344</td>\n",
       "      <td>0.125598</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>344</th>\n",
       "      <td>345</td>\n",
       "      <td>0.125815</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>345</th>\n",
       "      <td>346</td>\n",
       "      <td>0.125827</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>346</th>\n",
       "      <td>347</td>\n",
       "      <td>0.125236</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     epoch  train_loss\n",
       "337    338    0.128392\n",
       "338    339    0.129904\n",
       "339    340    0.124444\n",
       "340    341    0.127064\n",
       "341    342    0.127914\n",
       "342    343    0.124983\n",
       "343    344    0.125598\n",
       "344    345    0.125815\n",
       "345    346    0.125827\n",
       "346    347    0.125236"
      ]
     },
     "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>290</th>\n",
       "      <td>291</td>\n",
       "      <td>0.300152</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>291</th>\n",
       "      <td>292</td>\n",
       "      <td>0.300086</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>292</th>\n",
       "      <td>293</td>\n",
       "      <td>0.300018</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>293</th>\n",
       "      <td>294</td>\n",
       "      <td>0.299867</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>294</th>\n",
       "      <td>295</td>\n",
       "      <td>0.299799</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>295</th>\n",
       "      <td>296</td>\n",
       "      <td>0.299702</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>296</th>\n",
       "      <td>297</td>\n",
       "      <td>0.299633</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>297</th>\n",
       "      <td>298</td>\n",
       "      <td>0.299513</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>298</th>\n",
       "      <td>299</td>\n",
       "      <td>0.299447</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>299</th>\n",
       "      <td>300</td>\n",
       "      <td>0.299405</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     epoch  train_loss\n",
       "290    291    0.300152\n",
       "291    292    0.300086\n",
       "292    293    0.300018\n",
       "293    294    0.299867\n",
       "294    295    0.299799\n",
       "295    296    0.299702\n",
       "296    297    0.299633\n",
       "297    298    0.299513\n",
       "298    299    0.299447\n",
       "299    300    0.299405"
      ]
     },
     "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</td>\n",
       "      <td>5.169107</td>\n",
       "      <td>5.242520</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>6</td>\n",
       "      <td>6.233730</td>\n",
       "      <td>5.955557</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>7</td>\n",
       "      <td>6.721482</td>\n",
       "      <td>6.439866</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>5</td>\n",
       "      <td>4.967424</td>\n",
       "      <td>5.022872</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>4</td>\n",
       "      <td>5.541956</td>\n",
       "      <td>5.178524</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>7</td>\n",
       "      <td>6.871727</td>\n",
       "      <td>6.585367</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>5</td>\n",
       "      <td>5.459065</td>\n",
       "      <td>5.693310</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>5</td>\n",
       "      <td>4.943825</td>\n",
       "      <td>4.798308</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>6</td>\n",
       "      <td>5.616196</td>\n",
       "      <td>5.897882</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>5</td>\n",
       "      <td>5.477886</td>\n",
       "      <td>5.588525</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   y_true  y_pred_baseline  y_pred_selected_evolution\n",
       "0       5         5.169107                   5.242520\n",
       "1       6         6.233730                   5.955557\n",
       "2       7         6.721482                   6.439866\n",
       "3       5         4.967424                   5.022872\n",
       "4       4         5.541956                   5.178524\n",
       "5       7         6.871727                   6.585367\n",
       "6       5         5.459065                   5.693310\n",
       "7       5         4.943825                   4.798308\n",
       "8       6         5.616196                   5.897882\n",
       "9       5         5.477886                   5.588525"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "best_model_name = results_df.iloc[0][\"model\"]\n",
    "\n",
    "print(\"=== КЛЮЧЕВАЯ ИНФОРМАЦИЯ ДЛЯ ВЫВОДА ===\")\n",
    "print(f\"Зависимая переменная: {target_col}\")\n",
    "print()\n",
    "print(f\"Число исходных признаков: {len(feature_cols)}\")\n",
    "print(f\"Число признаков после кодирования (все признаки): {len(feature_names_all)}\")\n",
    "print(f\"Число отобранных исходных признаков: {len(selected_features)}\")\n",
    "print(f\"Число признаков после кодирования (отобранные признаки): {len(feature_names_sel)}\")\n",
    "print(f\"Фиксированная архитектура первой модели: {(64, 32)}\")\n",
    "print(f\"Архитектура, найденная эволюционным поиском: {best_row['hidden_layers']}\")\n",
    "print(f\"alpha найденной модели: {best_row['alpha']}\")\n",
    "print(f\"learning_rate_init найденной модели: {best_row['learning_rate_init']}\")\n",
    "print()\n",
    "print(\"Отобранные признаки:\")\n",
    "print(selected_features)\n",
    "print()\n",
    "print(\"Метрики моделей на тестовой выборке:\")\n",
    "display(results_df)\n",
    "print(\"Лучшая модель:\")\n",
    "display(results_df.head(1))\n",
    "print(\"Топ-10 признаков по важности:\")\n",
    "display(feature_importance_df.head(10))\n",
    "print(\"Топ-10 конфигураций эволюционного поиска:\")\n",
    "display(top_configs_df.head(10))\n",
    "print(\"Последние эпохи обучения базовой нейросети:\")\n",
    "display(baseline_result[\"losses\"].tail(10))\n",
    "print(\"Последние эпохи обучения модели с найденной архитектурой:\")\n",
    "display(best_result[\"losses\"].tail(10))\n",
    "print(\"Первые 10 фактических и предсказанных значений на тесте:\")\n",
    "pred_df = pd.DataFrame({\n",
    "    \"y_true\": np.asarray(y_test).ravel()[:10],\n",
    "    \"y_pred_baseline\": baseline_result[\"pred_test\"][:10],\n",
    "    \"y_pred_selected_evolution\": best_result[\"pred_test\"][:10],\n",
    "})\n",
    "display(pred_df)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "56a20bed",
   "metadata": {},
   "source": [
    "Итог\n",
    "\n",
    "Зависимой переменной выбрана quality. Наиболее важными признаками оказались alcohol, sulphates, total_sulfur_dioxide, fixed_acidity, ph, volatile_acidity; по ним была построена вторая нейросеть с архитектурой, найденной эволюционным поиском (96, 8).\n",
    "\n",
    "На тестовой выборке лучшей стала модель по отобранным признакам: R² = 0.413, RMSE = 0.645, MAE = 0.501. Базовая нейросеть по всем признакам показала более слабый результат (R² = 0.344, RMSE = 0.682, MAE = 0.529).\n",
    "\n",
    "Следовательно, для данной задачи достаточно информативным является сокращённый набор из 6 признаков, а использование эволюционного поиска архитектуры позволило получить наиболее качественную регрессионную модель."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
