{"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":3362,"databundleVersionId":31148,"sourceType":"competition"},{"sourceId":5441,"databundleVersionId":38425,"sourceType":"competition"},{"sourceId":791828,"sourceType":"datasetVersion","datasetId":119698},{"sourceId":1003830,"sourceType":"datasetVersion","datasetId":550917}],"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"### \"Dogs vs Cats\" veri seti kullanarak kedi ve köpek görüntülerini sınıflandırmak için bir Convolutional Neural Network - CNN modelinin oluşturulması, eğitilmesi ve değerlendirilmesi adım adım gerçekleştirilmektedir.","metadata":{}},{"cell_type":"markdown","source":"## ✅ 1. Veri Seti Çıkartma (Data Extraction)\n\n🔍 Ne Yapıyor?\n\nKaggle’daki dogs-vs-cats yarışma veri setinin train.zip ve test1.zip dosyalarını\n/kaggle/working/ dizinine çıkarıyor. Çıkarılan dosyaları listeliyor.\n\n📁 Veri Seti Yapısı\n\ntrain.zip: İçinde cat.0.jpg, dog.123.jpg gibi etiketli görüntüler var (toplam 25.000)\n\ntest1.zip: Sadece 1.jpg, 2.jpg gibi etiketsiz test görüntüleri (12.500)\n","metadata":{}},{"cell_type":"code","source":"import zipfile\nimport os\n\n# Zip dosyalarının yolları\ntrain_zip_path = '/kaggle/input/dogs-vs-cats/train.zip'\ntest_zip_path = '/kaggle/input/dogs-vs-cats/test1.zip'\n\n# Çıkartma dizini\nextract_dir = '/kaggle/working/'\n\n# Train zip dosyasını aç\nprint(\"Train zip dosyası açılıyor...\")\nwith zipfile.ZipFile(train_zip_path, 'r') as zip_ref:\n    zip_ref.extractall(extract_dir)\n    print(\"Train dosyaları çıkartıldı\")\n\n# Test zip dosyasını aç\nprint(\"Test zip dosyası açılıyor...\")\nwith zipfile.ZipFile(test_zip_path, 'r') as zip_ref:\n    zip_ref.extractall(extract_dir)\n    print(\"Test dosyaları çıkartıldı\")\n\n# Çıkartılan dosyaları kontrol et\nprint(\"\\nÇıkartılan dosyalar:\")\nextracted_files = os.listdir(extract_dir)\nfor file in extracted_files:\n    print(f\"📁 {file}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-26T07:56:57.792797Z","iopub.execute_input":"2025-09-26T07:56:57.793417Z","iopub.status.idle":"2025-09-26T07:57:13.630157Z","shell.execute_reply.started":"2025-09-26T07:56:57.793381Z","shell.execute_reply":"2025-09-26T07:57:13.629350Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## ✅ 2. Veri Dizini Tespiti (Dynamic Data Directory Detection)\n\n🔍 Ne Yapıyor?\n\ntrain.zip dosyası çıkarıldığında, dosyaların nerede olduğunu bulmaya çalışıyor.\n\nÜç olası yol kontrol ediliyor:\n\n* /kaggle/working/train/\n\n* /kaggle/working/train/train/ (bazen Kaggle bu şekilde çıkarabiliyor)\n\n* /kaggle/working/ (doğrudan kök dizine çıkarıldıysa)\n\nHer dizindeki dosyaların içinde cat veya dog geçen isimler varsa, bu dizin data_dir olarak atanıyor.\n\n🎯 Neden Gerekli?\n\nÇünkü Kaggle’da:\n\nBazı durumlarda train.zip’i /kaggle/working/train/ içine çıkarabilir.\nBazen /kaggle/working/train/train/ gibi çift katmanlı çıkarabilir.\nBazen de doğrudan /kaggle/working/ içine çıkar.","metadata":{}},{"cell_type":"code","source":"print(\"Dizin yapısı:\")\n\n# Olası dizin yolları\npossible_paths = [\n    '/kaggle/working/train/',\n    '/kaggle/working/train/train/',\n    '/kaggle/working/'\n]\n\nfor path in possible_paths:\n    if os.path.exists(path):\n        files = os.listdir(path)\n        print(f\"\\n📂 {path} içeriği ({len(files)} dosya):\")\n        for file in files[:10]:  # İlk 10 dosyayı göster\n            print(f\"   {file}\")\n        if len(files) > 10:\n            print(\"   ...\")\n        \n        # Eğer bu train dizini ise data_dir olarak ayarla\n        if any(file.startswith(('cat', 'dog')) for file in files):\n            data_dir = path\n            print(f\"✅ Train verileri bulundu: {data_dir}\")\n            break\nelse:\n    print(\"❌ Train dizini bulunamadı. Mevcut dizinleri kontrol edin.\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-26T07:57:23.470543Z","iopub.execute_input":"2025-09-26T07:57:23.471229Z","iopub.status.idle":"2025-09-26T07:57:23.489642Z","shell.execute_reply.started":"2025-09-26T07:57:23.471206Z","shell.execute_reply":"2025-09-26T07:57:23.489044Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## ✅ 3. Etiketli DataFrame Oluşturma\n\n🔍 Ne Yapıyor?\n\ndata_dir içindeki tüm dosyaları listeler.\n\nSadece cat veya dog ile başlayan dosyaları filtreler (güvenlik önlemi).\n\nHer dosya için:\n\n* cat.*.jpg → etiket 0 (kedi)\n* dog.*.jpg → etiket 1 (köpek)\n\nSonuç olarak, iki sütunlu bir pandas DataFrame'i oluşturur:\n\n* filename: Görüntü dosyasının adı\n* category: Sınıf etiketi (0 = kedi, 1 = köpek)\n\n🎯 Neden Bu Adım Önemli?\n\nDerin öğrenme modelleri, dosya yolları ve etiketleri liste veya DataFrame olarak alır.\n\nBu yapı, eğitim (train_generator) ve doğrulama (validation_generator) veri yükleyicileri için temel olur.\n\nAyrıca, veri görselleştirme, sınıf dengesi analizi ve hata ayıklama için kritik bir önem sağlar.","metadata":{}},{"cell_type":"code","source":"# Gerekli kütüphaneler\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom PIL import Image\nfrom sklearn.model_selection import train_test_split\nimport warnings\nwarnings.filterwarnings('ignore')\n\n# Görsel stil ayarları\nplt.style.use('ggplot')\nsns.set_palette(\"husl\")\n\n# DOSYA İSİMLERİNİ VE ETİKETLERİ OLUŞTURMA\nprint(\"Dosyalar yükleniyor...\")\nfilenames = os.listdir(data_dir)\n\n# Sadece kedi ve köpek dosyalarını filtrele (diğer dosyaları atla)\nfiltered_filenames = [f for f in filenames if f.startswith(('cat', 'dog'))]\nprint(f\"Toplam {len(filtered_filenames)} kedi/köpek görüntüsü bulundu\")\n\n# Dosya isimlerinden etiketleri oluştur\nlabels = []\nfor filename in filtered_filenames:\n    if filename.startswith('cat'):\n        labels.append(0)  # Kedi\n    else:\n        labels.append(1)  # Köpek\n\n# DataFrame oluştur\ndf = pd.DataFrame({\n    'filename': filtered_filenames,\n    'category': labels\n})\n\nprint(f\"Toplam görüntü sayısı: {len(df)}\")\nprint(df.head())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-26T07:57:41.380415Z","iopub.execute_input":"2025-09-26T07:57:41.380823Z","iopub.status.idle":"2025-09-26T07:57:41.415730Z","shell.execute_reply.started":"2025-09-26T07:57:41.380799Z","shell.execute_reply":"2025-09-26T07:57:41.414953Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## ✅ 4. Veri Seti İstatistikleri ve Görselleştirme\n\n🔍 Ne Yapıyor?\n\ndf['category'] sütunundan sınıf dağılımını hesaplıyor:\n\n* Kedi (0): 12,500\n* Köpek (1): 12,500\n\nYüzde olarak gösteriyor.\n\nİki farklı şekilde görselleştiriyor:\n\n* Pasta grafik → toplamda %50-%50 dağılım\n* Bar plot (countplot) → kategorik sayım\n\n🎯 Neden Bu Adım Önemli?\n\n* Model eğitimi öncesi, veri setinin dengeli olup olmadığını kontrol etmek kritiktir.\n* Dengesiz veri seti, modelin çoğunluk sınıfına önyargılı olmasını sağlar.\n* Bu grafikler, rapor veya sunumda “veri seti nasıl?” sorusuna cevap verir.","metadata":{}},{"cell_type":"code","source":"# VERİ SETİ İSTATİSTİKLERİ\nprint(\"📊 VERİ SETİ İSTATİSTİKLERİ\")\nprint(\"=\" * 40)\n\n# Sınıf dağılımı\nclass_distribution = df['category'].value_counts()\ncat_count = class_distribution[0]\ndog_count = class_distribution[1]\ntotal = len(df)\n\nprint(f\"Kediler (0): {cat_count} (%{cat_count/total*100:.1f})\")\nprint(f\"Köpekler (1): {dog_count} (%{dog_count/total*100:.1f})\")\nprint(f\"Toplam: {total} görüntü\")\n\n# Sınıf dağılımı görselleştirme\nplt.figure(figsize=(12, 5))\n\nplt.subplot(1, 2, 1)\nplt.pie([cat_count, dog_count], \n        labels=['Kediler', 'Köpekler'], \n        autopct='%1.1f%%', \n        colors=['#ff9999','#66b3ff'],\n        startangle=90)\nplt.title('Sınıf Dağılımı')\n\nplt.subplot(1, 2, 2)\nsns.countplot(x='category', data=df, palette=['#ff9999','#66b3ff'])\nplt.title('Sınıf Dağılımı')\nplt.xlabel('Kategori (0: Kedi, 1: Köpek)')\nplt.ylabel('Sayı')\nplt.xticks([0, 1], ['Kedi', 'Köpek'])\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-26T07:57:44.808180Z","iopub.execute_input":"2025-09-26T07:57:44.808705Z","iopub.status.idle":"2025-09-26T07:57:45.206442Z","shell.execute_reply.started":"2025-09-26T07:57:44.808681Z","shell.execute_reply":"2025-09-26T07:57:45.205729Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## ✅ 5. Örnek Görüntülerin Görselleştirilmesi\n\n🔍 Ne Yapıyor?\n\nVerilerden ilk 5 kedi (category == 0) ve ilk 5 köpek (category == 1) görüntüsünü seçer.\n\nHer görüntüyü:\n\n* Image.open() ile yükler\n* resize((150, 150)) ile standart boyuta getirir\n\n2 satır, 5 sütun olacak şekilde (2x5) bir subplot oluşturur:\n\n* Üst satır: Kediler\n* Alt satır: Köpekler\n\nHer görselin üzerine sınıf etiketini (Kedi / Köpek) yazar.\n\n🎯 Neden Bu Adım Önemli?\n\n* Veri setinde beklenmeyen sorunlar olup olmadığını kontrol etmek (bozuk dosya, yanlış etiket, tek tip arka plan vs.)\n\n* Veri setini tanıtmak\n\n* Veri artırma stratejisi belirlerken (döndürme, kırpma vs.) fikir verir","metadata":{}},{"cell_type":"code","source":"# 5. ÖRNEK GÖRÜNTÜLERİ GÖRSELLEŞTİRME\nprint(\"🖼️ ÖRNEK GÖRÜNTÜLER\")\nprint(\"=\" * 40)\n\nplt.figure(figsize=(15, 8))\n\n# Rastgele 5 kedi ve 5 köpek görüntüsü göster\nfor i in range(5):\n    # Kediler\n    cat_img_path = os.path.join(data_dir, df[df['category'] == 0].iloc[i]['filename'])\n    cat_img = Image.open(cat_img_path)\n    cat_img = cat_img.resize((150, 150))\n    \n    plt.subplot(2, 5, i + 1)\n    plt.imshow(cat_img)\n    plt.title('Kedi', fontsize=12)\n    plt.axis('off')\n    \n    # Köpekler\n    dog_img_path = os.path.join(data_dir, df[df['category'] == 1].iloc[i]['filename'])\n    dog_img = Image.open(dog_img_path)\n    dog_img = dog_img.resize((150, 150))\n    \n    plt.subplot(2, 5, i + 6)\n    plt.imshow(dog_img)\n    plt.title('Köpek', fontsize=12)\n    plt.axis('off')\n\nplt.suptitle('Örnek Kedi ve Köpek Görüntüleri', fontsize=16)\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-26T07:57:53.708772Z","iopub.execute_input":"2025-09-26T07:57:53.709048Z","iopub.status.idle":"2025-09-26T07:57:54.882113Z","shell.execute_reply.started":"2025-09-26T07:57:53.709029Z","shell.execute_reply":"2025-09-26T07:57:54.881136Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## ✅ 6. Veri Setinin Üçlü Bölünmesi (Train / Validation / Test)\n\n🔍 Ne Yapıyor?\n\nİlk adım: Tüm veriyi (df) ikiye böler:\n\n* Eğitim (train): %70  \n* Geçici (temp): %30 (validation + test) → stratify=df['category'] ile sınıf dengesi korunuyor.\n\nİkinci adım: temp_df’yi ikiye böler:\n\n* Doğrulama (validation): %15 (temp’in %50’si → toplamın %15’i)\n* Test (test): %15 (temp’in %50’si → toplamın %15’i)→ Yine stratify ile sınıf dengesi korunuyor.\n\n  \n📊 Sonuç Dağılımı\n\n* Eğitim: ~17.500 görüntü (%70)\n* Doğrulama: ~3.750 görüntü (%15)\n* Test: ~3.750 görüntü (%15)\n\n🎯 Neden Bu Adım Kritik?\n\n* Overfitting tespiti: Eğitim accuracy %99, doğrulama accuracy %70 → overfitting var!\n* Gerçek performans ölçümü: Test seti, modelin gerçek dünya performansını yansıtır.","metadata":{}},{"cell_type":"code","source":"# 6. TRAIN-VALIDATION-TEST AYIRMA\nprint(\"✂️ VERİ SETİ BÖLÜNME İŞLEMİ\")\nprint(\"=\" * 40)\n\n# Önce train ve temp (validation + test) olarak ayır\ntrain_df, temp_df = train_test_split(df, \n                                    test_size=0.3, \n                                    random_state=42, \n                                    stratify=df['category'])\n\n# Sonra temp'i validation ve test olarak ayır\nval_df, test_df = train_test_split(temp_df, \n                                  test_size=0.5, \n                                  random_state=42, \n                                  stratify=temp_df['category'])\n\nprint(\"Veri seti bölünme istatistikleri:\")\nprint(f\"Toplam görüntü: {len(df)}\")\nprint(f\"Eğitim seti: {len(train_df)} ({len(train_df)/len(df)*100:.1f}%)\")\nprint(f\"Doğrulama seti: {len(val_df)} ({len(val_df)/len(df)*100:.1f}%)\")\nprint(f\"Test seti: {len(test_df)} ({len(test_df)/len(df)*100:.1f}%)\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-26T07:58:05.546770Z","iopub.execute_input":"2025-09-26T07:58:05.547049Z","iopub.status.idle":"2025-09-26T07:58:05.567346Z","shell.execute_reply.started":"2025-09-26T07:58:05.547023Z","shell.execute_reply":"2025-09-26T07:58:05.566832Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":" ## ✅ 7. Bölünme Sonrası Sınıf Dağılımı Görselleştirmesi\n\n🔍 Ne Yapıyor?\n\n1.  train_df, val_df, test_df dataframe'leri alır.\n2. Her birinde:\n    * Kedi (0) ve köpek (1) sayılarını hesaplar.\n3. Üç pasta grafiği (pie chart) oluşturur:\n    * Sol: Eğitim seti\n    * Orta: Doğrulama seti\n    * Sağ: Test seti\n4. Her grafiğin altına toplam görüntü sayısını ve sınıf yüzdelerini yazar.\n\n📊 Beklenen Sonuç\n\nHer pasta grafiğinde:\n\n* %50 Kedi\n* %50 Köpek\n\n→ Çünkü bölünme sırasında stratify=df['category'] kullanıldı.\n\n🎯 Neden Bu Adım Önemli?\n\n* Veri bölünme hatası olup olmadığını gösterir.\n* Model eğitimi öncesi, verinin her parçasının dengeli olduğunu kanıtlar.","metadata":{}},{"cell_type":"code","source":"# 7. BÖLÜNME SONRASI GÖRSELLEŞTİRME\nprint(\"📊 BÖLÜNME SONRASI SINIF DAĞILIMLARI\")\nprint(\"=\" * 50)\n\nfig, axes = plt.subplots(1, 3, figsize=(18, 6))\n\ndatasets = [train_df, val_df, test_df]\ndataset_names = ['Eğitim Seti', 'Doğrulama Seti', 'Test Seti']\ncolors = ['#ff9999', '#66b3ff']\n\nfor i, (dataset, name) in enumerate(zip(datasets, dataset_names)):\n    cat_count = len(dataset[dataset['category'] == 0])\n    dog_count = len(dataset[dataset['category'] == 1])\n    \n    axes[i].pie([cat_count, dog_count], \n                labels=['Kedi', 'Köpek'], \n                autopct='%1.1f%%', \n                colors=colors,\n                startangle=90)\n    axes[i].set_title(f'{name}\\n({len(dataset)} görüntü)', fontsize=14)\n\nplt.suptitle('Veri Seti Bölünme Sonrası Sınıf Dağılımları', fontsize=16)\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-26T07:58:11.311423Z","iopub.execute_input":"2025-09-26T07:58:11.311723Z","iopub.status.idle":"2025-09-26T07:58:11.545087Z","shell.execute_reply.started":"2025-09-26T07:58:11.311702Z","shell.execute_reply":"2025-09-26T07:58:11.544393Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## ✅ 8. Veri Ön İşleme Özeti\n\n🔍 Ne Yapıyor?\n\n* Toplam görüntü sayısını ve sınıf dağılımını yazdırır.\n\n* Kedi/köpek oranını yüzde olarak gösterir.\n\n* Eğitim/doğrulama/test bölünmesinin sayısal sonuçlarını sunar.","metadata":{}},{"cell_type":"code","source":"# 8. ÖZET RAPOR\nprint(\"=\" * 60)\nprint(\"📋 VERİ ÖNİŞLEME ÖZET RAPORU\")\nprint(\"=\" * 60)\nprint(f\"📊 Toplam Görüntü Sayısı: {len(df):,}\")\nprint(f\"🐱 Kedi Görüntüleri: {len(df[df['category'] == 0]):,}\")\nprint(f\"🐶 Köpek Görüntüleri: {len(df[df['category'] == 1]):,}\")\nprint(f\"📈 Kedi/Köpek Oranı: %{len(df[df['category'] == 0])/len(df)*100:.1f} / %{len(df[df['category'] == 1])/len(df)*100:.1f}\")\n\nprint(f\"\\n📂 Veri Seti Bölünmesi:\")\nprint(f\"   🎯 Eğitim Seti: {len(train_df):,} görüntü\")\nprint(f\"   ✅ Doğrulama Seti: {len(val_df):,} görüntü\")\nprint(f\"   🧪 Test Seti: {len(test_df):,} görüntü\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-26T07:58:41.099163Z","iopub.execute_input":"2025-09-26T07:58:41.099943Z","iopub.status.idle":"2025-09-26T07:58:41.109342Z","shell.execute_reply.started":"2025-09-26T07:58:41.099922Z","shell.execute_reply":"2025-09-26T07:58:41.108815Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## ✅ 9. Gerekli Kütüphanelerin İçe Aktarılması\n\n🔍 Ne Yapıyor?\n\nTensorFlow ve Keras temel bileşenlerini içe aktarır:\n\n* Sequential: Modeli katman katman tanımlamak için\n* Conv2D, MaxPooling2D, ...: CNN katmanları\n* EarlyStopping, ReduceLROnPlateau: Eğitim sırasında akıllı durdurma ve öğrenme oranı ayarlama\n* Adam: Optimizer\n\nVeri görselleştirme ve sayısal işlem kütüphaneleri:\n\n* matplotlib.pyplot, numpy","metadata":{}},{"cell_type":"code","source":"# Gerekli kütüphaneleri import edelim\nimport tensorflow as tf\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout, BatchNormalization\nfrom tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau\nfrom tensorflow.keras.optimizers import Adam\nimport matplotlib.pyplot as plt\nimport numpy as np","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-26T07:58:46.239920Z","iopub.execute_input":"2025-09-26T07:58:46.240485Z","iopub.status.idle":"2025-09-26T07:59:04.049273Z","shell.execute_reply.started":"2025-09-26T07:58:46.240466Z","shell.execute_reply":"2025-09-26T07:59:04.048740Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## ✅ 10. Model Hiperparametreleri\n\n🔍 Ne Yapıyor?\n\nÜç temel hiperparametreyi tanımlar:\n\n* IMG_SIZE = 224: Giriş görüntülerinin boyutu (224×224 piksel)\n* BATCH_SIZE = 32: Her eğitim adımında kaç görüntü işleneceği\n* EPOCHS = 10: Eğitim döngüsü sayısı\n* \nBu parametreleri kullanıcıya açıklayıcı yorumlarla ve formatlı çıktı ile gösterir.\n\n🎯 Neden Bu Adım Önemli?\n\nTekrarlanabilirlik: Başka biri projeyi çalıştırırsa, aynı sonuçları alabilmeli.\n\nDeney Tasarımı: Farklı BATCH_SIZE veya IMG_SIZE ile deney yapmak istersen, tek bir yerden değiştirirsin.","metadata":{}},{"cell_type":"code","source":"# MODEL PARAMETRELERİ\nIMG_SIZE = 224 #Görseller modelin girişine sabit boyutta verilmeli.\n\nBATCH_SIZE = 32 #Eğitim sırasında model aynı anda kaç görseli işleyecek?\n\nEPOCHS = 10 #Epoch sayısı ne kadar yüksekse, model o kadar çok öğrenir,ama overfitting riski de artar.\n\n\nprint(\"🔧 MODEL PARAMETRELERİ\")\nprint(\"=\" * 40)\nprint(f\"Görüntü Boyutu: {IMG_SIZE}x{IMG_SIZE}\")\nprint(f\"Batch Size: {BATCH_SIZE}\")\nprint(f\"Epoch Sayısı: {EPOCHS}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-26T07:59:29.807330Z","iopub.execute_input":"2025-09-26T07:59:29.808297Z","iopub.status.idle":"2025-09-26T07:59:29.812969Z","shell.execute_reply.started":"2025-09-26T07:59:29.808273Z","shell.execute_reply":"2025-09-26T07:59:29.812163Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## ✅ 11. Veri Artırma ve Veri Yükleyiciler\n\n🔍 Ne Yapıyor?\n\n1. Veri Artırma (Data Augmentation) Tanımlama\n   \n* train_datagen: Eğitim verisi için zenginleştirme teknikleri:\n  \n    * rescale=1./255: Piksel değerlerini [0,1] aralığına normalize eder \n    * rotation_range=20: ±20° rastgele döndürme\n    * width/height_shift_range=0.2: %20 kaydırma\n    * horizontal_flip=True: Yatay çevirme (kedi/köpek için mantıklı)\n    * zoom_range=0.2: Yakınlaştırma/uzaklaştırma\n    * shear_range=0.2: Eğik perspektif\n    * fill_mode='nearest': Boşlukları akıllıca doldurma\n    \n* Bu, tek bir görüntüden çok sayıda varyasyon üretir → model gerçek dünya koşullarına daha dayanıklı olur. \n\n2. Doğrulama/Test için Sadece Normalizasyon\n    * valid_test_datagen: Sadece  rescale=1./255\n    * Augmentation yapılmaz → çünkü bu veriler modelin nihai performansını ölçmek içindir.\n    * Test verisi asla değiştirilmemeli.\n\n3. Etiketleri String’e Dönüştürme\n    * 0 → 'cat', 1 → 'dog'\n    * Çünkü flow_from_dataframe, class_mode='binary' kullanıldığında string etiketler bekler.\n\n4. Üç Veri Yükleyici Oluşturma\n   \n    * train_generator: Eğitim verisi (augmentation + shuffle)\n    * validation_generator: Doğrulama verisi (sadece normalize, shuffle=False)\n    * test_generator: Test verisi (sadece normalize, shuffle=False)\n    * shuffle=False → doğrulama/testte tahminlerin sırası korunur, Grad-CAM gibi analizlerde önemlidir.\n\n\n🎯 Neden Bu Adım Kritik?\n\n   * Overfitting önleyici: Augmentation olmadan, model 25.000 görüntüyü ezberleyebilir.\n   *  Gerçekçilik: Gerçek dünyada kediler her zaman düz durmaz → model dönmüş, kaymış * versiyonlara da maruz kalır.\n   *  Verimlilik: ImageDataGenerator, verileri belleğe yüklemek yerine ihtiyaç anında üretir → bellek tasarrufu.","metadata":{}},{"cell_type":"code","source":"# DATA AUGMENTATION ve DATA GENERATOR'LAR\nprint(\"🔄 DATA AUGMENTATION ve DATA GENERATOR'LAR\")\nprint(\"=\" * 50)\n\n# Data Augmentation ayarları\n# Görselleri çeşitlendirerek modelin overfitting yapmasını engeller.\n# Gerçek dünyadaki varyasyonlara karşı modelin dayanıklılığını artırır.\n# rescale=1./255: Görsellerin piksel değerleri 0–255 aralığındadır. Bu, modelin daha hızlı ve stabil öğrenmesi için normalize edilir.\n\ntrain_datagen = tf.keras.preprocessing.image.ImageDataGenerator(\n    rescale=1./255,             # BURADA NORMALIZE EDİYORUZ,Piksel değerlerini 0-1 aralığına çeker   \n    rotation_range=20,          # ±20 derece döndürme\n    width_shift_range=0.2,      # %20 yatay kaydırma\n    height_shift_range=0.2,     # %20 dikey kaydırma\n    horizontal_flip=True,       # Yatay çevirme\n    zoom_range=0.2,             # %20 zoom\n    shear_range=0.2,            # %20 kesme (shear) dönüşümü\n    fill_mode='nearest'         # Boşlukları en yakın pikselle doldur\n)\n\n# Validation ve test için sadece rescale\n# Doğrulama ve test verileri üzerinde augmentation yapılmaz.\n# Çünkü bu veriler modelin başarısını ölçmek için kullanılır; değiştirilmemelidir.                   \n\nvalid_test_datagen = tf.keras.preprocessing.image.ImageDataGenerator(\n    rescale=1./255) # BURADA NORMALIZE EDİYORUZ \n                    \n\n# ÖNCE: Category sütunundaki sayısal değerleri string'e çevirelim\ntrain_df['category'] = train_df['category'].replace({0: 'cat', 1: 'dog'})\nval_df['category'] = val_df['category'].replace({0: 'cat', 1: 'dog'})\ntest_df['category'] = test_df['category'].replace({0: 'cat', 1: 'dog'})\n\nprint(\"✅ Category sütunu string'e çevrildi:\")\nprint(train_df['category'].value_counts())\nprint()\n\n# DATA GENERATOR'LARI OLUŞTUR\nprint(\"📂 Data Generator'lar oluşturuluyor...\")\n\n# Train generator\ntrain_generator = train_datagen.flow_from_dataframe(\n    dataframe=train_df,\n    directory=data_dir,#-  Görsellerin bulunduğu klasör (data_dir)\n    x_col='filename',#Görsel dosya adı\n    y_col='category',#Etiket\n    target_size=(IMG_SIZE, IMG_SIZE),#Görsel boyutu (224x224)\n    batch_size=BATCH_SIZE,\n    class_mode='binary', #İkili sınıflandırma (cat ve dog)\n    shuffle=True #Eğitim sırasında veriler karıştırılır\n)\n\n# Validation generator\nvalidation_generator = valid_test_datagen.flow_from_dataframe(\n    dataframe=val_df,\n    directory=data_dir,\n    x_col='filename',\n    y_col='category',\n    target_size=(IMG_SIZE, IMG_SIZE),\n    batch_size=BATCH_SIZE,\n    class_mode='binary',\n    shuffle=False\n)\n\n# Test generator\ntest_generator = valid_test_datagen.flow_from_dataframe(\n    dataframe=test_df,\n    directory=data_dir,\n    x_col='filename',\n    y_col='category',\n    target_size=(IMG_SIZE, IMG_SIZE),\n    batch_size=BATCH_SIZE,\n    class_mode='binary',\n    shuffle=False\n)\n\nprint(\"✅ Data Generator'lar başarıyla oluşturuldu!\")\nprint(f\"Eğitim sınıfları: {train_generator.class_indices}\")\nprint(f\"Eğitim batch sayısı: {len(train_generator)}\")\nprint(f\"Doğrulama batch sayısı: {len(validation_generator)}\")\nprint(f\"Test batch sayısı: {len(test_generator)}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-26T07:59:38.278554Z","iopub.execute_input":"2025-09-26T07:59:38.278899Z","iopub.status.idle":"2025-09-26T07:59:38.521882Z","shell.execute_reply.started":"2025-09-26T07:59:38.278879Z","shell.execute_reply":"2025-09-26T07:59:38.521099Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## ✅ 12. CNN Model Mimarisi\n\n* Proje kapsamında, kedi ve köpek görüntülerini sınıflandırmak üzere özelleştirilmiş bir evrişimli sinir ağı (CNN) modeli geliştirilmiştir.\n\n* Model, dört ardışık konvolüsyon bloğundan oluşmaktadır. Her blok, evrişim katmanı (Conv2D), toplu normalleştirme (BatchNormalization), havuzlama (MaxPooling2D) ve bırakma (Dropout) katmanlarını içerir. Filtre sayısı her blokta iki kat artırılarak (32 → 64 → 128 → 256), modelin düşük seviyeli kenar ve doku özelliklerinden yüksek seviyeli nesne parçalarına kadar hiyerarşik öğrenmesi sağlanmıştır.\n\n* Konvolüsyon katmanlarının ardından, özellik haritaları düzleştirilerek iki tam bağlı katmana (Dense(512), Dense(256)) iletilmiştir. Bu katmanlarda %50 droupout bırakma oranı uygulanarak aşırı uyum (overfitting) riski minimize edilmiştir.\n\n* Çıkış katmanı, ikili sınıflandırma için sigmoid aktivasyon fonksiyonu kullanmakta olup, çıktı olarak köpek olma olasılığını (0–1 arası) üretmektedir. \n\n\n🔍 Ne Yapıyor?\n\n1. 4 adet konvolüsyon bloğu tanımlar:\n\n    * Her blok: Conv2D → BatchNormalization → MaxPooling2D → Dropout\n    * Filtre sayısı: 32 → 64 → 128 → 256 (her seviyede artar)\n\n2. Tam bağlı (fully connected) katmanlar:\n\n    * Flatten() → 2D çıktıyı 1D vektöre çevirir\n    * Dense(512) → güçlü öğrenme\n    * Dense(256) → ekstra soyutlama\n    * Her ikisinde BatchNorm + Dropout(0.5)\n\n3. Çıkış katmanı:\n\n    * Dense(1, activation='sigmoid') → ikili sınıflandırma\n\n\n🎯 Neden Bu Mimari İyi?\n\n* Düzenleme (regularization): Her katmanda overfitting önleme\n* Esneklik: Daha fazla veriyle daha iyi genelleme yapar","metadata":{}},{"cell_type":"code","source":"# CNN MODELİ OLUŞTURMA\nmodel = Sequential() #Katmanları sıralı şekilde eklemek için kullanıyoruz.\n\n# 1. KONVOLÜSYON KATMANI\nmodel.add(Conv2D(32, (3, 3), activation='relu', input_shape=(IMG_SIZE, IMG_SIZE, 3)))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(2, 2))\nmodel.add(Dropout(0.25))\n\n# 2. KONVOLÜSYON KATMANI\nmodel.add(Conv2D(64, (3, 3), activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(2, 2))\nmodel.add(Dropout(0.25))\n\n# 3. KONVOLÜSYON KATMANI\nmodel.add(Conv2D(128, (3, 3), activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(2, 2))\nmodel.add(Dropout(0.25))\n\n# 4. KONVOLÜSYON KATMANI\nmodel.add(Conv2D(256, (3, 3), activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(2, 2))\nmodel.add(Dropout(0.25))\n\n# Bu yapı 4 kez tekrarlanıyor, filtre sayısı her seferinde artırılıyor: 32 → 64 → 128 → 256\n# Bu, modelin daha karmaşık görsel özellikleri öğrenmesini sağlar.\n\n# FULLY CONNECTED KATMANLARI\n\nmodel.add(Flatten()) \n# Konvolüsyon çıktısını düzleştirir → Dense katmanlara geçiş\n\nmodel.add(Dense(512, activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(Dropout(0.5))\n# 512 nöronlu katman, güçlü öğrenme kapasitesi\n# %50 dropout: overfitting’e karşı güçlü önlem\n\n\nmodel.add(Dense(256, activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(Dropout(0.5))\n# Ek bir ara katman, modelin genelleme gücünü artırır.\n\n\n# ÇIKIŞ KATMANI (Binary classification için sigmoid)\n\nmodel.add(Dense(1, activation='sigmoid'))\n# Binary classification için sigmoid kullanılır.\n# Çıktı: 0–1 arası bir olasılık değeri → 0 → kedi, 1 → köpek\n\n\n# MODEL ÖZETİ\nmodel.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-26T07:59:46.879682Z","iopub.execute_input":"2025-09-26T07:59:46.880387Z","iopub.status.idle":"2025-09-26T07:59:50.401765Z","shell.execute_reply.started":"2025-09-26T07:59:46.880365Z","shell.execute_reply":"2025-09-26T07:59:50.401150Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## ✅ 13. Callback’lerin Tanımlanması\n\n🔍 Ne Yapıyor?\n\nİki akıllı \"gözlemci\" tanımlıyor:\n\n*  EarlyStopping → \"Eğitimi ne zaman durduracağını bilen akıllı durdurucu\"\n\n* Ne izler? → val_loss (doğrulama kaybı)\n* Ne zaman durdurur? → 5 epoch boyunca iyileşme yoksa\n* En iyi ağırlıkları geri yükleme → restore_best_weights=True\n* Amaç: Overfitting’i önlemek + gereksiz eğitimden kaçınmak\n\n    🕒 Örnek:\n\n    * Epoch 8’de en iyi val_loss = 0.35 oldu.\n    * Epoch 13’e kadar daha iyi sonuç alınamadı → eğitim durdu, ama epoch 8’in ağırlıkları kullanıldı. \n\n*  ReduceLROnPlateau → \"Öğrenme oranını ayarlayan akıllı termostat\"\n\n* Ne izler? → val_loss\n* Ne zaman devreye girer? → 3 epoch boyunca iyileşme yoksa\n* Ne yapar? → Öğrenme oranını %20’sine düşürür (factor=0.2)\n* Minimum sınır: min_lr=0.00001\n\n    📉 Örnek:\n\n    * Başlangıç öğrenme oranı: 0.001\n    * 3 epoch’ta val_loss düşmedi → yeni oran: 0.001 × 0.2 = 0.0002\n    * Artık model daha küçük adımlarla ince ayar yapıyor.\n\n🎯 Neden Bu Callback’ler Önemli?\n\n* EarlyStopping: Zaman ve kaynak tasarrufu + overfitting önleme\n\n* ReduceLROnPlateau: Modelin \"takıldığı\" noktalarda öğrenmeye devam etmesini sağlar.","metadata":{}},{"cell_type":"code","source":"# CALLBACK'LERİ TANIMLAMA\nprint(\"\\n⏰ CALLBACK'LERİ AYARLAMA\")\nprint(\"=\" * 40)\n\n# CALLBACK'LER\n\n\"\"\" \nEarlyStopping Ne yapar?\n- Eğitim sırasında val_loss (doğrulama kaybı) izlenir.\n- Eğer 5 epoch boyunca iyileşme olmazsa (patience=5), eğitim durdurulur.\n- restore_best_weights=True: En iyi sonuç alınan epoch’taki ağırlıklar geri yüklenir.\nNeden kullanılır?\n- Overfitting’i engeller.\n- Gereksiz yere uzun eğitim süresini kısaltır.\n- Modelin en iyi halini korur.\n\"\"\"\n\nearly_stopping = EarlyStopping(\n    monitor='val_loss',\n    patience=5,\n    restore_best_weights=True,\n    verbose=1\n)\n\n\"\"\"\nReduceLROnPlateau Ne yapar?\n- val_loss iyileşmiyorsa, öğrenme oranını (learning rate) azaltır.\n- factor=0.2: Öğrenme oranı %20’ye düşürülür.\n- patience=3: 3 epoch boyunca gelişme yoksa devreye girer.\n- min_lr: Öğrenme oranı bu değerin altına inemez.\nNeden kullanılır?\n- Modelin daha hassas öğrenmesini sağlar.\n- Özellikle sonlara doğru küçük iyileştirmeler için faydalıdır.\n\"\"\"\n\nreduce_lr = ReduceLROnPlateau(\n    monitor='val_loss',\n    factor=0.2,\n    patience=3,\n    min_lr=0.00001,\n    verbose=1\n)\n\n\"\"\"\nSonuç bu iki callback sayesinde:\n- Eğitim süreci daha akıllı ve verimli hale gelir.\n- Modelin en iyi halini koruyarak gereksiz epoch’lardan kaçılır.\n- Öğrenme oranı dinamik olarak ayarlanır → daha iyi sonuçlar\n\"\"\"\n\nprint(\"Callback'ler ayarlandı:\")\nprint(\"- Early Stopping: patience=5\")\nprint(\"- Reduce LR on Plateau: factor=0.2, patience=3\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-26T08:01:14.375003Z","iopub.execute_input":"2025-09-26T08:01:14.375290Z","iopub.status.idle":"2025-09-26T08:01:14.381361Z","shell.execute_reply.started":"2025-09-26T08:01:14.375269Z","shell.execute_reply":"2025-09-26T08:01:14.380680Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## ✅ 14. Modelin Derlenmesi (Compile)\n\n🔧 Model Derleme Nedir?\n\nModel mimarisini tanımladın (katmanlar, filtreler vs.), ama henüz nasıl öğreneceğini bilmiyor.\n\nDerleme, modeli eğitime hazırlamak için şu üç şeyi belirlemen demektir:\n\n* Optimizer -> Nasıl öğrenilecek? -> Adam(learning_rate=0.001)\n* Loss Function -> Ne kadar hata yapıyor? -> binary_crossentropy\n* Metrics -> Başarı nasıl ölçülecek? -> accuracy,precision,recall\n\n🔍 1. Optimizer: Adam(learning_rate=0.001)\n\n* Basit Açıklama:\"Modelin öğrenme stratejisi.\" \n\n* Adam: En popüler optimizer’dir.\n\n    * Hem hızlı, hem istikrarlı, hem de öğrenme oranını kendi ayarlar.\n\n* learning_rate=0.001:\n\n    * Çok büyük olsaydı → model \"aşırı tepki verir\", asla en iyi noktaya ulaşamazdı.\n\n    * Çok küçük olsaydı → öğrenme çok yavaş olurdu.\n      \n\n📉 2. Loss Function: binary_crossentropy\n\n* Basit Açıklama: \"Modelin ne kadar yanlış olduğunu ölçen cetvel.\" \n\n* İkili sınıflandırma (kedi/köpek) için en doğru seçim.\n\n* Nasıl çalışır?\n\n    * Gerçek etiket: kedi = 0\n    * Model tahmini: 0.9 (yani \"%90 köpek\")\n      → Çok büyük hata! → Loss değeri yüksek olur.\n\n* Model, bu loss’u en aza indirmeye çalışır.\n\n🖼️ Örnek: \n\n   * Gerçek: kedi (0), Tahmin: 0.1 → Loss düşük (iyi)\n   * Gerçek: kedi (0), Tahmin: 0.9 → Loss yüksek (kötü)\n\n📊 3. Metrics: accuracy, precision, recall\n\nNeden Sadece Accuracy Yetmez?\n\n* Diyelim ki veri setinde %95 kedi, %5 köpek olsaydı:\n\n    → Model hep \"kedi\" deseydi, %95 accuracy alırdı\n    → Ama hiç köpek tanıyamazdı → kullanışsız bir model\n\n* Bu yüzden üç metriğe ihtiyacın var:\n\n    * Accuracy - Tüm tahminlerin kaç tanesi doğru? - Yüksek (iyi)\n    * Precision - “Köpek” dediğimde ne kadar eminim? - Yüksek (iyi)\n    * Recall - Gerçek köpeklerin kaçını yakaladım? - Yüksek (iyi)\n\n\n* Basit Anlamda:\n\n    * Precision yüksek → Model \"evet\" dediğinde çoğunlukla doğru.\n    * Recall yüksek → Model gerçek köpekleri kaçırmıyor.\n","metadata":{}},{"cell_type":"code","source":"#  MODELİ DERLEME\nprint(\"\\n⚙️ MODELİ DERLEME\")\nprint(\"=\" * 40)\n\"\"\"\nModel Derleme Nedir?\nModeli oluşturduktan sonra, onu eğitmek için şu üç şeyi tanımlamamız gerekir:\n- optimizer → Nasıl öğrenilecek?\n- loss function → Ne kadar hata yapıyor?\n- metrics → Başarıyı nasıl ölçeceğiz?\n\"\"\"\n\n# Optimizer\n\"\"\"\n- Adam, en çok kullanılan öğrenme algoritmalarından biridir.\n- learning_rate=0.001: Öğrenme hızı. Küçük olursa yavaş ama hassas öğrenir; \n  büyük olursa hızlı ama riskli.\n- Adam, öğrenme hızını otomatik ayarlayabildiği için genelde iyi sonuç verir.\n\"\"\"\noptimizer = Adam(learning_rate=0.001)\n\n# Modeli derle\n\"\"\"\nLoss Function: binary_crossentropy\n- İkili sınıflandırma için en uygun hata fonksiyonu.\n- Modelin tahmini ile gerçek etiket arasındaki farkı ölçer.\n- Örnek: Gerçek etiket “kedi” (0), model tahmini “0.8” → yüksek hat\n\nMetrics: accuracy, precision, recall\n- accuracy: Doğru tahmin oranı\n- precision: “Köpek” dediği örneklerin ne kadarı gerçekten köpek?\n- recall: Gerçek köpeklerin ne kadarını doğru buldu?\n- Bu üç metrik birlikte kullanıldığında modelin hem genel başarısı \n  hem de sınıflar üzerindeki hassasiyeti ölçülür.\n- Sadece accuracy yeterli olmayabilir.  Örneğin: %90 kedi, %10 köpek olan bir veri setinde\n  model hep “kedi” dese bile %90 doğruluk alır.\n- precision ve recall, özellikle dengesiz veri setlerinde daha doğru değerlendirme sağlar.\n\"\"\"\nmodel.compile(\n    optimizer=optimizer,\n    loss='binary_crossentropy',  # Binary classification için\n    metrics=['accuracy', 'precision', 'recall']\n)\n\nprint(\"Model derleme tamamlandı:\")\nprint(f\"Optimizer: Adam (lr=0.001)\")\nprint(\"Loss: binary_crossentropy\")\nprint(\"Metrics: accuracy, precision, recall\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-26T08:01:20.339210Z","iopub.execute_input":"2025-09-26T08:01:20.339527Z","iopub.status.idle":"2025-09-26T08:01:20.352438Z","shell.execute_reply.started":"2025-09-26T08:01:20.339505Z","shell.execute_reply":"2025-09-26T08:01:20.351547Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## ✅ 15. Model Eğitimi (model.fit)\n\n🔍 Ne Yapıyor?\n\nModeli, belirlenen veri ve kurallarla öğrenmeye zorluyor:\n\n        history = model.fit(\n            train_generator,           # 📚 Eğitim verisi (augmentasyonlu)\n            epochs=EPOCHS,             # 🔁 Kaç tur çalışacak? (örneğin 10)\n            validation_data=validation_generator,  # 🧪 Her tur sonunda test\n            callbacks=[early_stopping, reduce_lr], # 🧠 Akıllı kurallar\n            verbose=1                  # 📢 Eğitim ilerlemesini göster\n        )\n\n🧠 Eğitim Sürecini \"Okul Benzetmesi\" ile Anlayalım\n\nDiyelim ki model bir öğrenci, sen de öğretmensin.\n\n📚 1. train_generator → Ders Kitabı + Ödevler\n\n* Her gün öğrenciye farklı versiyonlarda sorular soruyorsun:\n\n   * Resimleri döndür, çevir, yakınlaştır → gerçek hayatta karşılaşabileceği varyasyonlar\n     \n* Bu, öğrencinin ezber yapmasını değil, anlayarak öğrenmesini sağlar.\n\n🔁 2. epochs=EPOCHS → Sınav Dönemi\n\n* Öğrenci, tüm ders kitabını 10 kez (örneğin) tekrar eder.\n\n* Her tekrarda, daha iyi bağlantılar kurar, hatalarını düzeltir.\n\n🧪 3. validation_data → Ara Sınavlar\n\n* Her tekrarın sonunda, orijinal sorulardan oluşan bir sınav yaparsın.\n\n* Bu sınavda:\n\n    * Doğru cevap oranı → accuracy\n    * \"Köpek\" dediklerinin ne kadarı doğru? → precision\n    * Gerçek köpek sorularını kaçını bildi? → recall\n\n* Amaç: \"Ezber mi yapıyor, yoksa anlayarak mı öğreniyor?\" diye kontrol etmek.\n\n🧠 4. callbacks → Akıllı Kurallar\n\n* EarlyStopping:\n    → \"Son 5 sınavda puanın artmadıysa, yeter. Daha fazla tekrar fayda vermez.\"\n  \n* ReduceLROnPlateau:\n    → \"Takıldın mı? O zaman soruları daha küçük adımlarla çöz.\" (öğrenmeyi yavaşlat)\n\n📢 5. verbose=1 → İlerleme Raporu","metadata":{}},{"cell_type":"code","source":"# MODEL EĞİTİMİ\nprint(\"\\n🎯 MODEL EĞİTİMİ\")\nprint(\"=\" * 40)\n\n# Modeli eğit\nhistory = model.fit(\n    train_generator,\n    epochs=EPOCHS,\n    validation_data=validation_generator,\n    callbacks=[early_stopping, reduce_lr],\n    verbose=1\n)\n\n\"\"\"\n Ne yapıyor?\n- train_generator: Eğitim verisi, augmentasyon uygulanmış\n- validation_data: Doğrulama verisi, sadece normalize edilmiş\n- epochs=EPOCHS: Model veriyi kaç kez görecek (örneğin 15 kez)\n- callbacks: Eğitim sırasında akıllı durdurma ve öğrenme oranı ayarlama\n- verbose=1: Eğitim ilerlemesini detaylı olarak ekrana yazdırır\n\nEğitim Sürecinde Ne Olur?\nHer epoch'ta:\n- Model, batch batch görselleri işler\n- Her görsel için tahmin yapar\n- Gerçek etiketle karşılaştırır → hata hesaplanır\n- Bu hataya göre ağırlıklar güncellenir\n- Epoch sonunda doğrulama verisiyle başarı ölçülür\n\n\"\"\"\n\nprint(\"✅ Model eğitimi tamamlandı!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-26T08:01:58.411677Z","iopub.execute_input":"2025-09-26T08:01:58.412070Z","iopub.status.idle":"2025-09-26T08:35:22.389341Z","shell.execute_reply.started":"2025-09-26T08:01:58.412042Z","shell.execute_reply":"2025-09-26T08:35:22.388755Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## ✅ 16. Eğitim Performansının Görselleştirilmesi\n\n🔍 Ne Yapıyor?\n\nGrafikler:\n\n * Accuracy: Doğru tahmin oranı\n\n * Loss: Hata miktarı\n\n * Precision: \"Köpek\" dediklerinin ne kadarı doğru?\n\n * Recall: Gerçek köpeklerin ne kadarı yakalandı?\n\nNeden Önemli? \n\n * Eğitim ve doğrulama metriklerinin karşılaştırılması, overfitting veya underfitting durumlarını tespit eder.","metadata":{}},{"cell_type":"code","source":"# EĞİTİM GEÇMİŞİNİ GÖRSELLEŞTİRME\nprint(\"\\n📈 EĞİTİM PERFORMANS GRAFİKLERİ\")\nprint(\"=\" * 40)\n\nfig, axes = plt.subplots(2, 2, figsize=(15, 12))\n\n# Accuracy grafiği\naxes[0, 0].plot(history.history['accuracy'], label='Eğitim Accuracy')\naxes[0, 0].plot(history.history['val_accuracy'], label='Doğrulama Accuracy')\naxes[0, 0].set_title('Model Accuracy')\naxes[0, 0].set_xlabel('Epoch')\naxes[0, 0].set_ylabel('Accuracy')\naxes[0, 0].legend()\naxes[0, 0].grid(True)\n\"\"\"\n1. Accuracy Grafiği\n- Modelin ne kadar doğru tahmin yaptığını gösterir.\n- Eğitim ve doğrulama doğruluğu birlikte çizilir.\n- Doğrulama doğruluğu sabit kalıyorsa → model overfit olabilir.\n\"\"\"\n\n\n# Loss grafiği\naxes[0, 1].plot(history.history['loss'], label='Eğitim Loss')\naxes[0, 1].plot(history.history['val_loss'], label='Doğrulama Loss')\naxes[0, 1].set_title('Model Loss')\naxes[0, 1].set_xlabel('Epoch')\naxes[0, 1].set_ylabel('Loss')\naxes[0, 1].legend()\naxes[0, 1].grid(True)\n\"\"\"\n2. Loss Grafiği\n- Modelin yaptığı hatayı gösterir.\n- Loss azalıyorsa → model öğreniyor demektir.\n- Doğrulama loss artıyorsa → overfitting riski vardır.\n\"\"\"\n\n# Precision grafiği\naxes[1, 0].plot(history.history['precision'], label='Eğitim Precision')\naxes[1, 0].plot(history.history['val_precision'], label='Doğrulama Precision')\naxes[1, 0].set_title('Model Precision')\naxes[1, 0].set_xlabel('Epoch')\naxes[1, 0].set_ylabel('Precision')\naxes[1, 0].legend()\naxes[1, 0].grid(True)\n\"\"\"\n3. Precision Grafiği\n- Modelin “köpek” dediği örneklerin ne kadarının gerçekten köpek olduğunu gösterir.\n- Özellikle dengesiz veri setlerinde çok önemlidir.\n\"\"\"\n\n\n# Recall grafiği\naxes[1, 1].plot(history.history['recall'], label='Eğitim Recall')\naxes[1, 1].plot(history.history['val_recall'], label='Doğrulama Recall')\naxes[1, 1].set_title('Model Recall')\naxes[1, 1].set_xlabel('Epoch')\naxes[1, 1].set_ylabel('Recall')\naxes[1, 1].legend()\naxes[1, 1].grid(True)\n\"\"\"\n4. Recall Grafiği\n- Gerçek köpeklerin ne kadarını doğru tahmin ettiğini gösterir.\n- Yani modelin “kaçırdığı” pozitif örnekleri ölçer.\n\n\"\"\"\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-26T08:35:30.564762Z","iopub.execute_input":"2025-09-26T08:35:30.565320Z","iopub.status.idle":"2025-09-26T08:35:31.315458Z","shell.execute_reply.started":"2025-09-26T08:35:30.565299Z","shell.execute_reply":"2025-09-26T08:35:31.314660Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"📊 Yukarıdaki Grafikte Genel Görünüm\n\n4 grafik var:\n\n1. Model Accuracy → Doğruluk\n2. Model Loss → Kayıp (hata)\n3. Model Precision → Hassasiyet\n4. Model Recall → Duyarlılık   \n\n\n🔍 1. Model Accuracy (Doğruluk)\n\n✅ İdeal durum: Eğitim ve doğrulama accuracy birlikte yükseliyor ve yakın kalıyor. \n\n📌 Gözlemler:\n    \n    Eğitim accuracy: 0.58 → 0.87 (yüksek artış) ✅\n    Doğrulama accuracy: 0.62 → 0.85 (iyi artış) ✅\n    Fark: Son epoch’ta ~%2 fark → hafif overfitting, ama kabul edilebilir\n    💡 Yorum: Model öğreniyor, genelleme yapıyor, ama doğrulama accuracy’de küçük bir düşüş var → son epoch’larda hafif ezberleme başlamış olabilir. \n\n📉 2. Model Loss (Kayıp)\n\n✅ İdeal durum: Eğitim ve doğrulama loss birlikte düşüyor. \n    \n    📌 Gözlemler:\n    \n    Eğitim loss: 0.77 → 0.32 (düşüyor) ✅\n    Doğrulama loss: 0.68 → 0.30 (düşüyor) ✅\n    2. epoch’ta doğrulama loss’u yükseldi → model o epoch’ta bazı örnekleri yanlış öğrenmiş olabilir.\n    Sonra tekrar düştü → model kendi kendini düzeltti ✅\n    \n    💡 Yorum: Loss değerleri düşüyor → model hatasını azaltıyor. 2. epoch’taki küçük artış, öğrenmenin doğal dalgalanmasıdır — ciddi bir sorun değil. \n\n🎯 3. Model Precision (Hassasiyet)\n\n✅ İdeal durum: Yüksek precision → “köpek” dediği zaman çoğunlukla doğru. \n\n    📌 Gözlemler:\n    \n    Eğitim precision: 0.59 → 0.86 ✅\n    Doğrulama precision: 0.75 → 0.90 ✅\n    Doğrulama precision > Eğitim precision → Bu nadir ama mümkün!\n    → Muhtemelen doğrulama setindeki örnekler daha kolay veya eğitim sırasında bazı rastgeleliklerden kaynaklanıyor.\n    💡 Yorum: Model, “köpek” dediği zaman %90 ihtimalle doğru → çok güvenilir! \n\n🔄 4. Model Recall (Duyarlılık)\n\n⚠️ İdeal durum: Yüksek recall → gerçek köpekleri kaçırmıyor. \n\n    📌 Gözlemler:\n    \n    Eğitim recall: 0.60 → 0.86 ✅\n    Doğrulama recall: 0.40 → 0.77 ✅ (artış var!)\n    Başlangıçta çok düşük (0.40) → model ilk epoch’larda gerçek köpekleri kaçırıyor\n    Son epoch’larda %77’ye çıktı → iyileşme var ✅\n    💡 Yorum: Model, gerçek köpekleri yakalamada başlangıçta zorlanıyor, am zamanla %77’ye kadar geliyor. Bu, kabul edilebilir ama daha da iyileştirilebilir. \n\n🧠 Genel Değerlendirme\n\n* Accuracy - ✅ İyi -  Hem eğitim hem doğrulama yüksek ve yakın\n\n* Loss - ✅ İyi - Düşüyor, 2. epoch’taki küçük artış normal\n\n* Precision - ✅ Çok İyi - %90+ → model “evet” dediğinde güvenilir\n\n* Recall - 🟡 Orta - %77 → gerçek pozitifleri kaçırmaya eğilimli","metadata":{}},{"cell_type":"markdown","source":"## ✅ 17. Grad-CAM Görselleştirme\n\n🔍 Ne Yapıyor?\n\n1. Modelin hangi bölgelere odaklandığını gösteren heatmap üretir.\n\n2. Heatmap’i orijinal görüntü üzerine overlay ederek görselleştirir.\n   \n3. 4 örnek (2 kedi + 2 köpek) için:\n\n    * Orjinal görüntü\n    * Sadece heatmap\n    * Heatmap + görüntü\n     \n🧠 Grad-CAM Nasıl Çalışıyor? \n\n    Modelin son konvolüsyon katmanına bakarak, hangi piksellerin tahmine en çok katkıda bulunduğunu hesaplar. \n\nAdımlar:\n\n1. Son konvolüsyon katmanını (conv2d_3) seç.\n2. Tahmin edilen sınıfın kaybına göre (örneğin “köpek”), bu katmanın çıktılarının gradyanlarını al.\n3. Gradyanları ortalama alarak ağırlık oluştur.\n4. Bu ağırlıklarla konvolüsyon çıktısını çarp → heatmap.\n5. Heatmap’i orijinal görüntü boyutuna getir ve renklendir.","metadata":{}},{"cell_type":"code","source":"# GRAD-CAM \nprint(\"🔍 ÇALIŞAN GRAD-CAM GÖRSELLEŞTİRME\")\nprint(\"=\" * 50)\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport cv2\n\nimport tensorflow as tf\n\ndef grad_cam(model, img_array, layer_name='conv2d_3'):\n    \"\"\"\n    Ara model kullanmadan, sadece orijinal model ile çalışan Grad-CAM\n    \"\"\"\n    # Hedef katmanı al\n    target_layer = model.get_layer(layer_name)\n    \n    # Input tensor oluştur\n    input_tensor = tf.expand_dims(img_array, axis=0)\n    \n    with tf.GradientTape() as tape:\n        tape.watch(input_tensor)\n        \n        # İleri yayılım: tüm katmanları manuel geç\n        x = input_tensor\n        for layer in model.layers:\n            x = layer(x, training=False)\n            if layer.name == layer_name:\n                conv_output = x  # hedef konvolüsyon çıktısı\n        \n        final_output = x  # son çıkış\n        loss = final_output[0, 0]  # köpek olasılığı\n\n    # Gradyanı hedef katmanın çıktısına göre al\n    grads = tape.gradient(loss, conv_output)\n    if grads is None:\n        raise RuntimeError(\"Gradyanlar None — katman izlenebilir değil\")\n\n    # Global average pooling ile ağırlıkları hesapla\n    pooled_grads = tf.reduce_mean(grads, axis=(0, 1, 2))  # (channels,)\n    \n    # Heatmap oluştur\n    heatmap = tf.reduce_mean(tf.multiply(pooled_grads, conv_output[0]), axis=-1)\n    heatmap = tf.maximum(heatmap, 0)  # ReLU\n\n    # Resize ve normalize\n    heatmap = cv2.resize(heatmap.numpy(), (img_array.shape[1], img_array.shape[0]))\n    if heatmap.max() > 0:\n        heatmap = heatmap / heatmap.max()\n    \n    return heatmap, final_output[0, 0].numpy()\n\n\ndef create_heatmap_display(img_array, heatmap, alpha=0.6):\n    \"\"\"Heatmap'i görüntü üzerinde göster\"\"\"\n    # Heatmap'i renklendir\n    heatmap = np.uint8(255 * heatmap)\n    heatmap_colored = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)\n    \n    # Görüntüyü BGR'den RGB'ye çevir\n    img_bgr = np.uint8(255 * img_array)\n    img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_RGB2BGR)\n    \n    # Heatmap ve görüntüyü birleştir\n    superimposed = cv2.addWeighted(img_rgb, 1-alpha, heatmap_colored, alpha, 0)\n    superimposed_rgb = cv2.cvtColor(superimposed, cv2.COLOR_BGR2RGB)\n    \n    return superimposed_rgb\n\n# Örnek görüntüleri işle\nprint(\"🖼️ Örnek görüntüler işleniyor...\")\n\nprint(\"Model trainable:\", model.trainable)\n# Eğer False ise:\nmodel.trainable = True  # Grad-CAM için gerekli!\n\n# DataFrame indekslerini resetleyelim ve doğru şekilde seçelim\ntest_df_reset = test_df.reset_index(drop=True)\n\n# 2 kedi, 2 köpek örneği seç\ncat_samples = test_df_reset[test_df_reset['category'] == 'cat'].head(2).index.tolist()\ndog_samples = test_df_reset[test_df_reset['category'] == 'dog'].head(2).index.tolist()\nsample_indices = cat_samples + dog_samples\n\nprint(f\"📸 Örnekler: {len(cat_samples)} kedi, {len(dog_samples)} köpek\")\nprint(f\"📊 Seçilen indeksler: {sample_indices}\")\n\nplt.figure(figsize=(16, 12))\n\nfor i, idx in enumerate(sample_indices):\n    try:\n        # DataFrame'den doğru şekilde veri al\n        filename = test_df_reset.iloc[idx]['filename']\n        true_label = test_df_reset.iloc[idx]['category']\n        img_path = os.path.join(data_dir, filename)\n        \n        print(f\"📁 {i+1}. görüntü: {filename} ({true_label})\")\n        \n        # Görüntüyü yükle\n        img = tf.keras.preprocessing.image.load_img(img_path, target_size=(224, 224))\n        img_array = tf.keras.preprocessing.image.img_to_array(img) / 255.0\n        \n        # Grad-CAM uygula\n        #heatmap, prediction = working_gradcam(model, img_array)\n        heatmap, prediction = grad_cam(model, img_array)\n        predicted_label = 'dog' if prediction > 0.5 else 'cat'\n        confidence = prediction if prediction > 0.5 else 1 - prediction\n        \n        # Heatmap'i görselleştir\n        superimposed_img = create_heatmap_display(img_array, heatmap)\n        \n        # 1. ORJİNAL GÖRÜNTÜ\n        plt.subplot(3, 4, i + 1)\n        plt.imshow(img)\n        plt.title(f'Gerçek: {true_label}\\nTahmin: {predicted_label}', \n                 color='green' if true_label == predicted_label else 'red',\n                 fontsize=10, fontweight='bold')\n        plt.axis('off')\n        \n        # 2. HEATMAP\n        plt.subplot(3, 4, i + 5)\n        plt.imshow(heatmap, cmap='jet')\n        plt.title('Modelin Odaklandığı Bölgeler', fontsize=10, fontweight='bold')\n        plt.axis('off')\n        \n        # 3. BİRLEŞTİRİLMİŞ\n        plt.subplot(3, 4, i + 9)\n        plt.imshow(superimposed_img)\n        plt.title(f'Güven: {confidence:.2%}', fontsize=10, fontweight='bold')\n        plt.axis('off')\n        \n        print(f\"   ✅ Tahmin: {predicted_label} ({confidence:.2%})\")\n        \n    except Exception as e:\n        print(f\"❌ Hata: {idx} - {e}\")\n        continue\n\nplt.suptitle('GRAD-CAM BENZERİ GÖRSELLEŞTİRME: Modelin Hangi Bölgelere Bakabileceği', \n             fontsize=16, fontweight='bold', y=0.98)\nplt.tight_layout()\nplt.show()\n\nprint(\"\\n🎯 AÇIKLAMA:\")\nprint(\"- Kırmızı/Sarı bölgeler: Modelin yüksek aktivasyon gösterdiği bölgeler\")\nprint(\"- Mavi bölgeler: Modelin düşük aktivasyon gösterdiği bölgeler\")\nprint(\"- Bu görselleştirme, modelin karar vermede hangi bölgelere odaklanabileceğini simüle eder\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-26T08:35:47.085289Z","iopub.execute_input":"2025-09-26T08:35:47.086043Z","iopub.status.idle":"2025-09-26T08:35:50.654499Z","shell.execute_reply.started":"2025-09-26T08:35:47.086016Z","shell.execute_reply":"2025-09-26T08:35:50.653431Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"🔍 Yukarıdaki Grafik Ne Gösteriyor?\n\nHer sütun, 4 farklı görüntü için:\n\n* Orijinal görüntü + Gerçek & Tahmin etiketi\n* Sadece heatmap → Modelin odaklandığı bölgeler\n* Heatmap + orijinal görüntü → Görsel yorumlama\n\n📊 Her Örneği Ayrı Ayrı İnceleyelim\n\n🐱 1. Kedi – cat (Doğru Tahmin)\n\n    Güven: %99.17 → çok yüksek!\n    Heatmap: Gözler, kulaklar ve yüz ifadesi vurgulanmış.\n    Yorum: Model, kedinin yüz hatlarını net şekilde algılamış. Özellikle göz çevresi kırmızı/sarı → doğru odaklama.\n    💡 Bu, modelin kediye özgü fizyolojik özellikleri (küçük burun, dik kulak, yuvarlak göz) tespit ettiğini gösterir. \n\n🐱 2. Kedi – cat (Doğru Tahmin)\n\n    Güven: %91.15 → iyi ama biraz düşüş\n    Heatmap: Gözler ve kulaklar vurgulanmış, ama daha dağınık.\n    Yorum: Bu kedi, insan eliyle tutuluyor. Model hala yüzü odaklamış ama güven düşmüş — çünkü arka plan ve el karışıklığı var.\n    🤔 Model, “insan eli” gibi dış nesneleri dikkate almamış, sadece hayvanın yüzünü odaklamış → iyi genelleme! \n\n🐶 3. Köpek – dog (Doğru Tahmin)\n\n    Güven: %97.88 → çok yüksek!\n    Heatmap: Gözler, burun ve ağız çevresi vurgulanmış.\n    Yorum: Model, köpeğin yüz ifadesini ve özellikle açık dilini tespit etmiş. Burun ve gözlerde yoğunluk → doğru odaklama.\n    ✅ Bu çok önemli: Model sadece “yüz” değil, genel fizyolojiye göre de karar verebiliyor — bu da genelleme yeteneğini gösteriyor. \n\n🐶 4. Köpek – dog (Doğru Tahmin)\n\n    Güven: %81.25 → orta seviye\n    Heatmap: Gövde ve baş bölgesi vurgulanmış — özellikle kulaklar ve omuzlar.\n    Yorum: Bu köpek yukarıdan çekilmiş, yüz tam görünmüyor. Model kulak şekli, vücut yapısı ve tüy deseni üzerinden karar vermiş.\n    ✅ Bu çok önemli: Model sadece “yüz” değil, genel fizyolojiye göre de karar verebiliyor — bu da genelleme yeteneğini gösteriyor. \n\n\n🧠 Genel Değerlendirme\n\n1. Kedi:\n\n   Odaklanma: Gözler, kulaklar, yüz hatları\n\n   Güven Düzeyi: Yüksek (99%)\n\n   Açıklama: Net yüz ifadesi → güçlü sinyal\n   \n2. Kedi\n\n   Odaklanma: Gözler, kulaklar (dağınık)\n\n   Güven Düzeyi: Orta (91%)\n\n   Açıklama: El ve arka plan karışıklığı → güven düşüşü\n   \n3. Köpek:\n   \n   Odaklanma: Gözler, burun, ağız\n\n   Güven Düzeyi: Yüksek (98%)\n\n   Açıklama: Dil açık, yüz net — ama pozisyon zayıf\n   \n4. Köpek:\n\n   Odaklanma: Kulaklar, omuzlar, vücut\n\n   Güven Düzeyi:  Orta (81%)\n\n   Açıklama: Yüz görünmüyorsa, vücut yapısına bakıyor\n\n","metadata":{}},{"cell_type":"markdown","source":"## ✅ 18. Model Değerlendirmesi\n\n🔍 Ne Yapıyor?\n\nModeli üç veri seti üzerinde test eder:\n\n* Eğitim seti - Model ne kadar iyi öğrendi?\n* Doğrulama seti - Eğitim sırasında genelleme nasıl?\n* Test seti - Görülmemiş verilerde nihai performans nedir?\n\nHer biri için:\n\n* Loss (hata)\n* Accuracy (doğruluk)\n* Precision (hassasiyet)\n* Recall (duyarlılık)\n* Ayrıca F1-Score hesaplanıyor → precision ve recall’un harmonik ortalaması.\n\n🎯 Neden Bu Değerlendirme Önemli?\n\n* Test seti sonuçları, modelin gerçek dünya performansını yansıtır.\n* F1-Score, dengesiz veri setlerinde bile adil bir değerlendirme sağlar.","metadata":{}},{"cell_type":"code","source":"# MODEL DEĞERLENDİRME\nprint(\"\\n📊 MODEL DEĞERLENDİRME\")\nprint(\"=\" * 40)\n\n# Test seti üzerinde değerlendirme\ntest_loss, test_accuracy, test_precision, test_recall = model.evaluate(test_generator, verbose=0)\n\nprint(\"📝 TEST SETİ SONUÇLARI:\")\nprint(f\"Test Loss: {test_loss:.4f}\")\nprint(f\"Test Accuracy: {test_accuracy:.4f} (%{test_accuracy*100:.2f})\")\nprint(f\"Test Precision: {test_precision:.4f}\")\nprint(f\"Test Recall: {test_recall:.4f}\")\n\n# F1-Score hesapla\ntest_f1 = 2 * (test_precision * test_recall) / (test_precision + test_recall + 1e-7)\nprint(f\"Test F1-Score: {test_f1:.4f}\")\n\n# Validation seti üzerinde değerlendirme\nval_loss, val_accuracy, val_precision, val_recall = model.evaluate(validation_generator, verbose=0)\n\nprint(\"\\n📝 VALİDASYON SETİ SONUÇLARI:\")\nprint(f\"Validation Loss: {val_loss:.4f}\")\nprint(f\"Validation Accuracy: {val_accuracy:.4f} (%{val_accuracy*100:.2f})\")\nprint(f\"Validation Precision: {val_precision:.4f}\")\nprint(f\"Validation Recall: {val_recall:.4f}\")\n\n# Eğitim seti üzerinde değerlendirme\ntrain_loss, train_accuracy, train_precision, train_recall = model.evaluate(train_generator, verbose=0)\n\nprint(\"\\n📝 EĞİTİM SETİ SONUÇLARI:\")\nprint(f\"Training Loss: {train_loss:.4f}\")\nprint(f\"Training Accuracy: {train_accuracy:.4f} (%{train_accuracy*100:.2f})\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-26T08:36:11.317683Z","iopub.execute_input":"2025-09-26T08:36:11.317999Z","iopub.status.idle":"2025-09-26T08:39:32.259865Z","shell.execute_reply.started":"2025-09-26T08:36:11.317978Z","shell.execute_reply":"2025-09-26T08:39:32.258915Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"🔍 Detaylı Yorum\n\n*  Test Seti Performansı (En Önemlisi!)\n   \n    Accuracy: %90.72 → Görülmemiş verilerde çok yüksek başarı.\n   \n    Precision: %90.94 → “Köpek” dediğinde %91 oranında doğru.\n\n    Recall: %90.45 → Gerçek köpeklerin %90’ını yakalıyor.\n\n    F1-Score: 0.9070 → Dengeli bir performans → hiçbir metrik feda edilmemiş.\n\n\n*  Doğrulama vs Test Seti\n\n    Doğrulama Accuracy: %89.89\n\n    Test Accuracy: %90.72\n        → Test seti performansı doğrulama setinden daha yüksek!\n\n\n   * 💡 Bu nadiren görülen ama çok iyi bir durumdur: \n        Doğrulama seti, eğitim sırasında zor örnekler içerebilir.\n        Test seti ise daha temiz veya temsilci örnekler içerebilir.\n        Ya da model, eğitim sırasında doğrulama setine biraz overfit olmuş olabilir.\n     \n\n* Eğitim Seti Performansı\n\n    Accuracy: %88.87\n\n    Loss: 0.2574\n\n        🔍 İlginç bir durum:\n      \n        Eğitim accuracy < Doğrulama accuracy < Test accuracy\n        → Bu, normalin tersi gibi görünse de, aslında çok iyi bir işaret!\n\n    Neden?\n\n    * Model, eğitim sırasında regularization (Dropout, BatchNorm) kullandığı için,\n    eğitim setindeki performansı kasıtlı olarak düşürülmüş.\n\n    * Ama testte bu düzenlemeler devre dışı, bu yüzden gerçek performansı daha iyi çıkıyor.\n\n          ✅ Bu, Dropout ve BatchNorm’un doğru çalıştığını gösterir! \n\n* Overfitting Analizi\n   \n    * Eğitim Loss: 0.2574\n    * Doğrulama Loss: 0.2429\n    * Test Loss: 0.2237\n       *  → Loss değerleri: Eğitim > Doğrulama > Test\n       * → Bu, overfitting’in olmadığını, aksine modelin genelleme yeteneğinin mükemmel olduğunu gösterir.\n\n\n  \n* 🚫 Overfitting yok!\n* 🟢 Underfitting yok!\n* ✅ İdeal öğrenme!\n\n\n🎯 Neden Bu Sonuçlara İyi Diyebiliriz?\n\n    * %90+ Accuracy - Uygulamalarda kabul edilebilir sınır genellikle %85’tir\n    * Dengeli Precision/Recall - Model ne fazla “köpek” ne de fazla “kedi” tahmini yapıyor\n    * Test > Validation - Model, eğitim sırasında öğrenilenleri gerçek verilerde daha iyi uyguluyor\n    * Düşük Loss - Modelin hatası çok düşük → güvenilir tahminler","metadata":{}},{"cell_type":"markdown","source":"## ✅ 19. Görselleştirme (Bar + Eğitim Geçmişi Grafikleri)\n\n🔍 Ne Yapıyor?\n\n1. Performans Karşılaştırması (Bar Grafikleri)\n\n* Eğitim, doğrulama ve test setlerinin:\n  \n   * Accuracy\n   * Precision\n   * Recall\n   * Loss\n    değerlerini bar grafikleriyle karşılaştırır.\n\n* Her metrik için:\n\n   * Bar’ların üstüne sayısal değer yazılır.\n   * Accuracy ve Loss için overfitting farkı gösterilir.\n\n2. Eğitim Geçmişi (Çizgi Grafikleri)\n   \n* history.history verisinden:\n    * Accuracy → eğitim vs doğrulama\n    * Loss → eğitim vs doğrulama\n    grafikleri çizilir.\n  \n* Bu, modelin her epoch’ta nasıl geliştiğini gösterir.","metadata":{}},{"cell_type":"code","source":"# GÖRSELLEŞTİRME\nprint(\"\\n📈 PERFORMANS GRAFİKLERİ\")\nprint(\"=\" * 50)\n\n# Sadece mevcut metrikleri göster\navailable_metrics = []\nif len(train_results) == 4:\n    available_metrics = ['Accuracy', 'Precision', 'Recall', 'Loss']\nelse:\n    available_metrics = ['Accuracy', 'Loss']\n\n# Grafik boyutunu metrik sayısına göre ayarla\nn_metrics = len(available_metrics)\nif n_metrics == 4:\n    fig, axes = plt.subplots(2, 2, figsize=(15, 10))\n    axes = axes.flatten()\nelse:\n    fig, axes = plt.subplots(1, n_metrics, figsize=(5*n_metrics, 5))\n    if n_metrics == 1:\n        axes = [axes]\n\ncolors = ['#1f77b4', '#ff7f0e', '#2ca02c']  # Mavi, turuncu, yeşil\n\nfor i, metric in enumerate(available_metrics):\n    values = metrics_df[metric].values\n    \n    # Bar grafiği\n    bars = axes[i].bar(metrics_df['Set'], values, color=colors[:len(values)], alpha=0.7)\n    axes[i].set_title(f'{metric} Karşılaştırması', fontsize=14, fontweight='bold')\n    axes[i].set_ylabel(metric, fontsize=12)\n    axes[i].grid(True, alpha=0.3)\n    \n    # Değerleri üstte göster\n    for j, v in enumerate(values):\n        axes[i].text(j, v + 0.01, f'{v:.3f}', ha='center', va='bottom', fontweight='bold')\n    \n    # Overfitting çizgisi (sadece accuracy ve loss için)\n    if metric in ['Accuracy', 'Loss']:\n        if metric == 'Accuracy':\n            axes[i].plot(metrics_df['Set'], values, 'ro--', alpha=0.8, linewidth=2, markersize=8)\n            if metric == 'Accuracy':\n                axes[i].text(0.5, 0.9, f'Overfitting Gap: {accuracy_gap:.3f}', \n                           transform=axes[i].transAxes, ha='center', \n                           bbox=dict(boxstyle=\"round,pad=0.3\", facecolor=\"yellow\", alpha=0.7))\n        else:  # Loss\n            axes[i].plot(metrics_df['Set'], values, 'ro--', alpha=0.8, linewidth=2, markersize=8)\n\nplt.tight_layout()\nplt.show()\n\n# EĞİTİM GEÇMİŞİ GRAFİKLERİ\nprint(\"\\n📊 EĞİTİM GEÇMİŞİ GRAFİKLERİ\")\nprint(\"=\" * 50)\n\nplt.figure(figsize=(15, 5))\n\n# Accuracy grafiği\nplt.subplot(1, 2, 1)\nplt.plot(history.history['accuracy'], label='Eğitim Accuracy', linewidth=2)\nplt.plot(history.history['val_accuracy'], label='Validation Accuracy', linewidth=2)\nplt.title('Model Accuracy - Eğitim Geçmişi', fontsize=14, fontweight='bold')\nplt.xlabel('Epoch')\nplt.ylabel('Accuracy')\nplt.legend()\nplt.grid(True, alpha=0.3)\n\n# Loss grafiği\nplt.subplot(1, 2, 2)\nplt.plot(history.history['loss'], label='Eğitim Loss', linewidth=2)\nplt.plot(history.history['val_loss'], label='Validation Loss', linewidth=2)\nplt.title('Model Loss - Eğitim Geçmişi', fontsize=14, fontweight='bold')\nplt.xlabel('Epoch')\nplt.ylabel('Loss')\nplt.legend()\nplt.grid(True, alpha=0.3)\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-26T08:53:45.768007Z","iopub.execute_input":"2025-09-26T08:53:45.768538Z","iopub.status.idle":"2025-09-26T08:53:46.660058Z","shell.execute_reply.started":"2025-09-26T08:53:45.768515Z","shell.execute_reply":"2025-09-26T08:53:46.659373Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"📊 1. Performans Karşılaştırması (Bar Grafikleri)\n\nBu dört bar grafik, modelin eğitim, doğrulama ve test setlerindeki performansını karşılaştırıyor.\n\n🔍 A. Accuracy Karşılaştırması\n\n* Eğitim Accuracy: 0.893\n* Doğrulama Accuracy: 0.899\n* Test Accuracy: 0.907\n💡 Overfitting Gap: -0.006 → Negatif değer = Doğrulama > Eğitim → Bu çok iyi bir işaret! \n\n📌 Yorum:\n\n* Model, eğitim sırasında overfitting’e kapılmamış, aksine doğrulama setinde daha iyi performans göstermiş.\n* Test seti ise %90.7 ile en yüksek accuracy’yi vermiş → gerçek dünya verilerinde en iyi sonuç.\n\n✅ Bu, modelin genelleme yeteneğinin iyi olduğunu gösterir. \n\n🔍 B. Precision Karşılaştırması\n\n* Eğitim Precision: 0.906\n* Doğrulama Precision: 0.898\n* Test Precision: 0.909\n\n💡 Yüksek precision → Model “köpek” dediği zaman %91 ihtimalle doğru. \n\n📌 Yorum:\n\n* Test setinde en yüksek precision → model, güvenilir tahminler yapıyor.\n* Doğrulama setinde hafif düşüş var → muhtemelen bu sette bazı zor örnekler var.\n\n🔍 D. Loss Karşılaştırması\n\n* Eğitim Loss: 0.258\n* Doğrulama Loss: 0.243\n* Test Loss: 0.224\n💡 Loss: Eğitim > Doğrulama > Test → ideal durum! \n\n📌 Yorum:\n\n* Loss değerleri düşüyor → model hatasını azaltıyor.\n* Test loss’u en düşük → model, görülmemiş verilerde en az hata yapıyor.\n\n✅ Bu, overfitting’in olmadığını ve modelin genelleme yeteneğinin yüksek olduğunu kanıtlar. \n\n\n📈 2. Eğitim Geçmişi Grafikleri\n\nBu iki çizgi grafik, modelin epoch’a göre nasıl geliştiğini gösteriyor.\n\n🔍 A. Model Accuracy - Eğitim Geçmişi\n\n* Eğitim Accuracy (pembe): 0.58 → 0.87 (yükseliş)\n* Doğrulama Accuracy (sarı): 0.62 → 0.85 (yükseliş)\n\n💡 İdeal durum: İki eğri birlikte yükseliyor ve yakın kalıyor. \n\n📌 Yorum:\n\n* 4.epoch’ta doğrulama accuracy’si düşmüş → model o epoch’ta bazı örnekleri yanlış öğrenmiş olabilir.\n* Sonra tekrar düştü → model kendi kendini düzeltti ✅\n* Son epoch’ta eğitim ve doğrulama accuracy’si yakın → overfitting yok ✅\n\n🔍 B. Model Loss - Eğitim Geçmişi\n\n* Eğitim Loss (pembe): 0.77 → 0.32 (düşüyor)\n* Doğrulama Loss (sarı): 0.68 → 0.30 (düşüyor)\n\n💡 İdeal durum: İki eğri birlikte düşüyor. \n\n📌 Yorum:\n* epoch’ta doğrulama loss’u yükseldi → model o epoch’ta bazı örnekleri yanlış öğrenmiş olabilir.\n* Sonra tekrar düştü → model kendi kendini düzeltti ✅\n* Loss değerleri düşüyor → model hatasını azaltıyor ✅\n","metadata":{}},{"cell_type":"markdown","source":"## ✅ 20. 3 Farklı Model Yapılandırması\n\n🔍 Ne Yapıyor?\n\nÜç farklı model konfigürasyonu tanımlıyor:\n\n1. Basit Model\n    * Overfitting riskini azaltmak\n    * Az filtre, az nöron, orta dropout\n2. Kompleks Model\n    * Daha yüksek öğrenme kapasitesi\n    * Çok filtre, çok nöron, yüksek dropout, düşük öğrenme oranı\n3. RMSProp Model\n    * Farklı optimizasyon stratejisi\n    * RMSProp optimizer + dengeli mimari\n\n\n\n🧱 Model 1: Basit Model\n\n    'filters': [32, 64],      # Sadece 2 konvolüsyon katmanı\n    'dense_units': 256,       # Tek bir tam bağlı katman\n    'dropout': 0.3,           # Hafif düzenleme\n    'learning_rate': 0.001,   # Standart\n    'batch_size': 32          # Standart\n\n🎯 Amacı:\n* Overfitting riskini en aza indirmek\n* Küçük veri setlerinde veya hızlı prototipleme için ideal\n* Eğitim süresi kısa, bellek kullanımı düşük\n\n📌 Ne Zaman Kullanılır?\n* Veri seti küçükse\n* Model çok karmaşık olursa overfit oluyorsa\n* Gerçek zamanlı uygulamalarda (hız önemliyse)\n\n🧠 Model 2: Kompleks Model\n\n    'filters': [64, 128, 256], # 3 konvolüsyon katmanı, yüksek filtre sayısı\n    'dense_units': 512,        # Güçlü tam bağlı katman\n    'dropout': 0.5,            # Güçlü düzenleme\n    'learning_rate': 0.0001,   # Düşük LR → hassas öğrenme\n    'batch_size': 16           # Küçük batch → daha gürültülü gradyanlar\n\n🎯 Amacı:\n* Daha karmaşık özellikleri öğrenmek\n* Büyük veri setlerinde yüksek doğruluk elde etmek\n* Düşük öğrenme oranı → ince ayar yapma\n\n📌 Neden Düşük Öğrenme Oranı?\n* Kompleks modeller, yüksek öğrenme oranında kararsız olur.\n* Düşük LR → daha kararlı ve hassas öğrenme\n\n⚠️ Risk:\n* Overfitting riski yüksek → bu yüzden %50 dropout eklenmiş\n\n⚙️ Model 3: RMSProp Model\n\n    'filters': [32, 64, 128],  # Dengeli mimari\n    'dense_units': 256,        # Orta seviye\n    'dropout': 0.4,            # Orta düzenleme\n    'learning_rate': 0.001,    # Standart\n    'batch_size': 32,          # Standart\n    'optimizer': 'rmsprop'     # Adam yerine RMSProp\n\n🎯 Amacı:\n* Farklı bir optimizasyon algoritması test etmek\n/ RMSProp, bazı durumlarda Adam’dan daha iyi performans gösterebilir\n\n\n📌 RMSProp vs Adam:\n* Adam: Hızlı yakınsama, genelde iyi - Bazen lokal minimumda takılır\n* RMSProp: Dalgalanmalarda daha kararlı - Daha yavaş başlangıç","metadata":{}},{"cell_type":"code","source":"# 3 FARKLI MODEL KONFİGÜRASYONU\nmodel_configs = [\n    # MODEL 1: DAHA BASİT (Daha az overfit riski)\n    {\n        'name': 'Basit Model',\n        'filters': [32, 64],           # Daha az filtre\n        'dense_units': 256,            # Daha az nöron\n        'dropout': 0.3,                # Orta dropout\n        'learning_rate': 0.001,        # Standart LR\n        'batch_size': 32\n    },\n    \n    # MODEL 2: DAHA KOMPLEKS (Daha fazla kapasite)\n    {\n        'name': 'Kompleks Model', \n        'filters': [64, 128, 256],     # Daha fazla filtre\n        'dense_units': 512,            # Daha fazla nöron\n        'dropout': 0.5,                # Yüksek dropout\n        'learning_rate': 0.0001,       # Düşük LR\n        'batch_size': 16               # Küçük batch\n    },\n    \n    # MODEL 3: OPTIMIZER DEĞİŞİMİ\n    {\n        'name': 'RMSProp Model',\n        'filters': [32, 64, 128],\n        'dense_units': 256,\n        'dropout': 0.4,\n        'learning_rate': 0.001,\n        'batch_size': 32,\n        'optimizer': 'rmsprop'         # Farklı optimizer\n    }\n]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-26T08:53:55.296221Z","iopub.execute_input":"2025-09-26T08:53:55.296941Z","iopub.status.idle":"2025-09-26T08:53:55.301572Z","shell.execute_reply.started":"2025-09-26T08:53:55.296915Z","shell.execute_reply":"2025-09-26T08:53:55.300898Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## ✅ 21. Hiperparametre Optimizasyonu\n\n🔍 Ne Yapıyor?\n\n1. create_model() fonksiyonu: Verilen konfigürasyona göre dinamik model oluşturur.\n\n2. Her konfigürasyon için:\n\n    * Eğitim/doğrulama veri yükleyicileri batch_size’a göre güncellenir\n    * Model 10 epoch boyunca eğitilir\n    * EarlyStopping ile overfitting önlenir\n    * Eğitim süresi, doğruluk ve overfitting farkı kaydedilir\n\n3. Tüm sonuçlar results listesinde saklanır.\n\n🧱 create_model() Fonksiyonu — Dinamik Mimari\n\n🔑 Esnek Yapı:\n\n* Konvolüsyon katman sayısı: config['filters'] listesinin uzunluğuna göre değişir.\n    * Model 1: [32, 64] → 2 katman\n    * Model 2: [64, 128, 256] → 3 katman\n      \n* Dropout oranı:\n    * Konvolüsyon katmanlarında: config['dropout']\n    * Tam bağlı katmanda: config['dropout'] + 0.1 → daha güçlü düzenleme\n\n* Optimizer seçimi:\n    * Varsayılan: Adam\n    * Model 3: 'optimizer': 'rmsprop' → RMSProp kullanılır\n    * 💡 Bu fonksiyon, \"tek bir kodla birçok model\" oluşturmanı sağlar → kod tekrarını önler. \n\n⏱️ Eğitim Süreci — Hızlı Deneme\n\n🔧 Parametreler:\n   * Epoch: 10 → hızlı karşılaştırma için yeterli\n   * EarlyStopping: patience=3 → overfitting başlarsa erken dur\n   * Batch Size: Her model kendi config['batch_size'] değerini kullanır\n   * 💡 Neden 10 epoch?\n    Tam optimizasyon için yeterli olmasa da, hangi konfigürasyonun daha iyi olduğunu hızlıca anlamak için ideal. \n\n📊 Sonuç Kaydı — Karşılaştırmaya Hazır\n\n    * rain_accuracy - Eğitim setindeki en yüksek doğruluk\n    * val_accuracy - Doğrulama setindeki en yüksek doğruluk\n    * overfitting_gap - Eğitim - Doğrulama farkı\n    * training_time - Eğitim süresi (saniye)\n    * history - Eğitim geçmişi (grafik çizmek için)","metadata":{}},{"cell_type":"code","source":"# HIPERPARAMETRE OPTIMIZASYONU\nprint(\"⚙️ HIPERPARAMETRE OPTIMIZASYONU\")\nprint(\"=\" * 50)\n\nimport time\nfrom tensorflow.keras.optimizers import Adam, RMSprop\n\ndef create_model(config, input_shape=(224, 224, 3)):\n    \"\"\"Verilen konfigürasyona göre model oluştur\"\"\"\n    model = Sequential()\n    \n    # Konvolüsyon katmanları\n    for i, filters in enumerate(config['filters']):\n        if i == 0:\n            model.add(Conv2D(filters, (3, 3), activation='relu', input_shape=input_shape))\n        else:\n            model.add(Conv2D(filters, (3, 3), activation='relu'))\n        model.add(BatchNormalization())\n        model.add(MaxPooling2D(2, 2))\n        model.add(Dropout(config['dropout']))\n    \n    # Fully connected\n    model.add(Flatten())\n    model.add(Dense(config['dense_units'], activation='relu'))\n    model.add(BatchNormalization())\n    model.add(Dropout(config['dropout'] + 0.1))  # FC için daha yüksek dropout\n    model.add(Dense(1, activation='sigmoid'))\n    \n    # Optimizer\n    if config.get('optimizer', 'adam') == 'adam':\n        optimizer = Adam(learning_rate=config['learning_rate'])\n    else:\n        optimizer = RMSprop(learning_rate=config['learning_rate'])\n    \n    model.compile(optimizer=optimizer,\n                  loss='binary_crossentropy',\n                  metrics=['accuracy', 'precision', 'recall'])\n    \n    return model\n\n# Model konfigürasyonlarını deneyelim\nresults = []\n\nfor i, config in enumerate(model_configs):\n    print(f\"\\n🎯 MODEL {i+1}: {config['name']}\")\n    print(\"-\" * 30)\n    print(f\"Filtreler: {config['filters']}\")\n    print(f\"Dense Units: {config['dense_units']}\")\n    print(f\"Dropout: {config['dropout']}\")\n    print(f\"Learning Rate: {config['learning_rate']}\")\n    print(f\"Batch Size: {config['batch_size']}\")\n    \n    # Data generator'ı güncelle\n    train_gen = train_datagen.flow_from_dataframe(\n        dataframe=train_df,\n        directory=data_dir,\n        x_col='filename',\n        y_col='category',\n        target_size=(224, 224),\n        batch_size=config['batch_size'],\n        class_mode='binary',\n        shuffle=True\n    )\n    \n    val_gen = valid_test_datagen.flow_from_dataframe(\n        dataframe=val_df,\n        directory=data_dir,\n        x_col='filename',\n        y_col='category',\n        target_size=(224, 224),\n        batch_size=config['batch_size'],\n        class_mode='binary',\n        shuffle=False\n    )\n    \n    # Modeli oluştur ve eğit\n    start_time = time.time()\n    \n    model = create_model(config)\n    \n    history = model.fit(\n        train_gen,\n        epochs=10,  # Hızlı deneme için 10 epoch\n        validation_data=val_gen,\n        verbose=1,\n        callbacks=[EarlyStopping(monitor='val_loss', patience=3, restore_best_weights=True)]\n    )\n    \n    training_time = time.time() - start_time\n    \n    # Validation accuracy\n    val_accuracy = max(history.history['val_accuracy'])\n    train_accuracy = max(history.history['accuracy'])\n    overfitting_gap = train_accuracy - val_accuracy\n    \n    # Sonuçları kaydet\n    results.append({\n        'config_name': config['name'],\n        'train_accuracy': train_accuracy,\n        'val_accuracy': val_accuracy,\n        'overfitting_gap': overfitting_gap,\n        'training_time': training_time,\n        'config': config,\n        'history': history\n    })\n    \n    print(f\"✅ Tamamlandı - Val Accuracy: {val_accuracy:.4f}, Süre: {training_time:.1f}s\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-26T08:53:58.400553Z","iopub.execute_input":"2025-09-26T08:53:58.401189Z","iopub.status.idle":"2025-09-26T10:35:08.004699Z","shell.execute_reply.started":"2025-09-26T08:53:58.401166Z","shell.execute_reply":"2025-09-26T10:35:08.004004Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## ✅ 22. Sonuçların Karşılaştırılması\n\n🔍 Ne Yapıyor?\n\n1. Sonuçları tablo haline getirir (results_df)\n \n2. Üç farklı görselleştirme yapar:\n\n  * Validation Accuracy karşılaştırması\n  * Overfitting Gap karşılaştırması\n  * Eğitim Süresi karşılaştırması\n\n3. En iyi modeli otomatik seçer ve detaylarını gösterir.","metadata":{}},{"cell_type":"code","source":"# SONUÇLARI KARŞILAŞTIRMA\nprint(\"\\n📊 HIPERPARAMETRE OPTIMIZASYONU SONUÇLARI\")\nprint(\"=\" * 60)\n\nresults_df = pd.DataFrame([{\n    'Model': r['config_name'],\n    'Train Accuracy': r['train_accuracy'],\n    'Val Accuracy': r['val_accuracy'], \n    'Overfitting Gap': r['overfitting_gap'],\n    'Eğitim Süresi (s)': r['training_time'],\n    'Filtreler': str(r['config']['filters']),\n    'Dropout': r['config']['dropout'],\n    'Learning Rate': r['config']['learning_rate']\n} for r in results])\n\nprint(results_df.round(4))\n\n# Görselleştirme\nplt.figure(figsize=(12, 8))\n\n# Accuracy karşılaştırması\nplt.subplot(2, 2, 1)\nmodels = results_df['Model'].values\nval_accuracies = results_df['Val Accuracy'].values\n\nbars = plt.bar(models, val_accuracies, color=['skyblue', 'lightgreen', 'lightcoral'])\nplt.title('Validation Accuracy Karşılaştırması')\nplt.ylabel('Validation Accuracy')\nplt.xticks(rotation=45)\nfor bar, acc in zip(bars, val_accuracies):\n    plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.01, \n             f'{acc:.3f}', ha='center', va='bottom')\n\n# Overfitting gap karşılaştırması\nplt.subplot(2, 2, 2)\ngaps = results_df['Overfitting Gap'].values\nbars = plt.bar(models, gaps, color=['skyblue', 'lightgreen', 'lightcoral'])\nplt.title('Overfitting Gap Karşılaştırması')\nplt.ylabel('Overfitting Gap (Train - Val)')\nplt.xticks(rotation=45)\nfor bar, gap in zip(bars, gaps):\n    plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.001, \n             f'{gap:.3f}', ha='center', va='bottom')\n\n# Eğitim süreleri\nplt.subplot(2, 2, 3)\ntimes = results_df['Eğitim Süresi (s)'].values\nbars = plt.bar(models, times, color=['skyblue', 'lightgreen', 'lightcoral'])\nplt.title('Eğitim Süresi Karşılaştırması')\nplt.ylabel('Süre (saniye)')\nplt.xticks(rotation=45)\nfor bar, time_val in zip(bars, times):\n    plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 5, \n             f'{time_val:.0f}s', ha='center', va='bottom')\n\nplt.tight_layout()\nplt.show()\n\n# EN İYİ MODELİ SEÇ\nbest_result = max(results, key=lambda x: x['val_accuracy'])\nprint(f\"\\n🏆 EN İYİ MODEL: {best_result['config_name']}\")\nprint(f\"🎯 Validation Accuracy: {best_result['val_accuracy']:.4f}\")\nprint(f\"📊 Overfitting Gap: {best_result['overfitting_gap']:.4f}\")\nprint(f\"⏱️ Eğitim Süresi: {best_result['training_time']:.1f}s\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-26T10:35:13.116045Z","iopub.execute_input":"2025-09-26T10:35:13.116779Z","iopub.status.idle":"2025-09-26T10:35:13.621635Z","shell.execute_reply.started":"2025-09-26T10:35:13.116755Z","shell.execute_reply":"2025-09-26T10:35:13.620820Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"📈 Yukarıdaki Grafiklerin Yorumu\n\n📊 1. Validation Accuracy Karşılaştırması\n\n* RMSProp Model: 0.854 → En yüksek!\n* Basit Model: 0.771\n* Kompleks Model: 0.763\n* ✅ Bu, optimizer değişimi (Adam → RMSProp) ile performansın arttığını gösterir. \n\n📉 2. Overfitting Gap Karşılaştırması\n\n* Negatif değerler → Doğrulama > Eğitim → overfitting yok, hatta eğitimde ezberleme az.\n* RMSProp Model: -0.0386 → dengeli\n* Kompleks Model: -0.0477 → eğitimde daha az öğrenmiş (yüksek dropout + düşük LR)\n* 💡 Negatif overfitting gap, modelin eğitim sırasında \"ezberlemekten kaçındığını\" gösterir — bu, genelleme yeteneği için iyi bir işaret! \n\n⏱️ 3. Eğitim Süresi Karşılaştırması\n\n* Kompleks Model: 2096s → En uzun → küçük batch size + düşük LR\n* RMSProp Model: 1989s → Orta\n* Basit Model: 1984s → En kısa\n* ⚖️ RMSProp Model, en yüksek doğruluk + orta süre → en iyi denge \n\n🧠 Neden RMSProp Model En İyi?\n\n* Optimizer  - RMSProp, dalgalandığı durumlarda Adam’dan daha kararlı olabilir → bu projede avantaj sağladı\n\n* Mimari - 3 katmanlı, orta filtre sayısı → yeterli kapasite, fazla karmaşık değil\n\n* Dropout - 0.4 → overfitting’i kontrol ediyor\n\n* Learning Rate - 0.001 → standart, RMSProp ile iyi çalışmış","metadata":{}},{"cell_type":"markdown","source":"## ✅ 24. Özet Rapor","metadata":{}},{"cell_type":"code","source":"# ÖZET RAPOR\nprint(\"=\" * 70)\nprint(\"🎯 CNN MODEL EĞİTİMİ ÖZET RAPORU\")\nprint(\"=\" * 70)\nprint(f\"📊 Model Mimarisi: 4 Conv + 2 FC Katman\")\nprint(f\"🖼️ Giriş Boyutu: {IMG_SIZE}x{IMG_SIZE}x3\")\nprint(f\"🔄 Data Augmentation: Aktif\")\nprint(f\"⏱️ Eğitilen Epoch: {len(history.history['loss'])}\")\nprint(f\"📈 Final Validation Accuracy: %{val_accuracy*100:.2f}\")\nprint(f\"🎯 Final Test Accuracy: %{test_accuracy*100:.2f}\")\nprint(f\"📉 Final Test Loss: {test_loss:.4f}\")\nprint(f\"🎯 Final Test F1-Score: {test_f1:.4f}\")\n\n# Overfitting analizi\noverfitting_gap = train_accuracy - test_accuracy\nif overfitting_gap > 0.1:\n    status = \"❌ YÜKSEK OVERFITTING\"\nelif overfitting_gap > 0.05:\n    status = \"⚠️ ORTA SEVİYE OVERFITTING\"\nelse:\n    status = \"✅ DÜŞÜK OVERFITTING\"\n\nprint(f\"📊 Overfitting Durumu: {status} (Fark: {overfitting_gap:.4f})\")\n\nprint(\"\\n\" + \"=\" * 70)\nprint(\"🔍 MODEL KARŞILAŞTIRMASI: HANGİ MODELİ SEÇMELİ, HANGİSİNİ SEÇMEMELİ?\")\nprint(\"=\" * 70)\n\n# Karşılaştırma tablosu\nprint(f\"{'Model':<20} {'Val Acc':<10} {'Test Acc':<10} {'Overfitting':<15} {'Eğitim Süresi':<15}\")\nprint(\"-\" * 70)\nprint(f\"{'İlk Model (Referans)':<20} {'%89.89':<10} {'%90.72':<10} {'Düşük':<15} {'~1500s':<15}\")\nprint(f\"{'Basit Model':<20} {'%77.12':<10} {'-':<10} {'Çok Düşük':<15} {'~1984s':<15}\")\nprint(f\"{'Kompleks Model':<20} {'%76.35':<10} {'-':<10} {'Düşük':<15} {'~2096s':<15}\")\nprint(f\"{'RMSProp Model':<20} {'%85.41':<10} {'-':<10} {'Düşük':<15} {'~1989s':<15}\")\n\nprint(\"\\n✅ NİHAİ KARAR: İLK MODEL EN İYİ SEÇİM\")\nprint(\"   • En yüksek test accuracy (%90.72)\")\nprint(\"   • Dengeli F1-score (0.9070)\")\nprint(\"   • Kabul edilebilir eğitim süresi\")\nprint(\"   • Overfitting kontrol altında\")\n\nprint(\"\\n❌ NEDEN DİĞER MODELLERİ SEÇMEMELİYİZ?\")\nprint(\"   • Basit Model: Doğruluk çok düşük (%77.12) → yetersiz öğrenme kapasitesi\")\nprint(\"   • Kompleks Model: Doğruluk düşük (%76.35) + çok uzun eğitim süresi → verimsiz\")\nprint(\"   • RMSProp Model: İyi performans (%85.41) ama İlk Model'den %5+ daha düşük → yetersiz\")\n\nprint(\"=\" * 70)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-26T10:57:52.174859Z","iopub.execute_input":"2025-09-26T10:57:52.175130Z","iopub.status.idle":"2025-09-26T10:57:52.184147Z","shell.execute_reply.started":"2025-09-26T10:57:52.175111Z","shell.execute_reply":"2025-09-26T10:57:52.183359Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"📊 Bu Çıktı Ne Sağlar?\n\n1. Net Karşılaştırma\n   \nHer modelin güçlü ve zayıf yönleri tabloda görünür.\nTest Accuracy sadece İlk Model’de var → çünkü diğerleri test edilmedi.\n\n2. Karar Gerekçesi\n\nNeden İlk Model? → En yüksek test accuracy + dengeli metrikler\nNeden Diğerleri Değil? → Düşük doğruluk, uzun süre, yetersiz performans\n\n💡 Not: Neden Diğer Modellerin Test Accuracy’si Yok?\n * Diğer 3 model sadece doğrulama setiyle karşılaştırıldı.\n * Çünkü test seti, sadece nihai model için saklanmalı.\n","metadata":{}},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}