{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":104857,"databundleVersionId":12651513,"sourceType":"competition"}],"dockerImageVersionId":31040,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\nfrom catboost import CatBoostRegressor, Pool\nfrom sklearn.model_selection import KFold\nfrom sklearn.metrics import mean_squared_error","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-14T04:59:45.030911Z","iopub.execute_input":"2025-06-14T04:59:45.031381Z","iopub.status.idle":"2025-06-14T04:59:45.036192Z","shell.execute_reply.started":"2025-06-14T04:59:45.031357Z","shell.execute_reply":"2025-06-14T04:59:45.035427Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# =============================================================\n# Pure XGBoost lap‑time predictor (single split, early stopping)\n# =============================================================\n!pip install --quiet xgboost==2.0.3 pandas==2.2.2\n\nimport pandas as pd, numpy as np, os, xgboost as xgb, time, gc\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import mean_squared_error\n\n# ── 1.  Paths & column names ─────────────────────────────────\nDATA_DIR = \"/kaggle/input/burnout-datathon-ieeecsmuj\"   \nTARGET   = \"Lap_Time_Seconds\"                # ⬅️ lap‑time column\nID_COL   = \"Unique ID\"                       # ⬅️ ID column for submission\n\ntrain_df = pd.read_csv(os.path.join(DATA_DIR, \"train.csv\"))\ntest_df  = pd.read_csv(os.path.join(DATA_DIR, \"test.csv\"))\nprint(\"Train shape:\", train_df.shape, \"  Test shape:\", test_df.shape)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-14T08:46:18.697957Z","iopub.execute_input":"2025-06-14T08:46:18.698356Z","iopub.status.idle":"2025-06-14T08:46:46.503226Z","shell.execute_reply.started":"2025-06-14T08:46:18.698324Z","shell.execute_reply":"2025-06-14T08:46:46.502108Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ── 2.  Minimal feature engineering (checks each column) ────\ndef add_features(df):\n    if {\"Circuit_Length_km\", \"Avg_Speed_kmh\"}.issubset(df.columns):\n        df[\"secs_per_km\"] = (df[\"Circuit_Length_km\"] / df[\"Avg_Speed_kmh\"]) * 3600\n    if {\"Track_Temperature_Celsius\", \"Ambient_Temperature_Celsius\"}.issubset(df.columns):\n        df[\"track_minus_air\"] = df[\"Track_Temperature_Celsius\"] - df[\"Ambient_Temperature_Celsius\"]\n    if \"Track_Condition\" in df.columns:\n        df[\"is_wet\"] = df[\"Track_Condition\"].str.contains(\"Wet\", case=False, na=False).astype(int)\n    if {\"Tire_Compound_Front\", \"Tire_Compound_Rear\"}.issubset(df.columns):\n        df[\"tire_combo\"] = df[\"Tire_Compound_Front\"].fillna(\"\") + \"_\" + df[\"Tire_Compound_Rear\"].fillna(\"\")\n    return df\n\ntrain_df = add_features(train_df);  test_df = add_features(test_df)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-14T08:47:17.759703Z","iopub.execute_input":"2025-06-14T08:47:17.762032Z","iopub.status.idle":"2025-06-14T08:47:20.363442Z","shell.execute_reply.started":"2025-06-14T08:47:17.761977Z","shell.execute_reply":"2025-06-14T08:47:20.362467Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ── 3.  Convert position numeric → categorical string (if present) ──\nif \"position\" in train_df.columns:\n    train_df[\"Position_cat\"] = train_df[\"position\"].astype(str)\n    test_df[\"Position_cat\"]  = test_df[\"position\"].astype(str)\n    train_df.drop(columns=[\"position\"], inplace=True)\n    test_df.drop(columns=[\"position\"],  inplace=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-14T08:48:46.885702Z","iopub.execute_input":"2025-06-14T08:48:46.886298Z","iopub.status.idle":"2025-06-14T08:48:48.581109Z","shell.execute_reply.started":"2025-06-14T08:48:46.886173Z","shell.execute_reply":"2025-06-14T08:48:48.580155Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ── 4.  Identify categorical & numeric columns robustly ──────\ncat_cols = [c for c in train_df.columns\n            if train_df[c].dtype == \"object\" or train_df[c].dtype.name == \"category\"]\nnum_cols = [c for c in train_df.columns if c not in cat_cols + [TARGET]]\n\n# Keep only cats present in both frames\ncat_cols = [c for c in cat_cols if c in test_df.columns]\n\n# Fill NaNs\ntrain_df[cat_cols] = train_df[cat_cols].fillna(\"missing\")\ntest_df[cat_cols]  = test_df[cat_cols].fillna(\"missing\")\nfor col in num_cols:\n    med = train_df[col].median()\n    train_df[col].fillna(med, inplace=True)\n    test_df[col].fillna(med,  inplace=True)\n\n# Cast categorical dtype for XGB native cats\nfor c in cat_cols:\n    train_df[c] = train_df[c].astype(\"category\")\n    test_df[c]  = test_df[c].astype(\"category\")\n\nfeature_cols = cat_cols + num_cols\nprint(f\"Using {len(feature_cols)} features ({len(cat_cols)} categorical).\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-14T08:49:02.547047Z","iopub.execute_input":"2025-06-14T08:49:02.547397Z","iopub.status.idle":"2025-06-14T08:49:11.899774Z","shell.execute_reply.started":"2025-06-14T08:49:02.547373Z","shell.execute_reply":"2025-06-14T08:49:11.898775Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ── 5.  Train‑validation split ───────────────────────────────\nX_train, X_val, y_train, y_val = train_test_split(\n    train_df[feature_cols], train_df[TARGET],\n    test_size=0.2, random_state=42\n)\n\ndtrain = xgb.DMatrix(X_train, label=y_train, enable_categorical=True)\ndval   = xgb.DMatrix(X_val,   label=y_val,   enable_categorical=True)\ndtest  = xgb.DMatrix(test_df[feature_cols], enable_categorical=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-14T08:49:18.163760Z","iopub.execute_input":"2025-06-14T08:49:18.164081Z","iopub.status.idle":"2025-06-14T08:49:22.336576Z","shell.execute_reply.started":"2025-06-14T08:49:18.164057Z","shell.execute_reply":"2025-06-14T08:49:22.335911Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ── 6.  XGBoost parameters & training ────────────────────────\nparams = {\n    \"objective\": \"reg:squarederror\",\n    \"eval_metric\": \"rmse\",\n    \"learning_rate\": 0.05,\n    \"max_depth\": 8,\n    \"subsample\": 0.8,\n    \"colsample_bytree\": 0.8,\n    \"min_child_weight\": 10,\n    \"lambda\": 3.0,\n    \"tree_method\": \"hist\",          # ➡ “gpu_hist” if you enabled GPU runtime\n    \"enable_categorical\": True,\n    \"seed\": 42,\n}\n\nstart = time.time()\nmodel = xgb.train(\n    params,\n    dtrain,\n    num_boost_round=5000,\n    evals=[(dval, \"val\")],\n    early_stopping_rounds=200,\n    verbose_eval=250\n)\nprint(f\"⏱️  Training time: {time.time()-start:.1f} s\")\nprint(\"🔎 Best iteration:\", model.best_iteration)\nprint(\"🏁 Best val RMSE:\", model.best_score)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-14T08:49:41.873144Z","iopub.execute_input":"2025-06-14T08:49:41.873521Z","iopub.status.idle":"2025-06-14T09:23:57.598562Z","shell.execute_reply.started":"2025-06-14T08:49:41.873499Z","shell.execute_reply":"2025-06-14T09:23:57.596780Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ── 7.  Predict on test & create submission ──────────────────\ntest_preds = model.predict(dtest, iteration_range=(0, model.best_iteration + 1))\nsubmission = pd.DataFrame({ID_COL: test_df[ID_COL], TARGET: test_preds})\nsubmission.to_csv(\"submission_xgb.csv\", index=False)\nprint(\"✅ submission_xgb.csv saved:\", submission.shape)\nsubmission.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-14T09:24:34.430216Z","iopub.execute_input":"2025-06-14T09:24:34.430588Z","iopub.status.idle":"2025-06-14T09:27:00.795464Z","shell.execute_reply.started":"2025-06-14T09:24:34.430563Z","shell.execute_reply":"2025-06-14T09:27:00.794617Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nprint(\"Files in /kaggle/working/:\", os.listdir(\"/kaggle/working/\"))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-14T09:34:13.092877Z","iopub.execute_input":"2025-06-14T09:34:13.093488Z","iopub.status.idle":"2025-06-14T09:34:13.099427Z","shell.execute_reply.started":"2025-06-14T09:34:13.093458Z","shell.execute_reply":"2025-06-14T09:34:13.098670Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\n# List all files in the current directory\nprint(\"Files in working directory:\", os.listdir())\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-14T09:34:36.079336Z","iopub.execute_input":"2025-06-14T09:34:36.080391Z","iopub.status.idle":"2025-06-14T09:34:36.084920Z","shell.execute_reply.started":"2025-06-14T09:34:36.080362Z","shell.execute_reply":"2025-06-14T09:34:36.083987Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\n# Rename the file from old name to new name\nos.rename(\"submission_xgb.csv\", \"solution.csv\")\n\n# Check to confirm\nprint(\"✅ Renamed file:\")\nprint(os.listdir(\"/kaggle/working/\"))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-14T09:35:20.236382Z","iopub.execute_input":"2025-06-14T09:35:20.236718Z","iopub.status.idle":"2025-06-14T09:35:20.242993Z","shell.execute_reply.started":"2025-06-14T09:35:20.236692Z","shell.execute_reply":"2025-06-14T09:35:20.241503Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}