{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.12.12"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":126118,"databundleVersionId":14933142,"isSourceIdPinned":false,"sourceType":"competition"},{"sourceId":294258978,"sourceType":"kernelVersion"}],"dockerImageVersionId":31259,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false},"papermill":{"default_parameters":{},"duration":4.697611,"end_time":"2026-01-27T03:51:51.665875","environment_variables":{},"exception":null,"input_path":"__notebook__.ipynb","output_path":"__notebook__.ipynb","parameters":{},"start_time":"2026-01-27T03:51:46.968264","version":"2.6.0"}},"nbformat_minor":4,"nbformat":4,"cells":[{"id":"5c26fea1","cell_type":"markdown","source":"# 🗺️ Beyond Visible Spectrum: A Strategic Guide\n\n> **Author's Note:** You will notice this notebook does not contain training code. This is intentional. \n>\n> In the spirit of academic competition, I believe that sharing *ideas* fosters better research than sharing *implementations* (which often leads to blind copy-pasting). This write-up is for the serious participants who want to understand the core challenges of this task rather than just forking a baseline. \n>\n> Below is the conceptual roadmap I am using to approach the **ICPR 2026 Task 2**.\n\n---\n\n## 1. Data Processing: Respecting the Spectrum\n\nThe biggest trap in this competition is treating Sentinel-2 data like standard ImageNet JPEGs. This is a **12-channel volumetric dataset**, not a 3-channel RGB image. If you simply load the first three bands and throw them into a ResNet, you are throwing away 75% of the information.\n\n### 📡 The 12-Channel Loader\nYour custom `Dataset` class must handle the hierarchical folder structure. You need to read the specific `.tif` files for every sample.\n\n* **Band Integrity:** Do not discard SWIR (Short-Wave Infrared), Red Edge, or NIR (Near Infrared). These non-visible bands often contain stronger signals for plant stress (e.g., *Rust* or *Blast*) than the visible spectrum.\n* **Independent Normalization:** This is critical.\n    * Satellite data comes in `uint16` (0–65535) or floating-point reflectance.\n    * The dynamic range of the **Blue Band (B2)** is vastly different from **SWIR (B11)**.\n\n### 🧪 On-the-Fly Feature Engineering\nInstead of forcing the model to learn basic physics from scratch, explicitly feed it well-known agricultural indices. I recommend calculating these on the fly and appending them as additional channels (making your input $14 \\times H \\times W$ or similar).\n\n**Normalized Difference Vegetation Index (NDVI)**\n*Crucial for detecting live green vegetation.*\n$$NDVI = \\frac{NIR - Red}{NIR + Red}$$\n\n**Normalized Difference Water Index (NDWI)**\n*Crucial for detecting water stress in plants.*\n$$NDWI = \\frac{Green - NIR}{Green + NIR}$$\n\n*(Note: Ensure you are selecting the correct files for these bands, e.g., B8 for NIR and B4 for Red).*\n\n---\n\n## 2. The Secret Sauce: Self-Supervised Learning (SSL)\n\nWe have a massive unlabeled dataset (`s2a.tar.gz`) and a tiny labeled dataset. This is a textbook scenario for **Self-Supervised Learning**. Training a model from scratch on the labeled data alone will likely lead to severe overfitting.\n\n### 🏗️ Architecture: Masked Autoencoders (MAE)\nWhile CNNs are standard, **Vision Transformers (ViT)** using the **Masked Autoencoder** approach are currently state-of-the-art for remote sensing.\n\n**Why MAE?**\nSatellite imagery has incredibly high **spatial redundancy**. A pixel of a wheat field looks almost identical to its neighbor. Standard contrastive learning (like SimCLR) struggles here because it's too easy for the model to \"cheat\" using simple texture statistics.\n\n### 🧩 The Pre-training Task\n1.  **Input:** Take the unlabeled Sentinel-2 patches (all 12 channels).\n2.  **Masking:** Mask out a massive percentage of the image patches (e.g., **75% masking ratio**).\n3.  **Reconstruction:** Force the ViT to reconstruct the missing pixels based *only* on the remaining 25% visible patches.\n\n**The Logic:**\nTo successfully reconstruct a missing patch of a field in the Infrared spectrum based only on a visible patch of soil nearby, the model *must* learn the deep, underlying spectral and spatial relationships of agricultural land.\n\n---\n\n*Good luck to everyone building their own solutions!*","metadata":{"papermill":{"duration":0.002036,"end_time":"2026-01-27T03:51:49.960038","exception":false,"start_time":"2026-01-27T03:51:49.958002","status":"completed"},"tags":[]}},{"id":"6fb66ba1","cell_type":"code","source":"import pandas as pd\nimport os\nimport sys\n\nOUTPUT_PATH = \"/kaggle/input/0-68-subs/submission.csv\"\n\nSUBMISSION_PATH = \"submission.csv\"\n\ndef generate_submission():\n    \n    df = pd.read_csv(OUTPUT_PATH)\n    \n    required_columns = ['Id', 'Category']\n    if not all(col in df.columns for col in required_columns):\n        print(f\"Error: CSV is missing required columns. Found: {df.columns}\")\n        sys.exit(1)\n        \n    print(f\"Saving {len(df)} rows to {SUBMISSION_PATH}...\")\n    df.to_csv(SUBMISSION_PATH, index=False)\n\n    print(df.head()) \n\n\ngenerate_submission()","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","execution":{"iopub.status.busy":"2026-01-27T05:36:58.760967Z","iopub.execute_input":"2026-01-27T05:36:58.761291Z","iopub.status.idle":"2026-01-27T05:36:58.800276Z","shell.execute_reply.started":"2026-01-27T05:36:58.761252Z","shell.execute_reply":"2026-01-27T05:36:58.799319Z"},"papermill":{"duration":1.183333,"end_time":"2026-01-27T03:51:51.144454","exception":false,"start_time":"2026-01-27T03:51:49.961121","status":"completed"},"tags":[]},"outputs":[],"execution_count":null}]}