{"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":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# 1. Setup & Imports\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport gc\n\nfrom sklearn.model_selection import KFold\nfrom sklearn.impute import SimpleImputer\nfrom sklearn.metrics import mean_squared_error\nimport lightgbm as lgb\nimport shap\nfrom lightgbm import early_stopping\n\n# 2. Load Data\ntrain = pd.read_csv('/kaggle/input/burnout-datathon-ieeecsmuj/train.csv', engine='python')\ntest = pd.read_csv('/kaggle/input/burnout-datathon-ieeecsmuj/test.csv', engine='python')\nsub = pd.read_csv('/kaggle/input/burnout-datathon-ieeecsmuj/sample_submission.csv', engine='python')\n\n# 🧽 Clean Column Names\ntrain.columns = train.columns.str.strip().str.lower().str.replace(\" \", \"_\")\ntest.columns = test.columns.str.strip().str.lower().str.replace(\" \", \"_\")\n\n# ✅ Define target\ntarget = 'lap_time_seconds'\n\n# 3. EDA\nsns.histplot(train[target], kde=True)\nplt.title(\"Lap Time Distribution\")\nplt.show()\n\n# 4. Preprocessing\ndata = pd.concat([train.drop(columns=[target]), test], sort=False)\n\nnumeric = data.select_dtypes(include=['int64', 'float64']).columns.tolist()\ncat = data.select_dtypes(include=['object']).columns.tolist()\n\n# Impute missing values\nimp_num = SimpleImputer(strategy='median')\ndata[numeric] = imp_num.fit_transform(data[numeric])\n\nimp_cat = SimpleImputer(strategy='most_frequent')\ndata[cat] = imp_cat.fit_transform(data[cat])\n\n# Convert numeric to float32 to save memory\nfor col in numeric:\n    data[col] = data[col].astype(np.float32)\n\n# Convert categoricals to category dtype\nfor col in cat:\n    data[col] = data[col].astype('category')\n\n# Final feature set\nfeatures = numeric + cat\n\n# Split back to train/test\nX_train = data.iloc[:len(train)][features]\ny_train = train[target]\nX_test = data.iloc[len(train):][features]\n\n# 5. Modeling with KFold\noof = np.zeros(len(X_train))\npreds = np.zeros(len(X_test))\n\nkf = KFold(n_splits=3, shuffle=True, random_state=42)\n\nfor fold, (train_idx, val_idx) in enumerate(kf.split(X_train)):\n    print(f\"🔥 Fold {fold+1}\")\n    \n    X_tr, X_v = X_train.iloc[train_idx], X_train.iloc[val_idx]\n    y_tr, y_v = y_train.iloc[train_idx], y_train.iloc[val_idx]\n\n    model = lgb.LGBMRegressor(\n        n_estimators=1000,\n        learning_rate=0.05,\n        random_state=42,\n        n_jobs=-1\n    )\n    \n    model.fit(\n    X_tr, y_tr,\n    eval_set=[(X_v, y_v)],\n    eval_metric='rmse',\n    callbacks=[early_stopping(50)],\n    categorical_feature=cat,\n)\n\n    \n    oof[val_idx] = model.predict(X_v)\n    preds += model.predict(X_test) / kf.n_splits\n    \n    # Free up memory\n    del X_tr, X_v, y_tr, y_v\n    gc.collect()\n\nprint('✅ OOF RMSE:', np.sqrt(mean_squared_error(y_train, oof)))\n\n# 6. Feature Importance / SHAP (Optional on Sample)\nprint(\"🔍 Generating SHAP values on a sample\")\nsample_X = X_train.sample(1000, random_state=42)\nexplainer = shap.Explainer(model)\nshap_values = explainer(sample_X)\nshap.summary_plot(shap_values, sample_X, show=False)\nplt.tight_layout()\nplt.savefig('shap_summary.png')\nplt.close()\n\n# 7. Submission\nsub['lap_time_seconds'] = preds\nsub.to_csv('submission.csv', index=False)\nprint(\"🚀 Submission ready! Lap time predicted like a boss.\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-14T12:48:02.658598Z","iopub.execute_input":"2025-06-14T12:48:02.659275Z","iopub.status.idle":"2025-06-14T12:58:06.483704Z","shell.execute_reply.started":"2025-06-14T12:48:02.659237Z","shell.execute_reply":"2025-06-14T12:58:06.482764Z"}},"outputs":[],"execution_count":null}]}