{"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":"none","dataSources":[{"sourceId":112509,"databundleVersionId":14254895,"sourceType":"competition"}],"dockerImageVersionId":31259,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"\"\"\"\n================================================================================\nCSIRO IMAGE2BIOMASS - SUBMISSION FORMAT FIX\n================================================================================\nFixed: \"Submission Scoring Error\" - Guaranteed correct format\nCritical: Handles hidden test set that may be different from public\n================================================================================\n\"\"\"\n\n# ==============================================================================\n# CELL 1: MINIMAL IMPORTS (FAST & SAFE)\n# ==============================================================================\nimport warnings\nwarnings.filterwarnings('ignore')\n\nimport numpy as np\nimport pandas as pd\nimport torch\nimport torch.nn as nn\nfrom torch.utils.data import Dataset, DataLoader\nimport cv2\nimport os\nimport gc\nfrom pathlib import Path\n\ntry:\n    import timm\n    import albumentations as A\n    from albumentations.pytorch import ToTensorV2\n    from tqdm.auto import tqdm\n    print(\"✅ All imports successful\")\nexcept Exception as e:\n    print(f\"⚠️ Import warning: {e}\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-01-23T14:54:27.732899Z","iopub.execute_input":"2026-01-23T14:54:27.733258Z","iopub.status.idle":"2026-01-23T14:54:27.740558Z","shell.execute_reply.started":"2026-01-23T14:54:27.733228Z","shell.execute_reply":"2026-01-23T14:54:27.739519Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ==============================================================================\n# CELL 2: SAFE CONFIGURATION\n# ==============================================================================\nclass CFG:\n    # Competition paths\n    data_dir = '/kaggle/input/csiro-biomass'\n    \n    # Simple single-model approach (reliable)\n    model_name = 'efficientnet_b0'\n    img_size = (384, 384)\n    \n    # Training\n    n_folds = 3\n    epochs = 10\n    batch_size = 8\n    lr = 1e-4\n    \n    # CRITICAL: These must match competition exactly\n    target_names = ['Dry_Clover_g', 'Dry_Dead_g', 'Dry_Green_g', 'Dry_Total_g', 'GDM_g']\n    \n    # Device\n    device = 'cuda' if torch.cuda.is_available() else 'cpu'\n    num_workers = 0\n\ndef seed_all(seed=42):\n    import random\n    random.seed(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n\nseed_all(42)\nprint('CFG class done')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-23T14:54:27.742253Z","iopub.execute_input":"2026-01-23T14:54:27.742570Z","iopub.status.idle":"2026-01-23T14:54:27.766396Z","shell.execute_reply.started":"2026-01-23T14:54:27.742544Z","shell.execute_reply":"2026-01-23T14:54:27.765549Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ==============================================================================\n# CELL 3: ROBUST DATA LOADING WITH FORMAT DETECTION\n# ==============================================================================\ndef load_and_validate_data():\n    \"\"\"Load data with extensive validation\"\"\"\n    print(\"=\"*70)\n    print(\"LOADING DATA WITH VALIDATION\")\n    print(\"=\"*70)\n    \n    # Load train and test\n    train = pd.read_csv(f'{CFG.data_dir}/train.csv')\n    test = pd.read_csv(f'{CFG.data_dir}/test.csv')\n    \n    print(f\"Train shape: {train.shape}\")\n    print(f\"Test shape: {test.shape}\")\n    print(f\"Train columns: {list(train.columns)}\")\n    print(f\"Test columns: {list(test.columns)}\")\n    \n    # Extract image IDs - CRITICAL for correct submission format\n    for df in [train, test]:\n        if 'image_path' in df.columns:\n            df['image_id'] = df['image_path'].str.extract(r'(ID\\d+)')[0]\n        elif 'sample_id' in df.columns:\n            df['image_id'] = df['sample_id'].str.extract(r'(ID\\d+)')[0]\n        else:\n            raise ValueError(\"Cannot find image ID column!\")\n    \n    # Handle long format (if needed)\n    if 'target_name' in train.columns and 'target' in train.columns:\n        print(\"📊 Converting from long to wide format...\")\n        \n        # Get unique target names from the data itself\n        actual_targets = sorted(train['target_name'].unique())\n        print(f\"Actual targets in data: {actual_targets}\")\n        \n        # Update CFG with actual targets\n        CFG.target_names = actual_targets\n        \n        train = train.pivot_table(\n            index='image_id',\n            columns='target_name',\n            values='target',\n            aggfunc='first'\n        ).reset_index()\n    \n    # Verify all targets exist\n    missing_targets = [t for t in CFG.target_names if t not in train.columns]\n    if missing_targets:\n        print(f\"⚠️ Missing targets: {missing_targets}\")\n        for t in missing_targets:\n            train[t] = 0.0\n    \n    # Fill missing values\n    for target in CFG.target_names:\n        if target in train.columns:\n            train[target] = train[target].fillna(0.0)\n    \n    # Add simple features\n    train['feature'] = 0.5\n    test['feature'] = 0.5\n    \n    print(f\"\\n✅ Data loaded successfully\")\n    print(f\"Train images: {train['image_id'].nunique()}\")\n    print(f\"Test images: {test['image_id'].nunique()}\")\n    print(f\"Targets: {CFG.target_names}\")\n    \n    return train, test\n\ntrain_df, test_df = load_and_validate_data()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-23T14:54:27.768027Z","iopub.execute_input":"2026-01-23T14:54:27.768312Z","iopub.status.idle":"2026-01-23T14:54:27.816577Z","shell.execute_reply.started":"2026-01-23T14:54:27.768288Z","shell.execute_reply":"2026-01-23T14:54:27.815627Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ==============================================================================\n# CELL 8: CRITICAL - CORRECT SUBMISSION FORMAT\n# ==============================================================================\nimport os\nimport glob\nimport pandas as pd\n\ndef create_zero_submission(data_dir=\"/kaggle/input/csiro-biomass\",\n                           target_names=(\"Dry_Clover_g\",\"Dry_Dead_g\",\"Dry_Green_g\",\"Dry_Total_g\",\"GDM_g\"),\n                           out_path=\"submission.csv\"):\n    # Find test image directory (hidden test images appear here at scoring time)\n    test_img_dir = os.path.join(data_dir, \"test_images\")\n    if not os.path.exists(test_img_dir):\n        test_img_dir = os.path.join(data_dir, \"test\")\n\n    # Collect image IDs from actual files (robust to hidden test set differences)\n    exts = (\"*.jpg\", \"*.jpeg\", \"*.png\", \"*.JPG\", \"*.JPEG\", \"*.PNG\")\n    img_paths = []\n    for e in exts:\n        img_paths.extend(glob.glob(os.path.join(test_img_dir, e)))\n\n    if len(img_paths) == 0:\n        raise FileNotFoundError(f\"No images found under: {test_img_dir}\")\n\n    # Sort for deterministic output\n    img_ids = sorted(os.path.splitext(os.path.basename(p))[0] for p in img_paths)\n\n    # Build submission rows: 5 targets per image, exact format IDxxxx__TargetName\n    rows = []\n    for img_id in img_ids:\n        for t in target_names:\n            rows.append({\"sample_id\": f\"{img_id}__{t}\", \"target\": 0.0})\n\n    submission = pd.DataFrame(rows, columns=[\"sample_id\", \"target\"])\n    submission.to_csv(out_path, index=False)\n\n    print(f\"Saved {out_path}\")\n    print(\"Test image dir:\", test_img_dir)\n    print(\"Num images:\", len(img_ids))\n    print(\"Num rows:\", len(submission))\n    print(submission.head(10))\n\n    return submission\n\n# Create submission.csv with all zeros\nsubmission = create_zero_submission()\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-23T14:54:27.817818Z","iopub.execute_input":"2026-01-23T14:54:27.818288Z","iopub.status.idle":"2026-01-23T14:54:27.836990Z","shell.execute_reply.started":"2026-01-23T14:54:27.818246Z","shell.execute_reply":"2026-01-23T14:54:27.835983Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ==============================================================================\n# CELL 9: FINAL VALIDATION\n# ==============================================================================\n\nprint(\"\\n\" + \"=\"*70)\nprint(\"FINAL FILE VALIDATION\")\nprint(\"=\"*70)\n\n# Load saved file to verify\ntry:\n    sub_check = pd.read_csv('submission.csv')\n    \n    print(f\"✅ File loaded: {len(sub_check):,} rows\")\n    print(f\"✅ Columns: {list(sub_check.columns)}\")\n    print(f\"✅ Sample IDs format: {sub_check['sample_id'].iloc[0]}\")\n    print(f\"✅ Target range: [{sub_check['target'].min():.2f}, {sub_check['target'].max():.2f}]\")\n    print(f\"✅ No NaN: {sub_check['target'].notna().all()}\")\n    print(f\"✅ All positive: {(sub_check['target'] >= 0).all()}\")\n    \n    print(\"\\n\" + \"=\"*70)\n    print(\"🎉 ALL CHECKS PASSED - READY TO SUBMIT!\")\n    print(\"=\"*70)\n    \nexcept Exception as e:\n    print(f\"❌ ERROR loading submission: {e}\")\n\nprint(\"\\n📝 SUBMISSION READY!\")\nprint(\"Upload submission.csv to competition\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-23T14:54:27.906321Z","iopub.execute_input":"2026-01-23T14:54:27.907024Z","iopub.status.idle":"2026-01-23T14:54:27.918368Z","shell.execute_reply.started":"2026-01-23T14:54:27.906990Z","shell.execute_reply":"2026-01-23T14:54:27.917379Z"}},"outputs":[],"execution_count":null}]}