{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "ff807d08",
   "metadata": {},
   "source": [
    "# Регрессия и отбор признаков knockoff-методом\n",
    "\n",
    "В работе автоматически определяется ключевая зависимая переменная, затем строится нейросетевая регрессионная модель по всем признакам. После этого применяется knockoff-метод отбора признаков, строится нейросеть той же архитектуры на сокращённом наборе переменных и выполняется сравнение качества на тестовой выборке.\n",
    "\n",
    "**Важно:** финального текстового вывода в ноутбуке нет. В конце есть отдельная ячейка, печатающая все данные, необходимые для вывода по реальным результатам."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "e3964591",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Device: cuda\n"
     ]
    }
   ],
   "source": [
    "\n",
    "import os\n",
    "import re\n",
    "import random\n",
    "import warnings\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.model_selection import train_test_split\n",
    "from sklearn.compose import ColumnTransformer\n",
    "from sklearn.pipeline import Pipeline\n",
    "from sklearn.impute import SimpleImputer\n",
    "from sklearn.preprocessing import OneHotEncoder, StandardScaler\n",
    "from sklearn.metrics import r2_score, mean_absolute_error, mean_squared_error\n",
    "from sklearn.base import clone\n",
    "\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "from torch.utils.data import DataLoader, TensorDataset\n",
    "\n",
    "warnings.filterwarnings(\"ignore\")\n",
    "\n",
    "SEED = 42\n",
    "random.seed(SEED)\n",
    "np.random.seed(SEED)\n",
    "torch.manual_seed(SEED)\n",
    "torch.cuda.manual_seed_all(SEED)\n",
    "torch.backends.cudnn.deterministic = True\n",
    "torch.backends.cudnn.benchmark = False\n",
    "\n",
    "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
    "print(\"Device:\", device)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "702cd860",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Используемый файл: gallbladder_cancer_dataset.csv\n",
      "Форма датасета: (1000, 21)\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>Patient_ID</th>\n",
       "      <th>Age</th>\n",
       "      <th>Gender</th>\n",
       "      <th>BMI</th>\n",
       "      <th>Ethnicity</th>\n",
       "      <th>Smoking_History</th>\n",
       "      <th>Alcohol_Consumption</th>\n",
       "      <th>Family_History</th>\n",
       "      <th>Diabetes</th>\n",
       "      <th>Gallstones</th>\n",
       "      <th>...</th>\n",
       "      <th>Jaundice</th>\n",
       "      <th>Weight_Loss</th>\n",
       "      <th>Tumor_Size</th>\n",
       "      <th>Lymph_Node_Involvement</th>\n",
       "      <th>Stage</th>\n",
       "      <th>CEA_Level</th>\n",
       "      <th>CA19-9_Level</th>\n",
       "      <th>Treatment_Type</th>\n",
       "      <th>Survival_Months</th>\n",
       "      <th>Outcome</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>PID_1</td>\n",
       "      <td>68</td>\n",
       "      <td>Female</td>\n",
       "      <td>27.7</td>\n",
       "      <td>Hispanic</td>\n",
       "      <td>Yes</td>\n",
       "      <td>No</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Yes</td>\n",
       "      <td>No</td>\n",
       "      <td>...</td>\n",
       "      <td>Yes</td>\n",
       "      <td>0.4</td>\n",
       "      <td>2.9</td>\n",
       "      <td>No</td>\n",
       "      <td>II</td>\n",
       "      <td>8.48</td>\n",
       "      <td>228.94</td>\n",
       "      <td>Chemotherapy</td>\n",
       "      <td>23</td>\n",
       "      <td>Deceased</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>PID_2</td>\n",
       "      <td>81</td>\n",
       "      <td>Female</td>\n",
       "      <td>37.3</td>\n",
       "      <td>Asian</td>\n",
       "      <td>No</td>\n",
       "      <td>No</td>\n",
       "      <td>No</td>\n",
       "      <td>Yes</td>\n",
       "      <td>No</td>\n",
       "      <td>...</td>\n",
       "      <td>Yes</td>\n",
       "      <td>7.2</td>\n",
       "      <td>8.8</td>\n",
       "      <td>No</td>\n",
       "      <td>II</td>\n",
       "      <td>17.96</td>\n",
       "      <td>121.62</td>\n",
       "      <td>Chemotherapy</td>\n",
       "      <td>33</td>\n",
       "      <td>Deceased</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>PID_3</td>\n",
       "      <td>58</td>\n",
       "      <td>Male</td>\n",
       "      <td>27.5</td>\n",
       "      <td>African</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Yes</td>\n",
       "      <td>No</td>\n",
       "      <td>No</td>\n",
       "      <td>...</td>\n",
       "      <td>No</td>\n",
       "      <td>5.4</td>\n",
       "      <td>9.5</td>\n",
       "      <td>No</td>\n",
       "      <td>III</td>\n",
       "      <td>3.67</td>\n",
       "      <td>363.39</td>\n",
       "      <td>Chemotherapy</td>\n",
       "      <td>52</td>\n",
       "      <td>Deceased</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>PID_4</td>\n",
       "      <td>44</td>\n",
       "      <td>Female</td>\n",
       "      <td>28.4</td>\n",
       "      <td>Caucasian</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Yes</td>\n",
       "      <td>Yes</td>\n",
       "      <td>...</td>\n",
       "      <td>Yes</td>\n",
       "      <td>5.1</td>\n",
       "      <td>5.7</td>\n",
       "      <td>Yes</td>\n",
       "      <td>III</td>\n",
       "      <td>19.91</td>\n",
       "      <td>255.43</td>\n",
       "      <td>Chemotherapy</td>\n",
       "      <td>47</td>\n",
       "      <td>Deceased</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>PID_5</td>\n",
       "      <td>72</td>\n",
       "      <td>Male</td>\n",
       "      <td>39.8</td>\n",
       "      <td>Caucasian</td>\n",
       "      <td>No</td>\n",
       "      <td>Yes</td>\n",
       "      <td>No</td>\n",
       "      <td>Yes</td>\n",
       "      <td>No</td>\n",
       "      <td>...</td>\n",
       "      <td>No</td>\n",
       "      <td>2.4</td>\n",
       "      <td>4.2</td>\n",
       "      <td>No</td>\n",
       "      <td>IV</td>\n",
       "      <td>2.82</td>\n",
       "      <td>506.69</td>\n",
       "      <td>Chemotherapy</td>\n",
       "      <td>18</td>\n",
       "      <td>Deceased</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>5 rows × 21 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "  Patient_ID  Age  Gender   BMI  Ethnicity Smoking_History  \\\n",
       "0      PID_1   68  Female  27.7   Hispanic             Yes   \n",
       "1      PID_2   81  Female  37.3      Asian              No   \n",
       "2      PID_3   58    Male  27.5    African             Yes   \n",
       "3      PID_4   44  Female  28.4  Caucasian             Yes   \n",
       "4      PID_5   72    Male  39.8  Caucasian              No   \n",
       "\n",
       "  Alcohol_Consumption Family_History Diabetes Gallstones  ... Jaundice  \\\n",
       "0                  No            Yes      Yes         No  ...      Yes   \n",
       "1                  No             No      Yes         No  ...      Yes   \n",
       "2                 Yes            Yes       No         No  ...       No   \n",
       "3                 Yes            Yes      Yes        Yes  ...      Yes   \n",
       "4                 Yes             No      Yes         No  ...       No   \n",
       "\n",
       "  Weight_Loss  Tumor_Size  Lymph_Node_Involvement Stage CEA_Level  \\\n",
       "0         0.4         2.9                      No    II      8.48   \n",
       "1         7.2         8.8                      No    II     17.96   \n",
       "2         5.4         9.5                      No   III      3.67   \n",
       "3         5.1         5.7                     Yes   III     19.91   \n",
       "4         2.4         4.2                      No    IV      2.82   \n",
       "\n",
       "   CA19-9_Level  Treatment_Type Survival_Months   Outcome  \n",
       "0        228.94    Chemotherapy              23  Deceased  \n",
       "1        121.62    Chemotherapy              33  Deceased  \n",
       "2        363.39    Chemotherapy              52  Deceased  \n",
       "3        255.43    Chemotherapy              47  Deceased  \n",
       "4        506.69    Chemotherapy              18  Deceased  \n",
       "\n",
       "[5 rows x 21 columns]"
      ]
     },
     "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>dtype</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>Patient_ID</th>\n",
       "      <td>object</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Age</th>\n",
       "      <td>int64</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Gender</th>\n",
       "      <td>object</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>BMI</th>\n",
       "      <td>float64</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Ethnicity</th>\n",
       "      <td>object</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Smoking_History</th>\n",
       "      <td>object</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Alcohol_Consumption</th>\n",
       "      <td>object</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Family_History</th>\n",
       "      <td>object</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Diabetes</th>\n",
       "      <td>object</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Gallstones</th>\n",
       "      <td>object</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Abdominal_Pain</th>\n",
       "      <td>object</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Jaundice</th>\n",
       "      <td>object</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Weight_Loss</th>\n",
       "      <td>float64</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Tumor_Size</th>\n",
       "      <td>float64</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Lymph_Node_Involvement</th>\n",
       "      <td>object</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Stage</th>\n",
       "      <td>object</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>CEA_Level</th>\n",
       "      <td>float64</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>CA19-9_Level</th>\n",
       "      <td>float64</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Treatment_Type</th>\n",
       "      <td>object</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Survival_Months</th>\n",
       "      <td>int64</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Outcome</th>\n",
       "      <td>object</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                          dtype\n",
       "Patient_ID               object\n",
       "Age                       int64\n",
       "Gender                   object\n",
       "BMI                     float64\n",
       "Ethnicity                object\n",
       "Smoking_History          object\n",
       "Alcohol_Consumption      object\n",
       "Family_History           object\n",
       "Diabetes                 object\n",
       "Gallstones               object\n",
       "Abdominal_Pain           object\n",
       "Jaundice                 object\n",
       "Weight_Loss             float64\n",
       "Tumor_Size              float64\n",
       "Lymph_Node_Involvement   object\n",
       "Stage                    object\n",
       "CEA_Level               float64\n",
       "CA19-9_Level            float64\n",
       "Treatment_Type           object\n",
       "Survival_Months           int64\n",
       "Outcome                  object"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "# Поиск файла\n",
    "candidate_paths = [\n",
    "    Path(\"/mnt/data/gallbladder_cancer_dataset.csv\"),\n",
    "    Path(\"gallbladder_cancer_dataset.csv\"),\n",
    "    Path(\"/kaggle/input/gallbladder-cancer-patient-dataset/gallbladder_cancer_dataset.csv\"),\n",
    "]\n",
    "\n",
    "data_path = None\n",
    "for p in candidate_paths:\n",
    "    if p.exists():\n",
    "        data_path = p\n",
    "        break\n",
    "\n",
    "if data_path is None:\n",
    "    raise FileNotFoundError(\"CSV-файл не найден.\")\n",
    "\n",
    "df_raw = pd.read_csv(data_path)\n",
    "print(\"Используемый файл:\", data_path.name)\n",
    "print(\"Форма датасета:\", df_raw.shape)\n",
    "display(df_raw.head())\n",
    "print(\"\\nТипы данных:\")\n",
    "display(df_raw.dtypes.rename(\"dtype\").to_frame())\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "3105c0fe",
   "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>Patient_ID</td>\n",
       "      <td>patient_id</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Age</td>\n",
       "      <td>age</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Gender</td>\n",
       "      <td>gender</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>BMI</td>\n",
       "      <td>bmi</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>Ethnicity</td>\n",
       "      <td>ethnicity</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>Smoking_History</td>\n",
       "      <td>smoking_history</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>Alcohol_Consumption</td>\n",
       "      <td>alcohol_consumption</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>Family_History</td>\n",
       "      <td>family_history</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>Diabetes</td>\n",
       "      <td>diabetes</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>Gallstones</td>\n",
       "      <td>gallstones</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>Abdominal_Pain</td>\n",
       "      <td>abdominal_pain</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>Jaundice</td>\n",
       "      <td>jaundice</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>Weight_Loss</td>\n",
       "      <td>weight_loss</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>Tumor_Size</td>\n",
       "      <td>tumor_size</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>Lymph_Node_Involvement</td>\n",
       "      <td>lymph_node_involvement</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>15</th>\n",
       "      <td>Stage</td>\n",
       "      <td>stage</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>16</th>\n",
       "      <td>CEA_Level</td>\n",
       "      <td>cea_level</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17</th>\n",
       "      <td>CA19-9_Level</td>\n",
       "      <td>ca19_9_level</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18</th>\n",
       "      <td>Treatment_Type</td>\n",
       "      <td>treatment_type</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>19</th>\n",
       "      <td>Survival_Months</td>\n",
       "      <td>survival_months</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20</th>\n",
       "      <td>Outcome</td>\n",
       "      <td>outcome</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "             original_name         normalized_name\n",
       "0               Patient_ID              patient_id\n",
       "1                      Age                     age\n",
       "2                   Gender                  gender\n",
       "3                      BMI                     bmi\n",
       "4                Ethnicity               ethnicity\n",
       "5          Smoking_History         smoking_history\n",
       "6      Alcohol_Consumption     alcohol_consumption\n",
       "7           Family_History          family_history\n",
       "8                 Diabetes                diabetes\n",
       "9               Gallstones              gallstones\n",
       "10          Abdominal_Pain          abdominal_pain\n",
       "11                Jaundice                jaundice\n",
       "12             Weight_Loss             weight_loss\n",
       "13              Tumor_Size              tumor_size\n",
       "14  Lymph_Node_Involvement  lymph_node_involvement\n",
       "15                   Stage                   stage\n",
       "16               CEA_Level               cea_level\n",
       "17            CA19-9_Level            ca19_9_level\n",
       "18          Treatment_Type          treatment_type\n",
       "19         Survival_Months         survival_months\n",
       "20                 Outcome                 outcome"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "def normalize_col(name: str) -> str:\n",
    "    name = str(name).strip().lower()\n",
    "    name = re.sub(r\"[^a-z0-9]+\", \"_\", name)\n",
    "    name = re.sub(r\"_+\", \"_\", name).strip(\"_\")\n",
    "    return name\n",
    "\n",
    "original_columns = df_raw.columns.tolist()\n",
    "df = df_raw.copy()\n",
    "df.columns = [normalize_col(c) for c in df.columns]\n",
    "\n",
    "display(pd.DataFrame({\n",
    "    \"original_name\": original_columns,\n",
    "    \"normalized_name\": df.columns\n",
    "}))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9de1d1ea",
   "metadata": {},
   "source": [
    "## Выбор зависимой переменной"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "90ecaee7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Выбранная зависимая переменная: survival_months\n",
      "Потенциальные ID-поля: ['patient_id']\n"
     ]
    }
   ],
   "source": [
    "\n",
    "# Автоматический выбор целевой переменной для регрессии\n",
    "candidate_target_names = [\n",
    "    \"survival_months\", \"survival_time\", \"time_to_event\", \"days_survived\",\n",
    "    \"length_of_stay\", \"price\", \"cost\", \"charges\", \"target\"\n",
    "]\n",
    "\n",
    "numeric_cols = df.select_dtypes(include=[np.number]).columns.tolist()\n",
    "id_like_cols = [c for c in df.columns if (\"id\" in c and c != \"diabetes\")]\n",
    "\n",
    "target_col = None\n",
    "for name in candidate_target_names:\n",
    "    if name in df.columns and pd.api.types.is_numeric_dtype(df[name]):\n",
    "        target_col = name\n",
    "        break\n",
    "\n",
    "if target_col is None:\n",
    "    candidates = []\n",
    "    for c in numeric_cols:\n",
    "        nunique = df[c].nunique(dropna=True)\n",
    "        if c not in id_like_cols and nunique > max(15, int(0.05 * len(df))):\n",
    "            candidates.append((c, nunique))\n",
    "    if not candidates:\n",
    "        raise ValueError(\"Не удалось автоматически определить зависимую переменную.\")\n",
    "    target_col = sorted(candidates, key=lambda x: x[1], reverse=True)[0][0]\n",
    "\n",
    "print(\"Выбранная зависимая переменная:\", target_col)\n",
    "print(\"Потенциальные ID-поля:\", id_like_cols)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "12313f56",
   "metadata": {},
   "source": [
    "## Подготовка признаков"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "ee0cbbab",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Количество признаков до кодирования: 19\n",
      "Числовые признаки: ['age', 'bmi', 'weight_loss', 'tumor_size', 'cea_level', 'ca19_9_level']\n",
      "Категориальные признаки: ['gender', 'ethnicity', 'smoking_history', 'alcohol_consumption', 'family_history', 'diabetes', 'gallstones', 'abdominal_pain', 'jaundice', 'lymph_node_involvement', 'stage', 'treatment_type', 'outcome']\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>missing_count</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "Empty DataFrame\n",
       "Columns: [missing_count]\n",
       "Index: []"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "drop_cols = [c for c in id_like_cols if c != target_col]\n",
    "feature_cols = [c for c in df.columns if c not in drop_cols + [target_col]]\n",
    "\n",
    "X = df[feature_cols].copy()\n",
    "y = df[target_col].astype(float).copy()\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(\"Количество признаков до кодирования:\", len(feature_cols))\n",
    "print(\"Числовые признаки:\", numeric_features)\n",
    "print(\"Категориальные признаки:\", categorical_features)\n",
    "\n",
    "missing_df = X.isna().sum().rename(\"missing_count\").to_frame()\n",
    "display(missing_df[missing_df[\"missing_count\"] > 0].sort_values(\"missing_count\", ascending=False).head(20))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "4ade75fd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Размер train после преобразования: (640, 39)\n",
      "Размер val после преобразования: (160, 39)\n",
      "Размер test после преобразования: (200, 39)\n",
      "Первые преобразованные признаки: ['num__age', 'num__bmi', 'num__weight_loss', 'num__tumor_size', 'num__cea_level', 'num__ca19_9_level', 'cat__gender_Female', 'cat__gender_Male', 'cat__ethnicity_African', 'cat__ethnicity_Asian', 'cat__ethnicity_Caucasian', 'cat__ethnicity_Hispanic', 'cat__ethnicity_Other', 'cat__smoking_history_No', 'cat__smoking_history_Yes']\n"
     ]
    }
   ],
   "source": [
    "\n",
    "# Деление на train/validation/test\n",
    "X_train_full, X_test, y_train_full, y_test = train_test_split(\n",
    "    X, y, test_size=0.20, random_state=SEED\n",
    ")\n",
    "X_train, X_val, y_train, y_val = train_test_split(\n",
    "    X_train_full, y_train_full, test_size=0.20, random_state=SEED\n",
    ")\n",
    "\n",
    "numeric_transformer = Pipeline(steps=[\n",
    "    (\"imputer\", SimpleImputer(strategy=\"median\")),\n",
    "    (\"scaler\", StandardScaler()),\n",
    "])\n",
    "\n",
    "categorical_transformer = Pipeline(steps=[\n",
    "    (\"imputer\", SimpleImputer(strategy=\"most_frequent\")),\n",
    "    (\"onehot\", OneHotEncoder(handle_unknown=\"ignore\")),\n",
    "])\n",
    "\n",
    "preprocessor = ColumnTransformer(\n",
    "    transformers=[\n",
    "        (\"num\", numeric_transformer, numeric_features),\n",
    "        (\"cat\", categorical_transformer, categorical_features),\n",
    "    ],\n",
    "    remainder=\"drop\"\n",
    ")\n",
    "\n",
    "X_train_proc = preprocessor.fit_transform(X_train)\n",
    "X_val_proc = preprocessor.transform(X_val)\n",
    "X_test_proc = preprocessor.transform(X_test)\n",
    "X_train_full_proc = preprocessor.transform(X_train_full)\n",
    "\n",
    "feature_names_proc = preprocessor.get_feature_names_out()\n",
    "\n",
    "if hasattr(X_train_proc, \"toarray\"):\n",
    "    X_train_proc = X_train_proc.toarray()\n",
    "    X_val_proc = X_val_proc.toarray()\n",
    "    X_test_proc = X_test_proc.toarray()\n",
    "    X_train_full_proc = X_train_full_proc.toarray()\n",
    "\n",
    "print(\"Размер train после преобразования:\", X_train_proc.shape)\n",
    "print(\"Размер val после преобразования:\", X_val_proc.shape)\n",
    "print(\"Размер test после преобразования:\", X_test_proc.shape)\n",
    "print(\"Первые преобразованные признаки:\", list(feature_names_proc[:15]))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "d6e51840",
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    "def rmse(y_true, y_pred):\n",
    "    return float(np.sqrt(mean_squared_error(y_true, y_pred)))\n",
    "\n",
    "def regression_metrics(y_true, y_pred):\n",
    "    return {\n",
    "        \"r2\": float(r2_score(y_true, y_pred)),\n",
    "        \"rmse\": rmse(y_true, y_pred),\n",
    "        \"mae\": float(mean_absolute_error(y_true, y_pred)),\n",
    "    }\n",
    "\n",
    "class MLPRegressorTorch(nn.Module):\n",
    "    def __init__(self, input_dim, hidden_dims=(128, 64), dropout=0.15):\n",
    "        super().__init__()\n",
    "        layers = []\n",
    "        prev = input_dim\n",
    "        for h in hidden_dims:\n",
    "            layers += [nn.Linear(prev, h), nn.ReLU(), nn.Dropout(dropout)]\n",
    "            prev = h\n",
    "        layers += [nn.Linear(prev, 1)]\n",
    "        self.net = nn.Sequential(*layers)\n",
    "\n",
    "    def forward(self, x):\n",
    "        return self.net(x).squeeze(1)\n",
    "\n",
    "def make_loader(X_arr, y_arr, batch_size=64, shuffle=False):\n",
    "    X_t = torch.tensor(X_arr, dtype=torch.float32)\n",
    "    y_t = torch.tensor(np.asarray(y_arr), dtype=torch.float32)\n",
    "    ds = TensorDataset(X_t, y_t)\n",
    "    return DataLoader(ds, batch_size=batch_size, shuffle=shuffle)\n",
    "\n",
    "def train_nn_regression(\n",
    "    X_tr, y_tr, X_va, y_va, input_dim,\n",
    "    hidden_dims=(128, 64), dropout=0.15, lr=1e-3,\n",
    "    weight_decay=1e-4, epochs=120, batch_size=64, patience=15\n",
    "):\n",
    "    model = MLPRegressorTorch(input_dim=input_dim, hidden_dims=hidden_dims, dropout=dropout).to(device)\n",
    "    optimizer = torch.optim.Adam(model.parameters(), lr=lr, weight_decay=weight_decay)\n",
    "    criterion = nn.MSELoss()\n",
    "\n",
    "    train_loader = make_loader(X_tr, y_tr, batch_size=batch_size, shuffle=True)\n",
    "    val_loader = make_loader(X_va, y_va, batch_size=batch_size, shuffle=False)\n",
    "\n",
    "    best_state = None\n",
    "    best_val = np.inf\n",
    "    wait = 0\n",
    "    history = []\n",
    "\n",
    "    for epoch in range(1, epochs + 1):\n",
    "        model.train()\n",
    "        train_losses = []\n",
    "        for xb, yb in train_loader:\n",
    "            xb, yb = xb.to(device), yb.to(device)\n",
    "            optimizer.zero_grad()\n",
    "            pred = model(xb)\n",
    "            loss = criterion(pred, yb)\n",
    "            loss.backward()\n",
    "            optimizer.step()\n",
    "            train_losses.append(loss.item())\n",
    "\n",
    "        model.eval()\n",
    "        val_losses = []\n",
    "        preds_val, ys_val = [], []\n",
    "        with torch.no_grad():\n",
    "            for xb, yb in val_loader:\n",
    "                xb, yb = xb.to(device), yb.to(device)\n",
    "                pred = model(xb)\n",
    "                loss = criterion(pred, yb)\n",
    "                val_losses.append(loss.item())\n",
    "                preds_val.append(pred.cpu().numpy())\n",
    "                ys_val.append(yb.cpu().numpy())\n",
    "\n",
    "        preds_val = np.concatenate(preds_val)\n",
    "        ys_val = np.concatenate(ys_val)\n",
    "        val_rmse = rmse(ys_val, preds_val)\n",
    "        history.append({\n",
    "            \"epoch\": epoch,\n",
    "            \"train_loss\": float(np.mean(train_losses)),\n",
    "            \"val_loss\": float(np.mean(val_losses)),\n",
    "            \"val_rmse\": val_rmse,\n",
    "            \"val_r2\": float(r2_score(ys_val, preds_val)),\n",
    "        })\n",
    "\n",
    "        if val_rmse < best_val - 1e-5:\n",
    "            best_val = val_rmse\n",
    "            best_state = {k: v.cpu().clone() for k, v in model.state_dict().items()}\n",
    "            wait = 0\n",
    "        else:\n",
    "            wait += 1\n",
    "            if wait >= patience:\n",
    "                break\n",
    "\n",
    "    model.load_state_dict(best_state)\n",
    "    history_df = pd.DataFrame(history)\n",
    "    return model, history_df\n",
    "\n",
    "def predict_nn(model, X_arr, batch_size=256):\n",
    "    model.eval()\n",
    "    X_t = torch.tensor(X_arr, dtype=torch.float32)\n",
    "    loader = DataLoader(X_t, batch_size=batch_size, shuffle=False)\n",
    "    preds = []\n",
    "    with torch.no_grad():\n",
    "        for xb in loader:\n",
    "            xb = xb.to(device)\n",
    "            preds.append(model(xb).cpu().numpy())\n",
    "    return np.concatenate(preds)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5ce10502",
   "metadata": {},
   "source": [
    "## Нейросеть по всем признакам"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "f54f2a23",
   "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>epoch</th>\n",
       "      <th>train_loss</th>\n",
       "      <th>val_loss</th>\n",
       "      <th>val_rmse</th>\n",
       "      <th>val_r2</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>19</th>\n",
       "      <td>20</td>\n",
       "      <td>283.559297</td>\n",
       "      <td>317.918681</td>\n",
       "      <td>17.897406</td>\n",
       "      <td>-0.022919</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20</th>\n",
       "      <td>21</td>\n",
       "      <td>281.438071</td>\n",
       "      <td>317.185679</td>\n",
       "      <td>17.899927</td>\n",
       "      <td>-0.023207</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>21</th>\n",
       "      <td>22</td>\n",
       "      <td>282.324818</td>\n",
       "      <td>317.851400</td>\n",
       "      <td>17.912859</td>\n",
       "      <td>-0.024686</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>22</th>\n",
       "      <td>23</td>\n",
       "      <td>280.200229</td>\n",
       "      <td>318.395559</td>\n",
       "      <td>17.932322</td>\n",
       "      <td>-0.026914</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>23</th>\n",
       "      <td>24</td>\n",
       "      <td>279.947607</td>\n",
       "      <td>319.851400</td>\n",
       "      <td>17.961062</td>\n",
       "      <td>-0.030208</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    epoch  train_loss    val_loss   val_rmse    val_r2\n",
       "19     20  283.559297  317.918681  17.897406 -0.022919\n",
       "20     21  281.438071  317.185679  17.899927 -0.023207\n",
       "21     22  282.324818  317.851400  17.912859 -0.024686\n",
       "22     23  280.200229  318.395559  17.932322 -0.026914\n",
       "23     24  279.947607  319.851400  17.961062 -0.030208"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Метрики baseline на validation: {'r2': 0.002223450848188979, 'rmse': 17.676086145720248, 'mae': 15.558136057853698}\n",
      "Метрики baseline на test: {'r2': -0.007453788434143238, 'rmse': 18.280659073498683, 'mae': 15.949071445465087}\n"
     ]
    }
   ],
   "source": [
    "\n",
    "baseline_model, baseline_history = train_nn_regression(\n",
    "    X_train_proc, y_train.values,\n",
    "    X_val_proc, y_val.values,\n",
    "    input_dim=X_train_proc.shape[1],\n",
    "    hidden_dims=(128, 64),\n",
    "    dropout=0.15,\n",
    "    lr=1e-3,\n",
    "    weight_decay=1e-4,\n",
    "    epochs=120,\n",
    "    batch_size=64,\n",
    "    patience=15\n",
    ")\n",
    "\n",
    "baseline_pred_test = predict_nn(baseline_model, X_test_proc)\n",
    "baseline_pred_val = predict_nn(baseline_model, X_val_proc)\n",
    "\n",
    "baseline_metrics_test = regression_metrics(y_test.values, baseline_pred_test)\n",
    "baseline_metrics_val = regression_metrics(y_val.values, baseline_pred_val)\n",
    "\n",
    "display(baseline_history.tail())\n",
    "print(\"Метрики baseline на validation:\", baseline_metrics_val)\n",
    "print(\"Метрики baseline на test:\", baseline_metrics_test)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0048e7c2",
   "metadata": {},
   "source": [
    "## Knockoff-отбор признаков"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "7d8bf2a8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Порог knockoff: 0.8987016677856445\n",
      "Отобранные признаки: ['stage', 'abdominal', 'alcohol', 'jaundice', 'outcome', 'lymph', 'gender', 'ethnicity', 'smoking', 'gallstones', 'tumor_size', 'treatment']\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>original_feature</th>\n",
       "      <th>orig_importance</th>\n",
       "      <th>knockoff_importance</th>\n",
       "      <th>W_stat</th>\n",
       "      <th>selected</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>stage</td>\n",
       "      <td>36.798851</td>\n",
       "      <td>33.820023</td>\n",
       "      <td>2.978827</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>abdominal</td>\n",
       "      <td>18.562559</td>\n",
       "      <td>15.902373</td>\n",
       "      <td>2.660186</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>alcohol</td>\n",
       "      <td>18.306406</td>\n",
       "      <td>15.921711</td>\n",
       "      <td>2.384696</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>jaundice</td>\n",
       "      <td>18.384712</td>\n",
       "      <td>16.073227</td>\n",
       "      <td>2.311484</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>outcome</td>\n",
       "      <td>18.756935</td>\n",
       "      <td>16.921951</td>\n",
       "      <td>1.834983</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>lymph</td>\n",
       "      <td>18.951267</td>\n",
       "      <td>17.197437</td>\n",
       "      <td>1.753829</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>gender</td>\n",
       "      <td>17.272850</td>\n",
       "      <td>15.560019</td>\n",
       "      <td>1.712832</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>ethnicity</td>\n",
       "      <td>43.010582</td>\n",
       "      <td>41.448845</td>\n",
       "      <td>1.561736</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>smoking</td>\n",
       "      <td>18.130417</td>\n",
       "      <td>16.709576</td>\n",
       "      <td>1.420840</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>gallstones</td>\n",
       "      <td>17.253735</td>\n",
       "      <td>15.839079</td>\n",
       "      <td>1.414657</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>tumor_size</td>\n",
       "      <td>10.153769</td>\n",
       "      <td>8.880541</td>\n",
       "      <td>1.273229</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>treatment</td>\n",
       "      <td>33.744125</td>\n",
       "      <td>32.845421</td>\n",
       "      <td>0.898702</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>weight_loss</td>\n",
       "      <td>9.552622</td>\n",
       "      <td>8.741357</td>\n",
       "      <td>0.811265</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>diabetes</td>\n",
       "      <td>17.279274</td>\n",
       "      <td>16.651009</td>\n",
       "      <td>0.628264</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>age</td>\n",
       "      <td>9.903307</td>\n",
       "      <td>9.668497</td>\n",
       "      <td>0.234810</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>15</th>\n",
       "      <td>family</td>\n",
       "      <td>18.550709</td>\n",
       "      <td>18.507805</td>\n",
       "      <td>0.042902</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>16</th>\n",
       "      <td>ca19_9_level</td>\n",
       "      <td>8.373813</td>\n",
       "      <td>9.002457</td>\n",
       "      <td>-0.628644</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17</th>\n",
       "      <td>bmi</td>\n",
       "      <td>9.612047</td>\n",
       "      <td>10.485161</td>\n",
       "      <td>-0.873114</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18</th>\n",
       "      <td>cea_level</td>\n",
       "      <td>9.282860</td>\n",
       "      <td>10.723900</td>\n",
       "      <td>-1.441040</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   original_feature  orig_importance  knockoff_importance    W_stat  selected\n",
       "0             stage        36.798851            33.820023  2.978827      True\n",
       "1         abdominal        18.562559            15.902373  2.660186      True\n",
       "2           alcohol        18.306406            15.921711  2.384696      True\n",
       "3          jaundice        18.384712            16.073227  2.311484      True\n",
       "4           outcome        18.756935            16.921951  1.834983      True\n",
       "5             lymph        18.951267            17.197437  1.753829      True\n",
       "6            gender        17.272850            15.560019  1.712832      True\n",
       "7         ethnicity        43.010582            41.448845  1.561736      True\n",
       "8           smoking        18.130417            16.709576  1.420840      True\n",
       "9        gallstones        17.253735            15.839079  1.414657      True\n",
       "10       tumor_size        10.153769             8.880541  1.273229      True\n",
       "11        treatment        33.744125            32.845421  0.898702      True\n",
       "12      weight_loss         9.552622             8.741357  0.811265     False\n",
       "13         diabetes        17.279274            16.651009  0.628264     False\n",
       "14              age         9.903307             9.668497  0.234810     False\n",
       "15           family        18.550709            18.507805  0.042902     False\n",
       "16     ca19_9_level         8.373813             9.002457 -0.628644     False\n",
       "17              bmi         9.612047            10.485161 -0.873114     False\n",
       "18        cea_level         9.282860            10.723900 -1.441040     False"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "def make_gaussian_knockoffs(X, seed=42, ridge=1e-5):\n",
    "    rng = np.random.default_rng(seed)\n",
    "    X = np.asarray(X, dtype=float)\n",
    "    Xc = X - X.mean(axis=0, keepdims=True)\n",
    "\n",
    "    Sigma = np.cov(Xc, rowvar=False)\n",
    "    p = Sigma.shape[0]\n",
    "    Sigma = Sigma + ridge * np.eye(p)\n",
    "\n",
    "    eigvals = np.linalg.eigvalsh(Sigma)\n",
    "    lambda_min = float(np.min(eigvals))\n",
    "    s_value = min(2.0 * lambda_min, 1.0)\n",
    "    s_value = max(s_value, 1e-5)\n",
    "    S = np.eye(p) * s_value\n",
    "\n",
    "    invSigma = np.linalg.pinv(Sigma)\n",
    "    middle = 2 * S - S @ invSigma @ S\n",
    "    middle = (middle + middle.T) / 2\n",
    "\n",
    "    # Численно стабилизируем\n",
    "    eigvals_mid = np.linalg.eigvalsh(middle)\n",
    "    if eigvals_mid.min() < 1e-10:\n",
    "        middle += np.eye(p) * (1e-10 - eigvals_mid.min() + 1e-8)\n",
    "\n",
    "    C = np.linalg.cholesky(middle)\n",
    "\n",
    "    U = rng.normal(size=X.shape)\n",
    "    cov_term = S @ invSigma\n",
    "    knock = Xc @ (np.eye(p) - cov_term) + U @ C\n",
    "    return knock\n",
    "\n",
    "def first_layer_importance(model):\n",
    "    first_linear = None\n",
    "    for layer in model.net:\n",
    "        if isinstance(layer, nn.Linear):\n",
    "            first_linear = layer\n",
    "            break\n",
    "    W = first_linear.weight.detach().cpu().numpy()\n",
    "    return np.abs(W).sum(axis=0)\n",
    "\n",
    "def knockoff_threshold(W, q=0.20):\n",
    "    vals = np.sort(np.unique(np.abs(W[W != 0])))\n",
    "    for t in vals:\n",
    "        num = 1 + np.sum(W <= -t)\n",
    "        den = max(1, np.sum(W >= t))\n",
    "        if num / den <= q:\n",
    "            return float(t)\n",
    "    return None\n",
    "\n",
    "# Knockoffs на train_full для более устойчивой оценки\n",
    "X_knock_train = make_gaussian_knockoffs(X_train_full_proc, seed=SEED)\n",
    "X_aug = np.hstack([X_train_full_proc, X_knock_train])\n",
    "\n",
    "# Чтобы оценка важности была честной, делим train_full на новую train/val часть\n",
    "Xa_tr, Xa_va, ya_tr, ya_va = train_test_split(\n",
    "    X_aug, y_train_full.values, test_size=0.20, random_state=SEED\n",
    ")\n",
    "\n",
    "knock_model, knock_history = train_nn_regression(\n",
    "    Xa_tr, ya_tr, Xa_va, ya_va,\n",
    "    input_dim=X_aug.shape[1],\n",
    "    hidden_dims=(128, 64),\n",
    "    dropout=0.15,\n",
    "    lr=1e-3,\n",
    "    weight_decay=1e-4,\n",
    "    epochs=120,\n",
    "    batch_size=64,\n",
    "    patience=15\n",
    ")\n",
    "\n",
    "imp_aug = first_layer_importance(knock_model)\n",
    "p = X_train_full_proc.shape[1]\n",
    "Z = imp_aug[:p]\n",
    "Z_tilde = imp_aug[p:]\n",
    "W_proc = Z - Z_tilde\n",
    "\n",
    "proc_importance_df = pd.DataFrame({\n",
    "    \"processed_feature\": feature_names_proc,\n",
    "    \"orig_importance\": Z,\n",
    "    \"knockoff_importance\": Z_tilde,\n",
    "    \"W_stat\": W_proc,\n",
    "})\n",
    "\n",
    "def processed_to_original(name):\n",
    "    name = str(name)\n",
    "    if name.startswith(\"num__\"):\n",
    "        return name.replace(\"num__\", \"\")\n",
    "    if name.startswith(\"cat__\"):\n",
    "        rest = name.replace(\"cat__\", \"\")\n",
    "        return rest.split(\"_\", 1)[0]\n",
    "    return name\n",
    "\n",
    "proc_importance_df[\"original_feature\"] = proc_importance_df[\"processed_feature\"].map(processed_to_original)\n",
    "\n",
    "group_importance_df = (\n",
    "    proc_importance_df\n",
    "    .groupby(\"original_feature\", as_index=False)[[\"orig_importance\", \"knockoff_importance\", \"W_stat\"]]\n",
    "    .sum()\n",
    "    .sort_values(\"W_stat\", ascending=False)\n",
    "    .reset_index(drop=True)\n",
    ")\n",
    "\n",
    "thr = knockoff_threshold(group_importance_df[\"W_stat\"].values, q=0.20)\n",
    "\n",
    "if thr is not None:\n",
    "    selected_features = group_importance_df.loc[group_importance_df[\"W_stat\"] >= thr, \"original_feature\"].tolist()\n",
    "else:\n",
    "    selected_features = group_importance_df.loc[group_importance_df[\"W_stat\"] > 0, \"original_feature\"].head(8).tolist()\n",
    "\n",
    "if len(selected_features) < 3:\n",
    "    selected_features = group_importance_df.head(min(8, len(group_importance_df)))[\"original_feature\"].tolist()\n",
    "\n",
    "group_importance_df[\"selected\"] = group_importance_df[\"original_feature\"].isin(selected_features)\n",
    "\n",
    "print(\"Порог knockoff:\", thr)\n",
    "print(\"Отобранные признаки:\", selected_features)\n",
    "display(group_importance_df.head(20))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d0f1dbb0",
   "metadata": {},
   "source": [
    "## Нейросеть на отобранных признаках"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "7c5e62e8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Используемые признаки после knockoff:\n",
      "['stage', 'abdominal_pain', 'alcohol_consumption', 'jaundice', 'outcome', 'lymph_node_involvement', 'gender', 'ethnicity', 'smoking_history', 'gallstones', 'tumor_size', 'treatment_type']\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",
       "      <th>val_loss</th>\n",
       "      <th>val_rmse</th>\n",
       "      <th>val_r2</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>16</th>\n",
       "      <td>17</td>\n",
       "      <td>282.238783</td>\n",
       "      <td>315.111023</td>\n",
       "      <td>17.821967</td>\n",
       "      <td>-0.014314</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17</th>\n",
       "      <td>18</td>\n",
       "      <td>278.914943</td>\n",
       "      <td>314.897542</td>\n",
       "      <td>17.834377</td>\n",
       "      <td>-0.015727</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18</th>\n",
       "      <td>19</td>\n",
       "      <td>283.371710</td>\n",
       "      <td>317.400869</td>\n",
       "      <td>17.877411</td>\n",
       "      <td>-0.020635</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>19</th>\n",
       "      <td>20</td>\n",
       "      <td>285.315733</td>\n",
       "      <td>317.309886</td>\n",
       "      <td>17.885256</td>\n",
       "      <td>-0.021531</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20</th>\n",
       "      <td>21</td>\n",
       "      <td>279.127834</td>\n",
       "      <td>317.734100</td>\n",
       "      <td>17.900581</td>\n",
       "      <td>-0.023282</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    epoch  train_loss    val_loss   val_rmse    val_r2\n",
       "16     17  282.238783  315.111023  17.821967 -0.014314\n",
       "17     18  278.914943  314.897542  17.834377 -0.015727\n",
       "18     19  283.371710  317.400869  17.877411 -0.020635\n",
       "19     20  285.315733  317.309886  17.885256 -0.021531\n",
       "20     21  279.127834  317.734100  17.900581 -0.023282"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Метрики модели по отобранным признакам на validation: {'r2': 0.007794399633107463, 'rmse': 17.62667106986193, 'mae': 15.520126628875733}\n",
      "Метрики модели по отобранным признакам на test: {'r2': 0.00581900745014341, 'rmse': 18.15983967546831, 'mae': 15.860402421951294}\n"
     ]
    }
   ],
   "source": [
    "# исправление названий признаков после knockoff\n",
    "feature_mapping = {\n",
    "    'abdominal': 'abdominal_pain',\n",
    "    'alcohol': 'alcohol_consumption',\n",
    "    'lymph': 'lymph_node_involvement',\n",
    "    'smoking': 'smoking_history',\n",
    "    'treatment': 'treatment_type'\n",
    "}\n",
    "\n",
    "selected_features = [feature_mapping.get(f, f) for f in selected_features]\n",
    "\n",
    "# оставляем только существующие признаки\n",
    "selected_features = [f for f in selected_features if f in X.columns]\n",
    "\n",
    "print(\"Используемые признаки после knockoff:\")\n",
    "print(selected_features)\n",
    "\n",
    "X_sel = X[selected_features].copy()\n",
    "numeric_features_sel = X_sel.select_dtypes(include=[np.number]).columns.tolist()\n",
    "categorical_features_sel = [c for c in X_sel.columns if c not in numeric_features_sel]\n",
    "\n",
    "preprocessor_sel = ColumnTransformer(\n",
    "    transformers=[\n",
    "        (\"num\", Pipeline(steps=[\n",
    "            (\"imputer\", SimpleImputer(strategy=\"median\")),\n",
    "            (\"scaler\", StandardScaler()),\n",
    "        ]), numeric_features_sel),\n",
    "        (\"cat\", Pipeline(steps=[\n",
    "            (\"imputer\", SimpleImputer(strategy=\"most_frequent\")),\n",
    "            (\"onehot\", OneHotEncoder(handle_unknown=\"ignore\")),\n",
    "        ]), categorical_features_sel),\n",
    "    ],\n",
    "    remainder=\"drop\"\n",
    ")\n",
    "\n",
    "X_sel_train_full, X_sel_test, y_sel_train_full, y_sel_test = train_test_split(\n",
    "    X_sel, y, test_size=0.20, random_state=SEED\n",
    ")\n",
    "X_sel_train, X_sel_val, y_sel_train, y_sel_val = train_test_split(\n",
    "    X_sel_train_full, y_sel_train_full, test_size=0.20, random_state=SEED\n",
    ")\n",
    "\n",
    "X_sel_train_proc = preprocessor_sel.fit_transform(X_sel_train)\n",
    "X_sel_val_proc = preprocessor_sel.transform(X_sel_val)\n",
    "X_sel_test_proc = preprocessor_sel.transform(X_sel_test)\n",
    "\n",
    "if hasattr(X_sel_train_proc, \"toarray\"):\n",
    "    X_sel_train_proc = X_sel_train_proc.toarray()\n",
    "    X_sel_val_proc = X_sel_val_proc.toarray()\n",
    "    X_sel_test_proc = X_sel_test_proc.toarray()\n",
    "\n",
    "selected_model, selected_history = train_nn_regression(\n",
    "    X_sel_train_proc, y_sel_train.values,\n",
    "    X_sel_val_proc, y_sel_val.values,\n",
    "    input_dim=X_sel_train_proc.shape[1],\n",
    "    hidden_dims=(128, 64),   # синонимичная архитектура\n",
    "    dropout=0.15,\n",
    "    lr=1e-3,\n",
    "    weight_decay=1e-4,\n",
    "    epochs=120,\n",
    "    batch_size=64,\n",
    "    patience=15\n",
    ")\n",
    "\n",
    "selected_pred_test = predict_nn(selected_model, X_sel_test_proc)\n",
    "selected_pred_val = predict_nn(selected_model, X_sel_val_proc)\n",
    "\n",
    "selected_metrics_test = regression_metrics(y_sel_test.values, selected_pred_test)\n",
    "selected_metrics_val = regression_metrics(y_sel_val.values, selected_pred_val)\n",
    "\n",
    "display(selected_history.tail())\n",
    "print(\"Метрики модели по отобранным признакам на validation:\", selected_metrics_val)\n",
    "print(\"Метрики модели по отобранным признакам на test:\", selected_metrics_test)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "43373ea5",
   "metadata": {},
   "source": [
    "## Сравнение моделей"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "38c13ac6",
   "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>r2_rank</th>\n",
       "      <th>rmse_rank</th>\n",
       "      <th>integral_rank</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Нейросеть по признакам после knockoff-отбора</td>\n",
       "      <td>0.005819</td>\n",
       "      <td>18.159840</td>\n",
       "      <td>15.860402</td>\n",
       "      <td>0.007794</td>\n",
       "      <td>17.626671</td>\n",
       "      <td>15.520127</td>\n",
       "      <td>12</td>\n",
       "      <td>30</td>\n",
       "      <td>1.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>2.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Нейросеть по всем признакам</td>\n",
       "      <td>-0.007454</td>\n",
       "      <td>18.280659</td>\n",
       "      <td>15.949071</td>\n",
       "      <td>0.002223</td>\n",
       "      <td>17.676086</td>\n",
       "      <td>15.558136</td>\n",
       "      <td>19</td>\n",
       "      <td>39</td>\n",
       "      <td>2.0</td>\n",
       "      <td>2.0</td>\n",
       "      <td>4.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                          model   r2_test  rmse_test  \\\n",
       "1  Нейросеть по признакам после knockoff-отбора  0.005819  18.159840   \n",
       "0                   Нейросеть по всем признакам -0.007454  18.280659   \n",
       "\n",
       "    mae_test    r2_val   rmse_val    mae_val  n_original_features  \\\n",
       "1  15.860402  0.007794  17.626671  15.520127                   12   \n",
       "0  15.949071  0.002223  17.676086  15.558136                   19   \n",
       "\n",
       "   n_processed_features  r2_rank  rmse_rank  integral_rank  \n",
       "1                    30      1.0        1.0            2.0  \n",
       "0                    39      2.0        2.0            4.0  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "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Cy+88JfXT0pKShUsAWTKlIksWbI8wid5sLNnz7J06VJat25NoUKFiIqK4ptvvqFWrVocPXr0oRlj5syZY/7/1q1b+fbbb83fKQAPDw8AkpOTadasGdu2baNnz54UL16cQ4cOMXbsWE6ePMnSpUvN83z00UcMHz6cqlWrMmLECDJmzMiuXbvYsGEDDRo0YNy4ccTFxQFw7NgxPv74Y4YMGULx4sUBzKDVMAyaNWvGxo0b6datG6VLl2b16tUMHDiQixcvMnbsWJvP0qJFC1q2bEliYiI7duzg22+/5datW+ZnvHXrFrVr1+b06dP07duXQoUKsWDBAjp37kxMTIxN0H6/06dP89133/3dfxIAevbsSY0aNUhISGD16tV88cUXuLi4MHLkyEc6z72uXLnCtm3b2LZtG127dqVcuXKsX7+ewYMHEx4ezpQpU8yy3bt3Z9asWbz88su888477Nq1izFjxnDs2DGWLFlic95Tp07Rtm1bevfuTadOnZgxYwatW7dm1apV1K9fP826nD9/noYNG+Lv78/8+fNxckp5pLl58ya1atXi4sWL9OrViwIFCrB9+3YGDx7M5cuXGTdu3P/8+UXSFUNEnjuxsbEGYLz00kt/+xjAAIyQkBBz27lz5wwXFxejRYsW5rabN2+mOnbHjh0GYMyePdvcNmPGDAMwwsLCzG0nT540AOOzzz4zt3Xq1MnIkiVLqnMuWLDAAIyNGzcahmEYycnJRpEiRYzg4GAjOTnZpj6FChUy6tevb24bNmyYARh//PGHzTn37NljAMaMGTNsru/j42O+P3z4sOHg4GA0atTIpv43btwwsmfPbvTo0cPmnJGRkYabm1uq7ffbuHGjARjTp083/vjjD+PSpUvGqlWrDD8/P8NisRi7d++2KX/vz+Xll1826tataxiGYSQlJRmenp7GRx99ZISFhRmA8fnnn9vUP1OmTAZglC5d2ujXr5+xdOlSIz4+PlWdatWqZf673//q1avX3/o8CxYsSLUvS5YsRqdOncz3t2/fNpKSkmzKhIWFGc7OzsaIESMeep17pfU7ZTVnzhzDwcHB2Lp1q832KVOmGIDx22+/GYZhGKdOnTIcHByMFi1apKrTvb9XVtbPaf09vNfSpUsNwBg1apTN9pdfftmwWCzG6dOnzW2AMWzYMJtyVatWNQICAsz348aNMwBj7ty5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qlWNL774wrhz585Df34i9sJiGI/YPyoizyWLxUKfPn3+59ZsEZEnoWDBgpQoUYLly5c/66qI2BXNCRARERERsTMKAkRERERE7IyCABERERERO6M5ASIiIiIidkY9ASIiIiIidkZBgIiIiIiInVEQICIiIiJiZ9LtisHJyclcunSJbNmyYbFYnnV1RERERESeKMMwuHHjBl5eXjg4PLytP90GAZcuXcLb2/tZV0NERERE5Kk6f/48+fPnf2iZdBsEZMuWDUj5Ibi6uj7j2oiIiIiIPFnXr1/H29vbfA5+mHQbBFiHALm6uioIEBERERG78XeGwmtisIiIiIiInVEQICIiIiJiZxQEiIiIiIjYGQUBIiIiIiJ2RkGAiIiIiIidURAgIiIiImJnFASIiIiIiNgZBQEiIiIiInYm3S4W9m9Q8P0Vz7oKImInwj9p8qyrICIizxEFASIikq6pQUZEnqbnpVFGw4FEREREROyMggARERERETujIEBERERExM48dhCwZcsWXnzxRby8vLBYLCxdutRmv8ViSfP1+eefP/Ccw4cPT1Xe39//casqIiIiIiL8A0FAfHw8QUFBTJo0Kc39ly9ftnlNnz4di8VCq1atHnrewMBAm+O2bdv2uFUVERERERH+gexAjRo1olGjRg/c7+npafN+2bJl1KlTh8KFCz+8Yk5OqY4VEREREZHH91TnBERFRbFixQq6dev2l2VPnTqFl5cXhQsX5tVXXyUiIuKh5RMSErh+/brNS0REREREUnuqQcCsWbPIli0bLVu2fGi5SpUqMXPmTFatWsXkyZMJCwujRo0a3Lhx44HHjBkzBjc3N/Pl7e39T1dfRERERCRdeKpBwPTp03n11VdxcXF5aLlGjRrRunVrSpUqRXBwML/++isxMTHMnz//gccMHjyY2NhY83X+/Pl/uvoiIiIiIunCU1sxeOvWrZw4cYKffvrpkY/Nnj07RYsW5fTp0w8s4+zsjLOz8+NUUURERETELjy1noBp06ZRrlw5goKCHvnYuLg4zpw5Q968eZ9AzURERERE7MtjBwFxcXEcOHCAAwcOABAWFsaBAwdsJvJev36dBQsW0L179zTPUbduXSZOnGi+f/fdd9m8eTPh4eFs376dFi1a4OjoSPv27R+3uiIiIiIidu+xhwOFhIRQp04d8/2AAQMA6NSpEzNnzgRg3rx5GIbxwIf4M2fOEB0dbb6/cOEC7du358qVK+TOnZvq1auzc+dOcufO/bjVFRERERGxe48dBNSuXRvDMB5apmfPnvTs2fOB+8PDw23ez5s373GrJSIiIiIiD/BUswOJiIiIiMizpyBARERERMTOKAgQEREREbEzCgJEREREROyMggARERERETujIEBERERExM4oCBARERERsTMKAkRERERE7IyCABERERERO6MgQERERETEzigIEBERERGxMwoCRERERETsjIIAERERERE7oyBARERERMTOKAgQEREREbEzCgJEREREROyMggARERERETujIEBERERExM4oCBARERERsTOPHQRs2bKFF198ES8vLywWC0uXLrXZ37lzZywWi82rYcOGf3neSZMmUbBgQVxcXKhUqRK7d+9+3KqKiIiIiAj/QBAQHx9PUFAQkyZNemCZhg0bcvnyZfP1448/PvScP/30EwMGDGDYsGHs27ePoKAggoOD+f333x+3uiIiIiIids/pcU/QqFEjGjVq9NAyzs7OeHp6/u1zfvnll/To0YMuXboAMGXKFFasWMH06dN5//33H6u+IiIiIiL27qnMCdi0aRN58uShWLFivP7661y5cuWBZe/cucPevXupV6/en5V0cKBevXrs2LHjaVRXRERERCRde+yegL/SsGFDWrZsSaFChThz5gxDhgyhUaNG7NixA0dHx1Tlo6OjSUpKwsPDw2a7h4cHx48ff+B1EhISSEhIMN9fv379n/sQIiIiIiLpyBMPAtq1a2f+f8mSJSlVqhS+vr5s2rSJunXr/mPXGTNmDB999NE/dj4RERERkfTqqacILVy4MO7u7pw+fTrN/e7u7jg6OhIVFWWzPSoq6qHzCgYPHkxsbKz5On/+/D9abxERERGR9OKpBwEXLlzgypUr5M2bN839GTNmpFy5cqxfv97clpyczPr166lSpcoDz+vs7Iyrq6vNS0REREREUnvsICAuLo4DBw5w4MABAMLCwjhw4AARERHExcUxcOBAdu7cSXh4OOvXr+ell17Cz8+P4OBg8xx169Zl4sSJ5vsBAwbw3XffMWvWLI4dO8brr79OfHy8mS1IRERERET+d489JyAkJIQ6deqY7wcMGABAp06dmDx5MqGhocyaNYuYmBi8vLxo0KABI0eOxNnZ2TzmzJkzREdHm+/btm3LH3/8wdChQ4mMjKR06dKsWrUq1WRhERERERF5dI8dBNSuXRvDMB64f/Xq1X95jvDw8FTb+vbtS9++fR+naiIiIiIikoanPidARERERESeLQUBIiIiIiJ2RkGAiIiIiIidURAgIiIiImJnFASIiIiIiNgZBQEiIiIiInZGQYCIiIiIiJ1RECAiIiIiYmcUBIiIiIiI2BkFASIiIiIidkZBgIiIiIiInVEQICIiIiJiZxQEiIiIiIjYGQUBIiIiIiJ2RkGAiIiIiIidURAgIiIiImJnFASIiIiIiNgZBQEiIiIiInZGQYCIiIiIiJ1RECAiIiIiYmceOwjYsmULL774Il5eXlgsFpYuXWruu3v3Lu+99x4lS5YkS5YseHl50bFjRy5duvTQcw4fPhyLxWLz8vf3f9yqioiIiIgI/0AQEB8fT1BQEJMmTUq17+bNm+zbt48PP/yQffv2sXjxYk6cOEGzZs3+8ryBgYFcvnzZfG3btu1xqyoiIiIiIoDT456gUaNGNGrUKM19bm5urF271mbbxIkTqVixIhERERQoUODBFXNywtPT83GrJyIiIiIi93nqcwJiY2OxWCxkz579oeVOnTqFl5cXhQsX5tVXXyUiIuKh5RMSErh+/brNS0REREREUnuqQcDt27d57733aN++Pa6urg8sV6lSJWbOnMmqVauYPHkyYWFh1KhRgxs3bjzwmDFjxuDm5ma+vL29n8RHEBERERF57j21IODu3bu0adMGwzCYPHnyQ8s2atSI1q1bU6pUKYKDg/n111+JiYlh/vz5Dzxm8ODBxMbGmq/z58//0x9BRERERCRdeOw5AX+HNQA4d+4cGzZseGgvQFqyZ89O0aJFOX369APLODs74+zs/LhVFRERERFJ9554T4A1ADh16hTr1q0jV65cj3yOuLg4zpw5Q968eZ9ADUVERERE7MtjBwFxcXEcOHCAAwcOABAWFsaBAweIiIjg7t27vPzyy4SEhPD999+TlJREZGQkkZGR3LlzxzxH3bp1mThxovn+3XffZfPmzYSHh7N9+3ZatGiBo6Mj7du3f9zqioiIiIjYvcceDhQSEkKdOnXM9wMGDACgU6dODB8+nJ9//hmA0qVL2xy3ceNGateuDcCZM2eIjo429124cIH27dtz5coVcufOTfXq1dm5cye5c+d+3OqKiIiIiNi9xw4CateujWEYD9z/sH1W4eHhNu/nzZv3uNUSEREREZEHeOrrBIiIiIiIyLOlIEBERERExM4oCBARERERsTMKAkRERERE7IyCABERERERO6MgQERERETEzigIEBERERGxMwoCRERERETsjIIAERERERE7oyBARERERMTOKAgQEREREbEzCgJEREREROyMggARERERETujIEBERERExM4oCBARERERsTMKAkRERERE7IyCABERERERO6MgQERERETEzigIEBERERGxM48dBGzZsoUXX3wRLy8vLBYLS5cutdlvGAZDhw4lb968ZMqUiXr16nHq1Km/PO+kSZMoWLAgLi4uVKpUid27dz9uVUVEREREhH8gCIiPjycoKIhJkyaluf+zzz5jwoQJTJkyhV27dpElSxaCg4O5ffv2A8/5008/MWDAAIYNG8a+ffsICgoiODiY33///XGrKyIiIiJi9x47CGjUqBGjRo2iRYsWqfYZhsG4ceP44IMPeOmllyhVqhSzZ8/m0qVLqXoM7vXll1/So0cPunTpQkBAAFOmTCFz5sxMnz79casrIiIiImL3nuicgLCwMCIjI6lXr565zc3NjUqVKrFjx440j7lz5w579+61OcbBwYF69eo98BiAhIQErl+/bvMSEREREZHUnmgQEBkZCYCHh4fNdg8PD3Pf/aKjo0lKSnqkYwDGjBmDm5ub+fL29n7M2ouIiIiIpE/pJjvQ4MGDiY2NNV/nz59/1lUSEREREflXeqJBgKenJwBRUVE226Oiosx993N3d8fR0fGRjgFwdnbG1dXV5iUiIiIiIqk90SCgUKFCeHp6sn79enPb9evX2bVrF1WqVEnzmIwZM1KuXDmbY5KTk1m/fv0DjxERERERkb/P6XFPEBcXx+nTp833YWFhHDhwgJw5c1KgQAH69+/PqFGjKFKkCIUKFeLDDz/Ey8uL5s2bm8fUrVuXFi1a0LdvXwAGDBhAp06dKF++PBUrVmTcuHHEx8fTpUuXx62uiIiIiIjde+wgICQkhDp16pjvBwwYAECnTp2YOXMmgwYNIj4+np49exITE0P16tVZtWoVLi4u5jFnzpwhOjrafN+2bVv++OMPhg4dSmRkJKVLl2bVqlWpJguLiIiIiMijsxiGYTzrSjwJ169fx83NjdjY2Gc2P6Dg+yueyXVFxP6Ef9LkWVfhX0v3YhF5mp7l/fhRnn/TTXYgERERERH5exQEiIiIiIjYGQUBIiIiIiJ2RkGAiIiIiIidURAgIiIiImJnFASIiIiIiNgZBQEiIiIiInZGQYCIiIiIiJ1RECAiIiIiYmcUBIiIiIiI2BkFASIiIiIidkZBgIiIiIiInVEQICIiIiJiZxQEiIiIiIjYGQUBIiIiIiJ2RkGAiIiIiIidURAgIiIiImJnFASIiIiIiNgZBQEiIiIiInbmiQcBBQsWxGKxpHr16dMnzfIzZ85MVdbFxeVJV1NERERExG44PekL7Nmzh6SkJPP94cOHqV+/Pq1bt37gMa6urpw4ccJ8b7FYnmgdRURERETsyRMPAnLnzm3z/pNPPsHX15datWo98BiLxYKnp+eTrpqIiIiIiF16qnMC7ty5w9y5c+natetDW/fj4uLw8fHB29ubl156iSNHjjzFWoqIiIiIpG9PNQhYunQpMTExdO7c+YFlihUrxvTp01m2bBlz584lOTmZqlWrcuHChYeeOyEhgevXr9u8REREREQktacaBEybNo1GjRrh5eX1wDJVqlShY8eOlC5dmlq1arF48WJy587NN99889BzjxkzBjc3N/Pl7e39T1dfRERERCRdeGpBwLlz51i3bh3du3d/pOMyZMhAmTJlOH369EPLDR48mNjYWPN1/vz5x6muiIiIiEi69dSCgBkzZpAnTx6aNGnySMclJSVx6NAh8ubN+9Byzs7OuLq62rxERERERCS1pxIEJCcnM2PGDDp16oSTk21Coo4dOzJ48GDz/YgRI1izZg1nz55l3759vPbaa5w7d+6RexBERERERCRtTzxFKMC6deuIiIiga9euqfZFRETg4PBnLHLt2jV69OhBZGQkOXLkoFy5cmzfvp2AgICnUVURERERkXTvqQQBDRo0wDCMNPdt2rTJ5v3YsWMZO3bsU6iViIiIiIh9eqrZgURERERE5NlTECAiIiIiYmcUBIiIiIiI2BkFASIiIiIidkZBgIiIiIiInVEQICIiIiJiZxQEiIiIiIjYGQUBIiIiIiJ2RkGAiIiIiIidURAgIiIiImJnFASIiIiIiNgZBQEiIiIiInZGQYCIiIiIiJ1RECAiIiIiYmcUBIiIiIiI2BkFASIiIiIidkZBgIiIiIiInVEQICIiIiJiZxQEiIiIiIjYGQUBIiIiIiJ25okHAcOHD8disdi8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",
      "text/plain": [
       "<Figure size 800x400 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAxEAAAGGCAYAAAAEmwy0AAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjgsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvwVt1zgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAhc1JREFUeJzs3Xd8Tvf///HHlUQSKwkSGURsSVAjVuzWCKKq1GjVLmp9KKX0o7RKtTrUKtVhlardllqlpUjt2rOECImZhCDz/P7I7zp1Sajr820onvfb7bqRc97nfd7nGuec13kvi2EYBiIiIiIiIvfJ4WEXQEREREREHi0KIkRERERExC4KIkRERERExC4KIkRERERExC4KIkRERERExC4KIkRERERExC4KIkRERERExC4KIkRERERExC4KIkREROQfERcXx4kTJ0hNTX3YRRGRbKYgQkRE5F/s7NmzzJo1y/w7MjKSefPmPbwC3SYlJYXx48dToUIFXFxcyJcvH6VKlWL9+vUPu2giks0URIjI/+zPP/+kV69eFC9eHFdXV9zc3KhVqxYTJ07k5s2bD7t4T4xff/0Vi8VivhwdHSlYsCAvvPAChw8ftkn7yy+/UKtWLerVq0dwcDBjxox5SKWW+2WxWOjbty9r1qwhMjKSoUOH8ttvvz3sYpGUlETDhg156623qF+/PosWLWLdunVs2LCB0NDQh108EclmTg+7ACLyaFq5ciVt2rTBxcWFTp06Ua5cOZKTk9m8eTNDhgzh4MGDzJgx42EX84nyn//8h6pVq5KSksK+ffuYPn06v/76KwcOHMDHxweA0qVLs3btWnLnzs358+cpXrw4derUoV69eg+59HI3hQoVokePHjRp0gQAX19ffv3114dbKOCDDz5g27ZtrFmzhvr16z/s4ojIA6YgQkTsdurUKdq3b09AQAAbNmzA19fXXNe3b19OnDjBypUrH2IJn0x16tThhRdeMP8uU6YMvXv3Zs6cOQwdOhTIuCG1slgspKen4+CgSul/u08//ZT+/ftz6dIlypUrR+7cuR9qeVJTU/n0008ZPHiwAgiRJ5SuHCJit/Hjx3P9+nW++uormwDCqmTJkgwYMMD822Kx0K9fP+bNm0eZMmVwdXUlJCSETZs22Wx3+vRp+vTpQ5kyZciZMycFChSgTZs2REZG2qSbNWuWTfOdXLlyUb58eb788kubdF26dCFPnjyZyrd48WIsFkump7nbtm2jSZMmuLu7kytXLurVq8eWLVts0rz99ttYLBYuXbpks3znzp1YLBabtutdunShaNGiNumioqLImTMnFosl03GtWrWKOnXqkDt3bvLmzUt4eDgHDx7MVP77VadOHSCj2dmdUlNT6dSpE+Hh4Wa6u6lfvz7lypXLtPyjjz7KdBzff/894eHh+Pn54eLiQokSJXj33XdJS0u75z6s7+u9Xrd/XvfzWQFER0fTvXt3szzFihWjd+/eJCcnZ/oeZfW6/fPcsGGD+fl4eHjw3HPPZWoududx5M2bl2rVqrF8+fJMZVu0aBEhISHkzJkTT09PXn75ZaKjo23S3P4dKlGiBNWrV+fKlSt3/Q7dqUuXLjblyZcvH/Xr18/UHKpo0aI0b978rvlYm8xZP4OjR49y9epV8ubNS7169ciVKxfu7u40b96cAwcOZNp+z549NG3aFDc3N/LkyUODBg34/fffbdJYP49NmzbRq1cvChQogJubG506deLq1auZytulSxebZT179sTV1TXT7/qf/l2JSAbVRIiI3X788UeKFy9OzZo173ubjRs38t133/Gf//wHFxcXPvvsM5o0acL27dvNG9QdO3awdetW2rdvT+HChYmMjGTatGnUr1+fQ4cOkStXLps8J0yYgKenJwkJCXz99df06NGDokWL0rBhQ7uPacOGDTRt2pSQkBBGjRqFg4MDM2fO5JlnnuG3336jWrVqdueZlZEjR3Lr1q1My+fOnUvnzp0JCwvjgw8+4MaNG0ybNo3atWuzZ8+eTMHI/bDeYObLl89meXp6Ol27duX69essW7bsfzmMu5o1axZ58uRh0KBB5MmThw0bNjBy5EgSEhL48MMP77pdq1atKFmypPn3a6+9RlBQED179jSXBQUFAff/WZ07d45q1aoRFxdHz549CQwMJDo6msWLF3Pjxg3q1q3L3LlzzfzHjh0LwH//+19zmfU7/vPPP9O0aVOKFy/O22+/zc2bN5k8eTK1atVi9+7dmT4fa76XLl3is88+o02bNhw4cIAyZcqY71PXrl2pWrUq48aNIzY2lokTJ7Jlyxb27NmDh4fHXd+ru32H7sbT05MJEyYAGZ20J06cSLNmzYiKirrnfu7l8uXLAAwfPpxSpUrxzjvvcOvWLaZOnUqtWrXY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0KVLF1599VWqVKlyX2UdN24c7u7u5svf3/++thMRERERedI8lqMzTZ48mWvXrjF8+PD73mb48OHEx8ebr6ioqGwsoYiIiIjIoytbgwhPT08cHR2JjY21WR4bG4uPj0+W2/j4+NwzvfXfe6XZsGEDERERuLi44OTkRMmSJQGoUqUKnTt3znK/Li4uuLm52bxERERERCSzbA0inJ2dCQkJYf369eay9PR01q9fT2hoaJbbhIaG2qQHWLdunZm+WLFi+Pj42KRJSEhg27ZtZppJkyaxd+9e/vjjD/744w9ziNjvvvuOsWPH/qPHKCIiIiLypHHK7h0MGjSIzp07U6VKFapVq8ann35KYmIiXbt2BaBTp04UKlSIcePGATBgwADq1avHxx9/THh4OAsWLGDnzp3MmDEDAIvFwsCBAxkzZgylSpWiWLFivPXWW/j5+dGyZUsAihQpYlOGPHnyAFCiRAkKFy6c3YcsIiIiIvJYy/Ygol27dly8eJGRI0cSExNDxYoVWb16tdkx+syZMzg4/FUhUrNmTebPn8+IESN48803KVWqFMuXL6dcuXJmmqFDh5KYmEjPnj2Ji4ujdu3arF69GldX1+w+HBERERGRJ57FMAzjYRfi3yghIQF3d3fi4+PVP0JE5AlXdNjKh10EEXlCRL4f/tD2bc/972M5OpOIiIiIiGQfBREiIiIiImIXBREiIiIiImIXBREiIiIiImIXBREiIiIiImIXBREiIiIiImIXBREiIiIiImIXBREiIiIiImIXBREiIiIiImIXBREiIiIiImIXBREiIiIiImIXBREiIiIiImIXBREiIiIiImIXBREiIiIiImIXBREiIiIiImIXBREiIiIiImIXBREiIiIiImIXBREiIiIiImIXBREiIiIiImIXBREiIiIiImIXBREiIiIiImKXBxJETJ06laJFi+Lq6kr16tXZvn37PdMvWrSIwMBAXF1dKV++PD/99JPNesMwGDlyJL6+vuTMmZOGDRty/Phxc31kZCTdu3enWLFi5MyZkxIlSjBq1CiSk5Oz5fhERERERJ4k2R5EfPfddwwaNIhRo0axe/duKlSoQFhYGBcuXMgy/datW3nxxRfp3r07e/bsoWXLlrRs2ZIDBw6YacaPH8+kSZOYPn0627ZtI3fu3ISFhXHr1i0Ajhw5Qnp6Op9//jkHDx5kwoQJ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a8fFixcZOXIkMTExVKxYkdWrV5sdo8+cOYODw18VIjVr1mT+/PmMGDGCN998k1KlSrF8+XLKlStnphk6dCiJiYn07NmTuLg4ateuzerVq3F1dTXTzJs3j379+tGgQQMcHBxo3bo1kyZNyu7DFRERERF57GX7PBGPqn/DPBEanUlEHhSNPiQiIv+aeSJEREREROTxoyBCRERERETsoiBCRERERETsoiBCRERERETsoiBCRERERETsoiBCRERERETsoiBCRERERETsoiBCRERERETsoiBCRERERETsoiBCRERERETsoiBCRERERETsoiBCRERERETsoiBCRERERETsoiBCRERERETsoiBCRERERETsoiBCRERERETsoiBCRERERETsoiBCRERERETsoiBCRERERETsoiBCRERERETsoiBCRERERETskq1BxJUrV+jQoQNubm54eHjQvXt3rl+/fs9tbt26Rd++fSlQoAB58uShdevWxMbG2qQ5c+YM4eHh5MqVi4IFCzJkyBBSU1PN9UuXLqVRo0Z4eXnh5uZGaGgoa9asyZZjFBERERF50mRrENGhQwcOHjzIunXrWLFiBZs2baJnz5733Oa1117jxx9/ZNGiRWzcuJFz587RqlUrc31aWhrh4eEkJyezdetWZs+ezaxZsxg5cqSZZtOmTTRq1IiffvqJXbt28fTTT/Pss8+yZ8+ebDtWEREREZEnhcUwDCM7Mj58+DDBwcHs2LGDKlWqALB69WqaNWvG2bNn8fPzy7RNfHw8Xl5ezJ8/nxdeeAGAI0eOEBQUREREBDVq1GDVqlU0b96cc+fO4e3tDcD06dN54403uHjxIs7OzlmWp2zZsrRr184m2LiXhIQE3N3diY+Px83N7X95C/7Pig5b+VD2KyJPnsj3wx92EURE5CGz5/4322oiIiIi8PDwMAMIgIYNG+Lg4MC2bduy3GbXrl2kpKTQsGFDc1lgYCBFihQhIiLCzLd8+fJmAAEQFhZGQkICBw8ezDLf9PR0rl27Rv78+e9a3qSkJBISEmxeIiIiIiKSWbYFETExMRQsWNBmmZOTE/nz5ycmJuau2zg7O+Ph4WGz3Nvb29wmJibGJoCwrreuy8pHH33E9evXadu27V3LO27cONzd3c2Xv7//PY9PRERERORJZXcQMWzYMCwWyz1fR44cyY6y/k/mz5/P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9uxZSpUqleX+XVxccHFxueexiYiIiIiInTURXl5eBAYG3vPl7OxMaGgocXFx7Nq1y9x2w4YNpKenU7169SzzDgkJIUeOHKxfv95cdvToUc6cOUNoaCgAoaGh7N+/3yZAWbduHW5ubgQHBwNQq1Ytzp07ZzOc7LFjx3BwcKBw4cL2HK6IiIiIiGQhWzpWBwUF0aRJE3r06MH27dvZsmUL/fr1o3379ubITNHR0QQGBpo1C+7u7nTv3p1Bgwbxyy+/sGvXLrp27UpoaCg1atQAoHHjxgQHB9OxY0f27t3LmjVrGDFiBH379jVrEV566SUKFChA165dOXToEJs2bWLIkCF069aNnDlzZsfhioiIiIg8UbJtsrl58+YRGBhIgwYNaNasGbVr12bGjBnm+pSUFI4ePcqNGzfMZRMmTKB58+a0bt2aunXr4uPjw9KlS831jo6OrFixAkdHR0JDQ3n55Zfp1KkTo0ePNtPkyZOHdevWERcXR5UqVejQoQPPPvsskyZNyq5DFRERERF5omTLPBGPA80TISJPEs0TISIiD32eCBEREREReXwpiBAREREREbsoiBAREREREbsoiBAREREREbsoiBAREREREbsoiBAREREREbsoiBAREREREbsoiBAREREREbsoiBAREREREbsoiBAREREREbsoiBAREREREbsoiBAREREREbsoiBAREREREbsoiBAREREREbsoiBAREREREbsoiBAREREREbsoiBAREREREbs4PewCyN1Fvh/+sIsgIiIiIpKJaiJERERERMQuCiJERERERMQuCiJERERERMQu2RZEXLlyhQ4dOuDm5oaHhwfdu3fn+vXr99zm1q1b9O3blwIFCpAnTx5at25NbGysTZozZ84QHh5Orly5KFiwIEOGDCE1NdUmzbx586hQoQK5cuXC19eXbt26cfny5X/8GEVEREREnkTZFkR06NCBgwcPsm7dOlasWMGmTZvo2bPnPbd57bXX+PHHH1m0aBEbN27k3LlztGrVylyflpZGeHg4ycnJbN26ldmzZzNr1ixGjhxpptmyZQudOnWie/fuHDx4kEWLFrF9+3Z69OiRXYcqIiIiIvJEsRiGYfzTmR4+fJjg4GB27NhBlSpVAFi9ejXNmjXj7Nmz+Pn5ZdomPj4eLy8v5s+fzwsvvADAkSNHCAoKIiIigho1arBq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",
      "text/plain": [
       "<Figure size 800x400 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "results_df = pd.DataFrame([\n",
    "    {\n",
    "        \"model\": \"Нейросеть по всем признакам\",\n",
    "        \"r2_test\": baseline_metrics_test[\"r2\"],\n",
    "        \"rmse_test\": baseline_metrics_test[\"rmse\"],\n",
    "        \"mae_test\": baseline_metrics_test[\"mae\"],\n",
    "        \"r2_val\": baseline_metrics_val[\"r2\"],\n",
    "        \"rmse_val\": baseline_metrics_val[\"rmse\"],\n",
    "        \"mae_val\": baseline_metrics_val[\"mae\"],\n",
    "        \"n_original_features\": len(feature_cols),\n",
    "        \"n_processed_features\": int(X_train_proc.shape[1]),\n",
    "    },\n",
    "    {\n",
    "        \"model\": \"Нейросеть по признакам после knockoff-отбора\",\n",
    "        \"r2_test\": selected_metrics_test[\"r2\"],\n",
    "        \"rmse_test\": selected_metrics_test[\"rmse\"],\n",
    "        \"mae_test\": selected_metrics_test[\"mae\"],\n",
    "        \"r2_val\": selected_metrics_val[\"r2\"],\n",
    "        \"rmse_val\": selected_metrics_val[\"rmse\"],\n",
    "        \"mae_val\": selected_metrics_val[\"mae\"],\n",
    "        \"n_original_features\": len(selected_features),\n",
    "        \"n_processed_features\": int(X_sel_train_proc.shape[1]),\n",
    "    },\n",
    "])\n",
    "\n",
    "# Чем выше R2 и ниже RMSE, тем лучше\n",
    "results_df[\"r2_rank\"] = results_df[\"r2_test\"].rank(ascending=False, method=\"min\")\n",
    "results_df[\"rmse_rank\"] = results_df[\"rmse_test\"].rank(ascending=True, method=\"min\")\n",
    "results_df[\"integral_rank\"] = results_df[\"r2_rank\"] + results_df[\"rmse_rank\"]\n",
    "best_row = results_df.sort_values([\"integral_rank\", \"r2_test\", \"rmse_test\"], ascending=[True, False, True]).iloc[0]\n",
    "\n",
    "display(results_df.sort_values(\"integral_rank\"))\n",
    "\n",
    "plt.figure(figsize=(8, 4))\n",
    "plt.bar(results_df[\"model\"], results_df[\"rmse_test\"])\n",
    "plt.title(\"Сравнение RMSE на тестовой выборке\")\n",
    "plt.xticks(rotation=15, ha=\"right\")\n",
    "plt.tight_layout()\n",
    "plt.show()\n",
    "\n",
    "plt.figure(figsize=(8, 4))\n",
    "plt.bar(results_df[\"model\"], results_df[\"r2_test\"])\n",
    "plt.title(\"Сравнение R² на тестовой выборке\")\n",
    "plt.xticks(rotation=15, ha=\"right\")\n",
    "plt.tight_layout()\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ddf7af67",
   "metadata": {},
   "source": [
    "## Финальная ячейка с данными для вывода"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "4c215510",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "=== КЛЮЧЕВАЯ ИНФОРМАЦИЯ ДЛЯ ВЫВОДА ===\n",
      "Зависимая переменная: survival_months\n",
      "\n",
      "Число исходных признаков: 19\n",
      "Число отобранных исходных признаков: 12\n",
      "Отобранные признаки:\n",
      "['stage', 'abdominal_pain', 'alcohol_consumption', 'jaundice', 'outcome', 'lymph_node_involvement', 'gender', 'ethnicity', 'smoking_history', 'gallstones', 'tumor_size', 'treatment_type']\n",
      "\n",
      "Важность признаков по knockoff-методу:\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>original_feature</th>\n",
       "      <th>orig_importance</th>\n",
       "      <th>knockoff_importance</th>\n",
       "      <th>W_stat</th>\n",
       "      <th>selected</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>stage</td>\n",
       "      <td>36.798851</td>\n",
       "      <td>33.820023</td>\n",
       "      <td>2.978827</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>abdominal</td>\n",
       "      <td>18.562559</td>\n",
       "      <td>15.902373</td>\n",
       "      <td>2.660186</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>alcohol</td>\n",
       "      <td>18.306406</td>\n",
       "      <td>15.921711</td>\n",
       "      <td>2.384696</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>jaundice</td>\n",
       "      <td>18.384712</td>\n",
       "      <td>16.073227</td>\n",
       "      <td>2.311484</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>outcome</td>\n",
       "      <td>18.756935</td>\n",
       "      <td>16.921951</td>\n",
       "      <td>1.834983</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>lymph</td>\n",
       "      <td>18.951267</td>\n",
       "      <td>17.197437</td>\n",
       "      <td>1.753829</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>gender</td>\n",
       "      <td>17.272850</td>\n",
       "      <td>15.560019</td>\n",
       "      <td>1.712832</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>ethnicity</td>\n",
       "      <td>43.010582</td>\n",
       "      <td>41.448845</td>\n",
       "      <td>1.561736</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>smoking</td>\n",
       "      <td>18.130417</td>\n",
       "      <td>16.709576</td>\n",
       "      <td>1.420840</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>gallstones</td>\n",
       "      <td>17.253735</td>\n",
       "      <td>15.839079</td>\n",
       "      <td>1.414657</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>tumor_size</td>\n",
       "      <td>10.153769</td>\n",
       "      <td>8.880541</td>\n",
       "      <td>1.273229</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>treatment</td>\n",
       "      <td>33.744125</td>\n",
       "      <td>32.845421</td>\n",
       "      <td>0.898702</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>weight_loss</td>\n",
       "      <td>9.552622</td>\n",
       "      <td>8.741357</td>\n",
       "      <td>0.811265</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>diabetes</td>\n",
       "      <td>17.279274</td>\n",
       "      <td>16.651009</td>\n",
       "      <td>0.628264</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>age</td>\n",
       "      <td>9.903307</td>\n",
       "      <td>9.668497</td>\n",
       "      <td>0.234810</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>15</th>\n",
       "      <td>family</td>\n",
       "      <td>18.550709</td>\n",
       "      <td>18.507805</td>\n",
       "      <td>0.042902</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>16</th>\n",
       "      <td>ca19_9_level</td>\n",
       "      <td>8.373813</td>\n",
       "      <td>9.002457</td>\n",
       "      <td>-0.628644</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17</th>\n",
       "      <td>bmi</td>\n",
       "      <td>9.612047</td>\n",
       "      <td>10.485161</td>\n",
       "      <td>-0.873114</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18</th>\n",
       "      <td>cea_level</td>\n",
       "      <td>9.282860</td>\n",
       "      <td>10.723900</td>\n",
       "      <td>-1.441040</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   original_feature  orig_importance  knockoff_importance    W_stat  selected\n",
       "0             stage        36.798851            33.820023  2.978827      True\n",
       "1         abdominal        18.562559            15.902373  2.660186      True\n",
       "2           alcohol        18.306406            15.921711  2.384696      True\n",
       "3          jaundice        18.384712            16.073227  2.311484      True\n",
       "4           outcome        18.756935            16.921951  1.834983      True\n",
       "5             lymph        18.951267            17.197437  1.753829      True\n",
       "6            gender        17.272850            15.560019  1.712832      True\n",
       "7         ethnicity        43.010582            41.448845  1.561736      True\n",
       "8           smoking        18.130417            16.709576  1.420840      True\n",
       "9        gallstones        17.253735            15.839079  1.414657      True\n",
       "10       tumor_size        10.153769             8.880541  1.273229      True\n",
       "11        treatment        33.744125            32.845421  0.898702      True\n",
       "12      weight_loss         9.552622             8.741357  0.811265     False\n",
       "13         diabetes        17.279274            16.651009  0.628264     False\n",
       "14              age         9.903307             9.668497  0.234810     False\n",
       "15           family        18.550709            18.507805  0.042902     False\n",
       "16     ca19_9_level         8.373813             9.002457 -0.628644     False\n",
       "17              bmi         9.612047            10.485161 -0.873114     False\n",
       "18        cea_level         9.282860            10.723900 -1.441040     False"
      ]
     },
     "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>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",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Нейросеть по признакам после knockoff-отбора</td>\n",
       "      <td>0.005819</td>\n",
       "      <td>18.159840</td>\n",
       "      <td>15.860402</td>\n",
       "      <td>0.007794</td>\n",
       "      <td>17.626671</td>\n",
       "      <td>15.520127</td>\n",
       "      <td>12</td>\n",
       "      <td>30</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Нейросеть по всем признакам</td>\n",
       "      <td>-0.007454</td>\n",
       "      <td>18.280659</td>\n",
       "      <td>15.949071</td>\n",
       "      <td>0.002223</td>\n",
       "      <td>17.676086</td>\n",
       "      <td>15.558136</td>\n",
       "      <td>19</td>\n",
       "      <td>39</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                          model   r2_test  rmse_test  \\\n",
       "0  Нейросеть по признакам после knockoff-отбора  0.005819  18.159840   \n",
       "1                   Нейросеть по всем признакам -0.007454  18.280659   \n",
       "\n",
       "    mae_test    r2_val   rmse_val    mae_val  n_original_features  \\\n",
       "0  15.860402  0.007794  17.626671  15.520127                   12   \n",
       "1  15.949071  0.002223  17.676086  15.558136                   19   \n",
       "\n",
       "   n_processed_features  \n",
       "0                    30  \n",
       "1                    39  "
      ]
     },
     "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>n_original_features</th>\n",
       "      <th>n_processed_features</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Нейросеть по признакам после knockoff-отбора</td>\n",
       "      <td>0.005819</td>\n",
       "      <td>18.15984</td>\n",
       "      <td>15.860402</td>\n",
       "      <td>12</td>\n",
       "      <td>30</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                          model   r2_test  rmse_test  \\\n",
       "1  Нейросеть по признакам после knockoff-отбора  0.005819   18.15984   \n",
       "\n",
       "    mae_test  n_original_features  n_processed_features  \n",
       "1  15.860402                   12                    30  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Последние эпохи обучения baseline:\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",
       "      <th>val_loss</th>\n",
       "      <th>val_rmse</th>\n",
       "      <th>val_r2</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>19</th>\n",
       "      <td>20</td>\n",
       "      <td>283.559297</td>\n",
       "      <td>317.918681</td>\n",
       "      <td>17.897406</td>\n",
       "      <td>-0.022919</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20</th>\n",
       "      <td>21</td>\n",
       "      <td>281.438071</td>\n",
       "      <td>317.185679</td>\n",
       "      <td>17.899927</td>\n",
       "      <td>-0.023207</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>21</th>\n",
       "      <td>22</td>\n",
       "      <td>282.324818</td>\n",
       "      <td>317.851400</td>\n",
       "      <td>17.912859</td>\n",
       "      <td>-0.024686</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>22</th>\n",
       "      <td>23</td>\n",
       "      <td>280.200229</td>\n",
       "      <td>318.395559</td>\n",
       "      <td>17.932322</td>\n",
       "      <td>-0.026914</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>23</th>\n",
       "      <td>24</td>\n",
       "      <td>279.947607</td>\n",
       "      <td>319.851400</td>\n",
       "      <td>17.961062</td>\n",
       "      <td>-0.030208</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    epoch  train_loss    val_loss   val_rmse    val_r2\n",
       "19     20  283.559297  317.918681  17.897406 -0.022919\n",
       "20     21  281.438071  317.185679  17.899927 -0.023207\n",
       "21     22  282.324818  317.851400  17.912859 -0.024686\n",
       "22     23  280.200229  318.395559  17.932322 -0.026914\n",
       "23     24  279.947607  319.851400  17.961062 -0.030208"
      ]
     },
     "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>epoch</th>\n",
       "      <th>train_loss</th>\n",
       "      <th>val_loss</th>\n",
       "      <th>val_rmse</th>\n",
       "      <th>val_r2</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>16</th>\n",
       "      <td>17</td>\n",
       "      <td>282.238783</td>\n",
       "      <td>315.111023</td>\n",
       "      <td>17.821967</td>\n",
       "      <td>-0.014314</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17</th>\n",
       "      <td>18</td>\n",
       "      <td>278.914943</td>\n",
       "      <td>314.897542</td>\n",
       "      <td>17.834377</td>\n",
       "      <td>-0.015727</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18</th>\n",
       "      <td>19</td>\n",
       "      <td>283.371710</td>\n",
       "      <td>317.400869</td>\n",
       "      <td>17.877411</td>\n",
       "      <td>-0.020635</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>19</th>\n",
       "      <td>20</td>\n",
       "      <td>285.315733</td>\n",
       "      <td>317.309886</td>\n",
       "      <td>17.885256</td>\n",
       "      <td>-0.021531</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20</th>\n",
       "      <td>21</td>\n",
       "      <td>279.127834</td>\n",
       "      <td>317.734100</td>\n",
       "      <td>17.900581</td>\n",
       "      <td>-0.023282</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    epoch  train_loss    val_loss   val_rmse    val_r2\n",
       "16     17  282.238783  315.111023  17.821967 -0.014314\n",
       "17     18  278.914943  314.897542  17.834377 -0.015727\n",
       "18     19  283.371710  317.400869  17.877411 -0.020635\n",
       "19     20  285.315733  317.309886  17.885256 -0.021531\n",
       "20     21  279.127834  317.734100  17.900581 -0.023282"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "print(\"=== КЛЮЧЕВАЯ ИНФОРМАЦИЯ ДЛЯ ВЫВОДА ===\")\n",
    "print(\"Зависимая переменная:\", target_col)\n",
    "print(\"\\nЧисло исходных признаков:\", len(feature_cols))\n",
    "print(\"Число отобранных исходных признаков:\", len(selected_features))\n",
    "print(\"Отобранные признаки:\")\n",
    "print(selected_features)\n",
    "\n",
    "print(\"\\nВажность признаков по knockoff-методу:\")\n",
    "display(group_importance_df.sort_values(\"W_stat\", ascending=False).reset_index(drop=True))\n",
    "\n",
    "print(\"\\nМетрики моделей на тестовой выборке:\")\n",
    "display(results_df[[\n",
    "    \"model\", \"r2_test\", \"rmse_test\", \"mae_test\",\n",
    "    \"r2_val\", \"rmse_val\", \"mae_val\",\n",
    "    \"n_original_features\", \"n_processed_features\"\n",
    "]].sort_values([\"r2_test\", \"rmse_test\"], ascending=[False, True]).reset_index(drop=True))\n",
    "\n",
    "print(\"Лучшая модель:\")\n",
    "display(pd.DataFrame([best_row[[\n",
    "    \"model\", \"r2_test\", \"rmse_test\", \"mae_test\",\n",
    "    \"n_original_features\", \"n_processed_features\"\n",
    "]]]))\n",
    "\n",
    "print(\"\\nПоследние эпохи обучения baseline:\")\n",
    "display(baseline_history.tail())\n",
    "\n",
    "print(\"\\nПоследние эпохи обучения модели по отобранным признакам:\")\n",
    "display(selected_history.tail())\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6518a603",
   "metadata": {},
   "source": [
    "Итог\n",
    "\n",
    "В качестве зависимой переменной выбрана survival_months. С помощью knockoff-метода отобрано 12 наиболее влияющих признаков (в т.ч. stage, abdominal_pain, alcohol_consumption, jaundice, lymph_node_involvement, tumor_size, treatment_type).\n",
    "\n",
    "Сравнение моделей показало, что нейросеть по отобранным признакам имеет немного лучшее качество (R² = 0.0058, RMSE ≈ 18.16) по сравнению с моделью по всем признакам (R² = −0.0075, RMSE ≈ 18.28).\n",
    "\n",
    "Следовательно, knockoff-отбор признаков оказался полезным, поскольку позволил сократить число переменных (19 → 12) и одновременно немного улучшить точность модели."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
