{"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,"sourceType":"competition"},{"sourceId":698907,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":530200,"modelId":544144}],"dockerImageVersionId":31234,"isInternetEnabled":false,"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,"execution":{"iopub.status.busy":"2025-12-26T04:50:14.899100Z","iopub.execute_input":"2025-12-26T04:50:14.899485Z","iopub.status.idle":"2025-12-26T04:50:16.327563Z","shell.execute_reply.started":"2025-12-26T04:50:14.899456Z","shell.execute_reply":"2025-12-26T04:50:16.326138Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\n\nfrom sklearn.model_selection import GroupKFold\nfrom sklearn.preprocessing import LabelEncoder\nimport lightgbm as lgb","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-26T04:50:22.563580Z","iopub.execute_input":"2025-12-26T04:50:22.563932Z","iopub.status.idle":"2025-12-26T04:50:30.093541Z","shell.execute_reply.started":"2025-12-26T04:50:22.563907Z","shell.execute_reply":"2025-12-26T04:50:30.092413Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"DATA_DIR = r\"/kaggle/input/csiro-biomass\"\nEMB_DIR  = r\"/kaggle/input/dino/pytorch/default/1/dino_embeddings\"\n\ntrain_df = pd.read_csv(os.path.join(DATA_DIR, \"train.csv\"))\ntest_raw = pd.read_csv(os.path.join(DATA_DIR, \"test.csv\"))\ntest_df  = test_raw.copy()\n\ntrain_emb = np.load(os.path.join(EMB_DIR, \"train_embeddings.npy\"), allow_pickle=True).item()\ntest_emb  = np.load(os.path.join(EMB_DIR, \"test_embeddings.npy\"), allow_pickle=True).item()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-26T04:51:09.813340Z","iopub.execute_input":"2025-12-26T04:51:09.814409Z","iopub.status.idle":"2025-12-26T04:51:09.883046Z","shell.execute_reply.started":"2025-12-26T04:51:09.814372Z","shell.execute_reply":"2025-12-26T04:51:09.881691Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def attach_embeddings(df, emb_dict):\n    feats = np.vstack(df[\"image_path\"].map(emb_dict))\n    return pd.concat([df.reset_index(drop=True), pd.DataFrame(feats)], axis=1)\n\ntrain_df = attach_embeddings(train_df, train_emb)\ntest_df  = attach_embeddings(test_df, test_emb)\n\ntrain_df[\"Sampling_Date\"] = pd.to_datetime(train_df[\"Sampling_Date\"])\ntrain_df[\"month\"] = train_df[\"Sampling_Date\"].dt.month\ntest_df[\"month\"] = 0\n\ntarget_names = train_df[\"target_name\"].unique().tolist()\nTARGET2ID = {t: i for i, t in enumerate(target_names)}\nID2TARGET = {i: t for t, i in TARGET2ID.items()}\n\ncat_cols = [\"State\", \"Species\", \"target_name\"]\n\nfor col in cat_cols:\n    if col in train_df.columns and col in test_df.columns:\n        le = LabelEncoder()\n        le.fit(pd.concat([train_df[col], test_df[col]]))\n        train_df[col] = le.transform(train_df[col])\n        test_df[col]  = le.transform(test_df[col])\n    elif col in train_df.columns:\n        le = LabelEncoder()\n        le.fit(train_df[col])\n        train_df[col] = le.transform(train_df[col])\n        test_df[col] = -1\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\ntrain_df[\"w\"] = train_df[\"target_name\"].map(\n    {TARGET2ID[k]: v for k, v in WEIGHTS.items()}\n)\n\nEMB_COLS = [c for c in train_df.columns if isinstance(c, int)]\n\nDROP = [\"sample_id\", \"image_path\", \"Sampling_Date\", \"target\", \"w\"]\n\nFEATURES = EMB_COLS.copy()\nfor col in train_df.columns:\n    if col not in DROP and col in test_df.columns and col not in FEATURES:\n        FEATURES.append(col)\n\nX = train_df[FEATURES]\ny = train_df[\"target\"]\nw = train_df[\"w\"]\n\nX_test = test_df[FEATURES]\n\ngkf = GroupKFold(n_splits=5)\ngroups = train_df[\"image_path\"]\n\nmodels = []\nfor tr, va in gkf.split(X, y, groups):\n    model = lgb.LGBMRegressor(\n        n_estimators=2500,\n        learning_rate=0.02,\n        num_leaves=128,\n        subsample=0.8,\n        colsample_bytree=0.8,\n        random_state=42\n    )\n    model.fit(X.iloc[tr], y.iloc[tr], sample_weight=w.iloc[tr])\n    models.append(model)\n\npred = np.zeros(len(test_df))\nfor m in models:\n    pred += m.predict(X_test)\npred /= len(models)\n\ntest_df[\"pred\"] = pred\n\npivot = test_df.pivot(\n    index=\"image_path\",\n    columns=\"target_name\",\n    values=\"pred\"\n)\n\nID_DRY_TOTAL  = TARGET2ID[\"Dry_Total_g\"]\nID_DRY_GREEN  = TARGET2ID[\"Dry_Green_g\"]\nID_DRY_DEAD   = TARGET2ID[\"Dry_Dead_g\"]\nID_DRY_CLOVER = TARGET2ID[\"Dry_Clover_g\"]\n\npivot[ID_DRY_TOTAL] = np.maximum(\n    pivot[ID_DRY_TOTAL],\n    pivot[ID_DRY_GREEN] + pivot[ID_DRY_DEAD] + pivot[ID_DRY_CLOVER]\n)\n\ntest_df = test_df.merge(\n    pivot[ID_DRY_TOTAL],\n    left_on=\"image_path\",\n    right_index=True,\n    suffixes=(\"\", \"_fix\")\n)\n\nmask = test_df[\"target_name\"] == ID_DRY_TOTAL\ntest_df.loc[mask, \"pred\"] = test_df.loc[mask, f\"{ID_DRY_TOTAL}_fix\"]\n\nsubmission = test_raw[[\"sample_id\"]].copy()\nsubmission[\"target\"] = test_df[\"pred\"].values\nsubmission.to_csv(\"submission.csv\", index=False)\n\nprint(submission.head())\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-26T04:52:06.876786Z","iopub.execute_input":"2025-12-26T04:52:06.877159Z","iopub.status.idle":"2025-12-26T04:59:24.608733Z","shell.execute_reply.started":"2025-12-26T04:52:06.877135Z","shell.execute_reply":"2025-12-26T04:59:24.607693Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}