{"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":"none","dataSources":[{"sourceId":112509,"databundleVersionId":14254895,"sourceType":"competition"}],"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-24T06:52:54.279054Z","iopub.execute_input":"2025-12-24T06:52:54.279325Z","iopub.status.idle":"2025-12-24T06:52:56.688798Z","shell.execute_reply.started":"2025-12-24T06:52:54.279294Z","shell.execute_reply":"2025-12-24T06:52:56.687735Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport gc\nimport cv2\nimport numpy as np\nimport pandas as pd\n\nfrom tqdm import tqdm\nfrom sklearn.model_selection import GroupKFold\nfrom sklearn.preprocessing import LabelEncoder\n\nimport torch\nimport torch.nn as nn\nfrom torchvision import models, transforms\n\nimport lightgbm as lgb","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T06:53:18.112120Z","iopub.execute_input":"2025-12-24T06:53:18.112450Z","iopub.status.idle":"2025-12-24T06:53:33.195365Z","shell.execute_reply.started":"2025-12-24T06:53:18.112426Z","shell.execute_reply":"2025-12-24T06:53:33.194635Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"DATA_DIR = r\"/kaggle/input/csiro-biomass\"\n\ntrain_df = pd.read_csv(os.path.join(DATA_DIR, \"train.csv\"))\ntest_df_raw = pd.read_csv(os.path.join(DATA_DIR, \"test.csv\"))\ntest_df = test_df_raw.copy()\n\n\nprint(train_df.shape, test_df.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T06:53:45.536228Z","iopub.execute_input":"2025-12-24T06:53:45.537742Z","iopub.status.idle":"2025-12-24T06:53:45.567033Z","shell.execute_reply.started":"2025-12-24T06:53:45.537675Z","shell.execute_reply":"2025-12-24T06:53:45.566025Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"TARGET_WEIGHTS = {\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[\"sample_weight\"] = train_df[\"target_name\"].map(TARGET_WEIGHTS)\n\ntrain_df[\"Sampling_Date\"] = pd.to_datetime(train_df[\"Sampling_Date\"])\ntrain_df[\"year\"] = train_df[\"Sampling_Date\"].dt.year\ntrain_df[\"month\"] = train_df[\"Sampling_Date\"].dt.month\n\ntest_df[\"year\"] = 0\ntest_df[\"month\"] = 0\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\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\n\ndevice = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n\ncnn = models.resnet50(weights=None)\ncnn.fc = nn.Identity()\ncnn = cnn.to(device).eval()\n\nimg_tfms = transforms.Compose([\n    transforms.ToPILImage(),\n    transforms.Resize((224, 224)),\n    transforms.ToTensor(),\n    transforms.Normalize(\n        mean=[0.485, 0.456, 0.406],\n        std=[0.229, 0.224, 0.225]\n    )\n])\n\ndef extract_image_features(image_paths):\n    features = {}\n\n    with torch.no_grad():\n        for img_path in tqdm(image_paths.unique()):\n            full_path = os.path.join(DATA_DIR, img_path)\n\n            img = cv2.imread(full_path)\n            img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n            img = img_tfms(img).unsqueeze(0).to(device)\n\n            feat = cnn(img).cpu().numpy().squeeze()\n            features[img_path] = feat\n\n    return features\n\ntrain_img_feats = extract_image_features(train_df[\"image_path\"])\ntest_img_feats  = extract_image_features(test_df[\"image_path\"])\n\ndef attach_features(df, feat_dict):\n    img_features = np.vstack(df[\"image_path\"].map(feat_dict))\n    img_features = pd.DataFrame(img_features, index=df.index)\n    return pd.concat([df.reset_index(drop=True), img_features], axis=1)\n\ntrain_df = attach_features(train_df, train_img_feats)\ntest_df  = attach_features(test_df, test_img_feats)\n\nTARGET = \"target\"\n\nDROP_COLS = [\"sample_id\", \"image_path\", \"Sampling_Date\", TARGET]\nFEATURES = [c for c in train_df.columns if c not in DROP_COLS]\n\nfor col in FEATURES:\n    if col not in test_df.columns:\n        if col == \"Pre_GSHH_NDVI\":\n            test_df[col] = train_df[col].median()\n        elif col == \"Height_Ave_cm\":\n            test_df[col] = train_df[col].median()\n        else:\n            test_df[col] = 0\n\ntest_df = test_df[FEATURES]\n\nX = train_df[FEATURES]\ny = train_df[TARGET]\nw = train_df[\"sample_weight\"]\n\nX_test = test_df\n\ndef weighted_r2(y_true, y_pred, w):\n    y_bar = np.average(y_true, weights=w)\n    ss_res = np.sum(w * (y_true - y_pred) ** 2)\n    ss_tot = np.sum(w * (y_true - y_bar) ** 2)\n    return 1 - ss_res / ss_tot\n\ngkf = GroupKFold(n_splits=5)\ngroups = train_df[\"image_path\"]\n\noof = np.zeros(len(train_df))\nmodels = []\n\nfor fold, (tr_idx, va_idx) in enumerate(gkf.split(X, y, groups)):\n    print(f\"\\nFold {fold + 1}\")\n\n    X_tr, X_va = X.iloc[tr_idx], X.iloc[va_idx]\n    y_tr, y_va = y.iloc[tr_idx], y.iloc[va_idx]\n    w_tr, w_va = w.iloc[tr_idx], w.iloc[va_idx]\n\n    model = lgb.LGBMRegressor(\n        n_estimators=1500,\n        learning_rate=0.03,\n        num_leaves=64,\n        subsample=0.8,\n        colsample_bytree=0.8,\n        random_state=42\n    )\n\n    model.fit(\n        X_tr, y_tr,\n        sample_weight=w_tr,\n        eval_set=[(X_va, y_va)],\n        eval_sample_weight=[w_va],\n        eval_metric=\"l2\",\n    )\n\n    oof[va_idx] = model.predict(X_va)\n    models.append(model)\n\n    print(\"Fold R²:\", weighted_r2(y_va, oof[va_idx], w_va))\n\nprint(\"\\nOverall CV R²:\", weighted_r2(y, oof, w))\n\ntest_preds = np.zeros(len(test_df))\n\nfor model in models:\n    test_preds += model.predict(X_test)\n\ntest_preds /= len(models)\n\nsubmission = test_df_raw[[\"sample_id\"]].copy()\nsubmission[\"target\"] = test_preds\n\nsubmission.to_csv(\"submission.csv\", index=False)\nprint(\"submission.csv saved successfully\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-24T06:54:15.378091Z","iopub.execute_input":"2025-12-24T06:54:15.378548Z","iopub.status.idle":"2025-12-24T07:16:32.737252Z","shell.execute_reply.started":"2025-12-24T06:54:15.378521Z","shell.execute_reply":"2025-12-24T07:16:32.736126Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}