{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":112509,"databundleVersionId":14254895,"sourceType":"competition"}],"dockerImageVersionId":31236,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Import Library","metadata":{}},{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\nimport torch\nfrom PIL import Image\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.preprocessing import StandardScaler\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torchvision.transforms as transforms\nimport torchvision.models as models\nimport torch.optim as optim\nfrom torch.utils.data import Dataset, DataLoader","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-12-18T06:26:21.386719Z","iopub.execute_input":"2025-12-18T06:26:21.387435Z","iopub.status.idle":"2025-12-18T06:26:29.227440Z","shell.execute_reply.started":"2025-12-18T06:26:21.387403Z","shell.execute_reply":"2025-12-18T06:26:29.226803Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Prepare Dataset","metadata":{}},{"cell_type":"markdown","source":"### Define Dataset","metadata":{}},{"cell_type":"code","source":"class ImageDataset(Dataset):\n    def __init__(self, df, transform, scaler):\n        self.samples = list(df.itertuples(index=False))\n        self.image_dir = \"/kaggle/input/csiro-biomass\"\n        self.targets = ['Dry_Clover_g', 'Dry_Dead_g', 'Dry_Green_g', 'Dry_Total_g', 'GDM_g']\n        self.transform = transform\n        self.scaler = scaler\n\n    def __len__(self):\n        return len(self.samples)\n\n    def __getitem__(self, idx):\n        row = self.samples[idx]\n\n        img_path = os.path.join(self.image_dir, row.image_path)\n        image = Image.open(img_path).convert(\"RGB\")\n        image = self.transform(image)\n\n        target = torch.tensor([getattr(row, t) for t in self.targets], dtype=torch.float32)\n        target = torch.tensor(self.scaler.transform([target.numpy()])[0], dtype=torch.float32)\n\n        return image, target","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-18T06:26:29.228689Z","iopub.execute_input":"2025-12-18T06:26:29.229039Z","iopub.status.idle":"2025-12-18T06:26:29.235292Z","shell.execute_reply.started":"2025-12-18T06:26:29.229016Z","shell.execute_reply":"2025-12-18T06:26:29.234597Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Make Transform","metadata":{}},{"cell_type":"code","source":"transform = transforms.Compose([\n        transforms.Resize((384, 384)),\n        transforms.ToTensor(),\n        transforms.Normalize(mean=(0.485,0.456,0.406),\n                             std=(0.229,0.224,0.225)),\n])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-18T06:26:29.236210Z","iopub.execute_input":"2025-12-18T06:26:29.236660Z","iopub.status.idle":"2025-12-18T06:26:29.252643Z","shell.execute_reply.started":"2025-12-18T06:26:29.236624Z","shell.execute_reply":"2025-12-18T06:26:29.251964Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Load csv File","metadata":{}},{"cell_type":"code","source":"df = pd.read_csv(\"/kaggle/input/csiro-biomass/train.csv\")\ndf = df[[\"image_path\", \"target_name\", \"target\"]]\ndf = df.pivot_table(index=[\"image_path\"],columns='target_name',values=\"target\").reset_index()\n\ndf_train, df_val = train_test_split(df, test_size=0.2, random_state=42, shuffle=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-18T06:26:29.253569Z","iopub.execute_input":"2025-12-18T06:26:29.253824Z","iopub.status.idle":"2025-12-18T06:26:29.323891Z","shell.execute_reply.started":"2025-12-18T06:26:29.253803Z","shell.execute_reply":"2025-12-18T06:26:29.323062Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Make Scaler","metadata":{}},{"cell_type":"code","source":"scaler = StandardScaler()\ntargets=['Dry_Clover_g', 'Dry_Dead_g', 'Dry_Green_g', 'Dry_Total_g', 'GDM_g']\nscaler.fit(df_train[targets].values)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-18T06:26:29.325607Z","iopub.execute_input":"2025-12-18T06:26:29.325888Z","iopub.status.idle":"2025-12-18T06:26:29.339531Z","shell.execute_reply.started":"2025-12-18T06:26:29.325862Z","shell.execute_reply":"2025-12-18T06:26:29.338784Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Make DataLoader for Training","metadata":{}},{"cell_type":"code","source":"batch_size = 16\n\ntrain_dataset = ImageDataset(df_train, transform, scaler)\nval_dataset = ImageDataset(df_val, transform, scaler)\n\ntrain_dataloader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)\nval_dataloader = DataLoader(val_dataset,batch_size=batch_size)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-18T06:26:29.340468Z","iopub.execute_input":"2025-12-18T06:26:29.340709Z","iopub.status.idle":"2025-12-18T06:26:29.347675Z","shell.execute_reply.started":"2025-12-18T06:26:29.340677Z","shell.execute_reply":"2025-12-18T06:26:29.346978Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Define Model","metadata":{}},{"cell_type":"code","source":"class BiomassModel(nn.Module):\n    def __init__(self):\n        super(BiomassModel, self).__init__()\n        self.model = nn.Sequential(\n            nn.Conv2d(3, 64, 3, 2, 1, bias=False),\n            nn.BatchNorm2d(64),\n            nn.ReLU(True),\n\n            nn.Conv2d(64, 128, 3, 2, 1, bias=False),\n            nn.BatchNorm2d(128),\n            nn.ReLU(True),\n\n            nn.Conv2d(128, 256, 3, 2, 1, bias=False),\n            nn.BatchNorm2d(256),\n            nn.ReLU(True),\n\n            nn.Conv2d(256, 512, 3, 2, 1, bias=False),\n            nn.BatchNorm2d(512),\n            nn.ReLU(True),\n\n            nn.Conv2d(512, 1024, 3, 2, 1, bias=False),\n            nn.BatchNorm2d(1024),\n            nn.ReLU(True)\n        )\n\n        self.head = nn.Sequential(\n            nn.Linear(1024, 512),             \n            nn.Dropout(0.1),     \n\n            nn.Linear(512, 128),                 \n            nn.Dropout(0.1),     \n\n            nn.Linear(128, 5)\n        )\n        \n    def forward(self, images):\n        features = self.model(images)\n        mean_feats = features.mean(dim=(2,3))\n        out = self.head(mean_feats)\n        return out","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-18T06:26:29.348571Z","iopub.execute_input":"2025-12-18T06:26:29.348871Z","iopub.status.idle":"2025-12-18T06:26:29.363428Z","shell.execute_reply.started":"2025-12-18T06:26:29.348848Z","shell.execute_reply":"2025-12-18T06:26:29.362519Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Training","metadata":{}},{"cell_type":"markdown","source":"### Define Parameters","metadata":{}},{"cell_type":"code","source":"device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\nmodel = BiomassModel()\nmodel.to(device)\n\nlr = 1e-4\noptimizer = optim.Adam(model.parameters(), lr=lr)\ncriterion = nn.MSELoss()\nepochs = 20","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-18T06:26:29.364559Z","iopub.execute_input":"2025-12-18T06:26:29.364872Z","iopub.status.idle":"2025-12-18T06:26:29.707135Z","shell.execute_reply.started":"2025-12-18T06:26:29.364844Z","shell.execute_reply":"2025-12-18T06:26:29.706299Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Do Train","metadata":{}},{"cell_type":"code","source":"min_loss = np.inf\nbest_model = model\nfor epoch in range(epochs):\n    model.train()\n    train_loss = 0.0\n\n    for data, label in train_dataloader:\n        data = data.to(device)\n        label = label.to(device)\n\n        preds = model(data)\n        loss = criterion(preds, label)\n\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n\n        train_loss += loss.item()\n\n    train_loss_res = train_loss / len(train_dataloader)\n\n\n    model.eval()\n    test_loss = 0.0\n\n    with torch.no_grad():\n        for data, label in val_dataloader:\n            data = data.to(device)\n            label = label.to(device)\n\n            preds = model(data)\n            loss = criterion(preds, label)\n            test_loss += loss.item()\n\n    test_loss_res = test_loss / len(val_dataloader)\n\n    print(f\"epoch{epoch+1} | train_loss:{train_loss_res:.4f} | test_loss:{test_loss_res:.4f}\")\n\n    if min_loss >= test_loss_res:\n        print(f'best model (epoch{epoch+1}) | loss {test_loss_res}\\n')\n        min_loss = test_loss_res\n        best_model=model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-18T06:26:29.708114Z","iopub.execute_input":"2025-12-18T06:26:29.708395Z","iopub.status.idle":"2025-12-18T06:34:13.623176Z","shell.execute_reply.started":"2025-12-18T06:26:29.708371Z","shell.execute_reply":"2025-12-18T06:34:13.622506Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Make Submission File","metadata":{}},{"cell_type":"markdown","source":"### Predict","metadata":{}},{"cell_type":"code","source":"df_test = pd.read_csv('/kaggle/input/csiro-biomass/test.csv')\ntest_path = df_test[\"image_path\"].values.tolist()\ntest_target = df_test[\"target_name\"].values.tolist()\n\nres = []\nwith torch.no_grad():\n    for img_path,target in zip(test_path,test_target):\n        img_path = os.path.join('/kaggle/input/csiro-biomass', img_path)\n        image = Image.open(img_path).convert(\"RGB\")\n        image = transform(image).to(device).unsqueeze(0)\n\n        preds = best_model(image)\n        preds = scaler.inverse_transform(preds.detach().cpu())\n        preds=preds.reshape(-1)\n        if target == 'Dry_Clover_g':\n            res.append(preds[0])\n        elif target == 'Dry_Dead_g':\n            res.append(preds[1])\n        elif target == 'Dry_Green_g':\n            res.append(preds[2])\n        elif target == 'Dry_Total_g':\n            res.append(preds[3])\n        else: #GDM_g\n            res.append(preds[4])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-18T06:34:13.624167Z","iopub.execute_input":"2025-12-18T06:34:13.624675Z","iopub.status.idle":"2025-12-18T06:34:14.030501Z","shell.execute_reply.started":"2025-12-18T06:34:13.624651Z","shell.execute_reply":"2025-12-18T06:34:14.029861Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Make csv File","metadata":{}},{"cell_type":"code","source":"submission = pd.DataFrame({'sample_id':df_test['sample_id'],'target':res})\nsubmission.to_csv('submission.csv', index = False)\nprint(submission)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-18T06:34:14.031382Z","iopub.execute_input":"2025-12-18T06:34:14.031662Z","iopub.status.idle":"2025-12-18T06:34:14.046666Z","shell.execute_reply.started":"2025-12-18T06:34:14.031634Z","shell.execute_reply":"2025-12-18T06:34:14.045960Z"}},"outputs":[],"execution_count":null}]}