{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceType":"competition","sourceId":8586,"databundleVersionId":868729}],"dockerImageVersionId":31259,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nfrom sklearn.ensemble import RandomForestRegressor\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import mean_squared_error\nfrom sklearn.preprocessing import LabelEncoder\nimport lightgbm as lgb\nfrom catboost import CatBoostRegressor\n# Импортируем Ridge\nfrom sklearn.linear_model import Ridge\n\n# Шаг 1. Загружаем только необходимые данные\n# Шаг 1. Загружаем данные с activation_date\nprint(\"Загрузка данных...\")\n\ntrain = pd.read_csv(\n    '/kaggle/input/avito-demand-prediction/train.csv',\n    usecols=['price', 'item_seq_number', 'category_name', 'region',\n             'param_1', 'param_2', 'param_3', 'image_top_1',\n             'activation_date', 'deal_probability']\n)\ntest = pd.read_csv(\n    '/kaggle/input/avito-demand-prediction/test.csv',\n    usecols=['item_id', 'price', 'item_seq_number', 'category_name',\n            'region', 'param_1', 'param_2', 'param_3', 'image_top_1',\n            'activation_date']\n)\n\nprint(f\"Train shape: {train.shape}\")\nprint(f\"Test shape: {test.shape}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-22T11:40:58.815457Z","iopub.execute_input":"2026-03-22T11:40:58.815899Z","iopub.status.idle":"2026-03-22T11:41:19.503466Z","shell.execute_reply.started":"2026-03-22T11:40:58.815864Z","shell.execute_reply":"2026-03-22T11:41:19.502069Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Преобразуем activation_date в datetime\ntrain['activation_date'] = pd.to_datetime(train['activation_date'])\ntest['activation_date'] = pd.to_datetime(test['activation_date'])\n\n# Создаём временные признаки\ntrain['Weekday'] = train['activation_date'].dt.weekday  # День недели (0–6)\ntrain['Dayofmonth'] = train['activation_date'].dt.day      # День месяца (1–31)\ntrain['Weekofyear'] = train['activation_date'].dt.isocalendar().week  # Неделя года\n\ntest['Weekday'] = test['activation_date'].dt.weekday\ntest['Dayofmonth'] = test['activation_date'].dt.day\ntest['Weekofyear'] = test['activation_date'].dt.isocalendar().week","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-22T11:41:25.244643Z","iopub.execute_input":"2026-03-22T11:41:25.245202Z","iopub.status.idle":"2026-03-22T11:41:25.744865Z","shell.execute_reply.started":"2026-03-22T11:41:25.245167Z","shell.execute_reply":"2026-03-22T11:41:25.743801Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Шаг 2. Обработка пропусков в price и логарифмирование\nprice_median = train['price'].median()\ntrain['price'] = np.log1p(train['price'].fillna(price_median))\ntest['price'] = np.log1p(test['price'].fillna(price_median))\n\n# Шаг 3. Кодирование всех категориальных столбцов\ncat_columns = ['category_name', 'region', 'param_1', 'param_2', 'param_3']\nencoders = {}\n\nfor col in cat_columns:\n    # Объединяем train и test для единообразного кодирования\n    all_values = pd.concat([train[col], test[col]], axis=0).astype(str)\n    \n    # Создаём и обучаем энкодер\n    le = LabelEncoder()\n    le.fit(all_values)\n    encoders[col] = le\n    \n    # Применяем кодирование и добавляем суффикс '_encoded'\n    train[col + '_encoded'] = le.transform(train[col].astype(str))\n    test[col + '_encoded'] = le.transform(test[col].astype(str))\n\n# Шаг 4. Обработка пропусков в image_top_1\nimage_median = train['image_top_1'].median()\ntrain['image_top_1'] = train['image_top_1'].fillna(image_median)\ntest['image_top_1'] = test['image_top_1'].fillna(image_median)\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-22T11:41:28.837851Z","iopub.execute_input":"2026-03-22T11:41:28.838248Z","iopub.status.idle":"2026-03-22T11:41:32.709446Z","shell.execute_reply.started":"2026-03-22T11:41:28.838216Z","shell.execute_reply":"2026-03-22T11:41:32.707879Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Шаг 5. Выбор признаков (только закодированные и числовые столбцы)\nfeatures = [\n    'price',\n    'item_seq_number',\n    'category_name_encoded',\n    'region_encoded',\n    'param_1_encoded',\n    'param_2_encoded',\n    'param_3_encoded',\n    'image_top_1',\n    'Weekday',\n    'Dayofmonth',\n    'Weekofyear'\n]\n\n\nX_train = train[features]\ny_train = train['deal_probability']\n\n# Шаг 6. Разделение данных на обучение и валидацию\nX_train_split, X_val, y_train_split, y_val = train_test_split(\n    X_train, y_train, test_size=0.2, random_state=42\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-22T11:41:35.132586Z","iopub.execute_input":"2026-03-22T11:41:35.132979Z","iopub.status.idle":"2026-03-22T11:41:36.311859Z","shell.execute_reply.started":"2026-03-22T11:41:35.13295Z","shell.execute_reply":"2026-03-22T11:41:36.310294Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Шаг 7. Обучение моделей\n\n# 7.1 RandomForest (ваш исходный вариант)\nrf_model = RandomForestRegressor(\n    n_estimators=200,        # Было 50 → 200\n    max_depth=15,           # Было 10 → 15\n    min_samples_split=10,   # Было 5 → 10\n    min_samples_leaf=5,     # Добавляем минимальный размер листа\n    random_state=42,\n    n_jobs=-1\n)\n\nrf_model.fit(X_train_split, y_train_split)\n\n# RandomForest\nrf_pred_val = rf_model.predict(X_val)\nrf_mse = np.mean((y_val - rf_pred_val) ** 2)\nrf_rmse = np.sqrt(rf_mse)\nprint(f\"RMSE RandomForest на валидации: {rf_rmse:.4f}\")\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-22T11:41:40.279596Z","iopub.execute_input":"2026-03-22T11:41:40.280854Z","iopub.status.idle":"2026-03-22T11:50:34.459626Z","shell.execute_reply.started":"2026-03-22T11:41:40.280802Z","shell.execute_reply":"2026-03-22T11:50:34.458556Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 7.2 LightGBM\nlgb_train = lgb.Dataset(X_train_split, label=y_train_split)\nlgb_val = lgb.Dataset(X_val, label=y_val, reference=lgb_train)\n\nlgb_params = {\n    'objective': 'regression',\n    'metric': 'rmse',\n    'num_leaves': 270,           # Увеличиваем сложность дерева\n    'learning_rate': 0.0175,     # Уменьшаем скорость обучения\n    'feature_fraction': 0.5,    # Берём 50 % признаков на итерацию\n    'bagging_fraction': 0.75,   # Берём 75 % объектов на итерацию\n    'bagging_freq': 2,          # Частота бэггинга — каждые 2 итерации\n    'min_data_in_leaf': 100,   # Минимум объектов в листе\n    'max_depth': 15,          # Ограничиваем глубину\n    'verbose': 0,\n    'random_state': 42\n}\n\n\nlgb_model = lgb.train(\n    lgb_params,\n    lgb_train,\n    num_boost_round=1000,\n    valid_sets=[lgb_train, lgb_val],\n    valid_names=['train', 'valid']\n)\n\n# Оценка на валидации для LightGBM\nlgb_pred_val = lgb_model.predict(X_val, num_iteration=lgb_model.best_iteration)\nlgb_mse = np.mean((y_val - lgb_pred_val) ** 2)\nlgb_rmse = np.sqrt(lgb_mse)\nprint(f\"RMSE LightGBM на валидации: {lgb_rmse:.4f}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-22T11:51:01.607186Z","iopub.execute_input":"2026-03-22T11:51:01.607675Z","iopub.status.idle":"2026-03-22T11:53:11.384869Z","shell.execute_reply.started":"2026-03-22T11:51:01.60764Z","shell.execute_reply":"2026-03-22T11:53:11.384065Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 7.3 CatBoost\ncat_model = CatBoostRegressor(\n    iterations=2000,       # Было 1000 → 2000\n    learning_rate=0.03,    # Уменьшаем скорость обучения\n    depth=8,             # Увеличиваем глубину\n    l2_leaf_reg=3,      # Регуляризация\n    loss_function='RMSE',\n    verbose=100,\n    random_seed=42,\n    early_stopping_rounds=100  # Ранняя остановка при отсутствии улучшения\n)\n\ncat_model.fit(\n    X_train_split, y_train_split,\n    eval_set=(X_val, y_val),\n    verbose=False\n)\n# CatBoost\ncat_pred_val = cat_model.predict(X_val)\ncat_mse = np.mean((y_val - cat_pred_val) ** 2)\ncat_rmse = np.sqrt(cat_mse)\nprint(f\"RMSE CatBoost на валидации: {cat_rmse:.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-22T11:53:32.514491Z","iopub.execute_input":"2026-03-22T11:53:32.514909Z","iopub.status.idle":"2026-03-22T11:57:13.86355Z","shell.execute_reply.started":"2026-03-22T11:53:32.514877Z","shell.execute_reply":"2026-03-22T11:57:13.862479Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Шаг 9. Предсказание на тестовой выборке и создание сабмитов\nX_test = test[features]\n\n# RandomForest\nrf_pred = rf_model.predict(X_test)\nrf_pred = np.clip(rf_pred, 0, 1)\n\n# LightGBM\nlgb_pred = lgb_model.predict(X_test, num_iteration=lgb_model.best_iteration)\nlgb_pred = np.clip(lgb_pred, 0, 1)\n\n# CatBoost\ncat_pred = cat_model.predict(X_test)\ncat_pred = np.clip(cat_pred, 0, 1)\n\n# Создание отдельных сабмитов для каждой модели\nsubmission_rf = pd.DataFrame({\n    'item_id': test['item_id'],\n    'deal_probability': rf_pred\n})\nsubmission_rf.to_csv('submission_rf.csv', index=False)\nprint(\"Файл сабмита RandomForest сохранён: submission_rf.csv\")\n\nsubmission_lgb = pd.DataFrame({\n    'item_id': test['item_id'],\n    'deal_probability': lgb_pred\n})\nsubmission_lgb.to_csv('submission_lgb.csv', index=False)\nprint(\"Файл сабмита LightGBM сохранён: submission_lgb.csv\")\n\nsubmission_cat = pd.DataFrame({\n    'item_id': test['item_id'],\n    'deal_probability': cat_pred\n})\nsubmission_cat.to_csv('submission_cat.csv', index=False)\nprint(\"Файл сабмита CatBoost сохранён: submission_cat.csv\")\n\n# 1. Создаём мета-матрицу (features для Ridge) на валидационной выборке\nmeta_X_val = pd.DataFrame({\n    'rf_pred': rf_pred_val,\n    'lgb_pred': lgb_pred_val,\n    'cat_pred': cat_pred_val\n})\n\n# Целевая переменная для обучения Ridge\ny_val_ridge = y_val\n\n# 2. Обучаем Ridge (модель второго уровня)\nridge_model = Ridge(alpha=1.0)  # alpha — гиперпараметр регуляризации\nridge_model.fit(meta_X_val, y_val_ridge)\n\n# Выводим веса моделей\nprint(\"Веса моделей в стекинге (Ridge):\", ridge_model.coef_)\nprint(\"Свободный член (intercept):\", ridge_model.intercept_)\n\n# 3. Создаём мета-матрицу для теста\nmeta_X_test = pd.DataFrame({\n    'rf_pred': rf_pred,   # предсказания на тесте (уже есть у вас)\n    'lgb_pred': lgb_pred,\n    'cat_pred': cat_pred\n})\n\n# 4. Предсказываем финальный результат через Ridge\nstack_pred = ridge_model.predict(meta_X_test)\nstack_pred = np.clip(stack_pred, 0, 1)  # обрезка в диапазон [0, 1]\n\n# 5. Создаём сабмит для стекинга\nsubmission_stack = pd.DataFrame({\n    'item_id': test['item_id'],\n    'deal_probability': stack_pred\n})\nsubmission_stack.to_csv('submission.csv', index=False)\nprint(\"Файл сабмита стекинга (Ridge) сохранён: submission.csv\")\n\n# 6. Оцениваем RMSE стекинга на валидации\nstack_pred_val = ridge_model.predict(meta_X_val)\nstack_pred_val = np.clip(stack_pred_val, 0, 1)\nstack_mse = np.mean((y_val - stack_pred_val) ** 2)\nstack_rmse = np.sqrt(stack_mse)\nprint(f\"RMSE стекинга (Ridge) на валидации: {stack_rmse:.4f}\")\n\n# Обновляем вывод лучших результатов\nmodels_rmse = {\n    'RandomForest': rf_rmse,\n    'LightGBM': lgb_rmse,\n    'CatBoost': cat_rmse,\n    'Stacking (Ridge)': stack_rmse\n}\n\nbest_model = min(models_rmse, key=models_rmse.get)\nbest_rmse = models_rmse[best_model]\n\nprint(f\"\\nЛучшая модель: {best_model} с RMSE = {best_rmse:.4f}\")\nprint(\"Все файлы сабмитов созданы. Проверьте папки с результатами.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-03-22T12:04:48.676064Z","iopub.execute_input":"2026-03-22T12:04:48.676983Z","iopub.status.idle":"2026-03-22T12:05:37.407045Z","shell.execute_reply.started":"2026-03-22T12:04:48.676938Z","shell.execute_reply":"2026-03-22T12:05:37.404823Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}