{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","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"},{"sourceId":14352666,"sourceType":"datasetVersion","datasetId":9164307}],"dockerImageVersionId":31240,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true},"papermill":{"default_parameters":{},"duration":74.247693,"end_time":"2025-12-31T11:05:06.460609","environment_variables":{},"exception":null,"input_path":"__notebook__.ipynb","output_path":"__notebook__.ipynb","parameters":{},"start_time":"2025-12-31T11:03:52.212916","version":"2.6.0"}},"nbformat_minor":4,"nbformat":4,"cells":[{"id":"28dd57d3","cell_type":"markdown","source":"# Biomass Regression - Inference Notebook\n\nThis notebook loads the trained model and generates predictions for test data.\n","metadata":{"papermill":{"duration":0.003165,"end_time":"2025-12-31T11:03:54.921651","exception":false,"start_time":"2025-12-31T11:03:54.918486","status":"completed"},"tags":[]}},{"id":"dc23ed00","cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport torch\nimport torch.nn as nn\nfrom torch.utils.data import Dataset, DataLoader\nfrom pathlib import Path\nfrom PIL import Image\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2\nfrom transformers import AutoConfig, AutoModel\nimport warnings\nwarnings.filterwarnings(\"ignore\")","metadata":{"execution":{"iopub.status.busy":"2025-12-31T12:46:26.784715Z","iopub.execute_input":"2025-12-31T12:46:26.785082Z","iopub.status.idle":"2025-12-31T12:47:19.320914Z","shell.execute_reply.started":"2025-12-31T12:46:26.784940Z","shell.execute_reply":"2025-12-31T12:47:19.320298Z"},"papermill":{"duration":48.61045,"end_time":"2025-12-31T11:04:43.534502","exception":false,"start_time":"2025-12-31T11:03:54.924052","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"163c54cb","cell_type":"code","source":"class BiomassRegressionModel(nn.Module):\n    def __init__(self, model_name=\"../input/1-csiro-models/dinov2-small-imagenet1k model/dinov2-small-imagenet1k-1-layer\", dropout=0.3, hidden_dim=512):\n        super().__init__()\n        self.config = AutoConfig.from_pretrained(model_name)\n        self.backbone = AutoModel.from_pretrained(model_name, config=self.config)\n        hidden_size = self.config.hidden_size\n        self.shared = nn.Sequential(\n            nn.Linear(hidden_size, hidden_dim),\n            nn.BatchNorm1d(hidden_dim),\n            nn.ReLU(),\n            nn.Dropout(dropout),\n            nn.Linear(hidden_dim, 128),\n            nn.ReLU(),\n            nn.Dropout(dropout * 0.67)\n        )\n        self.heads = nn.ModuleList([nn.Linear(128, 1) for _ in range(5)])\n        for head in self.heads:\n            nn.init.normal_(head.weight, std=0.02)\n            nn.init.zeros_(head.bias)\n\n    def forward(self, pixel_values):\n        outputs = self.backbone(pixel_values=pixel_values)\n        cls_token = outputs.last_hidden_state[:, 0, :]\n        shared_features = self.shared(cls_token)\n        outputs = torch.cat([head(shared_features) for head in self.heads], dim=1)\n        return outputs\n","metadata":{"papermill":{"duration":0.013359,"end_time":"2025-12-31T11:04:43.550784","exception":false,"start_time":"2025-12-31T11:04:43.537425","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"a671fcbc","cell_type":"code","source":"class args:\n    TEST_CSV = \"../input/csiro-biomass/test.csv\"\n    SAMPLE_SUBMISSION_CSV = \"../input/csiro-biomass/sample_submission.csv\"\n    TRAIN_CSV = \"../input/csiro-biomass/train.csv\"\n    IMAGE_ROOT = \"../input/csiro-biomass\"\n    MODEL_PATH = \"../input/1-csiro-models/1_final_model_best.pt\"\n    DEVICE = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n    BATCH_SIZE = 8\n","metadata":{"papermill":{"duration":0.103398,"end_time":"2025-12-31T11:04:43.656873","exception":false,"start_time":"2025-12-31T11:04:43.553475","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"ead5dc2c","cell_type":"code","source":"df_test = pd.read_csv(args.TEST_CSV)\ndf_ss = pd.read_csv(args.SAMPLE_SUBMISSION_CSV)\n\ndf_test_wide = (\n    df_test.pivot_table(\n        index=[\"image_path\"],\n        columns=\"target_name\",\n        values=\"sample_id\",\n        aggfunc=\"first\"\n    )\n    .reset_index()\n)\ndf_test_wide.columns.name = None\ndf_test_wide = df_test_wide[[\"image_path\"]]\n","metadata":{"papermill":{"duration":0.073801,"end_time":"2025-12-31T11:04:43.733422","exception":false,"start_time":"2025-12-31T11:04:43.659621","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"5c16b60b","cell_type":"code","source":"df_train = pd.read_csv(args.TRAIN_CSV)\ntarget_cols = [\"Dry_Green_g\", \"Dry_Dead_g\", \"Dry_Clover_g\", \"GDM_g\", \"Dry_Total_g\"]\ndf_train_wide = (\n    df_train[[\"image_path\", \"target_name\", \"target\"]]\n    .pivot_table(index=[\"image_path\"], columns=\"target_name\", values=\"target\", aggfunc=\"first\")\n    .reset_index()\n)\ndf_train_wide.columns.name = None\ntarget_mean = df_train_wide[target_cols].mean().values.astype(np.float32)\ntarget_std = df_train_wide[target_cols].std().values.astype(np.float32)\ntarget_std = np.maximum(target_std, 1e-8)\n","metadata":{"papermill":{"duration":0.02861,"end_time":"2025-12-31T11:04:43.765043","exception":false,"start_time":"2025-12-31T11:04:43.736433","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"84462c15","cell_type":"code","source":"test_transforms = A.Compose([\n    A.Resize(384, 384),\n    A.Normalize(mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)),\n    ToTensorV2()\n])\n","metadata":{"papermill":{"duration":0.013143,"end_time":"2025-12-31T11:04:43.780792","exception":false,"start_time":"2025-12-31T11:04:43.767649","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"26ad4ec1","cell_type":"code","source":"class BiomassTestDataset(Dataset):\n    def __init__(self, dataframe, image_root, transforms=None):\n        self.data = dataframe.reset_index(drop=True)\n        self.image_root = Path(image_root)\n        self.transforms = transforms\n        \n    def __len__(self):\n        return len(self.data)\n    \n    def __getitem__(self, idx):\n        row = self.data.iloc[idx]\n        rel_path = Path(row[\"image_path\"])\n        image_path = self.image_root / rel_path\n        image = Image.open(image_path).convert(\"RGB\")\n        image = np.array(image)\n        if self.transforms is not None:\n            image = self.transforms(image=image)[\"image\"]\n        return {\n            \"image\": image,\n            \"image_path\": str(rel_path),\n            \"image_id\": image_path.stem\n        }\n","metadata":{"papermill":{"duration":0.010645,"end_time":"2025-12-31T11:04:43.793974","exception":false,"start_time":"2025-12-31T11:04:43.783329","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"91ecaaa5","cell_type":"code","source":"test_dataset = BiomassTestDataset(df_test_wide, image_root=args.IMAGE_ROOT, transforms=test_transforms)\ntest_loader = DataLoader(test_dataset, batch_size=args.BATCH_SIZE, shuffle=False, num_workers=0)\n","metadata":{"papermill":{"duration":0.009329,"end_time":"2025-12-31T11:04:43.805728","exception":false,"start_time":"2025-12-31T11:04:43.796399","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"a8051f8c","cell_type":"code","source":"model = BiomassRegressionModel().to(args.DEVICE)\nsaved_state = torch.load(args.MODEL_PATH, map_location=args.DEVICE)\nmodel_state = model.state_dict()\nfor key in saved_state.keys():\n    if key in model_state and model_state[key].shape == saved_state[key].shape:\n        model_state[key] = saved_state[key]\nmodel.load_state_dict(model_state, strict=False)\nmodel.eval()\n","metadata":{"papermill":{"duration":18.391044,"end_time":"2025-12-31T11:05:02.199533","exception":false,"start_time":"2025-12-31T11:04:43.808489","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"e7b36a0e","cell_type":"code","source":"all_predictions = []\nall_image_ids = []\n\nwith torch.no_grad():\n    for batch in test_loader:\n        images = batch[\"image\"].to(args.DEVICE, dtype=torch.float)\n        image_ids = batch[\"image_id\"]\n        outputs = model(pixel_values=images)\n        predictions = outputs.detach().cpu().numpy()\n        for i in range(predictions.shape[0]):\n            pred_normalized = predictions[i]\n            pred_original = pred_normalized * target_std + target_mean\n            pred_original = np.maximum(pred_original, 0.0)\n            all_predictions.append(pred_original)\n            all_image_ids.append(image_ids[i])\n","metadata":{"papermill":{"duration":1.164758,"end_time":"2025-12-31T11:05:03.367110","exception":false,"start_time":"2025-12-31T11:05:02.202352","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"962b2ef6","cell_type":"code","source":"target_names = [\"Dry_Green_g\", \"Dry_Dead_g\", \"Dry_Clover_g\", \"GDM_g\", \"Dry_Total_g\"]\nprediction_rows = []\nfor img_id, preds in zip(all_image_ids, all_predictions):\n    for i, target_name in enumerate(target_names):\n        sample_id = f\"{img_id}__{target_name}\"\n        prediction_rows.append({\n            \"sample_id\": sample_id,\n            \"target\": float(preds[i])\n        })\ndf_predictions = pd.DataFrame(prediction_rows)\n","metadata":{"papermill":{"duration":0.015765,"end_time":"2025-12-31T11:05:03.386025","exception":false,"start_time":"2025-12-31T11:05:03.370260","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"da0fa681","cell_type":"code","source":"df_predictions.to_csv(\"submission.csv\", index=False)\n","metadata":{"papermill":{"duration":0.015794,"end_time":"2025-12-31T11:05:03.426906","exception":false,"start_time":"2025-12-31T11:05:03.411112","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null}]}