{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":112509,"databundleVersionId":14254895,"isSourceIdPinned":false,"sourceType":"competition"}],"dockerImageVersionId":31192,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# =============================\n# Kaggle-ready script using metadata + local evaluation\n# =============================\nimport pandas as pd\nimport numpy as np\nimport lightgbm as lgb\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import r2_score\n\n# -----------------------------\n# 1. Load data\n# -----------------------------\ntrain = pd.read_csv(\"/kaggle/input/csiro-biomass/train.csv\")\ntest = pd.read_csv(\"/kaggle/input/csiro-biomass/test.csv\")\n\n# -----------------------------\n# 2. Prepare metadata features\n# -----------------------------\ndef prepare_metadata(df, fit_mapping=None):\n    out = pd.DataFrame(index=df.index)\n    \n    # --- Date features ---\n    if \"Sampling_Date\" in df.columns:\n        dt = pd.to_datetime(df[\"Sampling_Date\"], errors=\"coerce\")\n        out[\"day\"] = dt.dt.day.fillna(-1)\n        out[\"month\"] = dt.dt.month.fillna(-1)\n        out[\"year\"] = dt.dt.year.fillna(-1)\n    else:\n        out[\"day\"] = -1\n        out[\"month\"] = -1\n        out[\"year\"] = -1\n    \n    # --- Numeric features ---\n    numeric = [\"Height_Ave_cm\", \"Pre_GSHH_NDVI\"]\n    for col in numeric:\n        if col in df.columns:\n            out[col] = df[col].fillna(0.0)\n        else:\n            out[col] = 0.0\n    \n    # --- Categorical features ---\n    categorical = [\"State\", \"Species\", \"target_name\"]\n    mapping = fit_mapping if fit_mapping is not None else {}\n    for col in categorical:\n        vals = df[col].fillna(\"NA\").astype(str) if col in df.columns else pd.Series(\"NA\", index=df.index)\n        if fit_mapping is None:\n            unique_vals = vals.unique().tolist()\n            col_map = {v: i for i, v in enumerate(unique_vals)}\n            mapping[col] = col_map\n        else:\n            col_map = mapping[col]\n        out[col] = vals.map(lambda x: col_map.get(x, len(col_map)))  # unseen -> new index\n    \n    return out, mapping\n\n# Prepare metadata for train & test\ntrain_meta, mappings = prepare_metadata(train)\ntest_meta, _ = prepare_metadata(test, fit_mapping=mappings)\n\nfeatures = train_meta.columns.tolist()\n\n# -----------------------------\n# 3. Define target weights (competition metric)\n# -----------------------------\nweights = {\n    \"Dry_Green_g\": 0.1,\n    \"Dry_Dead_g\": 0.1,\n    \"Dry_Clover_g\": 0.1,\n    \"GDM_g\": 0.2,\n    \"Dry_Total_g\": 0.5\n}\n\n# -----------------------------\n# 4. Train & evaluate locally\n# -----------------------------\npreds = []\nr2_scores = []\n\nfor target in weights.keys():\n    df_target = train[train[\"target_name\"] == target].copy()\n    X = train_meta.loc[df_target.index, features]\n    y = df_target[\"target\"]\n    \n    # Split train/validation\n    X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)\n    \n    # Train model\n    model = lgb.LGBMRegressor(\n        n_estimators=500,\n        learning_rate=0.05,\n        num_leaves=31,\n        random_state=42\n    )\n    model.fit(X_train, y_train)\n    \n    # Validate\n    y_pred_val = model.predict(X_val)\n    r2 = r2_score(y_val, y_pred_val)\n    r2_scores.append(r2)\n    print(f\"{target} R²: {r2:.4f}\")\n    \n    # Predict on test\n    df_test_target = test[test[\"target_name\"] == target].copy()\n    X_test = test_meta.loc[df_test_target.index, features]\n    df_test_target[\"target\"] = model.predict(X_test)\n    \n    preds.append(df_test_target[[\"sample_id\", \"target\"]])\n\n# -----------------------------\n# 5. Compute weighted R²\n# -----------------------------\nweighted_r2 = np.average(r2_scores, weights=[weights[t] for t in weights.keys()])\nprint(f\"Weighted R² (local validation): {weighted_r2:.4f}\")\n\n# -----------------------------\n# 6. Merge predictions and save\n# -----------------------------\nsubmission = pd.concat(preds)\nsubmission.to_csv(\"submission.csv\", index=False)\nprint(\"Saved submission.csv ✅\")\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-12-05T14:43:47.755683Z","iopub.execute_input":"2025-12-05T14:43:47.756074Z","iopub.status.idle":"2025-12-05T14:43:48.616978Z","shell.execute_reply.started":"2025-12-05T14:43:47.756047Z","shell.execute_reply":"2025-12-05T14:43:48.615841Z"}},"outputs":[],"execution_count":null}]}