{"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"}],"dockerImageVersionId":31239,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\n\nprint(os.listdir(\"/kaggle/input\"))\nprint(os.listdir(\"/kaggle/working\"))\nos.listdir(\"/kaggle/input/csiro-biomass\")\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T11:55:13.632786Z","iopub.execute_input":"2025-12-20T11:55:13.633191Z","iopub.status.idle":"2025-12-20T11:55:13.647285Z","shell.execute_reply.started":"2025-12-20T11:55:13.633156Z","shell.execute_reply":"2025-12-20T11:55:13.645868Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\n\nfile_path = \"/kaggle/input/csiro-biomass/train.csv\"\ntrain_df = pd.read_csv(file_path)\ntrain_df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T11:55:42.760407Z","iopub.execute_input":"2025-12-20T11:55:42.761555Z","iopub.status.idle":"2025-12-20T11:55:43.092820Z","shell.execute_reply.started":"2025-12-20T11:55:42.761469Z","shell.execute_reply":"2025-12-20T11:55:43.091759Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T11:55:52.081927Z","iopub.execute_input":"2025-12-20T11:55:52.082163Z","iopub.status.idle":"2025-12-20T11:55:52.088428Z","shell.execute_reply.started":"2025-12-20T11:55:52.082146Z","shell.execute_reply":"2025-12-20T11:55:52.087064Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df.columns","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T11:55:59.233876Z","iopub.execute_input":"2025-12-20T11:55:59.234210Z","iopub.status.idle":"2025-12-20T11:55:59.244634Z","shell.execute_reply.started":"2025-12-20T11:55:59.234190Z","shell.execute_reply":"2025-12-20T11:55:59.242893Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df['target_name'].unique()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T11:56:08.099757Z","iopub.execute_input":"2025-12-20T11:56:08.100007Z","iopub.status.idle":"2025-12-20T11:56:08.112873Z","shell.execute_reply.started":"2025-12-20T11:56:08.099991Z","shell.execute_reply":"2025-12-20T11:56:08.111610Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df[\"image_id\"] = train_df[\"sample_id\"].str.split(\"__\").str[0]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T11:56:15.176669Z","iopub.execute_input":"2025-12-20T11:56:15.177033Z","iopub.status.idle":"2025-12-20T11:56:15.187010Z","shell.execute_reply.started":"2025-12-20T11:56:15.177008Z","shell.execute_reply":"2025-12-20T11:56:15.185894Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"image_counts = train_df[\"image_id\"].value_counts()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T11:56:25.013038Z","iopub.execute_input":"2025-12-20T11:56:25.013416Z","iopub.status.idle":"2025-12-20T11:56:25.023795Z","shell.execute_reply.started":"2025-12-20T11:56:25.013386Z","shell.execute_reply":"2025-12-20T11:56:25.021793Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Targets per image (should be 5):\")\nprint(image_counts.head())\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T11:56:33.035597Z","iopub.execute_input":"2025-12-20T11:56:33.035920Z","iopub.status.idle":"2025-12-20T11:56:33.042345Z","shell.execute_reply.started":"2025-12-20T11:56:33.035901Z","shell.execute_reply":"2025-12-20T11:56:33.041384Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"\\nAll images have 5 targets?\",\n      (image_counts == 5).all())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T11:56:43.942855Z","iopub.execute_input":"2025-12-20T11:56:43.943181Z","iopub.status.idle":"2025-12-20T11:56:43.950366Z","shell.execute_reply.started":"2025-12-20T11:56:43.943155Z","shell.execute_reply":"2025-12-20T11:56:43.949275Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Pivot long - format data to image level format\ntrain_pivot = train_df.pivot(\n    index = 'image_id',\n    columns = 'target_name',\n    values = 'target'\n).reset_index()\n\nprint(\"Shape after pivot :\",train_pivot.shape)\nprint(\"\\nColumns\")\nprint(train_pivot.columns)\n\nprint(train_pivot.head())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T11:56:50.651987Z","iopub.execute_input":"2025-12-20T11:56:50.652338Z","iopub.status.idle":"2025-12-20T11:56:50.687161Z","shell.execute_reply.started":"2025-12-20T11:56:50.652320Z","shell.execute_reply":"2025-12-20T11:56:50.685055Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_pivot.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T11:57:04.253098Z","iopub.execute_input":"2025-12-20T11:57:04.253890Z","iopub.status.idle":"2025-12-20T11:57:04.259686Z","shell.execute_reply.started":"2025-12-20T11:57:04.253862Z","shell.execute_reply":"2025-12-20T11:57:04.258894Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nfrom PIL import Image\nfrom torch.utils.data import Dataset\nimport torchvision.transforms as T\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T11:57:11.200762Z","iopub.execute_input":"2025-12-20T11:57:11.201086Z","iopub.status.idle":"2025-12-20T11:57:20.094388Z","shell.execute_reply.started":"2025-12-20T11:57:11.201065Z","shell.execute_reply":"2025-12-20T11:57:20.093549Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nfrom PIL import Image\nfrom torch.utils.data import Dataset\nimport torchvision.transforms as T\n\nclass BiomassDataset(Dataset):\n    def __init__(self, dataframe):\n        self.df = dataframe\n        self.image_dir = \"/kaggle/input/csiro-biomass/train\"\n\n        self.target_cols = [\n            \"Dry_Green_g\",\n            \"Dry_Dead_g\",\n            \"Dry_Clover_g\",\n            \"GDM_g\",\n            \"Dry_Total_g\"\n        ]\n\n        self.transform = T.Compose([\n            T.Resize((224, 224)),\n            T.ToTensor()\n        ])\n\n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self, idx):\n        row = self.df.iloc[idx]\n\n        image_id = row[\"image_id\"]\n        image_path = os.path.join(self.image_dir, image_id + \".jpg\")\n\n        image = Image.open(image_path).convert(\"RGB\")\n        image = self.transform(image)\n\n        targets = row[self.target_cols].values.astype(\"float32\")\n\n        return image, targets\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T11:57:28.106094Z","iopub.execute_input":"2025-12-20T11:57:28.106651Z","iopub.status.idle":"2025-12-20T11:57:28.114095Z","shell.execute_reply.started":"2025-12-20T11:57:28.106624Z","shell.execute_reply":"2025-12-20T11:57:28.113239Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"dataset = BiomassDataset(train_pivot)\n\nimg, y = dataset[0]\n\nprint(type(img), img.shape)\nprint(type(y), y)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T11:57:37.694167Z","iopub.execute_input":"2025-12-20T11:57:37.694499Z","iopub.status.idle":"2025-12-20T11:57:37.893168Z","shell.execute_reply.started":"2025-12-20T11:57:37.694470Z","shell.execute_reply":"2025-12-20T11:57:37.892476Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nfrom torchvision import models\n\nmodel = models.resnet18(weights=None)  # ❌ no downloading\nstate_dict = torch.load(\"resnet18_weights.pth\", map_location=\"cpu\")\nmodel.load_state_dict(state_dict)\n\nmodel.eval()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T11:59:08.161323Z","iopub.execute_input":"2025-12-20T11:59:08.162327Z","iopub.status.idle":"2025-12-20T11:59:08.359663Z","shell.execute_reply.started":"2025-12-20T11:59:08.162274Z","shell.execute_reply":"2025-12-20T11:59:08.358572Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nfrom torchvision import models\n\nclass BiomassModel(nn.Module):\n    def __init__(self, weights_path=None):\n        super().__init__()\n        \n        # Load ResNet18 without internet\n        self.backbone = models.resnet18(weights=None)\n        \n        # Load offline pretrained weights if path provided\n        if weights_path:\n            state_dict = torch.load(weights_path, map_location=\"cpu\")\n            self.backbone.load_state_dict(state_dict)\n        \n        # Replace final layer for 5 regression targets\n        self.backbone.fc = nn.Linear(self.backbone.fc.in_features, 5)\n\n    def forward(self, x):\n        return self.backbone(x)\n\n# load offline weights\nmodel = BiomassModel(weights_path=\"resnet18_weights.pth\")\n\ndummy_input = torch.randn(1, 3, 224, 224)\nout = model(dummy_input)\nprint(out.shape)  # should be [1, 5]\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T11:59:13.186830Z","iopub.execute_input":"2025-12-20T11:59:13.187119Z","iopub.status.idle":"2025-12-20T11:59:13.431199Z","shell.execute_reply.started":"2025-12-20T11:59:13.187103Z","shell.execute_reply":"2025-12-20T11:59:13.430319Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from torch.utils.data import DataLoader\n\ntrain_dataset = BiomassDataset(train_pivot)\ntrain_loader = DataLoader(\n    train_dataset,\n    batch_size=16,\n    shuffle=True\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T11:59:22.758261Z","iopub.execute_input":"2025-12-20T11:59:22.759183Z","iopub.status.idle":"2025-12-20T11:59:22.764077Z","shell.execute_reply.started":"2025-12-20T11:59:22.759150Z","shell.execute_reply":"2025-12-20T11:59:22.762529Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.optim as optim\n\ndevice = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n\nmodel = BiomassModel().to(device)\n\ncriterion = nn.MSELoss()     # regression loss\noptimizer = optim.Adam(model.parameters(), lr=1e-4)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T11:59:29.890098Z","iopub.execute_input":"2025-12-20T11:59:29.890424Z","iopub.status.idle":"2025-12-20T11:59:30.025368Z","shell.execute_reply.started":"2025-12-20T11:59:29.890405Z","shell.execute_reply":"2025-12-20T11:59:30.023714Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"epochs = 5\n\nfor epoch in range(epochs):\n    model.train()\n    total_loss = 0\n\n    for images, targets in train_loader:\n        images = images.to(device)\n        targets = targets.to(device)\n\n        preds = model(images)\n        loss = criterion(preds, targets)\n\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n\n        total_loss += loss.item()\n\n    avg_loss = total_loss / len(train_loader)\n    print(f\"Epoch [{epoch+1}/{epochs}] - Loss: {avg_loss:.4f}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T11:59:38.444387Z","iopub.execute_input":"2025-12-20T11:59:38.444732Z","iopub.status.idle":"2025-12-20T12:03:34.899706Z","shell.execute_reply.started":"2025-12-20T11:59:38.444715Z","shell.execute_reply":"2025-12-20T12:03:34.898917Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\ntorch.save(model.state_dict(), \"biomass_model.pth\")\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T12:03:49.677411Z","iopub.execute_input":"2025-12-20T12:03:49.677851Z","iopub.status.idle":"2025-12-20T12:03:49.734375Z","shell.execute_reply.started":"2025-12-20T12:03:49.677818Z","shell.execute_reply":"2025-12-20T12:03:49.733555Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = BiomassModel().to(device)\nmodel.load_state_dict(torch.load(\"biomass_model.pth\", map_location=device))\nmodel.eval()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T12:03:55.946051Z","iopub.execute_input":"2025-12-20T12:03:55.946311Z","iopub.status.idle":"2025-12-20T12:03:56.132736Z","shell.execute_reply.started":"2025-12-20T12:03:55.946297Z","shell.execute_reply":"2025-12-20T12:03:56.131186Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from PIL import Image\nimport torchvision.transforms as T\nimport os\nos.listdir()\n\ntest_dir = '/kaggle/input/csiro-biomass/test'\n\ntest_image_name = os.listdir(test_dir)[0]\nprint(test_image_name)\n\ntest_image_id = test_image_name.split(\".\")[0]\nprint(test_image_id)\n\nfrom PIL import Image\nimport torchvision.transforms as T\n\nimage_path = os.path.join(test_dir, test_image_name)\nimage = Image.open(image_path).convert(\"RGB\")\n\ntransform = T.Compose([\n    T.Resize((224, 224)),\n    T.ToTensor()\n])\n\nimage = transform(image).unsqueeze(0).to(device)\n\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T12:04:06.467945Z","iopub.execute_input":"2025-12-20T12:04:06.469369Z","iopub.status.idle":"2025-12-20T12:04:06.565949Z","shell.execute_reply.started":"2025-12-20T12:04:06.469277Z","shell.execute_reply":"2025-12-20T12:04:06.565138Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.eval()\n\nwith torch.no_grad():\n    preds = model(image)\n\npreds = preds.cpu().numpy()[0]\npreds = preds.clip(min=0)\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T12:04:15.356675Z","iopub.execute_input":"2025-12-20T12:04:15.357919Z","iopub.status.idle":"2025-12-20T12:04:15.418340Z","shell.execute_reply.started":"2025-12-20T12:04:15.357866Z","shell.execute_reply":"2025-12-20T12:04:15.417173Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\n\ntarget_names = [\n    \"Dry_Green_g\",\n    \"Dry_Dead_g\",\n    \"Dry_Clover_g\",\n    \"GDM_g\",\n    \"Dry_Total_g\"\n]\n\nrows = []\n\nfor name, value in zip(target_names, preds):\n    rows.append({\n        \"sample_id\": f\"{test_image_id}__{name}\",\n        \"target\": float(value)\n    })\n\nsubmission = pd.DataFrame(rows)\nsubmission\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T12:05:48.804334Z","iopub.execute_input":"2025-12-20T12:05:48.804716Z","iopub.status.idle":"2025-12-20T12:05:48.816121Z","shell.execute_reply.started":"2025-12-20T12:05:48.804698Z","shell.execute_reply":"2025-12-20T12:05:48.814879Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission.to_csv(\"/kaggle/working/submission.csv\", index=False)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T12:05:56.924886Z","iopub.execute_input":"2025-12-20T12:05:56.925287Z","iopub.status.idle":"2025-12-20T12:05:56.939666Z","shell.execute_reply.started":"2025-12-20T12:05:56.925256Z","shell.execute_reply":"2025-12-20T12:05:56.937663Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\nsubmission_path = \"/kaggle/working/submission.csv\"\nsubmission.to_csv(submission_path, index=False)\n\nprint(\"Saved files:\", os.listdir(\"/kaggle/working\"))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-20T12:06:03.983631Z","iopub.execute_input":"2025-12-20T12:06:03.983996Z","iopub.status.idle":"2025-12-20T12:06:03.991527Z","shell.execute_reply.started":"2025-12-20T12:06:03.983973Z","shell.execute_reply":"2025-12-20T12:06:03.990141Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}