{"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":"gpu","dataSources":[{"sourceId":117682,"databundleVersionId":14443416,"sourceType":"competition"}],"dockerImageVersionId":31193,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# Install Segmentation Models Pytorch (SMP) langsung dari internet\n!pip install segmentation-models-pytorch\n\nimport os\nimport cv2\nimport numpy as np\nimport pandas as pd\nimport torch\nfrom torch.utils.data import Dataset, DataLoader\nimport segmentation_models_pytorch as smp\nfrom tqdm.notebook import tqdm\n\n# Konfigurasi\nDEVICE = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nBATCH_SIZE = 16 # Turunkan kalau Out Of Memory (OOM)\nEPOCHS = 5      # Tambah jadi 10-20 kalau mau hasil bagus\nLR = 1e-4\nMODEL_NAME = \"model_v3_final.pth\" # Nama file output nanti","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-12-06T16:48:42.300526Z","iopub.execute_input":"2025-12-06T16:48:42.300794Z","iopub.status.idle":"2025-12-06T16:49:59.338158Z","shell.execute_reply.started":"2025-12-06T16:48:42.300768Z","shell.execute_reply":"2025-12-06T16:49:59.337539Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class VesuviusDataset(Dataset):\n    def __init__(self, df, mode='train'):\n        self.df = df\n        self.mode = mode\n        # Path folder data kompetisi\n        self.root_dir = \"/kaggle/input/vesuvius-challenge-surface-detection\"\n        \n    def __len__(self):\n        return len(self.df)\n    \n    def __getitem__(self, idx):\n        # Logika loading data Vesuvius itu agak rumit karena .tif\n        # Ini contoh simplified logic (konsepnya):\n        \n        # 1. Ambil ID gambar dan label\n        # (Di kompetisi aslinya kamu perlu load 65 slice .tif lalu di-stack)\n        # Untuk kerangka ini, kita anggap load gambar dummy/simple dulu\n        # supaya kodenya jalan.\n        \n        # --- PLACEHOLDER CODE (Ganti dengan Logic Loader Vesuvius Asli) ---\n        # Anggap kita punya gambar ukuran 256x256\n        image = np.zeros((256, 256, 3), dtype=np.float32) \n        mask = np.zeros((256, 256), dtype=np.float32)\n        # ------------------------------------------------------------------\n        \n        # Konversi ke Tensor PyTorch\n        image = np.transpose(image, (2, 0, 1)) # Channel first\n        image = torch.tensor(image)\n        mask = torch.tensor(mask).unsqueeze(0) # Tambah channel dimension\n        \n        return image, mask\n\n# Dummy DataFrame (Ganti dengan logic pembagian data aslimu)\n# Di Vesuvius biasanya kita memotong-motong gambar besar (tiles)\ndummy_df = pd.DataFrame({'id': range(100)}) \n\n# Buat DataLoader\ntrain_dataset = VesuviusDataset(dummy_df, mode='train')\ntrain_loader = DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-06T16:49:59.341769Z","iopub.execute_input":"2025-12-06T16:49:59.341994Z","iopub.status.idle":"2025-12-06T16:49:59.350423Z","shell.execute_reply.started":"2025-12-06T16:49:59.341960Z","shell.execute_reply":"2025-12-06T16:49:59.349748Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 1. Buat Model\nmodel = smp.Unet(\n    encoder_name=\"resnet34\",\n    encoder_weights=\"imagenet\", # ✅ BISA DOWNLOAD KARENA INTERNET ON\n    in_channels=3,              # Sesuaikan dengan input kamu\n    classes=1,\n    activation=None\n).to(DEVICE)\n\n# 2. Optimizer & Loss\noptimizer = torch.optim.Adam(model.parameters(), lr=LR)\ncriterion = torch.nn.BCEWithLogitsLoss()\n\nprint(\"🚀 Mulai Training...\")\n\n# 3. Loop Training\nfor epoch in range(EPOCHS):\n    model.train()\n    epoch_loss = 0\n    \n    # Pakai tqdm untuk progress bar\n    bar = tqdm(train_loader, desc=f\"Epoch {epoch+1}/{EPOCHS}\")\n    \n    for images, masks in bar:\n        images = images.to(DEVICE)\n        masks = masks.to(DEVICE)\n        \n        optimizer.zero_grad()\n        \n        # Forward pass\n        outputs = model(images)\n        loss = criterion(outputs, masks)\n        \n        # Backward pass\n        loss.backward()\n        optimizer.step()\n        \n        epoch_loss += loss.item()\n        bar.set_postfix(loss=loss.item())\n    \n    print(f\"Epoch {epoch+1} selesai. Rata-rata Loss: {epoch_loss / len(train_loader)}\")\n\n# 4. PENYIMPANAN MODEL (INI YANG PALING PENTING)\ntorch.save(model.state_dict(), MODEL_NAME)\nprint(f\"✅ Model berhasil disimpan sebagai: {MODEL_NAME}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-06T16:49:59.351581Z","iopub.execute_input":"2025-12-06T16:49:59.351826Z","iopub.status.idle":"2025-12-06T16:50:10.552725Z","shell.execute_reply.started":"2025-12-06T16:49:59.351810Z","shell.execute_reply":"2025-12-06T16:50:10.552018Z"}},"outputs":[],"execution_count":null}]}