{"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,"isSourceIdPinned":false,"sourceType":"competition"},{"sourceId":283311593,"sourceType":"kernelVersion"}],"dockerImageVersionId":31193,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport pandas as pd\nimport numpy as np\nfrom PIL import Image\nimport torch\nimport torch.nn as nn\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms\nimport warnings\nwarnings.filterwarnings('ignore')\n\n# Set device\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nprint(f\"Using device: {device}\")\n\n# Load test data\ntest_df = pd.read_csv('/kaggle/input/csiro-biomass/test.csv')\nprint(f\"Test samples: {len(test_df)}\")\n\n# Get unique image paths\nunique_image_paths = test_df['image_path'].unique()\nprint(f\"Found {len(unique_image_paths)} unique test images\")\n\n# Dataset for inference\nclass TestBiomassDataset(Dataset):\n    def __init__(self, image_paths, transform=None):\n        self.image_paths = image_paths\n        self.transform = transform\n        \n    def __len__(self):\n        return len(self.image_paths)\n    \n    def __getitem__(self, idx):\n        img_path = self.image_paths[idx]\n        full_path = f\"/kaggle/input/csiro-biomass/{img_path}\"\n        \n        try:\n            image = Image.open(full_path).convert('RGB')\n        except Exception as e:\n            print(f\"Error loading image {full_path}: {e}\")\n            # Create blank image if file not found\n            image = Image.new('RGB', (500, 500), color='black')\n        \n        if self.transform:\n            image = self.transform(image)\n        \n        return image, img_path\n\n# Transform for inference\ntest_transform = transforms.Compose([\n    transforms.Resize((500, 500)),\n    transforms.ToTensor(),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n])\n\n# Create test dataset and dataloader\ntest_dataset = TestBiomassDataset(unique_image_paths, transform=test_transform)\ntest_loader = DataLoader(test_dataset, batch_size=32, shuffle=False, num_workers=4)\n\n# Define model architecture (same as training)\ndef create_model():\n    # Try to use the same architecture as training\n    try:\n        from transformers import AutoModelForImageClassification, AutoConfig\n        config = AutoConfig.from_pretrained(\"eva/eva02-base-patch14-224\")\n        model = AutoModelForImageClassification.from_config(config)\n        \n        # Modify classifier head\n        model.classifier = nn.Sequential(\n            nn.Linear(model.config.hidden_size, 1024),\n            nn.ReLU(),\n            nn.Dropout(0.2),\n            nn.Linear(1024, 512),\n            nn.ReLU(),\n            nn.Dropout(0.2),\n            nn.Linear(512, 3)\n        )\n    except:\n        # Fallback to ResNet\n        import torchvision.models as models\n        model = models.resnet50()\n        model.fc = nn.Sequential(\n            nn.Linear(model.fc.in_features, 1024),\n            nn.ReLU(),\n            nn.Dropout(0.2),\n            nn.Linear(1024, 512),\n            nn.ReLU(),\n            nn.Dropout(0.2),\n            nn.Linear(512, 3)\n        )\n    \n    return model\n\nmodel = create_model()\n\n# Load trained weights\ncheckpoint_path = '/kaggle/input/eva-02-model-training/biomass_model_final.pth'\nif os.path.exists(checkpoint_path):\n    model.load_state_dict(torch.load(checkpoint_path, map_location=device))\n    print(f\"Loaded model from {checkpoint_path}\")\nelse:\n    # Try to find the latest checkpoint\n    checkpoints = [f for f in os.listdir('/kaggle/working') if f.startswith('biomass_model_epoch_') and f.endswith('.pth')]\n    if checkpoints:\n        latest_checkpoint = sorted(checkpoints, key=lambda x: int(x.split('_')[-1].split('.')[0]))[-1]\n        model.load_state_dict(torch.load(f'/kaggle/working/{latest_checkpoint}', map_location=device))\n        print(f\"Loaded model from {latest_checkpoint}\")\n    else:\n        print(\"Warning: No trained model found. Using untrained model.\")\n\n# Use DataParallel if multiple GPUs\nif torch.cuda.device_count() > 1:\n    model = nn.DataParallel(model)\n\nmodel = model.to(device)\nmodel.eval()\n\n# Run inference\nimage_predictions = {}\nprint(\"Running inference...\")\n\nwith torch.no_grad():\n    for batch_idx, (images, img_paths) in enumerate(test_loader):\n        images = images.to(device)\n        \n        outputs = model(images)\n        \n        # Get predictions\n        if hasattr(outputs, 'logits'):\n            predictions = outputs.logits.cpu().numpy()\n        else:\n            predictions = outputs.cpu().numpy()\n        \n        for i, img_path in enumerate(img_paths):\n            # Get predictions for the three components\n            dry_clover = max(0, float(predictions[i][0]))  # Ensure non-negative\n            dry_dead = max(0, float(predictions[i][1]))\n            dry_green = max(0, float(predictions[i][2]))\n            \n            # Calculate derived values\n            dry_total = dry_clover + dry_dead + dry_green\n            gdm = max(0, dry_total - dry_dead)  # Ensure non-negative\n            \n            image_predictions[img_path] = {\n                'Dry_Clover_g': dry_clover,\n                'Dry_Dead_g': dry_dead,\n                'Dry_Green_g': dry_green,\n                'Dry_Total_g': dry_total,\n                'GDM_g': gdm\n            }\n        \n        if batch_idx % 10 == 0:\n            print(f\"Processed {batch_idx * len(images)} images...\")\n\n# Create submission dataframe\nsubmission_rows = []\n\nfor idx, row in test_df.iterrows():\n    sample_id = row['sample_id']\n    img_path = row['image_path']\n    target_name = row['target_name']\n    \n    if img_path in image_predictions:\n        prediction = image_predictions[img_path][target_name]\n    else:\n        prediction = 0.0\n    \n    submission_rows.append({\n        'sample_id': sample_id,\n        'target': float(prediction)\n    })\n\nsubmission_df = pd.DataFrame(submission_rows)\n\n# Save submission\nsubmission_path = '/kaggle/working/submission.csv'\nsubmission_df.to_csv(submission_path, index=False)\nprint(f\"\\nSubmission saved to {submission_path}\")\nprint(f\"Total predictions: {len(submission_df)}\")\n\n# Show sample of predictions\nprint(\"\\nSample predictions:\")\nprint(submission_df.head(15))\n\n# Calculate some statistics\nif img_path in image_predictions:\n    print(\"\\nSample prediction for one image:\")\n    sample_img = list(image_predictions.keys())[0]\n    print(f\"Image: {sample_img}\")\n    for key, value in image_predictions[sample_img].items():\n        print(f\"  {key}: {value:.4f}\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-12-02T08:30:57.228055Z","iopub.execute_input":"2025-12-02T08:30:57.228356Z","iopub.status.idle":"2025-12-02T08:31:16.272278Z","shell.execute_reply.started":"2025-12-02T08:30:57.228328Z","shell.execute_reply":"2025-12-02T08:31:16.271297Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}