{"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":"nvidiaTeslaT4","dataSources":[{"sourceType":"competition","sourceId":125281,"databundleVersionId":14781158}],"dockerImageVersionId":31287,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"### Bu çalışmanın amacı, PyTorch kullanarak uydu görüntülerinden arazi kullanım sınıflarını yüksek doğrulukla tahmin eden bir derin öğrenme modeli geliştirmektir","metadata":{}},{"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-02-26T07:59:00.559180Z","iopub.execute_input":"2026-02-26T07:59:00.559480Z","iopub.status.idle":"2026-02-26T07:59:00.868447Z","shell.execute_reply.started":"2026-02-26T07:59:00.559446Z","shell.execute_reply":"2026-02-26T07:59:00.867678Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import torch\nfrom torch.utils.data import Dataset, DataLoader, Subset\nfrom torchvision import transforms\nfrom sklearn.model_selection import train_test_split\nimport random","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T07:59:00.869510Z","iopub.execute_input":"2026-02-26T07:59:00.870036Z","iopub.status.idle":"2026-02-26T07:59:04.291756Z","shell.execute_reply.started":"2026-02-26T07:59:00.870009Z","shell.execute_reply":"2026-02-26T07:59:04.290959Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class SatelliteDataset(Dataset):\n    def __init__(self, npz_file, mode='train', transform=None):\n        data = np.load(npz_file)\n        self.images = data['x']          # (N, 64, 64, 3)\n        self.mode = mode\n        self.transform = transform\n        if mode == 'train':\n            self.labels = data['y']\n\n    def __len__(self):\n        return len(self.images)\n\n    def __getitem__(self, idx):\n        img = self.images[idx]\n\n        if self.transform:\n            img = self.transform(img)\n\n        if self.mode == 'train':\n            label = torch.tensor(self.labels[idx], dtype=torch.long)\n            return img, label\n        else:\n            return img","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T07:59:04.292726Z","iopub.execute_input":"2026-02-26T07:59:04.293170Z","iopub.status.idle":"2026-02-26T07:59:04.299148Z","shell.execute_reply.started":"2026-02-26T07:59:04.293144Z","shell.execute_reply":"2026-02-26T07:59:04.298459Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"data = np.load(\"/kaggle/input/cugb-ml-2025-cnn/train.npz\")\nprint(data.files)\nprint(data['x'].shape)\nprint(data['y'].shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T07:59:04.300068Z","iopub.execute_input":"2026-02-26T07:59:04.300768Z","iopub.status.idle":"2026-02-26T07:59:06.188259Z","shell.execute_reply.started":"2026-02-26T07:59:04.300743Z","shell.execute_reply":"2026-02-26T07:59:06.187561Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"##### Simple Transform( No Augmentation At first- Just Transform to Tensor)","metadata":{}},{"cell_type":"code","source":"transform = transforms.Compose([\n    transforms.ToTensor()\n])\n\n\n### Bu ne yapar?\n\n# (64,64,3) → (3,64,64)\n\n# uint8 → float\n\n# 0-255 → 0-1\n\n# Bu olmadan CNN calismazdi.","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T07:59:06.189191Z","iopub.execute_input":"2026-02-26T07:59:06.189454Z","iopub.status.idle":"2026-02-26T07:59:06.192941Z","shell.execute_reply.started":"2026-02-26T07:59:06.189419Z","shell.execute_reply":"2026-02-26T07:59:06.192279Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"##### Create Dataset","metadata":{}},{"cell_type":"code","source":"TRAIN_PATH = \"/kaggle/input/cugb-ml-2025-cnn/train.npz\"\nTEST_PATH  = \"/kaggle/input/cugb-ml-2025-cnn/test.npz\"\n\ntrain_dataset = SatelliteDataset(TRAIN_PATH, mode='train', transform=transform)\n# mevcut train datasini okuduk. goruntu de var , label da var.\ntest_dataset  = SatelliteDataset(TEST_PATH, mode='test', transform=transform)\n# mevcut test datasini okuduk. goruntu var , label yok.","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T07:59:06.193815Z","iopub.execute_input":"2026-02-26T07:59:06.194042Z","iopub.status.idle":"2026-02-26T07:59:08.526930Z","shell.execute_reply.started":"2026-02-26T07:59:06.194023Z","shell.execute_reply":"2026-02-26T07:59:08.526070Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#✔ .npz okuduk\n#✔ Custom Dataset yazdık\n#✔ Tensor dönüşümü yaptık\n#✔ Batch çekebiliyoruz","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T07:59:08.529682Z","iopub.execute_input":"2026-02-26T07:59:08.529979Z","iopub.status.idle":"2026-02-26T07:59:08.533333Z","shell.execute_reply.started":"2026-02-26T07:59:08.529955Z","shell.execute_reply":"2026-02-26T07:59:08.532696Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"##### Seed asamasi split random olacak","metadata":{}},{"cell_type":"code","source":"import random\ndef seed_everything(seed=42):\n    random.seed(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed_all(seed)\n\nseed_everything(42)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T07:59:08.534403Z","iopub.execute_input":"2026-02-26T07:59:08.534659Z","iopub.status.idle":"2026-02-26T07:59:08.548242Z","shell.execute_reply.started":"2026-02-26T07:59:08.534638Z","shell.execute_reply":"2026-02-26T07:59:08.547696Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"##### Stratified split","metadata":{}},{"cell_type":"code","source":"# Tüm label'ları al\nlabels = train_dataset.labels  # numpy array\n\n# Index üret\nindices = np.arange(len(labels))\n\ntrain_idx, val_idx = train_test_split(\n    indices,\n    test_size=0.2,\n    stratify=labels,\n    random_state=42\n)\n# 10 sınıfın oranı train ve val içinde korunur.  Dengesiz validation oluşmaz.","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T07:59:08.549055Z","iopub.execute_input":"2026-02-26T07:59:08.549331Z","iopub.status.idle":"2026-02-26T07:59:08.566651Z","shell.execute_reply.started":"2026-02-26T07:59:08.549310Z","shell.execute_reply":"2026-02-26T07:59:08.566147Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"##### subset olusturma","metadata":{}},{"cell_type":"code","source":"train_subset = Subset(train_dataset, train_idx)\nval_subset = Subset(train_dataset, val_idx)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T07:59:08.567428Z","iopub.execute_input":"2026-02-26T07:59:08.567661Z","iopub.status.idle":"2026-02-26T07:59:08.571113Z","shell.execute_reply.started":"2026-02-26T07:59:08.567642Z","shell.execute_reply":"2026-02-26T07:59:08.570563Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"##### data loader","metadata":{}},{"cell_type":"code","source":"train_loader = DataLoader(train_subset, batch_size=32, shuffle=True)\nval_loader   = DataLoader(val_subset, batch_size=32, shuffle=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T07:59:08.571907Z","iopub.execute_input":"2026-02-26T07:59:08.572188Z","iopub.status.idle":"2026-02-26T07:59:08.583046Z","shell.execute_reply.started":"2026-02-26T07:59:08.572168Z","shell.execute_reply":"2026-02-26T07:59:08.582471Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Train size:\", len(train_subset))\nprint(\"Val size:\", len(val_subset))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T07:59:08.584077Z","iopub.execute_input":"2026-02-26T07:59:08.584420Z","iopub.status.idle":"2026-02-26T07:59:08.594414Z","shell.execute_reply.started":"2026-02-26T07:59:08.584388Z","shell.execute_reply":"2026-02-26T07:59:08.593806Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"images, labels = next(iter(train_loader))\nprint(\"Batch image shape:\", images.shape)\nprint(\"Batch label shape:\", labels.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T07:59:08.595246Z","iopub.execute_input":"2026-02-26T07:59:08.595536Z","iopub.status.idle":"2026-02-26T07:59:08.612911Z","shell.execute_reply.started":"2026-02-26T07:59:08.595509Z","shell.execute_reply":"2026-02-26T07:59:08.612229Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Küçük veri varsa → augmentation koyar\n\n# Görüntü sınıflandırma ise → mutlaka augmentation dener\n\n# Remote sensing ise → özellikle augmentation kullanır\n\n# Çünkü:\n\n# Bu görüntüler:\n\n# Yukarıdan çekilmiş\n\n# Yön bağımlılığı az\n\n# Dönme değişmezliği (rotation invariance) var\n\n# Şu an bizim kodda tek bir transform var.\n\n# Ama augmentation sadece train tarafında olmalı.\n\n# Bu yüzden artık: Train dataset → augmentation + tensor , Val dataset → sadece tensor , Test dataset → sadece tensor \n# şeklinde ayırmamız gerekiyor.","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T07:59:08.613880Z","iopub.execute_input":"2026-02-26T07:59:08.614115Z","iopub.status.idle":"2026-02-26T07:59:08.625701Z","shell.execute_reply.started":"2026-02-26T07:59:08.614095Z","shell.execute_reply":"2026-02-26T07:59:08.624951Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"##### yeni transforms","metadata":{}},{"cell_type":"code","source":"train_transform = transforms.Compose([\n    transforms.ToPILImage(),\n    transforms.RandomHorizontalFlip(),\n    transforms.RandomVerticalFlip(),\n    transforms.RandomRotation(90),\n    transforms.ToTensor()\n])\n\nval_transform = transforms.Compose([\n    transforms.ToTensor()\n])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T07:59:08.626368Z","iopub.execute_input":"2026-02-26T07:59:08.626569Z","iopub.status.idle":"2026-02-26T07:59:08.637753Z","shell.execute_reply.started":"2026-02-26T07:59:08.626551Z","shell.execute_reply":"2026-02-26T07:59:08.637008Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"##### datasetleri ayri transform ile olusturma","metadata":{}},{"cell_type":"code","source":"train_dataset_full = SatelliteDataset(TRAIN_PATH, mode='train', transform=train_transform)\nval_dataset_full   = SatelliteDataset(TRAIN_PATH, mode='train', transform=val_transform)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T07:59:08.638664Z","iopub.execute_input":"2026-02-26T07:59:08.639014Z","iopub.status.idle":"2026-02-26T07:59:12.331786Z","shell.execute_reply.started":"2026-02-26T07:59:08.638981Z","shell.execute_reply":"2026-02-26T07:59:12.331149Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Simdi baslangic seviyesinde augmentation yaptik ve buradan sonra aslina augmentation konusunda cok baslangic seviyesinde mudahale ettik.\n\n### Ust seviye scientist projelerde RandomCrop,  ColorJitter,  Gaussian noise,  RandomResizedCrop  ,MixUp / CutMix de dusunulur.","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T07:59:12.332660Z","iopub.execute_input":"2026-02-26T07:59:12.332922Z","iopub.status.idle":"2026-02-26T07:59:12.336139Z","shell.execute_reply.started":"2026-02-26T07:59:12.332890Z","shell.execute_reply":"2026-02-26T07:59:12.335442Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"##### CNN","metadata":{}},{"cell_type":"code","source":"import torch.nn as nn\n\nclass SimpleCNN(nn.Module):\n    def __init__(self, num_classes=10):\n        super(SimpleCNN, self).__init__()\n\n        self.features = nn.Sequential(\n            nn.Conv2d(3, 32, 3, padding=1),   # 64x64\n            nn.ReLU(),\n            nn.MaxPool2d(2),                  # 32x32\n\n            nn.Conv2d(32, 64, 3, padding=1),\n            nn.ReLU(),\n            nn.MaxPool2d(2),                  # 16x16\n\n            nn.Conv2d(64, 128, 3, padding=1),\n            nn.ReLU(),\n            nn.MaxPool2d(2)                   # 8x8\n        )\n\n        self.classifier = nn.Sequential(\n            nn.Flatten(),\n            nn.Linear(128 * 8 * 8, 256),\n            nn.ReLU(),\n            nn.Dropout(0.3),\n            nn.Linear(256, num_classes)\n        )\n\n    def forward(self, x):\n        x = self.features(x)\n        x = self.classifier(x)\n        return x","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T07:59:12.337152Z","iopub.execute_input":"2026-02-26T07:59:12.337454Z","iopub.status.idle":"2026-02-26T07:59:12.348463Z","shell.execute_reply.started":"2026-02-26T07:59:12.337420Z","shell.execute_reply":"2026-02-26T07:59:12.347937Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = SimpleCNN()\nprint(model)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T07:59:12.349970Z","iopub.execute_input":"2026-02-26T07:59:12.350261Z","iopub.status.idle":"2026-02-26T07:59:12.379463Z","shell.execute_reply.started":"2026-02-26T07:59:12.350236Z","shell.execute_reply":"2026-02-26T07:59:12.378766Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#LOSS\n\ncriterion = nn.CrossEntropyLoss()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T07:59:12.380352Z","iopub.execute_input":"2026-02-26T07:59:12.380704Z","iopub.status.idle":"2026-02-26T07:59:12.384101Z","shell.execute_reply.started":"2026-02-26T07:59:12.380671Z","shell.execute_reply":"2026-02-26T07:59:12.383353Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# OPTIMIZER\n\nimport torch.optim as optim\n\noptimizer = optim.Adam(model.parameters(), lr=0.001)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T07:59:12.385649Z","iopub.execute_input":"2026-02-26T07:59:12.385874Z","iopub.status.idle":"2026-02-26T07:59:12.395635Z","shell.execute_reply.started":"2026-02-26T07:59:12.385854Z","shell.execute_reply":"2026-02-26T07:59:12.394831Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# TRAINING LOOP\n\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel = model.to(device)\n\nnum_epochs = 10\n\nfor epoch in range(num_epochs):\n\n    model.train()\n    train_loss = 0\n    train_correct = 0\n    train_total = 0\n\n    for images, labels in train_loader:\n\n        images = images.to(device)\n        labels = labels.to(device)\n\n        optimizer.zero_grad()\n\n        outputs = model(images)\n        loss = criterion(outputs, labels)\n\n        loss.backward()\n        optimizer.step()\n\n        train_loss += loss.item()\n\n        _, predicted = torch.max(outputs, 1)\n        train_total += labels.size(0)\n        train_correct += (predicted == labels).sum().item()\n\n    train_acc = train_correct / train_total","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T07:59:12.396500Z","iopub.execute_input":"2026-02-26T07:59:12.396750Z","iopub.status.idle":"2026-02-26T07:59:52.072479Z","shell.execute_reply.started":"2026-02-26T07:59:12.396721Z","shell.execute_reply":"2026-02-26T07:59:52.071638Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# VALIDATION LOOP\n\nmodel.eval()\nval_loss = 0\nval_correct = 0\nval_total = 0\n\nwith torch.no_grad():\n    for images, labels in val_loader:\n\n        images = images.to(device)\n        labels = labels.to(device)\n\n        outputs = model(images)\n        loss = criterion(outputs, labels)\n\n        val_loss += loss.item()\n\n        _, predicted = torch.max(outputs, 1)\n        val_total += labels.size(0)\n        val_correct += (predicted == labels).sum().item()\n\nval_acc = val_correct / val_total","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T07:59:52.073528Z","iopub.execute_input":"2026-02-26T07:59:52.073842Z","iopub.status.idle":"2026-02-26T07:59:52.599269Z","shell.execute_reply.started":"2026-02-26T07:59:52.073795Z","shell.execute_reply":"2026-02-26T07:59:52.598697Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"##### Professional Validation Analysis","metadata":{}},{"cell_type":"code","source":"from sklearn.metrics import classification_report, confusion_matrix\n\nall_preds = []\nall_labels = []\n\nmodel.eval()\nwith torch.no_grad():\n    for images, labels in val_loader:\n        images = images.to(device)\n        labels = labels.to(device)\n\n        outputs = model(images)\n        _, predicted = torch.max(outputs, 1)\n\n        all_preds.extend(predicted.cpu().numpy())\n        all_labels.extend(labels.cpu().numpy())\n\nprint(classification_report(all_labels, all_preds))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T07:59:52.603964Z","iopub.execute_input":"2026-02-26T07:59:52.604252Z","iopub.status.idle":"2026-02-26T07:59:53.140450Z","shell.execute_reply.started":"2026-02-26T07:59:52.604204Z","shell.execute_reply":"2026-02-26T07:59:53.139669Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Ornekte bu asama bizden istenmiyordu ancak biz yine de siniflarin duzgun ayrisip ayrismadigini gormek istedik, bilgi amacli. Simdi burayi gecip basarili baseline modeli kaydediyoruz.","metadata":{}},{"cell_type":"code","source":"best_val_acc = 0\nif val_acc > best_val_acc:\n    best_val_acc = val_acc\n    torch.save(model.state_dict(), \"baseline_best_model.pth\")\n    print(f\"Yeni en iyi model kaydedildi. Val Acc: {val_acc:.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T08:00:46.007878Z","iopub.execute_input":"2026-02-26T08:00:46.008682Z","iopub.status.idle":"2026-02-26T08:00:46.037540Z","shell.execute_reply.started":"2026-02-26T08:00:46.008650Z","shell.execute_reply":"2026-02-26T08:00:46.036948Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Transfer Learning","metadata":{}},{"cell_type":"code","source":"import torchvision.models as models\n\nmodel_tl = models.resnet18(pretrained=True)\n\n# Son katmanı değiştiriyoruz\nmodel_tl.fc = nn.Linear(model_tl.fc.in_features, 10)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T08:02:27.522346Z","iopub.execute_input":"2026-02-26T08:02:27.523042Z","iopub.status.idle":"2026-02-26T08:02:28.096350Z","shell.execute_reply.started":"2026-02-26T08:02:27.523014Z","shell.execute_reply":"2026-02-26T08:02:28.095622Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for param in model_tl.parameters():\n    param.requires_grad = False\n\nfor param in model_tl.fc.parameters():\n    param.requires_grad = True\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T08:02:38.366038Z","iopub.execute_input":"2026-02-26T08:02:38.366378Z","iopub.status.idle":"2026-02-26T08:02:38.370408Z","shell.execute_reply.started":"2026-02-26T08:02:38.366349Z","shell.execute_reply":"2026-02-26T08:02:38.369688Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"criterion = nn.CrossEntropyLoss()\noptimizer = torch.optim.Adam(model_tl.fc.parameters(), lr=0.001)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T08:02:46.222447Z","iopub.execute_input":"2026-02-26T08:02:46.222971Z","iopub.status.idle":"2026-02-26T08:02:46.227116Z","shell.execute_reply.started":"2026-02-26T08:02:46.222940Z","shell.execute_reply":"2026-02-26T08:02:46.226493Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel_tl = model_tl.to(device)\n\nbest_val_acc = 0\nnum_epochs = 10\n\nfor epoch in range(num_epochs):\n\n    model_tl.train()\n    train_correct = 0\n    train_total = 0\n\n    for images, labels in train_loader:\n        images = images.to(device)\n        labels = labels.to(device)\n\n        optimizer.zero_grad()\n\n        outputs = model_tl(images)\n        loss = criterion(outputs, labels)\n\n        loss.backward()\n        optimizer.step()\n\n        _, predicted = torch.max(outputs, 1)\n        train_total += labels.size(0)\n        train_correct += (predicted == labels).sum().item()\n\n    train_acc = train_correct / train_total\n\n    # VALIDATION\n    model_tl.eval()\n    val_correct = 0\n    val_total = 0\n\n    with torch.no_grad():\n        for images, labels in val_loader:\n            images = images.to(device)\n            labels = labels.to(device)\n\n            outputs = model_tl(images)\n            _, predicted = torch.max(outputs, 1)\n\n            val_total += labels.size(0)\n            val_correct += (predicted == labels).sum().item()\n\n    val_acc = val_correct / val_total\n\n    print(f\"Epoch [{epoch+1}/{num_epochs}] \"\n          f\"| Train Acc: {train_acc:.4f} \"\n          f\"| Val Acc: {val_acc:.4f}\")\n\n    if val_acc > best_val_acc:\n        best_val_acc = val_acc\n        torch.save(model_tl.state_dict(), \"resnet_frozen_best.pth\")\n        print(\"🔥 Yeni en iyi TL model kaydedildi.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T08:02:57.910811Z","iopub.execute_input":"2026-02-26T08:02:57.911588Z","iopub.status.idle":"2026-02-26T08:03:45.835997Z","shell.execute_reply.started":"2026-02-26T08:02:57.911541Z","shell.execute_reply":"2026-02-26T08:03:45.835200Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Bu sonuclar yetersizdir.\n\nResNet ImageNet üzerinde şu istatistikle eğitildi:\n\nmean = [0.485, 0.456, 0.406] , std  = [0.229, 0.224, 0.225]\n\nBackbone Freeze KALKIYOR (Full Fine-Tune)\n\nLearning Rate DÜŞÜRÜLECEK lr = 1e-4","metadata":{}},{"cell_type":"markdown","source":"##### 2.deneme","metadata":{}},{"cell_type":"code","source":"from torchvision import transforms\n\ntrain_transform = transforms.Compose([\n    transforms.ToPILImage(),\n    transforms.RandomResizedCrop(64, scale=(0.8, 1.0)),\n    transforms.RandomHorizontalFlip(),\n    transforms.RandomVerticalFlip(),\n    transforms.RandomRotation(30),\n    transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2),\n    transforms.ToTensor(),\n    transforms.Normalize(\n        mean=[0.485, 0.456, 0.406],\n        std=[0.229, 0.224, 0.225]\n    )\n])\n\nval_transform = transforms.Compose([\n    transforms.ToPILImage(),\n    transforms.ToTensor(),\n    transforms.Normalize(\n        mean=[0.485, 0.456, 0.406],\n        std=[0.229, 0.224, 0.225]\n    )\n])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T08:05:23.175709Z","iopub.execute_input":"2026-02-26T08:05:23.176486Z","iopub.status.idle":"2026-02-26T08:05:23.181993Z","shell.execute_reply.started":"2026-02-26T08:05:23.176450Z","shell.execute_reply":"2026-02-26T08:05:23.181242Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_dataset_full = SatelliteDataset(TRAIN_PATH, mode='train', transform=train_transform)\nval_dataset_full   = SatelliteDataset(TRAIN_PATH, mode='train', transform=val_transform)\n\ntrain_subset = Subset(train_dataset_full, train_idx)\nval_subset   = Subset(val_dataset_full, val_idx)\n\ntrain_loader = DataLoader(train_subset, batch_size=64, shuffle=True)\nval_loader   = DataLoader(val_subset, batch_size=64, shuffle=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T08:05:57.068636Z","iopub.execute_input":"2026-02-26T08:05:57.069283Z","iopub.status.idle":"2026-02-26T08:06:00.755973Z","shell.execute_reply.started":"2026-02-26T08:05:57.069241Z","shell.execute_reply":"2026-02-26T08:06:00.755276Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"##### Model Full Fine Tune","metadata":{}},{"cell_type":"code","source":"model_tl = models.resnet18(weights=models.ResNet18_Weights.DEFAULT)\nmodel_tl.fc = nn.Linear(model_tl.fc.in_features, 10)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T08:06:16.608412Z","iopub.execute_input":"2026-02-26T08:06:16.609007Z","iopub.status.idle":"2026-02-26T08:06:16.808891Z","shell.execute_reply.started":"2026-02-26T08:06:16.608979Z","shell.execute_reply":"2026-02-26T08:06:16.808269Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"##### Optimizer+ Full Model","metadata":{}},{"cell_type":"code","source":"import torch.optim as optim\n\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model_tl.parameters(), lr=1e-4)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T08:06:40.438493Z","iopub.execute_input":"2026-02-26T08:06:40.439154Z","iopub.status.idle":"2026-02-26T08:06:40.443477Z","shell.execute_reply.started":"2026-02-26T08:06:40.439125Z","shell.execute_reply":"2026-02-26T08:06:40.442854Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"##### Training Loop","metadata":{}},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel_tl = model_tl.to(device)\n\nbest_val_acc = 0\nnum_epochs = 20\n\nfor epoch in range(num_epochs):\n\n    # TRAIN\n    model_tl.train()\n    train_correct = 0\n    train_total = 0\n\n    for images, labels in train_loader:\n        images = images.to(device)\n        labels = labels.to(device)\n\n        optimizer.zero_grad()\n        outputs = model_tl(images)\n        loss = criterion(outputs, labels)\n        loss.backward()\n        optimizer.step()\n\n        _, predicted = torch.max(outputs, 1)\n        train_total += labels.size(0)\n        train_correct += (predicted == labels).sum().item()\n\n    train_acc = train_correct / train_total\n\n    # VALIDATION\n    model_tl.eval()\n    val_correct = 0\n    val_total = 0\n\n    with torch.no_grad():\n        for images, labels in val_loader:\n            images = images.to(device)\n            labels = labels.to(device)\n\n            outputs = model_tl(images)\n            _, predicted = torch.max(outputs, 1)\n\n            val_total += labels.size(0)\n            val_correct += (predicted == labels).sum().item()\n\n    val_acc = val_correct / val_total\n\n    print(f\"Epoch [{epoch+1}/{num_epochs}] \"\n          f\"| Train Acc: {train_acc:.4f} \"\n          f\"| Val Acc: {val_acc:.4f}\")\n\n    if val_acc > best_val_acc:\n        best_val_acc = val_acc\n        torch.save(model_tl.state_dict(), \"resnet_full_best.pth\")\n        print(\"🔥 Yeni en iyi model kaydedildi.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T08:07:06.875192Z","iopub.execute_input":"2026-02-26T08:07:06.875743Z","iopub.status.idle":"2026-02-26T08:16:45.595350Z","shell.execute_reply.started":"2026-02-26T08:07:06.875714Z","shell.execute_reply":"2026-02-26T08:16:45.594499Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Modelimizin egitimi su asamada sona ermistir. Zaman kisitlamasindan oturu 20 epochs ile birlikte egitimi sonlandirmak zorunda kaldik. Aslinda modelin hala ogrenmeye devam ettigini. son epochta hala en iyi val acc almaya devam etmemiz onun ispatidir. ancak su anda modelimizi full train datasinda egitip artik test datasi ile tahmini yaparak calismamizi sonlandiriyoruz.","metadata":{}},{"cell_type":"markdown","source":"##### Full data training","metadata":{}},{"cell_type":"code","source":"full_dataset = SatelliteDataset(TRAIN_PATH, mode='train', transform=train_transform)\nfull_loader = DataLoader(full_dataset, batch_size=64, shuffle=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T08:16:48.631598Z","iopub.execute_input":"2026-02-26T08:16:48.632221Z","iopub.status.idle":"2026-02-26T08:16:50.482577Z","shell.execute_reply.started":"2026-02-26T08:16:48.632174Z","shell.execute_reply":"2026-02-26T08:16:50.481976Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"##### Modeli yeniden kur- ayni mimari","metadata":{}},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\nmodel_final = models.resnet18(weights=models.ResNet18_Weights.DEFAULT)\nmodel_final.fc = nn.Linear(model_final.fc.in_features, 10)\nmodel_final = model_final.to(device)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T08:17:49.312830Z","iopub.execute_input":"2026-02-26T08:17:49.313469Z","iopub.status.idle":"2026-02-26T08:17:49.487929Z","shell.execute_reply.started":"2026-02-26T08:17:49.313439Z","shell.execute_reply":"2026-02-26T08:17:49.487230Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Loss & optimizer (full fine-tune)\n\ncriterion = nn.CrossEntropyLoss()\noptimizer = optim.Adam(model_final.parameters(), lr=1e-4)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T08:18:11.800016Z","iopub.execute_input":"2026-02-26T08:18:11.800408Z","iopub.status.idle":"2026-02-26T08:18:11.805086Z","shell.execute_reply.started":"2026-02-26T08:18:11.800380Z","shell.execute_reply":"2026-02-26T08:18:11.804535Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Final training\n\nnum_epochs_final = 15\n\nfor epoch in range(num_epochs_final):\n    model_final.train()\n\n    running_loss = 0.0\n    correct = 0\n    total = 0\n\n    for images, labels in full_loader:\n        images = images.to(device)\n        labels = labels.to(device)\n\n        optimizer.zero_grad()\n        outputs = model_final(images)\n        loss = criterion(outputs, labels)\n        loss.backward()\n        optimizer.step()\n\n        running_loss += loss.item() * labels.size(0)\n        _, preds = torch.max(outputs, 1)\n        total += labels.size(0)\n        correct += (preds == labels).sum().item()\n\n    epoch_loss = running_loss / total\n    epoch_acc = correct / total\n    print(f\"[FULL] Epoch [{epoch+1}/{num_epochs_final}] | \"\n          f\"Train Loss: {epoch_loss:.4f} | Train Acc: {epoch_acc:.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T08:18:34.127825Z","iopub.execute_input":"2026-02-26T08:18:34.128422Z","iopub.status.idle":"2026-02-26T08:26:57.057674Z","shell.execute_reply.started":"2026-02-26T08:18:34.128393Z","shell.execute_reply":"2026-02-26T08:26:57.056999Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Önceki fine-tuning aşamasında seçilen hiperparametrelerin (özellikle learning rate ve donmuş katman stratejisi) tam veri üzerinde optimal olmayabileceğini göz önünde bulundurarak, final aşamada ImageNet ön-eğitimli varsayılan ağırlıklar üzerinden düşük öğrenme oranı ile tam veri üzerinde yeniden eğitim tercih edilmiştir. Bu yaklaşım, validation’a aşırı uyum riskini azaltarak daha dengeli bir genelleme sağlamayı amaçlamaktadır.","metadata":{}},{"cell_type":"code","source":"torch.save(model_final.state_dict(), \"resnet_full_final.pth\")\nprint(\"✅ Final model kaydedildi: resnet_full_final.pth\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T08:26:57.059033Z","iopub.execute_input":"2026-02-26T08:26:57.059344Z","iopub.status.idle":"2026-02-26T08:26:57.124910Z","shell.execute_reply.started":"2026-02-26T08:26:57.059321Z","shell.execute_reply":"2026-02-26T08:26:57.124267Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"##### Submission","metadata":{}},{"cell_type":"code","source":"test_dataset = SatelliteDataset(TEST_PATH, mode=\"test\", transform=val_transform)\ntest_loader  = DataLoader(test_dataset, batch_size=64, shuffle=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T08:26:57.125795Z","iopub.execute_input":"2026-02-26T08:26:57.126120Z","iopub.status.idle":"2026-02-26T08:26:57.595633Z","shell.execute_reply.started":"2026-02-26T08:26:57.126093Z","shell.execute_reply":"2026-02-26T08:26:57.595051Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_final.eval()\n# modeli eval moduna aldik, kritik hamle.","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T08:26:57.597421Z","iopub.execute_input":"2026-02-26T08:26:57.597713Z","iopub.status.idle":"2026-02-26T08:26:57.603717Z","shell.execute_reply.started":"2026-02-26T08:26:57.597691Z","shell.execute_reply":"2026-02-26T08:26:57.603158Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_preds = []\n\nwith torch.no_grad():\n    for images in test_loader:\n        images = images.to(device)\n        outputs = model_final(images)\n        _, preds = torch.max(outputs, 1)\n        test_preds.extend(preds.cpu().numpy())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T08:26:57.604554Z","iopub.execute_input":"2026-02-26T08:26:57.604906Z","iopub.status.idle":"2026-02-26T08:26:59.725349Z","shell.execute_reply.started":"2026-02-26T08:26:57.604874Z","shell.execute_reply":"2026-02-26T08:26:59.724733Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission = pd.DataFrame({\n    \"Id\": np.arange(len(test_preds)),\n    \"Category\": test_preds\n})\nsubmission.to_csv(\"submission.csv\", index=False)\nprint(\"✅ submission.csv üretildi\")\nprint(submission.head())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-26T08:26:59.726170Z","iopub.execute_input":"2026-02-26T08:26:59.726476Z","iopub.status.idle":"2026-02-26T08:26:59.764225Z","shell.execute_reply.started":"2026-02-26T08:26:59.726452Z","shell.execute_reply":"2026-02-26T08:26:59.763563Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Bu calismada once kendi cnn modelimizle bir tahmin modeli gelistirmis olup yeteri seviyede dogruluga erisilememistir ve TL ile model iyilestirmesi yapilarak siniflandirmalar yapilmistir. BU projede ilk defa byTorch kullanilmis olup keras modellerinden sonra ogrenilmesi faydali bir asama olmustur.","metadata":{}}]}