{"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":11848,"databundleVersionId":862157},{"sourceType":"datasetVersion","sourceId":15596587,"datasetId":9979767,"databundleVersionId":16529406}],"dockerImageVersionId":31287,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport pandas as pd\nimport cv2\nfrom torch.utils.data import DataLoader, Dataset\nfrom torchvision import transforms\nfrom sklearn.model_selection import train_test_split\n\n# Kaggle için en olası dosya yolu\nBASE_PATH = '/kaggle/input/competitions/histopathologic-cancer-detection/'\nTRAIN_DIR = os.path.join(BASE_PATH, 'train/')\nLABEL_CSV = os.path.join(BASE_PATH, 'train_labels.csv')\n\n# Yolun doğruluğunu kontrol et\nif not os.path.exists(LABEL_CSV):\n    # Alternatif yol (bazı Kaggle versiyonlarında 'competitions' klasörü olmaz)\n    BASE_PATH = '/kaggle/input/histopathologic-cancer-detection/'\n    TRAIN_DIR = os.path.join(BASE_PATH, 'train/')\n    LABEL_CSV = os.path.join(BASE_PATH, 'train_labels.csv')\n\nprint(f\"Veri yolu: {BASE_PATH}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-08T12:19:10.758530Z","iopub.execute_input":"2026-04-08T12:19:10.758918Z","iopub.status.idle":"2026-04-08T12:19:10.766088Z","shell.execute_reply.started":"2026-04-08T12:19:10.758886Z","shell.execute_reply":"2026-04-08T12:19:10.765434Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class ChannelAttention(nn.Module):\n    def __init__(self, in_planes, ratio=16):\n        super(ChannelAttention, self).__init__()\n        self.avg_pool = nn.AdaptiveAvgPool2d(1)\n        self.max_pool = nn.AdaptiveMaxPool2d(1)\n        self.fc = nn.Sequential(\n            nn.Conv2d(in_planes, in_planes // ratio, 1, bias=False),\n            nn.ReLU(),\n            nn.Conv2d(in_planes // ratio, in_planes, 1, bias=False)\n        )\n        self.sigmoid = nn.Sigmoid()\n\n    def forward(self, x):\n        avg_out = self.fc(self.avg_pool(x))\n        max_out = self.fc(self.max_pool(x))\n        return self.sigmoid(avg_out + max_out)\n\nclass SpatialAttention(nn.Module):\n    def __init__(self, kernel_size=7):\n        super(SpatialAttention, self).__init__()\n        self.conv1 = nn.Conv2d(2, 1, kernel_size, padding=kernel_size//2, bias=False)\n        self.sigmoid = nn.Sigmoid()\n\n    def forward(self, x):\n        avg_out = torch.mean(x, dim=1, keepdim=True)\n        max_out, _ = torch.max(x, dim=1, keepdim=True)\n        res = torch.cat([avg_out, max_out], dim=1)\n        return self.sigmoid(self.conv1(res))\n\nclass AttentionBlock(nn.Module):\n    def __init__(self, in_planes):\n        super(AttentionBlock, self).__init__()\n        self.ca = ChannelAttention(in_planes)\n        self.sa = SpatialAttention()\n\n    def forward(self, x):\n        x = x * self.ca(x)\n        x = x * self.sa(x)\n        return x\n\nclass CancerDetectionCNN(nn.Module):\n    def __init__(self, num_classes=1):\n        super(CancerDetectionCNN, self).__init__()\n        self.conv1 = nn.Conv2d(3, 64, kernel_size=3, padding=1)\n        self.bn1 = nn.BatchNorm2d(64)\n        \n        self.layer1 = nn.Sequential(\n            nn.Conv2d(64, 128, kernel_size=3, padding=1),\n            nn.BatchNorm2d(128),\n            nn.ReLU(),\n            AttentionBlock(128)\n        )\n        \n        self.layer2 = nn.Sequential(\n            nn.Conv2d(128, 256, kernel_size=3, padding=1, stride=2),\n            nn.BatchNorm2d(256),\n            nn.ReLU(),\n            AttentionBlock(256)\n        )\n        \n        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))\n        self.fc = nn.Linear(256, num_classes)\n\n    def forward(self, x):\n        x = F.relu(self.bn1(self.conv1(x)))\n        x = self.layer1(x)\n        x = self.layer2(x)\n        x = self.avgpool(x)\n        x = torch.flatten(x, 1)\n        return self.fc(x)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-08T12:19:13.971129Z","iopub.execute_input":"2026-04-08T12:19:13.971933Z","iopub.status.idle":"2026-04-08T12:19:13.984604Z","shell.execute_reply.started":"2026-04-08T12:19:13.971890Z","shell.execute_reply":"2026-04-08T12:19:13.983736Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class HistopathDataset(Dataset):\n    def __init__(self, df, data_dir, transform=None):\n        self.df = df\n        self.data_dir = data_dir\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self, idx):\n        # ID'nin sonuna .tif ekliyoruz\n        img_id = str(self.df.iloc[idx, 0])\n        img_name = os.path.join(self.data_dir, img_id + \".tif\")\n        \n        image = cv2.imread(img_name)\n        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n        label = self.df.iloc[idx, 1]\n        \n        if self.transform:\n            image = self.transform(image)\n            \n        return image, torch.tensor(label, dtype=torch.float32)\n\n# --- Veri Hazırlığı ---\ndf = pd.read_csv(LABEL_CSV)\n\ntrain_df, val_df = train_test_split(df, test_size=0.2, stratify=df['label'], random_state=42)\n\ntransform = transforms.Compose([\n    transforms.ToPILImage(),\n    transforms.CenterCrop(48), # 96x96'nın merkezindeki en önemli yere odaklan\n    transforms.ToTensor(),\n    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))\n])\n\ntrain_dataset = HistopathDataset(train_df, TRAIN_DIR, transform=transform)\nval_dataset = HistopathDataset(val_df, TRAIN_DIR, transform=transform)\n\ntrain_loader = DataLoader(train_dataset, batch_size=64, shuffle=True, num_workers=2)\nval_loader = DataLoader(val_dataset, batch_size=64, shuffle=False, num_workers=2)\n\nprint(f\"Dataset hazır: {len(train_dataset)} eğitim, {len(val_dataset)} doğrulama resmi.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-08T12:19:17.558076Z","iopub.execute_input":"2026-04-08T12:19:17.558402Z","iopub.status.idle":"2026-04-08T12:19:17.885069Z","shell.execute_reply.started":"2026-04-08T12:19:17.558360Z","shell.execute_reply":"2026-04-08T12:19:17.884324Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#model eğitimi\nimport torch.optim as optim\nfrom sklearn.metrics import roc_auc_score\nimport numpy as np\nfrom tqdm.notebook import tqdm # İlerleme çubuğu için\n\n# GPU kontrolü\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nprint(f\"Kullanılan cihaz: {device}\")\n\nmodel = CancerDetectionCNN().to(device)\n\n# Kayıp fonksiyonu ve Optimizer\ncriterion = nn.BCEWithLogitsLoss()\noptimizer = optim.Adam(model.parameters(), lr=0.001)\n\n# Scheduler\nscheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, 'min', patience=2, factor=0.5)\n\ndef train_model(epochs=5):\n    best_auc = 0.0\n    \n    for epoch in range(epochs):\n        # --- EĞİTİM AŞAMASI ---\n        model.train()\n        train_loss = 0.0\n        \n        train_loader_tqdm = tqdm(train_loader, desc=f\"Epoch {epoch+1}/{epochs} [Eğitim]\")\n        \n        for images, labels in train_loader_tqdm:\n            images, labels = images.to(device), labels.to(device).unsqueeze(1)\n            \n            optimizer.zero_grad()\n            outputs = model(images)\n            loss = criterion(outputs, labels)\n            loss.backward()\n            optimizer.step()\n            \n            train_loss += loss.item()\n            \n            # Çubuğun yanına anlık kaybı yazdır \n            train_loader_tqdm.set_postfix(loss=loss.item())\n        \n        # --- DOĞRULAMA AŞAMASI ---\n        model.eval()\n        val_loss = 0.0\n        val_preds = []\n        val_labels = []\n        \n        val_loader_tqdm = tqdm(val_loader, desc=f\"Epoch {epoch+1}/{epochs} [Doğrulama]\")\n        \n        with torch.no_grad():\n            for images, labels in val_loader_tqdm:\n                images, labels = images.to(device), labels.to(device).unsqueeze(1)\n                outputs = model(images)\n                loss = criterion(outputs, labels)\n                val_loss += loss.item()\n                \n                preds = torch.sigmoid(outputs)\n                val_preds.extend(preds.cpu().numpy())\n                val_labels.extend(labels.cpu().numpy())\n        \n        # Metrikler\n        avg_train_loss = train_loss / len(train_loader)\n        avg_val_loss = val_loss / len(val_loader)\n        auc_score = roc_auc_score(val_labels, val_preds)\n        \n        scheduler.step(avg_val_loss)\n        \n        print(f\"\\n Epoch [{epoch+1}/{epochs}] Tamamlandı!\")\n        print(f\"Train Loss: {avg_train_loss:.4f} | Val Loss: {avg_val_loss:.4f} | Val AUC: {auc_score:.4f}\")\n        \n        if auc_score > best_auc:\n            best_auc = auc_score\n            torch.save(model.state_dict(), 'best_cancer_model.pth')\n            print(\" En iyi model kaydedildi!\")\n\ntrain_model(epochs=15)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-08T09:26:58.261331Z","iopub.execute_input":"2026-04-08T09:26:58.262232Z","iopub.status.idle":"2026-04-08T11:15:05.108823Z","shell.execute_reply.started":"2026-04-08T09:26:58.262195Z","shell.execute_reply":"2026-04-08T11:15:05.107858Z"},"jupyter":{"source_hidden":true}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel = CancerDetectionCNN().to(device) \n# Dataset olarak yüklediğim ağırlıkları oku\nmodel.load_state_dict(torch.load('/kaggle/input/datasets/sudenazozen/cancerbest/best_cancer_model.pth'))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-08T12:19:21.497750Z","iopub.execute_input":"2026-04-08T12:19:21.498045Z","iopub.status.idle":"2026-04-08T12:19:21.524625Z","shell.execute_reply.started":"2026-04-08T12:19:21.498023Z","shell.execute_reply":"2026-04-08T12:19:21.524005Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport seaborn as sns\nfrom sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay, roc_curve, auc, classification_report\nimport numpy as np\nimport torch\nimport torch.nn.functional as F\nimport cv2\n\n# 1. Eğitim Geçmişi Grafikleri (Loss ve AUC)\ndef plot_academic_history():\n    # Bu değerleri bugün aldığın sonuçlara göre buraya sabitledik\n    train_losses = [0.3663, 0.3116, 0.2863, 0.2703, 0.2573]\n    val_losses = [0.3275, 0.3043, 0.2788, 0.2620, 0.2524]\n    auc_scores = [0.9340, 0.9472, 0.9501, 0.9564, 0.9585]\n    epochs = range(1, len(train_losses) + 1)\n\n    plt.style.use('seaborn-v0_8-whitegrid')\n    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 6))\n\n    # Loss Grafiği\n    ax1.plot(epochs, train_losses, 'o-', color='royalblue', linewidth=2, label='Eğitim Kaybı')\n    ax1.plot(epochs, val_losses, 's-', color='darkorange', linewidth=2, label='Doğrulama Kaybı')\n    ax1.set_title('Model Kayıp Analizi (Cross-Entropy Loss)', fontsize=14)\n    ax1.set_xlabel('Epoch', fontsize=12)\n    ax1.set_ylabel('Loss', fontsize=12)\n    ax1.legend()\n\n    # AUC Grafiği\n    ax2.plot(epochs, auc_scores, 'd-', color='forestgreen', linewidth=2, label='Validation AUC')\n    ax2.set_title('Model Başarım Gelişimi (AUC-ROC)', fontsize=14)\n    ax2.set_xlabel('Epoch', fontsize=12)\n    ax2.set_ylabel('AUC Score', fontsize=12)\n    ax2.legend()\n    \n    plt.tight_layout()\n    plt.savefig('training_metrics.png', dpi=300)\n    plt.show()\n\n# 2. Detaylı Metrikler ve Karmaşıklık Matrisi\ndef plot_detailed_evaluation(model, loader):\n    model.eval()\n    y_true, y_pred, y_probs = [], [], []\n\n    with torch.no_grad():\n        for images, labels in loader:\n            images = images.to(device)\n            outputs = model(images)\n            probs = torch.sigmoid(outputs).cpu().numpy()\n            preds = (probs > 0.5).astype(int)\n            \n            y_true.extend(labels.numpy())\n            y_pred.extend(preds)\n            y_probs.extend(probs)\n\n    # Confusion Matrix\n    cm = confusion_matrix(y_true, y_pred)\n    plt.figure(figsize=(8, 6))\n    sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=['Sağlıklı', 'Kanserli'], yticklabels=['Sağlıklı', 'Kanserli'])\n    plt.title('Karmaşıklık Matrisi (Confusion Matrix)', fontsize=14)\n    plt.ylabel('Gerçek Etiket')\n    plt.xlabel('Tahmin Edilen Etiket')\n    plt.savefig('confusion_matrix.png', dpi=300)\n    plt.show()\n\n    # ROC Eğrisi\n    fpr, tpr, _ = roc_curve(y_true, y_probs)\n    roc_auc = auc(fpr, tpr)\n    plt.figure(figsize=(8, 6))\n    plt.plot(fpr, tpr, color='darkred', lw=2, label=f'ROC Eğrisi (Alan = {roc_auc:.4f})')\n    plt.plot([0, 1], [0, 1], color='gray', linestyle='--')\n    plt.title('Receiver Operating Characteristic (ROC)', fontsize=14)\n    plt.xlabel('Yanlış Pozitif Oranı (FPR)')\n    plt.ylabel('Doğru Pozitif Oranı (TPR)')\n    plt.legend(loc=\"lower right\")\n    plt.savefig('roc_curve.png', dpi=300)\n    plt.show()\n\n    # Akademik Metrik Tablosu (Console çıktısı için)\n    print(\"\\n--- SINIFLANDIRMA RAPORU ---\")\n    print(classification_report(y_true, y_pred, target_names=['Sağlıklı', 'Kanserli']))\n\n# 3. Attention Görselleştirme (Grad-CAM benzeri)\ndef plot_attention_grid(model, dataset, num_samples=4):\n    plt.figure(figsize=(15, 4 * num_samples))\n    model.eval()\n    \n    for i in range(num_samples):\n        # Rastgele bir örnek seç \n        idx = np.random.randint(len(dataset))\n        image, label = dataset[idx]\n        input_tensor = image.unsqueeze(0).to(device)\n        \n        with torch.no_grad():\n            # Attention katmanından ağırlıkları al (Modele göre indeksler değişebilir)\n            x = F.relu(model.bn1(model.conv1(input_tensor)))\n            x_layer1 = model.layer1[0:3](x)\n            attn_weights = model.layer1[3].sa(x_layer1)\n            output = model(input_tensor)\n            prob = torch.sigmoid(output).item()\n\n        # Görselleştirme hazırlığı\n        img = image.permute(1, 2, 0).cpu().numpy()\n        img = (img - img.min()) / (img.max() - img.min())\n        attn_map = attn_weights.squeeze().cpu().numpy()\n        attn_map = cv2.resize(attn_map, (img.shape[1], img.shape[0]))\n\n        # Orijinal Görüntü\n        plt.subplot(num_samples, 2, 2*i + 1)\n        plt.imshow(img)\n        plt.title(f\"Örnek {i+1} | Gerçek: {int(label)} | Tahmin: %{prob*100:.1f}\")\n        plt.axis('off')\n\n        # Attention Map\n        plt.subplot(num_samples, 2, 2*i + 2)\n        plt.imshow(img)\n        plt.imshow(attn_map, alpha=0.5, cmap='jet')\n        plt.title(f\"Attention (Dikkat) Haritası\")\n        plt.axis('off')\n\n    plt.tight_layout()\n    plt.savefig('attention_results.png', dpi=300)\n    plt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-08T12:03:28.462005Z","iopub.execute_input":"2026-04-08T12:03:28.462798Z","iopub.status.idle":"2026-04-08T12:03:28.853183Z","shell.execute_reply.started":"2026-04-08T12:03:28.462769Z","shell.execute_reply":"2026-04-08T12:03:28.852644Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# --- FONKSİYONLARI ÇALIŞTIRMA KOMUTLARI ---\n\n# 1. Grafikleri çizdir\nplot_academic_history()\n\n# 2. Karmaşıklık matrisi ve ROC eğrisini oluştur\nplot_detailed_evaluation(model, val_loader)\n\n# 3. Dikkat haritalarını görselleştir\nplot_attention_grid(model, val_dataset)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-08T12:03:38.878852Z","iopub.execute_input":"2026-04-08T12:03:38.879551Z","iopub.status.idle":"2026-04-08T12:07:45.882250Z","shell.execute_reply.started":"2026-04-08T12:03:38.879520Z","shell.execute_reply":"2026-04-08T12:07:45.881449Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def failure_analysis(model, dataset, num_examples=5):\n    model.eval()\n    errors = []\n    \n    print(\"Hata analizi yapılıyor, lütfen bekleyin...\")\n    with torch.no_grad():\n        for i in range(len(dataset)):\n            image, label = dataset[i]\n            input_tensor = image.unsqueeze(0).to(device)\n            output = model(input_tensor)\n            prob = torch.sigmoid(output).item()\n            pred = 1 if prob > 0.5 else 0\n            \n            if pred != label:\n                errors.append((image, label, prob, i))\n            if len(errors) >= num_examples:\n                break\n\n    # Yanıltıcı örnekleri görselleştir\n    plt.figure(figsize=(15, 5))\n    for i, (img, lbl, prb, idx) in enumerate(errors):\n        plt.subplot(1, num_examples, i+1)\n        # Görüntü düzeltme (Denormalizasyon)\n        img_to_show = img.permute(1, 2, 0).cpu().numpy()\n        img_to_show = (img_to_show - img_to_show.min()) / (img_to_show.max() - img_to_show.min())\n        \n        plt.imshow(img_to_show)\n        plt.title(f\"Gerçek: {int(lbl)}\\nTahmin: {prb:.2f}\")\n        plt.axis('off')\n    plt.show()\n\nfailure_analysis(model, val_dataset, num_examples=5)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-08T12:19:46.611561Z","iopub.execute_input":"2026-04-08T12:19:46.611886Z","iopub.status.idle":"2026-04-08T12:19:47.031139Z","shell.execute_reply.started":"2026-04-08T12:19:46.611858Z","shell.execute_reply":"2026-04-08T12:19:47.030416Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\nimport matplotlib.pyplot as plt\nimport torch.nn.functional as F\nimport cv2\n\ndef visualize_attention(model, dataset, idx=0):\n    model.eval()\n    image, label = dataset[idx]\n    image_input = image.unsqueeze(0).to(device)\n    \n    # Modelden tahmini ve dikkat haritasını alacağız\n    with torch.no_grad():\n        # Tahmin ve Olasılık Hesaplama (Eşik: 0.45)\n        output = model(image_input)\n        prob = torch.sigmoid(output).item() # İkili sınıflandırma için\n        prediction = 1 if prob >= 0.45 else 0\n        \n        # Giriş katmanından geçir\n        x = F.relu(model.bn1(model.conv1(image_input)))\n        # Layer 1'den geçir\n        x = model.layer1[0:3](x) # Conv, BN, ReLU kısımları\n        attn_weights = model.layer1[3].sa(x) # Spatial Attention ağırlıkları\n        \n    # Görselleştirme\n    img = image.permute(1, 2, 0).cpu().numpy()\n    img = (img - img.min()) / (img.max() - img.min()) # Normalize et\n    \n    attn_map = attn_weights.squeeze().cpu().numpy()\n    attn_map = cv2.resize(attn_map, (img.shape[1], img.shape[0]))\n    \n    plt.figure(figsize=(12, 6))\n    plt.subplot(1, 2, 1)\n    plt.imshow(img)\n    plt.title(f\"Orijinal Hücre\\nGerçek Etiket: {int(label)}\")\n    \n    plt.subplot(1, 2, 2)\n    plt.imshow(img)\n    plt.imshow(attn_map, alpha=0.5, cmap='jet') # Isı haritasını bindir\n    # Tahmin ve Olasılık buraya eklendi\n    plt.title(f\"Attention (Odak) Haritası\\nTahmin: {prediction} (Olasılık: {prob:.4f})\")\n    plt.show()\n\n# Kullanım:\n# visualize_attention(model, val_dataset, idx=10)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-08T12:20:05.913670Z","iopub.execute_input":"2026-04-08T12:20:05.913990Z","iopub.status.idle":"2026-04-08T12:20:05.922363Z","shell.execute_reply.started":"2026-04-08T12:20:05.913962Z","shell.execute_reply":"2026-04-08T12:20:05.921593Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Rastgele örnek üzerinde dene\nfor i in range(5):\n    visualize_attention(model, val_dataset, idx=i*10)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-04-08T12:20:09.254952Z","iopub.execute_input":"2026-04-08T12:20:09.255715Z","iopub.status.idle":"2026-04-08T12:20:10.333040Z","shell.execute_reply.started":"2026-04-08T12:20:09.255685Z","shell.execute_reply":"2026-04-08T12:20:10.332417Z"}},"outputs":[],"execution_count":null}]}