{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":112509,"databundleVersionId":14254895,"sourceType":"competition"}],"dockerImageVersionId":31193,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"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-11-11T08:35:42.530714Z","iopub.execute_input":"2025-11-11T08:35:42.530963Z","iopub.status.idle":"2025-11-11T08:35:44.701085Z","shell.execute_reply.started":"2025-11-11T08:35:42.530939Z","shell.execute_reply":"2025-11-11T08:35:44.700308Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport pandas as pd\nimport numpy as np\nfrom tqdm import tqdm\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom sklearn.model_selection import train_test_split, KFold\nfrom sklearn.metrics import r2_score\n\nimport torch\nimport torch.nn as nn\nfrom torch.utils.data import Dataset, DataLoader\nimport torchvision\nfrom torchvision import transforms, models\nfrom PIL import Image\nimport warnings\nwarnings.filterwarnings(\"ignore\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-11T08:40:40.966550Z","iopub.execute_input":"2025-11-11T08:40:40.966896Z","iopub.status.idle":"2025-11-11T08:40:49.095491Z","shell.execute_reply.started":"2025-11-11T08:40:40.966872Z","shell.execute_reply":"2025-11-11T08:40:49.094957Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ==============================\n# 2️⃣ Load Dataset\n# ==============================\ntrain_csv = \"/kaggle/input/csiro-biomass/train.csv\"\ntest_csv = \"/kaggle/input/csiro-biomass/test.csv\"\nsample_submission_csv = \"/kaggle/input/csiro-biomass/sample_submission.csv\"\n\ntrain_df = pd.read_csv(train_csv)\ntest_df = pd.read_csv(test_csv)\nsample_submission = pd.read_csv(sample_submission_csv)\n\ntrain_img_dir = \"/kaggle/input/csiro-biomass/train\"\ntest_img_dir = \"/kaggle/input/csiro-biomass/test\"\n\nprint(\"Train shape:\", train_df.shape)\nprint(\"Test shape:\", test_df.shape)\ntrain_df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-11T08:42:28.342479Z","iopub.execute_input":"2025-11-11T08:42:28.343114Z","iopub.status.idle":"2025-11-11T08:42:28.395119Z","shell.execute_reply.started":"2025-11-11T08:42:28.343090Z","shell.execute_reply":"2025-11-11T08:42:28.394516Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ==============================\n# 3️⃣ Statistical overview\n# ==============================\n# Convert long format to wide format\ntrain_wide = train_df.pivot(index='image_path', columns='target_name', values='target').reset_index()\n\n# Optional: Rename columns for simplicity\ntrain_wide.columns.name = None  # remove the name 'target_name'\ntrain_wide.head()\n\n# Now you can do statistical overview\ntargets = [\"Dry_Green_g\", \"Dry_Dead_g\", \"Dry_Clover_g\", \"GDM_g\", \"Dry_Total_g\"]\ntrain_wide[targets].describe()\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-11T08:47:19.188539Z","iopub.execute_input":"2025-11-11T08:47:19.189268Z","iopub.status.idle":"2025-11-11T08:47:19.245574Z","shell.execute_reply.started":"2025-11-11T08:47:19.189241Z","shell.execute_reply":"2025-11-11T08:47:19.244665Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ==============================\n# 4️⃣ Visualize some images (fixed)\n# ==============================\ndef plot_sample_images(df, img_dir, n=6):\n    fig, axes = plt.subplots(1, n, figsize=(18, 6))\n    for i, ax in enumerate(axes):\n        # Use 'image_path' instead of 'image_id'\n        img_rel_path = df.iloc[i][\"image_path\"]  # e.g., \"train/ID1011485656.jpg\"\n        img_path = os.path.join(\"/kaggle/input/csiro-biomass\", img_rel_path)\n        img = Image.open(img_path)\n        ax.imshow(img)\n        ax.set_title(os.path.basename(img_rel_path))\n        ax.axis(\"off\")\n    plt.show()\n\n# Call the function\nplot_sample_images(train_df, \"/kaggle/input/csiro-biomass/train/\", n=6)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-11T08:50:51.260144Z","iopub.execute_input":"2025-11-11T08:50:51.260427Z","iopub.status.idle":"2025-11-11T08:50:52.883400Z","shell.execute_reply.started":"2025-11-11T08:50:51.260407Z","shell.execute_reply":"2025-11-11T08:50:52.882781Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#==============================\n# 5️⃣ Preprocess Images (Resize, Normalize, Augment)\n# ==============================\ntrain_transforms = transforms.Compose([\n    transforms.Resize((224,224)),\n    transforms.RandomHorizontalFlip(),\n    transforms.RandomVerticalFlip(),\n    transforms.ToTensor(),\n    transforms.Normalize([0.485,0.456,0.406], [0.229,0.224,0.225])\n])\n\ntest_transforms = transforms.Compose([\n    transforms.Resize((224,224)),\n    transforms.ToTensor(),\n    transforms.Normalize([0.485,0.456,0.406], [0.229,0.224,0.225])\n])\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-11T08:51:18.309402Z","iopub.execute_input":"2025-11-11T08:51:18.310124Z","iopub.status.idle":"2025-11-11T08:51:18.314970Z","shell.execute_reply.started":"2025-11-11T08:51:18.310100Z","shell.execute_reply":"2025-11-11T08:51:18.314361Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ==============================\n# 6️⃣ Custom Dataset\n# ==============================\nclass BiomassDataset(Dataset):\n    def __init__(self, df, img_dir, targets=None, transform=None):\n        self.df = df\n        self.img_dir = img_dir\n        self.targets = targets\n        self.transform = transform\n        \n    def __len__(self):\n        return len(self.df)\n    \n    def __getitem__(self, idx):\n        img_id = self.df.iloc[idx][\"image_id\"]\n        img_path = os.path.join(self.img_dir, img_id + \".jpg\")\n        image = Image.open(img_path).convert(\"RGB\")\n        if self.transform:\n            image = self.transform(image)\n        if self.targets:\n            target = self.df.iloc[idx][self.targets].values.astype(np.float32)\n            return image, torch.tensor(target)\n        else:\n            return image, img_id","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-11T08:51:41.363720Z","iopub.execute_input":"2025-11-11T08:51:41.363983Z","iopub.status.idle":"2025-11-11T08:51:41.369421Z","shell.execute_reply.started":"2025-11-11T08:51:41.363967Z","shell.execute_reply":"2025-11-11T08:51:41.368685Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ==============================\n# 7️⃣ DataLoader\n# ==============================\ntrain_dataset = BiomassDataset(train_df, train_img_dir, targets=targets, transform=train_transforms)\ntrain_loader = DataLoader(train_dataset, batch_size=16, shuffle=True, num_workers=2)\n\n# ==============================\n# 8️⃣ Define Model (Pretrained ResNet50)\n# ==============================\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\nmodel = models.resnet50(pretrained=True)\nnum_ftrs = model.fc.in_features\nmodel.fc = nn.Linear(num_ftrs, len(targets))\nmodel = model.to(device)\n\ncriterion = nn.MSELoss()\noptimizer = torch.optim.Adam(model.parameters(), lr=1e-4)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-11T08:52:00.229153Z","iopub.execute_input":"2025-11-11T08:52:00.229684Z","iopub.status.idle":"2025-11-11T08:52:01.662630Z","shell.execute_reply.started":"2025-11-11T08:52:00.229659Z","shell.execute_reply":"2025-11-11T08:52:01.662050Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class BiomassDataset(Dataset):\n    def __init__(self, df, img_dir, targets=None, transform=None):\n        self.df = df.reset_index(drop=True)\n        self.img_dir = img_dir\n        self.targets = targets\n        self.transform = transform\n        \n    def __len__(self):\n        return len(self.df)\n    \n    def __getitem__(self, idx):\n        # Use 'image_path' instead of 'image_id'\n        img_rel_path = self.df.iloc[idx][\"image_path\"]  # e.g., \"train/ID1011485656.jpg\"\n        img_path = os.path.join(\"/kaggle/input/csiro-biomass\", img_rel_path)\n        image = Image.open(img_path).convert(\"RGB\")\n        \n        if self.transform:\n            image = self.transform(image)\n        \n        if self.targets:  # training mode\n            # get target values from wide-format df\n            target = self.df.iloc[idx][self.targets].values.astype(np.float32)\n            return image, torch.tensor(target)\n        else:  # test mode\n            # return image and image id (for submission)\n            img_id = os.path.basename(img_rel_path).split(\".\")[0]\n            return image, img_id\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-11T08:54:16.040444Z","iopub.execute_input":"2025-11-11T08:54:16.040782Z","iopub.status.idle":"2025-11-11T08:54:16.049190Z","shell.execute_reply.started":"2025-11-11T08:54:16.040731Z","shell.execute_reply":"2025-11-11T08:54:16.048547Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 10️⃣ Predict on Test Set\n# ==============================\ntest_dataset = BiomassDataset(test_df, test_img_dir, targets=None, transform=test_transforms)\ntest_loader = DataLoader(test_dataset, batch_size=16, shuffle=False, num_workers=2)\n\nmodel.eval()\npreds = []\nids = []\n\nwith torch.no_grad():\n    for imgs, img_ids in tqdm(test_loader):\n        imgs = imgs.to(device)\n        outputs = model(imgs)\n        preds.append(outputs.cpu().numpy())\n        ids.extend(img_ids)\n\npreds = np.vstack(preds)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-11T08:54:57.738518Z","iopub.execute_input":"2025-11-11T08:54:57.738827Z","iopub.status.idle":"2025-11-11T08:54:59.019350Z","shell.execute_reply.started":"2025-11-11T08:54:57.738804Z","shell.execute_reply":"2025-11-11T08:54:59.018645Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ==============================\n# 11️⃣ Generate Submission CSV\n# ==============================\nsubmission_list = []\n\nfor i, img_id in enumerate(ids):\n    for j, target in enumerate(targets):\n        submission_list.append({\n            \"sample_id\": f\"{img_id}__{target}\",\n            \"target\": float(preds[i][j])\n        })\n\nsubmission_df = pd.DataFrame(submission_list)\nsubmission_df.to_csv(\"submission.csv\", index=False)\nsubmission_df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-11T08:55:17.436214Z","iopub.execute_input":"2025-11-11T08:55:17.436533Z","iopub.status.idle":"2025-11-11T08:55:17.459247Z","shell.execute_reply.started":"2025-11-11T08:55:17.436506Z","shell.execute_reply":"2025-11-11T08:55:17.458625Z"}},"outputs":[],"execution_count":null}]}