{"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":671394,"sourceType":"modelInstanceVersion","modelInstanceId":508588,"modelId":523251}],"dockerImageVersionId":31193,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport cv2\nimport time\nimport random\nimport numpy as np\nimport pandas as pd\nimport torch\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\nimport matplotlib.pyplot as plt\nimport timm\nimport torchvision.transforms as T\nimport random\nimport PIL.Image as Image\nBASE_DIR = \"/kaggle/input/csiro-biomass/\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T13:53:58.559308Z","iopub.execute_input":"2025-12-04T13:53:58.559571Z","iopub.status.idle":"2025-12-04T13:54:03.890357Z","shell.execute_reply.started":"2025-12-04T13:53:58.559551Z","shell.execute_reply":"2025-12-04T13:54:03.889721Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#timm.list_models()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T13:54:03.891511Z","iopub.execute_input":"2025-12-04T13:54:03.891779Z","iopub.status.idle":"2025-12-04T13:54:03.895040Z","shell.execute_reply.started":"2025-12-04T13:54:03.891759Z","shell.execute_reply":"2025-12-04T13:54:03.894384Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"torch.cuda.is_available()\nos.cpu_count()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T13:54:03.895670Z","iopub.execute_input":"2025-12-04T13:54:03.895870Z","iopub.status.idle":"2025-12-04T13:54:03.965511Z","shell.execute_reply.started":"2025-12-04T13:54:03.895853Z","shell.execute_reply":"2025-12-04T13:54:03.964747Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"prev = pd.read_csv(f'{BASE_DIR}sample_submission.csv')\nprev","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T13:54:03.967714Z","iopub.execute_input":"2025-12-04T13:54:03.968000Z","iopub.status.idle":"2025-12-04T13:54:03.994354Z","shell.execute_reply.started":"2025-12-04T13:54:03.967980Z","shell.execute_reply":"2025-12-04T13:54:03.993789Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train = pd.read_csv(f'{BASE_DIR}train.csv')\n\ntest = pd.read_csv(f'{BASE_DIR}test.csv')\n#example to see an image\ni = random.randint(0, len(train))\nprint(\"Target: {}, Image Path: {}\".format(train['target'][i], train['image_path'][i]))\nImage.open(\"/kaggle/input/csiro-biomass/\" + train['image_path'][i])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T13:54:03.995028Z","iopub.execute_input":"2025-12-04T13:54:03.995279Z","iopub.status.idle":"2025-12-04T13:54:04.564043Z","shell.execute_reply.started":"2025-12-04T13:54:03.995258Z","shell.execute_reply":"2025-12-04T13:54:04.562698Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class Config:\n    SEED = 42             # Şans faktörünü sabitlemek için (Her çalıştırışta aynı sonucu almak)\n    IMG_SIZE = 512        # Doku ve gölgeleri görebilmek için yüksek çözünürlük seçtik\n    BATCH_SIZE = 16       # GPU hafızasına göre artırıp azaltabilirsin (8, 16, 32)\n    EPOCHS = 0         # Modeli kaç tur eğiteceğiz?\n    LEARNING_RATE = 0.0001  # Öğrenme hızı (Çok büyük olursa ezberler, küçük olursa öğrenmez)\n    MODEL_NAME = 'tf_efficientnet_b0_ns' # Seçtiğimiz model (Noisy Student ağırlıklarıyla)\n    TARGET_COLS = [\"Dry_Clover_g\", \"Dry_Dead_g\", \"Dry_Green_g\", \"Dry_Total_g\", \"GDM_g\"]\n    NUM_CLASSES = 5 # Çıkış sayısı artık 5\n    DEVICE = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\n# Rastgeleliği sabitleme fonksiyonu (Tekrarlanabilirlik için şart)\ndef seed_everything(seed):\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.backends.cudnn.deterministic = True\n\nseed_everything(Config.SEED)\n# print(f\"Cihaz kullanılıyor: {Config.DEVICE}\") # Bu satırı aşağıya taşıdık","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T13:54:04.565749Z","iopub.execute_input":"2025-12-04T13:54:04.566108Z","iopub.status.idle":"2025-12-04T13:54:04.575748Z","shell.execute_reply.started":"2025-12-04T13:54:04.566062Z","shell.execute_reply":"2025-12-04T13:54:04.574934Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class BiomassDataset(Dataset):\n    def __init__(self, df, img_dir, transform=None, mode='train'):\n        self.df = df\n        self.img_dir = img_dir\n        self.transform = transform\n        self.mode = mode\n        \n        self.img_ids = df['image_path'].values\n        if self.mode == 'train':\n            self.targets = df[Config.TARGET_COLS].values\n\n    def __len__(self):\n        return len(self.df)\n    \n    def __getitem__(self, idx):\n        # 1. Resmi Bul ve Oku\n        img_name = self.img_ids[idx]\n        img_path = os.path.join(self.img_dir, img_name)\n        \n        image = cv2.imread(img_path)\n        if image is None:\n            raise FileNotFoundError(f\"Resim bulunamadı: {img_path}\")\n        \n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # BGR -> RGB\n        \n        # 2. Augmentation (Veri Çoğaltma/İşleme)\n        if self.transform:\n            # Torchvision için:\n            image = self.transform(image)\n            \n        # 3. Eğer Test modundaysak sadece resmi döndür\n        if self.mode == 'test':\n            return image\n        \n        # 4. Train modundaysak Resmi ve Hedefi döndür\n        target = self.targets[idx]\n        # Target'ı float32 tensor yapıyoruz (Regresyon için şart)\n        return image, torch.tensor(target, dtype=torch.float32)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T13:54:04.576622Z","iopub.execute_input":"2025-12-04T13:54:04.576833Z","iopub.status.idle":"2025-12-04T13:54:04.600335Z","shell.execute_reply.started":"2025-12-04T13:54:04.576816Z","shell.execute_reply":"2025-12-04T13:54:04.599454Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# --- AUGMENTATION AYARLARI ---\ndef get_transforms(data='train'):\n    if data == 'train':\n        return T.Compose([\n            T.ToPILImage(),\n            T.Resize((Config.IMG_SIZE, Config.IMG_SIZE)),\n            T.RandomHorizontalFlip(),\n            T.RandomVerticalFlip(),\n            T.RandomRotation(30),\n            T.ToTensor(),\n            T.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n        ])\n    else:\n        return T.Compose([\n            T.ToPILImage(),\n            T.Resize((Config.IMG_SIZE, Config.IMG_SIZE)),\n            T.ToTensor(),\n            T.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n        ])\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T13:54:04.601404Z","iopub.execute_input":"2025-12-04T13:54:04.601795Z","iopub.status.idle":"2025-12-04T13:54:04.622488Z","shell.execute_reply.started":"2025-12-04T13:54:04.601766Z","shell.execute_reply":"2025-12-04T13:54:04.621776Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\nclass BiomassModel(nn.Module):\n    def __init__(self, model_name=Config.MODEL_NAME, pretrained=False):\n        super(BiomassModel, self).__init__()\n        \n        self.backbone = timm.create_model(model_name, pretrained=pretrained, num_classes=0)\n\n        in_feature = self.backbone.num_features\n\n        self.head = nn.Sequential(\n            nn.Linear(in_feature, 512),\n            nn.ReLU(),\n            nn.Dropout(0.2),\n            nn.Linear(512, 5)\n        )\n\n    # Alternatif Constructor (Pythonic Yöntem)\n    @classmethod\n    def from_path(cls, model_path, model_name=Config.MODEL_NAME):\n        # Önce modeli oluştur (Ağırlık yükleyeceğimiz için pretrained=False olabilir ama True da zarar vermez)\n        model = cls(model_name=model_name, pretrained=False)\n        \n        # Kayıtlı ağırlıkları yükle\n        model.load_state_dict(torch.load(model_path, map_location=Config.DEVICE))\n        return model\n\n    def forward(self, x):\n        features = self.backbone(x)\n\n        scores = self.head(features)\n\n        return scores","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T13:54:04.623530Z","iopub.execute_input":"2025-12-04T13:54:04.623736Z","iopub.status.idle":"2025-12-04T13:54:04.640077Z","shell.execute_reply.started":"2025-12-04T13:54:04.623716Z","shell.execute_reply":"2025-12-04T13:54:04.639509Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def test_model(model, image):\n    image = image.to(Config.DEVICE)\n    with torch.no_grad():\n        scores = model(image)\n    return scores\n\n# image = cv2.imread(\"./test/ID1001187975.jpg\")\n# image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n# transforms = get_transforms('valid')\n# transformed = transforms(image=image)\n# tensor = transformed['image'] # Şu an boyutu: (3, 512, 512)\n# tensor = tensor.unsqueeze(0)\n\n\ndef train_model(model, train_loader, val_loader):\n    model.to(Config.DEVICE)\n    print(\"Multiple GPUs:\", torch.cuda.device_count())\n    model = torch.nn.DataParallel(model)\n\n    criterion = nn.MSELoss()\n    optimizer = optim.AdamW(params = model.parameters(), lr = Config.LEARNING_RATE)\n\n    best_loss = float('inf')\n\n    for epoch in range(Config.EPOCHS):\n        print(\"Train :Epoch basladi {}\".format(epoch))\n        model.train()\n\n        train_loss = 0.0\n        \n        # enumerate ekledik ki batch numarasını görelim\n        for i, (images, targets) in enumerate(train_loader):       \n            images, targets = images.to(Config.DEVICE), targets.to(Config.DEVICE)\n\n            model.zero_grad()\n\n            scores = model(images)\n\n            loss = criterion(scores, targets)\n            loss.backward()\n            optimizer.step()\n\n            train_loss += loss.item()\n            \n\n            # Bir sonraki döngü için veri yükleme zamanlayıcısını sıfırla\n            t0 = time.time()\n\n        avg_train_loss = train_loss / len(train_loader)\n        print(\"Train :Epoch bitti {}\".format(epoch))\n        model.eval()\n        val_loss = 0.0\n        print(\"Val :Epoch basladi {}\".format(epoch))\n        with torch.no_grad():\n            for images, targets in val_loader:\n                images, targets = images.to(Config.DEVICE), targets.to(Config.DEVICE)\n\n                scores = model(images)\n\n                loss = criterion(scores, targets)\n                val_loss += loss.item()\n\n            avg_val_loss = val_loss / len(val_loader)\n\n        if avg_val_loss < best_loss:\n            # Val loader'dan bir batch al\n            image, target = next(iter(val_loader))\n            image, target = image.to(Config.DEVICE), target.to(Config.DEVICE)\n        \n            model.eval()\n            with torch.no_grad():\n                scores = model(image)\n        \n            # Scores'u target ile aynı aralığa getir (sadece görüntüleme için)\n            scores_post = torch.clamp(scores, min=0)\n        \n            best_loss = avg_val_loss\n            torch.save(model.state_dict(), \"best_model.pth\")\n            print(\"En iyi model kaydedildi, Loss : {}, Scores : {}, Target : {}\".format(best_loss, scores[0], target[0]))\n        print(\"Val :Epoch bitti{}\".format(epoch))\n        print(\"Epoch {} : Train Loss {}, Validation Loss {}\".format(epoch + 1, avg_train_loss, avg_val_loss))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T13:54:04.641938Z","iopub.execute_input":"2025-12-04T13:54:04.642184Z","iopub.status.idle":"2025-12-04T13:54:04.662730Z","shell.execute_reply.started":"2025-12-04T13:54:04.642167Z","shell.execute_reply":"2025-12-04T13:54:04.662160Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(f\"Cihaz kullanılıyor: {Config.DEVICE}\")\n# --- VERİ YOLUNU AYARLA ---\n# NOT: Burayı kendi Kaggle veri yoluna göre güncellemelisin!\nTRAIN_CSV = f\"{BASE_DIR}/train.csv\"\nTRAIN_IMG_DIR = f\"{BASE_DIR}\"\n\n# 1. CSV'yi Oku\ndf = pd.read_csv(TRAIN_CSV)\n\ntry:\n    if 'image_path' in df.columns:\n\n        df['image_id'] = df['image_path'].apply(lambda x: os.path.basename(x))\n\n        # 2. PIVOT İŞLEMİ (Sihirli Dokunuş)\n        # Satırları sütuna çeviriyoruz\n        # DÜZELTME: image_path bilgisini de index'e ekliyoruz ki kaybolmasın\n        df_pivot =df.pivot_table(index=['image_id', 'image_path'], columns='target_name', values='target').reset_index()\n\n        # Sütunların sırasını garantiye alalım (Karışıklık olmasın)\n        df_pivot = df_pivot[['image_id', 'image_path'] + Config.TARGET_COLS]\n    \n        print(\"Pivot işlemi başarılı! Veri seti 'Wide' formata çevrildi.\")\n        df = df_pivot # Artık ana verimiz bu\n    \nexcept KeyError as e:\n    print(f\"Hata oluştu: {e}\")\n    print(\"Veri zaten Wide formatta olabilir veya sütun isimleri farklı. Lütfen df.head() kontrol et.\")\n\n# Kontrol edelim\nprint(f\"Yeni Veri Seti Boyutu: {len(df)}\")\n\n# print(f\"Toplam Veri Sayısı: {len(df)}\")\n\n# # 2. Train / Validation Diye Böl (%80 Eğitim - %20 Doğrulama)\ntrain_df, val_df = train_test_split(df, test_size=0.2, random_state=Config.SEED)\n\nprint(f\"Eğitim Seti: {len(train_df)} resim\")\nprint(f\"Doğrulama Seti: {len(val_df)} resim\")\n\n# 3. Dataset ve DataLoader Oluştur\ntrain_dataset = BiomassDataset(train_df, TRAIN_IMG_DIR, transform=get_transforms('train'))\nval_dataset = BiomassDataset(val_df, TRAIN_IMG_DIR, transform=get_transforms('valid'))\n\ntrain_loader = DataLoader(train_dataset, batch_size=Config.BATCH_SIZE, shuffle=True, num_workers=2, pin_memory=False)\nval_loader = DataLoader(val_dataset, batch_size=Config.BATCH_SIZE, shuffle=False, num_workers=2, pin_memory=False)\n\n# --- KONTROL ---\n# DataLoader'dan bir paket (batch) çekip boyutlarına bakalım\nimages, targets = next(iter(train_loader))\nprint(f\"\\nBatch Boyutları:\")\nprint(f\"Resimler: {images.shape} (Batch, Kanal, Yükseklik, Genişlik)\")\nprint(f\"Hedefler: {targets.shape}\")\n\nmodel = BiomassModel()\nstate_dict = torch.load(\"/kaggle/input/best-model/pytorch/default/1/best_model.pth\")\nnew_state_dict = {}\nfor k, v in state_dict.items():\n    name = k.replace(\"module.\", \"\") # 'module.' öneki kaldırılıyor\n    new_state_dict[name] = v\n\nmodel.load_state_dict(new_state_dict)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T13:54:04.663575Z","iopub.execute_input":"2025-12-04T13:54:04.663954Z","iopub.status.idle":"2025-12-04T13:54:07.923703Z","shell.execute_reply.started":"2025-12-04T13:54:04.663933Z","shell.execute_reply":"2025-12-04T13:54:07.922893Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_model(model, train_loader=train_loader, val_loader=val_loader)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T13:54:07.924725Z","iopub.execute_input":"2025-12-04T13:54:07.924967Z","iopub.status.idle":"2025-12-04T13:54:07.947679Z","shell.execute_reply.started":"2025-12-04T13:54:07.924946Z","shell.execute_reply":"2025-12-04T13:54:07.947082Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport torch\nfrom PIL import Image\nfrom torchvision import transforms as T\nfrom tqdm import tqdm\nimport os\n\n# Ayarlar\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel.to(device)\nmodel.eval()\n\n# Dönüşümler\ntransform = T.Compose([\n    T.Resize((Config.IMG_SIZE, Config.IMG_SIZE)),\n    T.ToTensor(),\n    T.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])\n])\n\n# Test verisini oku\ntest_df = pd.read_csv(\"/kaggle/input/csiro-biomass/test.csv\")\n# EĞER sample_submission varsa onu da okumak ID formatını görmek için iyidir, \n# ama burada test_df üzerinden gidiyoruz.\n\n# 1. Tahminleri Tutacak Sözlük (Dictionary)\n# Key: image_path, Value: [tahmin_vektörü]\npreds_dict = {}\n\nunique_image_paths = test_df['image_path'].unique()\n\nprint(f\"Toplam {len(unique_image_paths)} benzersiz resim için tahmin yapılıyor...\")\n\nwith torch.no_grad():\n    for img_path in tqdm(unique_image_paths):\n        full_path = os.path.join(BASE_DIR, img_path)\n        \n        try:\n            # Resmi aç\n            img = Image.open(full_path).convert('RGB')\n            x = transform(img).unsqueeze(0).to(device)\n            \n            # Tahmin\n            y_pred = model(x)\n            # Tensor'u numpy array'e çevir ve sözlüğe kaydet\n            preds_dict[img_path] = y_pred.squeeze().cpu().numpy()\n            \n        except Exception as e:\n            # Hata durumunda (resim bozuksa vs) kodun patlamasını engelle\n            # Ortalama bir değer veya 0 atayabilirsin\n            print(f\"Hata: {img_path} okunamadı. {e}\")\n            preds_dict[img_path] = [0, 0, 0, 0, 0] # 5 tane 0 (Safe Mode)\n\n# 2. Submission Dosyasını Oluşturma\nsubmission_rows = []\n\n# Buradaki mantık: Her bir resim için 5 hedef sütunu (Target Cols) dönüyoruz.\n# Kaggle genellikle sample_id formatını şöyle ister: {dosya_adi}__{hedef_adi}\n# Ancak en garantisi dosya ismini path'ten temiz bir şekilde almaktır.\n\nfor img_path in unique_image_paths:\n    # Tahminleri sözlükten çek\n    preds = preds_dict.get(img_path, [0]*5)\n    \n    # Dosya ismini (ID) güvenli alma\n    # os.path.splitext uzantıyı (.jpg) ne olursa olsun güvenli ayırır\n    file_name = os.path.basename(img_path) # test/im_123.jpg -> im_123.jpg\n    image_id = os.path.splitext(file_name)[0] # im_123.jpg -> im_123\n    \n    for i, target_col in enumerate(Config.TARGET_COLS):\n        submission_rows.append({\n            'sample_id': f\"{image_id}__{target_col}\",\n            'target': preds[i]\n        })\n\nsubmission_df = pd.DataFrame(submission_rows)\nsubmission_df.to_csv(\"submission.csv\", index=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-04T13:54:07.948394Z","iopub.execute_input":"2025-12-04T13:54:07.948662Z","iopub.status.idle":"2025-12-04T13:54:08.375811Z","shell.execute_reply.started":"2025-12-04T13:54:07.948638Z","shell.execute_reply":"2025-12-04T13:54:08.374922Z"}},"outputs":[],"execution_count":null}]}