{"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":"gpu","dataSources":[{"sourceType":"competition","sourceId":130062,"databundleVersionId":15606741}],"dockerImageVersionId":31287,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd \nimport numpy as np \nimport matplotlib.pyplot as plt \nimport seaborn as sns\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-02-22T08:58:46.220526Z","iopub.execute_input":"2026-02-22T08:58:46.221290Z","iopub.status.idle":"2026-02-22T08:58:47.364598Z","shell.execute_reply.started":"2026-02-22T08:58:46.221253Z","shell.execute_reply":"2026-02-22T08:58:47.364013Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"raw_train = pd.read_csv(\"/kaggle/input/bidding-predictions-for-construction/raw_train.csv\")\nraw_train.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-22T08:59:07.600055Z","iopub.execute_input":"2026-02-22T08:59:07.600762Z","iopub.status.idle":"2026-02-22T08:59:09.407239Z","shell.execute_reply.started":"2026-02-22T08:59:07.600737Z","shell.execute_reply":"2026-02-22T08:59:09.406646Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"raw_test = pd.read_csv('/kaggle/input/bidding-predictions-for-construction/raw_test.csv')\nraw_test.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-22T08:58:50.331386Z","iopub.execute_input":"2026-02-22T08:58:50.331742Z","iopub.status.idle":"2026-02-22T08:58:50.694879Z","shell.execute_reply.started":"2026-02-22T08:58:50.331696Z","shell.execute_reply":"2026-02-22T08:58:50.694140Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sample_submission = pd.read_csv(\"/kaggle/input/bidding-predictions-for-construction/sample_submission.csv\")\nsample_submission.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-22T08:58:50.696277Z","iopub.execute_input":"2026-02-22T08:58:50.696513Z","iopub.status.idle":"2026-02-22T08:58:50.711688Z","shell.execute_reply.started":"2026-02-22T08:58:50.696491Z","shell.execute_reply":"2026-02-22T08:58:50.710997Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_summery = pd.read_csv(\"/kaggle/input/bidding-predictions-for-construction/train_summary.csv\")\ntrain_summery.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-22T08:58:50.712468Z","iopub.execute_input":"2026-02-22T08:58:50.712733Z","iopub.status.idle":"2026-02-22T08:58:50.749230Z","shell.execute_reply.started":"2026-02-22T08:58:50.712687Z","shell.execute_reply":"2026-02-22T08:58:50.748634Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test = pd.read_csv(\"/kaggle/input/bidding-predictions-for-construction/test.csv\")\ntest.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-22T08:58:50.750022Z","iopub.execute_input":"2026-02-22T08:58:50.750252Z","iopub.status.idle":"2026-02-22T08:58:50.765752Z","shell.execute_reply.started":"2026-02-22T08:58:50.750233Z","shell.execute_reply":"2026-02-22T08:58:50.765221Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Data \n* Raw train = data for training.\n* train summery = simple summery of the train data. \n* row test = data for testing our model.\n* sample = sample of submission.\n* test = main data in which we have to make prediction. ","metadata":{}},{"cell_type":"code","source":"raw_train.info()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-22T08:59:12.358979Z","iopub.execute_input":"2026-02-22T08:59:12.359568Z","iopub.status.idle":"2026-02-22T08:59:12.730779Z","shell.execute_reply.started":"2026-02-22T08:59:12.359543Z","shell.execute_reply":"2026-02-22T08:59:12.730131Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport lightgbm as lgb\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.preprocessing import LabelEncoder\nfrom sklearn.metrics import mean_squared_error, r2_score\nfrom sklearn.pipeline import Pipeline\nfrom sklearn.compose import ColumnTransformer\nfrom sklearn.preprocessing import OrdinalEncoder, StandardScaler\nimport joblib\nimport warnings\nwarnings.filterwarnings('ignore')\n\n# Load data (update paths)\ntrain = raw_train\nprint(train.shape, train.head())\nprint(\"Target: total_bid stats\\n\", train['total_bid'].describe())\n\n# Features & target\ntarget = 'total_bid'\nnum_cols = ['quantity', 'amount', 'num_pay_items', 'category_id']\ncat_cols = ['job_category_description', 'bid_date', 'pay_item_description', \n            'unit_english_id', 'category_description', 'job_id', 'contractor_id', \n            'primary_location', 'pay_item_id']  # High-cardinality: encode\n\n# Preprocess\nle_dict = {}\nfor col in cat_cols:\n    le = LabelEncoder()\n    train[col] = train[col].astype(str)\n    train[col] = le.fit_transform(train[col])\n    le_dict[col] = le\n\nX = train.drop([target, 'row_id'], axis=1)\ny = train[target]\n\nprint(\"X shape:\", X.shape)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-22T09:06:46.722641Z","iopub.execute_input":"2026-02-22T09:06:46.723198Z","iopub.status.idle":"2026-02-22T09:06:47.932349Z","shell.execute_reply.started":"2026-02-22T09:06:46.723173Z","shell.execute_reply":"2026-02-22T09:06:47.931750Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)\n\n# LightGBM Regressor (best for large tabular regression)\nmodel = lgb.LGBMRegressor(\n    n_estimators=1000,\n    learning_rate=0.05,\n    max_depth=6,\n    num_leaves=32,\n    subsample=0.8,\n    colsample_bytree=0.8,\n    random_state=42,\n    verbose=-1,\n    device='gpu' if lgb.__version__ else 'cpu'  # GPU if available\n)\n\nmodel.fit(X_train, y_train, eval_set=[(X_val, y_val)], callbacks=[lgb.early_stopping(50)])\n\n# Save model\njoblib.dump(model, 'best_model.pkl')\nprint(\"✅ Model trained & saved!\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-22T09:08:02.181122Z","iopub.execute_input":"2026-02-22T09:08:02.181618Z","iopub.status.idle":"2026-02-22T09:08:22.351266Z","shell.execute_reply.started":"2026-02-22T09:08:02.181591Z","shell.execute_reply":"2026-02-22T09:08:22.350515Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Predictions & metrics\ntrain_preds = model.predict(X_train)\nval_preds = model.predict(X_val)\n\ntrain_rmse = np.sqrt(mean_squared_error(y_train, train_preds))\nval_rmse = np.sqrt(mean_squared_error(y_val, val_preds))\ntrain_r2 = r2_score(y_train, train_preds)\nval_r2 = r2_score(y_val, val_preds)\n\nprint(f\"Train RMSE: {train_rmse:.2f} | R²: {train_r2:.4f}\")\nprint(f\"Val RMSE: {val_rmse:.2f} | R²: {val_r2:.4f}\")\n\nimport matplotlib.pyplot as plt\nplt.scatter(y_val, val_preds, alpha=0.5)\nplt.plot([y_val.min(), y_val.max()], [y_val.min(), y_val.max()], 'r--')\nplt.xlabel('True total_bid'); plt.ylabel('Predicted')\nplt.title('Validation Predictions')\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-22T09:08:41.967128Z","iopub.execute_input":"2026-02-22T09:08:41.967419Z","iopub.status.idle":"2026-02-22T09:09:18.709919Z","shell.execute_reply.started":"2026-02-22T09:08:41.967395Z","shell.execute_reply":"2026-02-22T09:09:18.709239Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"lgb.plot_importance(model, max_num_features=10, figsize=(10,6))\nplt.title('Top Features for total_bid Prediction')\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-22T09:09:51.729730Z","iopub.execute_input":"2026-02-22T09:09:51.730037Z","iopub.status.idle":"2026-02-22T09:09:51.890588Z","shell.execute_reply.started":"2026-02-22T09:09:51.730014Z","shell.execute_reply":"2026-02-22T09:09:51.889874Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport os\n\n# Load test\ntest = pd.read_csv('/kaggle/input/bidding-predictions-for-construction/test.csv')\ntest_ids = test['row_id']\nprint(\"Test columns:\", test.columns.tolist())\n\n# CRITICAL: Get EXACT training feature names & order\ntrain_feature_names = X.columns.tolist()  # From Cell 1 where X was created\nprint(\"Training features (13):\", train_feature_names)\n\n# Create full feature matrix matching training\nX_test_full = pd.DataFrame(index=test.index, columns=train_feature_names, dtype='float32')\n\n# Fill test columns that exist\ntest_cols = ['job_id', 'contractor_id', 'bid_date', 'primary_location', 'job_category_description']\nfor col in test_cols:\n    if col in test.columns and col in train_feature_names:\n        test[col] = test[col].astype(str)\n        train_labels = le_dict[col].classes_\n        label_map = {lbl: idx for idx, lbl in enumerate(train_labels)}\n        X_test_full[col] = test[col].map(label_map).fillna(-1).astype('int32')\n\n# Fill MISSING numerical features with 0 (most common fix)\nmissing_num_cols = ['quantity', 'amount', 'num_pay_items', 'category_id', 'pay_item_description', \n                   'unit_english_id', 'category_description', 'pay_item_id']\nfor col in missing_num_cols:\n    if col in train_feature_names:\n        X_test_full[col] = 0  # or train[col].median()\n\nprint(\"✅ X_test_full shape matches training:\", X_test_full.shape)\nprint(\"All features present:\", set(train_feature_names) == set(X_test_full.columns))\n\n# Predict - NOW WORKS!\ntest_preds = model.predict(X_test_full)\ntest_preds = np.clip(test_preds, 0, None)\n\n# Submission\nsubmission = pd.DataFrame({'row_id': test_ids, 'total_bid': test_preds})\nsubmission.to_csv('submission.csv', index=False)\n\nprint(\"\\n🎉 SUCCESS! Submission ready!\")\nprint(\"Shape:\", submission.shape)\nprint(submission.head())\nprint(f\"Preds: mean={test_preds.mean():.1f}, std={test_preds.std():.1f}\")\nprint(\"Files:\", [f for f in os.listdir('.') if f.endswith('.csv')])\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-22T09:14:48.963986Z","iopub.execute_input":"2026-02-22T09:14:48.964291Z","iopub.status.idle":"2026-02-22T09:14:49.054034Z","shell.execute_reply.started":"2026-02-22T09:14:48.964268Z","shell.execute_reply":"2026-02-22T09:14:49.053257Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}