{"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"},{"sourceId":4533,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":3325,"modelId":986}],"dockerImageVersionId":31192,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"This notebook is a failed attempt of preprocesing the images, then feeding them into a NN with 3 output nodes, each from dry_clover, dry_dead and dry_green. R2 score is in negatives, therefore we cannot use a single NN for final output generation.","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport os\nfrom tqdm import tqdm\nimport cv2\nfrom transformers import AutoImageProcessor, AutoModel\nfrom PIL import Image\nimport torch\nimport glob\nimport timm\nimport torchvision.transforms as T\nimport torch.nn as nn\nimport torch.optim as optim\nfrom torch.utils.data import Dataset, DataLoader\nfrom sklearn.model_selection import train_test_split\nfrom torchvision import transforms\nimport requests\nimport datetime\n\nLR = 1e-4\nEPOCHS = 10\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nMAIN_PATH = \"/kaggle/input/csiro-biomass\"","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-12-08T16:28:44.73916Z","iopub.execute_input":"2025-12-08T16:28:44.739692Z","iopub.status.idle":"2025-12-08T16:29:28.314893Z","shell.execute_reply.started":"2025-12-08T16:28:44.739668Z","shell.execute_reply":"2025-12-08T16:29:28.314121Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_data = pd.read_csv(\"/kaggle/input/csiro-biomass/train.csv\")\ntest_data = pd.read_csv(\"/kaggle/input/csiro-biomass/test.csv\")\nsample_data = pd.read_csv(\"/kaggle/input/csiro-biomass/sample_submission.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-08T16:29:28.316029Z","iopub.execute_input":"2025-12-08T16:29:28.31628Z","iopub.status.idle":"2025-12-08T16:29:28.354147Z","shell.execute_reply.started":"2025-12-08T16:29:28.316256Z","shell.execute_reply":"2025-12-08T16:29:28.353589Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for i, _ in train_data.iterrows():\n    train_data.loc[i, \"sample_id\"] = train_data.loc[i, \"sample_id\"].split(\"_\")[0]\ncols = [c for c in train_data.columns if c not in [\"target_name\", \"target\"]]\ndf_static = (\n    train_data[cols]\n      .drop_duplicates(subset=\"sample_id\")\n)\n\ndf_pivot = (\n    train_data.pivot(index=\"sample_id\", columns=\"target_name\", values=\"target\")\n      .rename(columns=lambda x: f\"{x}_target\")\n      .reset_index()\n)\n\ndf_final = df_static.merge(df_pivot, on=\"sample_id\", how=\"left\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-08T16:29:28.355084Z","iopub.execute_input":"2025-12-08T16:29:28.355334Z","iopub.status.idle":"2025-12-08T16:29:28.79862Z","shell.execute_reply.started":"2025-12-08T16:29:28.355307Z","shell.execute_reply":"2025-12-08T16:29:28.798139Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_final.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-08T16:29:28.799858Z","iopub.execute_input":"2025-12-08T16:29:28.800266Z","iopub.status.idle":"2025-12-08T16:29:28.822061Z","shell.execute_reply.started":"2025-12-08T16:29:28.800247Z","shell.execute_reply":"2025-12-08T16:29:28.821599Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X = np.array(df_final[\"image_path\"])\ny = np.array(df_final.loc[:, [\"Dry_Clover_g_target\", \"Dry_Dead_g_target\", \"Dry_Green_g_target\"]])\nX_train, X_test, y_train, y_test = train_test_split(X, y, train_size = 0.8)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-08T16:29:28.822874Z","iopub.execute_input":"2025-12-08T16:29:28.823176Z","iopub.status.idle":"2025-12-08T16:29:28.827659Z","shell.execute_reply.started":"2025-12-08T16:29:28.823159Z","shell.execute_reply":"2025-12-08T16:29:28.827144Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class CSIRO_Dataset(Dataset):\n    def __init__(self, X, y, directory):\n        self.X = X\n        self.y = y\n        self.directory = directory\n    def __len__(self):\n        return self.X.shape[0]\n    def __getitem__(self, index):\n        semi_image_path = self.X[index]\n        full_path = os.path.join(self.directory, semi_image_path)\n        try:\n            img = cv2.imread(full_path)\n            img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n            transform = T.Compose([\n                T.ToTensor()\n            ])\n    \n            img = transform(img)\n        except Exception as e:\n            print(\"FAILIURE IN LOADING THE IMAGE!\")\n            print(full_path)\n            raise e\n        if (self.y.any()):\n            output = torch.tensor(self.y, dtype = torch.float32)[index]\n            return img, output\n        else:\n            return img, torch.tensor([])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-08T16:29:28.828593Z","iopub.execute_input":"2025-12-08T16:29:28.828791Z","iopub.status.idle":"2025-12-08T16:29:28.843257Z","shell.execute_reply.started":"2025-12-08T16:29:28.828776Z","shell.execute_reply":"2025-12-08T16:29:28.84272Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_dataset = CSIRO_Dataset(X_train, y_train, MAIN_PATH)\ntest_dataset = CSIRO_Dataset(X_test, y_test, MAIN_PATH)\ntrain_dataloader = DataLoader(train_dataset, batch_size = 32, shuffle = True)\ntest_dataloader = DataLoader(test_dataset, batch_size = 32)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-08T16:29:28.843886Z","iopub.execute_input":"2025-12-08T16:29:28.844156Z","iopub.status.idle":"2025-12-08T16:29:28.864623Z","shell.execute_reply.started":"2025-12-08T16:29:28.844141Z","shell.execute_reply":"2025-12-08T16:29:28.864121Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_path = \"/kaggle/input/dinov2/pytorch/small/1\"\nprocessor = AutoImageProcessor.from_pretrained(model_path)\nmodel = AutoModel.from_pretrained(model_path).to(device)\nfor param in model.parameters():\n    param.requires_grad = False\nmodel.eval()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-08T16:29:28.865229Z","iopub.execute_input":"2025-12-08T16:29:28.865456Z","iopub.status.idle":"2025-12-08T16:29:31.528904Z","shell.execute_reply.started":"2025-12-08T16:29:28.865421Z","shell.execute_reply":"2025-12-08T16:29:31.528284Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\n\nclass DINOHead(nn.Module):\n    def __init__(self, output_dim=3):\n        super().__init__()\n\n        self.input_dim = 384 \n        \n        self.network = nn.Sequential(\n            # Layer 1\n            nn.Linear(self.input_dim, 1024),\n            nn.BatchNorm1d(1024),\n            nn.ReLU(),\n            nn.Dropout(0.2),\n            # Layer 2\n            nn.Linear(1024, 512),\n            nn.BatchNorm1d(512),\n            nn.ReLU(),\n            nn.Dropout(0.2),\n            # Layer 3\n            nn.Linear(512, 128),\n            nn.BatchNorm1d(128),\n            nn.ReLU(),\n            nn.Linear(128, output_dim)\n        )\n\n    def forward(self, dinov2_output):\n        output = dinov2_output.squeeze(1)\n        cls_token = output[:, 0, :] # CLS Token\n        print(cls_token.shape)\n        return self.network(cls_token)\n\nhead = DINOHead().to(device)\nhead.train()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-08T16:29:31.529654Z","iopub.execute_input":"2025-12-08T16:29:31.529914Z","iopub.status.idle":"2025-12-08T16:29:31.550348Z","shell.execute_reply.started":"2025-12-08T16:29:31.529896Z","shell.execute_reply":"2025-12-08T16:29:31.549751Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def calculate_r2(preds, targets):\n    target_mean = torch.mean(targets, dim=0)\n    ss_tot = torch.sum((targets - target_mean) ** 2, dim=0)\n    ss_res = torch.sum((targets - preds) ** 2, dim=0)\n    r2 = 1 - (ss_res / (ss_tot + 1e-8))\n    return torch.mean(r2)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-08T16:29:31.552377Z","iopub.execute_input":"2025-12-08T16:29:31.552709Z","iopub.status.idle":"2025-12-08T16:29:31.592004Z","shell.execute_reply.started":"2025-12-08T16:29:31.552693Z","shell.execute_reply":"2025-12-08T16:29:31.591304Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"optimizer = optim.Adam(head.parameters(), lr=LR)\ncriterion = nn.MSELoss()\n\nprint(\"Training Start...\")\n\nfor epoch in range(EPOCHS):\n    total_loss = 0.0\n    total_r2 = 0.0\n    num_batches = 0\n\n    loop_train = tqdm(train_dataloader, desc=f\"Epoch {epoch+1}/{EPOCHS}\")\n    \n    for batch_idx, (images, targets) in enumerate(loop_train):\n        images = images.to(device)\n        targets = targets.to(device)\n        preprocessed = []\n        with torch.no_grad():\n            for image in images:\n                inputs = processor(images=image, return_tensors=\"pt\")\n                inputs = inputs.to(device)\n                outputs = model(**inputs)\n                features = outputs.last_hidden_state\n                preprocessed.append(features)\n        preprocessed = torch.stack(preprocessed, dim=0)\n        preds = head(preprocessed)\n        loss = criterion(preds, targets)\n\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n        r2 = calculate_r2(preds, targets)\n        total_loss += loss.item()\n        total_r2 += r2.item()\n        num_batches += 1\n        loop_train.set_postfix(loss=loss.item(), r2=r2.item())\n\n    avg_loss = total_loss / num_batches\n    avg_r2 = total_r2 / num_batches\n    print(f\"--- Epoch {epoch+1} Train Summary ---\")\n    print(f\"Avg Train MSE Loss: {avg_loss:.4f}\")\n    print(f\"Avg Train R2 Score: {avg_r2:.4f}\")\n    print(\"-----------------------------\")\n\n    loop_test = tqdm(test_dataloader, desc=f\"Epoch {epoch+1}/{EPOCHS}\")\n    \n    for batch_idx, (images, targets) in enumerate(loop_test):\n        images = images.to(device)\n        targets = targets.to(device)\n        preprocessed = []\n        with torch.no_grad():\n            for image in images:\n                inputs = processor(images=image, return_tensors=\"pt\")\n                inputs = inputs.to(device)\n                outputs = model(**inputs)\n                features = outputs.last_hidden_state\n                preprocessed.append(features)\n            preprocessed = torch.stack(preprocessed, dim=0)\n            preds = head(preprocessed)\n            loss = criterion(preds, targets)\n\n            r2 = calculate_r2(preds, targets)\n            total_loss += loss.item()\n            total_r2 += r2.item()\n            num_batches += 1\n            loop_test.set_postfix(loss=loss.item(), r2=r2.item())\n\n    avg_loss = total_loss / num_batches\n    avg_r2 = total_r2 / num_batches\n    print(f\"--- Epoch {epoch+1} Test Summary ---\")\n    print(f\"Avg Test MSE Loss: {avg_loss:.4f}\")\n    print(f\"Avg Test R2 Score: {avg_r2:.4f}\")\n    print(\"-----------------------------\")\n\nprint(\"Training Complete.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-08T16:29:31.592725Z","iopub.execute_input":"2025-12-08T16:29:31.592911Z","iopub.status.idle":"2025-12-08T16:45:46.46734Z","shell.execute_reply.started":"2025-12-08T16:29:31.592898Z","shell.execute_reply":"2025-12-08T16:45:46.466685Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_data.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-08T16:45:46.468064Z","iopub.execute_input":"2025-12-08T16:45:46.46828Z","iopub.status.idle":"2025-12-08T16:45:46.476456Z","shell.execute_reply.started":"2025-12-08T16:45:46.468252Z","shell.execute_reply":"2025-12-08T16:45:46.475449Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for i, _ in test_data.iterrows():\n    test_data.loc[i, \"sample_id\"] = test_data.loc[i, \"sample_id\"].split(\"_\")[0]\ncols = [c for c in test_data.columns if c not in [\"target_name\", \"target\"]]\nfinal_test_data = (\n    test_data[cols]\n      .drop_duplicates(subset=\"sample_id\")\n)\nfinal_test_data = final_test_data[\"image_path\"]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-08T16:45:46.477198Z","iopub.execute_input":"2025-12-08T16:45:46.477448Z","iopub.status.idle":"2025-12-08T16:45:46.500892Z","shell.execute_reply.started":"2025-12-08T16:45:46.477423Z","shell.execute_reply":"2025-12-08T16:45:46.50016Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"prediction_dataset = CSIRO_Dataset(final_test_data, np.array([]), MAIN_PATH)\nprediction_dataloader = DataLoader(prediction_dataset, batch_size = 1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-08T16:45:46.502378Z","iopub.execute_input":"2025-12-08T16:45:46.502758Z","iopub.status.idle":"2025-12-08T16:45:46.518377Z","shell.execute_reply.started":"2025-12-08T16:45:46.502742Z","shell.execute_reply":"2025-12-08T16:45:46.517671Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"prediction_dataset.__getitem__(0)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-08T16:45:46.519011Z","iopub.execute_input":"2025-12-08T16:45:46.519282Z","iopub.status.idle":"2025-12-08T16:45:46.652451Z","shell.execute_reply.started":"2025-12-08T16:45:46.519265Z","shell.execute_reply":"2025-12-08T16:45:46.651855Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"The code below is eradicated due to low scores and errors.\nConclusion : FC (3 output nodes) will not work in this scenario. Each 3 of the outputs needs to be calculated using separate models.","metadata":{}},{"cell_type":"code","source":"# for images, _ in prediction_dataloader:\n#     images = images.to(device)\n#     targets = targets.to(device)\n#     preprocessed = []\n#     with torch.no_grad():\n#         for image in images:\n#             inputs = processor(images=image, return_tensors=\"pt\")\n#             inputs = inputs.to(device)\n#             outputs = model(**inputs)\n#             features = outputs.last_hidden_state\n#             preprocessed.append(features)\n#         preprocessed = torch.stack(preprocessed, dim=0)\n#         print(preprocessed.shape)\n#         preds = head(preprocessed)\n#         print(preds)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-08T16:45:46.653092Z","iopub.execute_input":"2025-12-08T16:45:46.653328Z","iopub.status.idle":"2025-12-08T16:45:47.030645Z","shell.execute_reply.started":"2025-12-08T16:45:46.653306Z","shell.execute_reply":"2025-12-08T16:45:47.029627Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}