{"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,"isSourceIdPinned":false,"sourceType":"competition"},{"sourceId":680478,"sourceType":"modelInstanceVersion","isSourceIdPinned":false,"modelInstanceId":516278,"modelId":530937}],"dockerImageVersionId":31192,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport torch\nimport torch.nn as nn\nfrom torchvision import transforms, models\nfrom PIL import Image\nfrom tqdm import tqdm\n\n# Config\nIMG_SIZE = 224\nDEVICE = 'cuda' if torch.cuda.is_available() else 'cpu'\nTARGET_ORDER = ['Dry_Clover_g', 'Dry_Dead_g', 'Dry_Green_g', 'Dry_Total_g', 'GDM_g']\n\n# Model\nclass PastureBiomassModel(nn.Module):\n    def __init__(self):\n        super().__init__()\n        resnet = models.resnet50(weights=None)\n        self.backbone = nn.Sequential(*list(resnet.children())[:-1])\n        \n        self.regressor = nn.Sequential(\n            nn.Linear(2050, 512), nn.BatchNorm1d(512), nn.ReLU(), nn.Dropout(0.3),\n            nn.Linear(512, 256), nn.BatchNorm1d(256), nn.ReLU(), nn.Dropout(0.3),\n            nn.Linear(256, 128), nn.BatchNorm1d(128), nn.ReLU(), nn.Dropout(0.2),\n            nn.Linear(128, 5)\n        )\n        \n    def forward(self, image, metadata):\n        img_features = self.backbone(image).view(image.size(0), -1)\n        combined = torch.cat([img_features, metadata], dim=1)\n        return self.regressor(combined)\n\n# Load model\nmodel = PastureBiomassModel()\nmodel_path = '/kaggle/input/model-v2/pytorch/default/1/best_model_v2.pth'\nmodel.load_state_dict(torch.load(model_path, map_location=DEVICE))\nmodel.to(DEVICE).eval()\n\n# load test df\ntest_df = pd.read_csv('/kaggle/input/csiro-biomass/test.csv')\nunique_images = test_df.groupby('image_path').first().reset_index()\n\n# Transform\ntransform = transforms.Compose([\n    transforms.Resize((IMG_SIZE, IMG_SIZE)),\n    transforms.ToTensor(),\n    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n])\n\n# Predict\npredictions = []\nfor _, row in tqdm(unique_images.iterrows(), total=len(unique_images)):\n    img_path = f\"/kaggle/input/csiro-biomass/{row['image_path']}\"\n    \n    image = Image.open(img_path).convert('RGB')\n    image_tensor = transform(image).unsqueeze(0).to(DEVICE)\n    \n    ndvi = row.get('Pre_GSHH_NDVI', 0.5) if pd.notna(row.get('Pre_GSHH_NDVI')) else 0.5\n    height = row.get('Height_Ave_cm', 10.0) if pd.notna(row.get('Height_Ave_cm')) else 10.0\n    metadata = torch.FloatTensor([[ndvi, height]]).to(DEVICE)\n    \n    with torch.no_grad():\n        preds = model(image_tensor, metadata).cpu().numpy()[0]\n    \n    preds = np.clip(preds, 0, None)\n    predictions.append({'image_path': row['image_path'], **dict(zip(TARGET_ORDER, preds))})\n\n# last\npred_df = pd.DataFrame(predictions)\nresult = test_df.merge(pred_df, on='image_path')\nsubmission = pd.DataFrame({\n    'sample_id': result['sample_id'],\n    'target': result.apply(lambda x: x[x['target_name']], axis=1)\n})\nsubmission.to_csv('submission.csv', index=False)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-12-11T18:55:53.976453Z","iopub.execute_input":"2025-12-11T18:55:53.976820Z","iopub.status.idle":"2025-12-11T18:55:54.742946Z","shell.execute_reply.started":"2025-12-11T18:55:53.976796Z","shell.execute_reply":"2025-12-11T18:55:54.741767Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pred_df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-11T18:51:33.941225Z","iopub.execute_input":"2025-12-11T18:51:33.941575Z","iopub.status.idle":"2025-12-11T18:51:33.952535Z","shell.execute_reply.started":"2025-12-11T18:51:33.941505Z","shell.execute_reply":"2025-12-11T18:51:33.951827Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}