{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":3362,"databundleVersionId":31148,"sourceType":"competition"}],"dockerImageVersionId":31090,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Kedi ve Köpek Sınıflandırması CNN Projesi – VGG16 Transfer Öğrenimi + Grad-CAM + Random Search + L2 Düzenleme\n## 1. Çalışma Ortamının Hazırlanması\n\nBu kısımda, proje süresince kullanacağımız tüm kütüphaneler yüklenerek çalışma ortamı hazırlanır. Amaç, veri işleme, görselleştirme, model oluşturma ve performans değerlendirmesi için gerekli araçları hazır hale getirmektir.\n\n---\n\n### 🔹 Temel Kütüphaneler\n- **NumPy (`np`)** → Sayısal hesaplamalar, dizi ve matris işlemleri için.  \n- **Matplotlib & Seaborn** → Eğitim sırasında doğruluk ve kayıp grafikleri ile Confusion Matrix görselleştirmeleri.  \n- **os & zipfile** → Dosya ve klasör yönetimi, sıkıştırılmış dosyaların açılması.  \n- **cv2 (OpenCV)** → Görsellerin okunması, yeniden boyutlandırılması ve ön işleme.  \n- **tqdm** → Döngülerde ilerleme durumunu göstermek için.  \n- **random** → Rastgele seçimler, örneğin rastgele görsel göstermek için.  \n- **warnings.filterwarnings('ignore')** → Gereksiz uyarıları gizleyerek temiz bir çıktı sağlar.\n\n---\n\n### 🔹 Scikit-learn Araçları\n- **train_test_split** → Veri setini eğitim, doğrulama ve test kümelerine böler.  \n- **classification_report & confusion_matrix** → Modelin performansını ölçmek için detaylı metrikler sunar.\n\n---\n\n### 🔹 TensorFlow / Keras Bileşenleri\n- **Model, Layers (Input, Dense, Flatten, Dropout)** → CNN yapısını kurmak için gerekli katmanlar.  \n- **ImageDataGenerator** → Veri artırma teknikleri (döndürme, yakınlaştırma, yatay/vertical çevirme).  \n- **to_categorical** → Etiketleri one-hot formatına çevirir.  \n- **Callbacks**:\n  - `EarlyStopping`: Overfitting önlemek için eğitimi durdurur.  \n  - `ModelCheckpoint`: En iyi model ağı kaydeder.  \n  - `ReduceLROnPlateau`: Öğrenme oranını otomatik olarak ayarlar.  \n- **VGG16 & preprocess_input** → Önceden eğitilmiş model ve uygun giriş verisi ön işleme.  \n- **l2** → Ağırlıklara ceza ekleyerek aşırı uyumu (overfitting) azaltır.\n\n---\n\n### 🔹 TensorFlow Sürümü Kontrolü\nOrtamda yüklü TensorFlow sürümünü görüntülemek için:\n```python\nprint(\"TensorFlow sürümü:\", tf.__version__)\n","metadata":{}},{"cell_type":"code","source":"# 1. Ortam Kurulumu\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport os\nimport cv2\nfrom tqdm import tqdm\nimport warnings\nwarnings.filterwarnings('ignore')\nimport zipfile\nimport random\n\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import classification_report, confusion_matrix\n\nimport tensorflow as tf\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.layers import Input, Dense, Flatten, Dropout\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.utils import to_categorical\nfrom tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau\nfrom tensorflow.keras.applications.vgg16 import VGG16, preprocess_input\nfrom tensorflow.keras.regularizers import l2\n\nprint(\"TensorFlow version:\", tf.__version__)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-25T00:14:59.702951Z","iopub.execute_input":"2025-09-25T00:14:59.703130Z","iopub.status.idle":"2025-09-25T00:15:15.460764Z","shell.execute_reply.started":"2025-09-25T00:14:59.703113Z","shell.execute_reply":"2025-09-25T00:15:15.459903Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 2. Veri Yükleme ve Eğitim-Doğrulama-Test Bölünmesi\n\nBu bölümde, Dogs vs Cats veri seti açılır, görseller işlenir, etiketlenir ve eğitim süreci için **eğitim, doğrulama ve test** kümelerine ayrılır.\n\n---\n\n### 🔹 Veri Setini Açma\n- Kaggle ortamındaki `train.zip` dosyası `/kaggle/working/` dizinine çıkarılır.  \n- Çıkarılan dosyaların yolu `rec_egitim_yolu` değişkeninde saklanır.\n\n---\n\n### 🔹 Veri Yükleme Fonksiyonu\n- `veri_yukle` fonksiyonu şu işlemleri yapar:  \n  - Köpek görselleri → etiket **1**  \n  - Kedi görselleri → etiket **0**  \n- Her bir görsel:  \n  - `cv2.imread` ile okunur  \n  - `(128,128)` boyutuna yeniden boyutlandırılır  \n  - `preprocess_input` ile normalize edilir  \n- Fonksiyonun çıktıları:  \n  - `X` → Görsellerin NumPy dizisi  \n  - `y` → Etiketler\n\n---\n\n### 🔹 One-Hot Encoding\n- `to_categorical` kullanılarak etiketler `[0,1]` veya `[1,0]` formatına çevrilir.  \n- Bu dönüşüm, `categorical_crossentropy` kayıp fonksiyonu ile uyumlu çalışır.\n\n---\n\n### 🔹 Sınıf Dağılımı Kontrolü\n- `sns.barplot` ile kedi ve köpek görsellerinin sayısı görselleştirilir.  \n- Bu adım, veri setinde sınıf dengesinin korunup korunmadığını kontrol etmek için önemlidir.\n\n---\n\n### 🔹 Örnek Görsellerin Gösterimi\n- Rastgele seçilen bir kedi ve bir köpek görseli ekrana basılır.  \n- Böylece veri yükleme ve ön işleme sürecinin doğru çalıştığı doğrulanır.\n\n---\n\n### 🔹 Eğitim-Doğrulama-Test Ayrımı\n- `train_test_split` ile veri önce **%80 eğitim / %20 test** olacak şekilde bölünür.  \n- Eğitim verisinin **%20’si** ayrıca doğrulama kümesi olarak ayrılır.  \n- `stratify` parametresi sayesinde kedi ve köpek oranı tüm alt kümelerde korunur.  \n- Sonuç olarak üç alt küme oluşur:  \n  - **Eğitim (Train)** → Modelin öğrenmesi için  \n  - **Doğrulama (Validation)** → Hiperparametre ayarlamaları ve overfitting kontrolü için  \n  - **Test (Test)** → Nihai model değerlendirmesi için\n\n---\n\n✅ **Özet:**  \nBu aşamada veri seti başarıyla yüklenmiş, işlenmiş, sınıf dağılımı kontrol edilmiş ve görseller **eğitim, doğrulama ve test** kümeleri halinde model eğitimi için hazır hâle getirilmiştir.\n","metadata":{}},{"cell_type":"code","source":"# 2. Veri Yükleme ve Train-Validation-Test Split\nort_veri_yolu = \"/kaggle/input/dogs-vs-cats\"\nwith zipfile.ZipFile(os.path.join(ort_veri_yolu, \"train.zip\"), 'r') as zip_ref:\n    zip_ref.extractall(\"/kaggle/working/\")\nrec_egitim_yolu = \"/kaggle/working/train\"\n\ndef veri_yukle(veri_yolu, boyut=(128,128)):\n    goruntuler, etiketler = [], []\n    kopek_yollari = [os.path.join(veri_yolu,f) for f in os.listdir(veri_yolu) if f.startswith('dog')]\n    for yol in tqdm(kopek_yollari, desc=\"Köpekler\"):\n        img = cv2.imread(yol)\n        if img is not None:\n            img = cv2.resize(img, boyut)\n            img = preprocess_input(img)\n            goruntuler.append(img)\n            etiketler.append(1)\n    kedi_yollari = [os.path.join(veri_yolu,f) for f in os.listdir(veri_yolu) if f.startswith('cat')]\n    for yol in tqdm(kedi_yollari, desc=\"Kediler\"):\n        img = cv2.imread(yol)\n        if img is not None:\n            img = cv2.resize(img, boyut)\n            img = preprocess_input(img)\n            goruntuler.append(img)\n            etiketler.append(0)\n    return np.array(goruntuler), np.array(etiketler)\n\nX, y = veri_yukle(rec_egitim_yolu)\ny_cat = to_categorical(y, 2)\n\n# Sınıf dağılımı görselleştirme\nunique, counts = np.unique(y, return_counts=True)\nplt.figure(figsize=(6,4))\nsns.barplot(x=['Kedi','Köpek'], y=counts)\nplt.title(\"Sınıf Dağılımı\")\nplt.ylabel(\"Görüntü Sayısı\")\nplt.show()\n\n# Örnek görseller\nplt.figure(figsize=(12,6))\nfor i, label in enumerate([0,1]):  # 0=Kedi, 1=Köpek\n    idx = np.where(y==label)[0]\n    sample_idx = random.choice(idx)\n    img = ((X[sample_idx]+1)*127.5).astype('uint8')\n    plt.subplot(1,2,i+1)\n    plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))\n    plt.axis('off')\n    plt.title('Kedi' if label==0 else 'Köpek')\nplt.show()\n\n# Train-Test-Validation split\nX_train, X_test, y_train, y_test = train_test_split(X, y_cat, test_size=0.2, stratify=y, random_state=42)\nX_train, X_val, y_train, y_val = train_test_split(\n    X_train, y_train, test_size=0.2, stratify=np.argmax(y_train, axis=1), random_state=42\n)\nprint(f\"Train: {X_train.shape}, Validation: {X_val.shape}, Test: {X_test.shape}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-25T00:15:15.462257Z","iopub.execute_input":"2025-09-25T00:15:15.462793Z","iopub.status.idle":"2025-09-25T00:15:55.699975Z","shell.execute_reply.started":"2025-09-25T00:15:15.462774Z","shell.execute_reply":"2025-09-25T00:15:55.699223Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 3. Veri Artırma (Data Augmentation)\n\nBu bölümde, eğitim verisinin çeşitliliğini artırmak ve modelin **overfitting** yapmasını engellemek için **veri artırma teknikleri** uygulanır.\n\n---\n\n### 🔹 Veri Artırmanın Amaçları\n- Eğitim sırasında verilerden farklı varyasyonlar oluşturur.  \n- Modelin genelleme yeteneğini güçlendirir.  \n- Özellikle küçük veri setlerinde başarıyı artırır.\n\n---\n\n### 🔹 Kullanılan Parametreler\n- **rotation_range=40** → Görselleri ±40 derece arasında rastgele döndürür.  \n- **width_shift_range=0.3** → Görselleri yatay eksende %30’a kadar kaydırır.  \n- **height_shift_range=0.3** → Görselleri dikey eksende %30’a kadar kaydırır.  \n- **horizontal_flip=True** → Görselleri yatayda çevirir (ayna etkisi).  \n- **zoom_range=0.3** → Görselleri %30 oranında yakınlaştırır veya uzaklaştırır.  \n- **brightness_range=[0.7,1.3]** → Görsellerin parlaklığını %70–%130 aralığında değiştirir.\n\n---\n\n✅ **Özet:**  \nBu aşamada `ImageDataGenerator` ile veriler üzerinde döndürme, kaydırma, yakınlaştırma, yatay çevirme ve parlaklık ayarlamaları uygulanır. Böylece model, farklı görsel varyasyonlarıyla eğitilir ve daha güçlü bir genelleme yeteneği kazanır.\n","metadata":{}},{"cell_type":"code","source":"# 3. Data Augmentation\ndatagen = ImageDataGenerator(\n    rotation_range=40,\n    width_shift_range=0.3,\n    height_shift_range=0.3,\n    horizontal_flip=True,\n    zoom_range=0.3,\n    brightness_range=[0.7,1.3]\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-25T00:15:55.700806Z","iopub.execute_input":"2025-09-25T00:15:55.701088Z","iopub.status.idle":"2025-09-25T00:15:55.705002Z","shell.execute_reply.started":"2025-09-25T00:15:55.701061Z","shell.execute_reply":"2025-09-25T00:15:55.704363Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 4. Random Search ile Hiperparametre Denemeleri\n\nBu bölümde, farklı **hiperparametre kombinasyonları** test edilerek modelin en iyi performansı elde etmesi hedeflenir. Yaklaşım, **Random Search** mantığına dayanmaktadır.\n\n---\n\n### 🔹 Amaç\n- Öğrenme oranı (learning rate), dropout oranı ve batch size gibi hiperparametrelerin farklı değerlerini deneyerek modelin performansını değerlendirmek.  \n- Validation (doğrulama) başarısını en yüksek seviyeye çıkaran parametre setini belirlemek.\n\n---\n\n### 🔹 İşlem Adımları\n\n1. **Parametre Kombinasyonları**\n   - Üç farklı set oluşturulmuştur:  \n     - `{learning_rate: 0.001, dropout_rate: 0.5, batch_size: 32}`  \n     - `{learning_rate: 0.0005, dropout_rate: 0.5, batch_size: 32}`  \n     - `{learning_rate: 0.0001, dropout_rate: 0.4, batch_size: 64}`\n\n2. **Model Kurulumu (VGG16 Transfer Learning)**\n   - `VGG16` tabanlı önceden eğitilmiş model (`imagenet`) kullanılır.  \n   - `include_top=False` → Son sınıflandırma katmanı çıkarılır.  \n   - Tüm katmanlar **dondurulur** (`trainable=False`) ve özellik çıkarıcı olarak kullanılır.\n\n3. **Yeni Katmanların Eklenmesi**\n   - `Flatten` → Özellikleri tek boyuta indirger.  \n   - `Dense(512, relu)` → 512 nöronlu tam bağlı katman + **L2 regularization**.  \n   - `Dropout` → Parametre setindeki değere göre uygulanır.  \n   - `Dense(2, softmax)` → Çıkış katmanı (kedi ve köpek sınıfları).\n\n4. **Modelin Derlenmesi**\n   - Optimizasyon: **Adam**  \n   - Learning rate parametre setinden alınır  \n   - Kayıp fonksiyonu: **categorical_crossentropy**  \n   - Ölçüt: **accuracy**\n\n5. **Eğitim Süreci**\n   - `ImageDataGenerator` ile artırılmış eğitim verisi kullanılır.  \n   - `batch_size` parametre setinden alınır.  \n   - 5 epoch boyunca eğitim yapılır.  \n   - Validation seti ile doğruluk takip edilir.\n\n6. **Sonuçların Karşılaştırılması**\n   - Her denemenin en iyi **validation accuracy** kaydedilir.  \n   - En yüksek doğruluk sağlayan parametre seti `best_params` olarak seçilir.\n\n---\n\n✅ **Özet:**  \nBu adımda farklı **learning rate, dropout ve batch size** kombinasyonları test edilerek, modelin doğrulama başarısını en üst düzeye çıkaran parametreler belirlenmiştir. Bu yöntem, **hiperparametre optimizasyonu** ile model performansını artırmayı sağlar.\n","metadata":{}},{"cell_type":"code","source":"# 4. Random Search Hiperparametre Denemeleri\nparam_combinations = [\n    {'learning_rate':0.001,'dropout_rate':0.5,'batch_size':32},\n    {'learning_rate':0.0005,'dropout_rate':0.5,'batch_size':32},\n    {'learning_rate':0.0001,'dropout_rate':0.4,'batch_size':64},\n]\n\nbest_score = 0\nbest_params = None\n\nfor i, params in enumerate(param_combinations):\n    print(f\"\\nTest Kombinasyonu {i+1}/{len(param_combinations)}: {params}\")\n    \n    base_model = VGG16(weights='imagenet', include_top=False, input_shape=(128,128,3))\n    for layer in base_model.layers:\n        layer.trainable = False\n    \n    x = Flatten()(base_model.output)\n    x = Dense(512, activation='relu', kernel_regularizer=l2(0.001))(x)\n    x = Dropout(params['dropout_rate'])(x)\n    outputs = Dense(2, activation='softmax')(x)\n    \n    model = Model(base_model.input, outputs)\n    opt = tf.keras.optimizers.Adam(learning_rate=params['learning_rate'])\n    model.compile(optimizer=opt, loss='categorical_crossentropy', metrics=['accuracy'])\n    \n    history = model.fit(\n        datagen.flow(X_train, y_train, batch_size=params['batch_size']),\n        steps_per_epoch=len(X_train)//params['batch_size'],\n        epochs=5,\n        validation_data=(X_val, y_val),\n        verbose=1\n    )\n    \n    val_acc = max(history.history['val_accuracy'])\n    print(f\"En iyi validation accuracy: {val_acc:.4f}\")\n    \n    if val_acc > best_score:\n        best_score = val_acc\n        best_params = params\n\nprint(f\"\\nEn iyi parametreler: {best_params}, Validation Accuracy: {best_score:.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-25T00:15:55.705785Z","iopub.execute_input":"2025-09-25T00:15:55.706037Z","iopub.status.idle":"2025-09-25T00:34:09.560241Z","shell.execute_reply.started":"2025-09-25T00:15:55.706012Z","shell.execute_reply":"2025-09-25T00:34:09.559681Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 5. Nihai Model Eğitimi\n\nBu bölümde, **en iyi hiperparametreler** kullanılarak modelin son eğitimi gerçekleştirilir. Eğitim sırasında **callbacks** ile overfitting önlenir ve en iyi ağırlıklar saklanır.\n\n---\n\n### 🔹 Model Kurulumu\n- `VGG16` tabanlı transfer öğrenimi modeli kullanılır.  \n- `weights='imagenet'` → Önceden eğitilmiş ağırlıklar yüklenir.  \n- `include_top=False` → Son sınıflandırma katmanı çıkarılır.  \n- Katmanlar **dondurulur** (`trainable=False`) → Önceden öğrenilmiş özellikler korunur.\n\n---\n\n### 🔹 Yeni Katmanların Eklenmesi\n- `Flatten` → Özellikleri tek boyutlu hâle getirir.  \n- `Dense(512, relu)` → 512 nöronlu tam bağlı katman + **L2 regularization**.  \n- `Dropout` → Hiperparametre optimizasyonunda belirlenen oran uygulanır.  \n- `Dense(2, softmax)` → Çıkış katmanı (kedi ve köpek sınıfları).\n\n---\n\n### 🔹 Modelin Derlenmesi\n- Optimizasyon: **Adam** ve **en uygun learning rate** kullanılır.  \n- Kayıp fonksiyonu: **categorical_crossentropy**  \n- Ölçüt: **accuracy**\n\n---\n\n### 🔹 Callbacks Kullanımı\n- `EarlyStopping` → Validation kaybı 7 epoch boyunca iyileşmezse eğitimi durdurur ve en iyi ağırlıkları geri yükler.  \n- `ModelCheckpoint` → En iyi ağırlıkları `best_model.h5` dosyasına kaydeder.  \n- `ReduceLROnPlateau` → Validation kaybı 3 epoch boyunca iyileşmezse öğrenme oranını 0.2 faktörü ile azaltır.\n\n---\n\n### 🔹 Model Eğitimi\n- Eğitim, `ImageDataGenerator` ile artırılmış veriler üzerinde yapılır.  \n- `batch_size` ve diğer hiperparametreler **en iyi parametreler** setinden alınır.  \n- 25 epoch boyunca eğitim gerçekleştirilir ve validation seti ile performans izlenir.\n\n---\n\n✅ **Özet:**  \nBu aşamada, transfer öğrenimli CNN modeli **en iyi hiperparametreler** ile eğitilmiş, overfitting kontrol edilmiştir ve en iyi ağırlıklar kaydedilmiştir. Model artık **test ve değerlendirme** aşamasına hazırdır.\n","metadata":{}},{"cell_type":"code","source":"# 5. Final Model Eğitimi\nfinal_base = VGG16(weights='imagenet', include_top=False, input_shape=(128,128,3))\nfor layer in final_base.layers:\n    layer.trainable = False\n\nx = Flatten()(final_base.output)\nx = Dense(512, activation='relu', kernel_regularizer=l2(0.001))(x)\nx = Dropout(best_params['dropout_rate'])(x)\noutputs = Dense(2, activation='softmax')(x)\nfinal_model = Model(final_base.input, outputs)\n\nfinal_model.compile(\n    optimizer=tf.keras.optimizers.Adam(best_params['learning_rate']),\n    loss='categorical_crossentropy',\n    metrics=['accuracy']\n)\n\ncallbacks = [\n    EarlyStopping(patience=7, restore_best_weights=True),\n    ModelCheckpoint('best_model.h5', save_best_only=True),\n    ReduceLROnPlateau(patience=3, factor=0.2)\n]\n\nhistory = final_model.fit(\n    datagen.flow(X_train, y_train, batch_size=best_params['batch_size']),\n    steps_per_epoch=len(X_train)//best_params['batch_size'],\n    epochs=25,\n    validation_data=(X_val, y_val),\n    callbacks=callbacks,\n    verbose=1\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-25T00:34:09.561678Z","iopub.execute_input":"2025-09-25T00:34:09.561893Z","iopub.status.idle":"2025-09-25T01:04:11.615877Z","shell.execute_reply.started":"2025-09-25T00:34:09.561875Z","shell.execute_reply":"2025-09-25T01:04:11.615263Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 6. Model Değerlendirme ve Overfitting/Underfitting Analizi\n\nBu bölümde, eğitilen modelin performansı görselleştirilir, overfitting veya underfitting olup olmadığı incelenir ve test verisi üzerinden değerlendirme yapılır.\n\n---\n\n### 🔹 Eğitim ve Doğrulama Grafikleri\n- `history.history` kullanılarak:  \n  - **Loss** (Eğitim ve Validation) grafiği çizilir  \n  - **Accuracy** (Eğitim ve Validation) grafiği çizilir  \n- Bu grafikler, modelin öğrenme sürecini ve performans eğilimlerini görselleştirir.\n\n---\n\n### 🔹 Overfitting / Underfitting Kontrolü\n- Eğitim ve doğrulama accuracy farkı hesaplanır:  \n  ```python\n  acc_diff = abs(val_acc - train_acc)\n\n---\n\n### 🔹 Durum Değerlendirmesi\n\n- `acc_diff < 0.05` → ✅ Model dengeli, eğitim ve doğrulama performansı birbirine yakın.  \n- `val_acc < train_acc` → ⚠️ Bir miktar overfitting olabilir.  \n- `val_acc > train_acc` → ⚠️ Bir miktar underfitting olabilir.\n\n---\n\n### 🔹 Test Verisi Üzerinde Performans\n\n- `final_model.evaluate` ile test kaybı ve doğruluk ölçülür.  \n- `final_model.predict` ile tahminler alınır ve gerçek sınıflarla karşılaştırılır.\n\n---\n\n### 🔹 Confusion Matrix ve Sınıf Bazlı Raporlama\n\n- `confusion_matrix` kullanılarak doğru ve yanlış sınıflandırmalar **heatmap** ile görselleştirilir.  \n- `classification_report` ile her sınıf için:  \n  - Precision  \n  - Recall  \n  - F1-score  \n  raporlanır (Kedi ve Köpek sınıfları).\n\n---\n\n✅ **Özet:**  \nBu aşamada modelin eğitim süreci grafiklerle analiz edilmiş, overfitting/underfitting durumu kontrol edilmiş ve test seti üzerinde performansı ölçülmüştür. Confusion matrix ve sınıf bazlı raporlar, modelin hangi sınıflarda daha başarılı olduğunu gösterir.\n","metadata":{}},{"cell_type":"code","source":"# 6. Model Değerlendirme ve Overfitting/Underfitting Kontrolü\nplt.figure(figsize=(12,4))\nplt.subplot(1,2,1)\nplt.plot(history.history['loss'], label='Eğitim Loss')\nplt.plot(history.history['val_loss'], label='Doğrulama Loss')\nplt.title('Loss')\nplt.legend()\nplt.subplot(1,2,2)\nplt.plot(history.history['accuracy'], label='Eğitim Accuracy')\nplt.plot(history.history['val_accuracy'], label='Doğrulama Accuracy')\nplt.title('Accuracy')\nplt.legend()\nplt.show()\n\n# Gerçekçi overfit/underfit yorumlama\ntrain_acc = history.history['accuracy'][-1]\nval_acc = history.history['val_accuracy'][-1]\n\nacc_diff = abs(val_acc - train_acc)\n\nif acc_diff < 0.06:\n    print(f\"✅ Model dengeli. Eğitim ve doğrulama accuracy farkı çok küçük ({acc_diff:.4f}).\")\nelif val_acc < train_acc:\n    print(f\"⚠️ Model biraz overfitting yapıyor olabilir. Accuracy farkı: {acc_diff:.4f}\")\nelse:\n    print(f\"⚠️ Model biraz underfitting yapıyor olabilir. Accuracy farkı: {acc_diff:.4f}\")\n\ntest_loss, test_acc = final_model.evaluate(X_test, y_test, verbose=0)\nprint(f\"Test Accuracy: {test_acc*100:.2f}%\")\n\ny_pred = np.argmax(final_model.predict(X_test), axis=1)\ny_true = np.argmax(y_test, axis=1)\n\nplt.figure(figsize=(6,4))\nsns.heatmap(confusion_matrix(y_true, y_pred), annot=True, fmt='d', cmap='Blues')\nplt.title('Confusion Matrix')\nplt.show()\n\nprint(classification_report(y_true, y_pred, target_names=['Kedi','Köpek']))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-25T01:04:11.616756Z","iopub.execute_input":"2025-09-25T01:04:11.617006Z","iopub.status.idle":"2025-09-25T01:04:24.900487Z","shell.execute_reply.started":"2025-09-25T01:04:11.616979Z","shell.execute_reply":"2025-09-25T01:04:24.899919Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 7. Grad-CAM ile Görselleştirme\n\nBu bölümde, eğitilen CNN modelinin **hangi bölgeleri kullanarak sınıflandırma yaptığı** görselleştirilir. Bu yöntem, modelin karar mekanizmasını anlamak ve yorumlamak için kullanılır.\n\n---\n\n### 🔹 Amaç\n- Modelin odaklandığı alanları görselleştirmek.  \n- Sınıflandırma kararlarının **görsel olarak açıklanabilirliğini** artırmak.  \n- Overfitting veya hatalı sınıflandırma durumlarını incelemek.\n\n---\n\n### 🔹 Grad-CAM Fonksiyonları\n\n1. **make_gradcam_heatmap**  \n   - Son Conv2D katmanı ve model çıktısı kullanılarak **gradient tabanlı ısı haritası (heatmap)** oluşturur.  \n   - `pred_index` belirtilmezse, modelin en yüksek tahmine göre sınıf seçilir.  \n   - Heatmap, ilgili sınıfa ait önem derecelerini 0-1 arasında normalize eder.\n\n2. **display_gradcam**  \n   - Heatmap’i orijinal görselin üzerine uygular.  \n   - `alpha` parametresi ile ısı haritasının opaklığı ayarlanır.  \n   - Sonuç, modelin dikkat ettiği bölgelerin görsel olarak anlaşılmasını sağlar.\n\n---\n\n### 🔹 Görselleştirme Adımları\n- Test setinden rastgele 4 görsel seçilir.  \n- Her görsel için:  \n  - Son Conv2D katmanı belirlenir.  \n  - Grad-CAM ısı haritası oluşturulur.  \n  - Orijinal görsel ve heatmap birleştirilerek ekrana çizilir.  \n- Başlıkta modelin tahmini sınıf (`Pred`) gösterilir.\n\n---\n\n✅ **Özet:**  \nBu aşamada Grad-CAM yöntemi kullanılarak modelin **karar verdiği bölgeler** görselleştirilmiş, modelin “neden bu sınıfı seçtiği” görsel olarak analiz edilmiştir. Böylece modelin açıklanabilirliği ve yorumlanabilirliği artırılmıştır.\n","metadata":{}},{"cell_type":"code","source":"# 7. Grad-CAM\nfrom tensorflow.keras.layers import Conv2D\n\ndef make_gradcam_heatmap(img_array, model, last_conv_layer_name, pred_index=None):\n    grad_model = Model(inputs=model.input,\n                       outputs=[model.get_layer(last_conv_layer_name).output, model.output])\n    with tf.GradientTape() as tape:\n        conv_outputs, predictions = grad_model(img_array)\n        if pred_index is None:\n            pred_index = tf.argmax(predictions[0])\n        class_channel = predictions[:, pred_index]\n    grads = tape.gradient(class_channel, conv_outputs)\n    pooled_grads = tf.reduce_mean(grads, axis=(0,1,2))\n    conv_outputs = conv_outputs[0]\n    heatmap = conv_outputs @ pooled_grads[..., tf.newaxis]\n    heatmap = tf.squeeze(heatmap)\n    heatmap = tf.maximum(heatmap,0)/tf.math.reduce_max(heatmap)\n    return heatmap.numpy()\n\ndef display_gradcam(img, heatmap, alpha=0.4):\n    heatmap_resized = cv2.resize(heatmap, (img.shape[1], img.shape[0]))\n    heatmap_colored = cv2.applyColorMap(np.uint8(255*heatmap_resized), cv2.COLORMAP_JET)\n    img_original = ((img + 1) * 127.5).astype('uint8')\n    superimposed_img = cv2.addWeighted(img_original, 1-alpha, heatmap_colored, alpha,0)\n    return superimposed_img\n\nplt.figure(figsize=(12,6))\nfor i in range(4):\n    plt.subplot(2,4,i+1)\n    img = np.expand_dims(X_test[i], axis=0)\n    last_conv_layer = [layer.name for layer in final_model.layers if isinstance(layer, Conv2D)][-1]\n    heatmap = make_gradcam_heatmap(img, final_model, last_conv_layer)\n    superimposed = display_gradcam(X_test[i], heatmap)\n    plt.imshow(cv2.cvtColor(superimposed, cv2.COLOR_BGR2RGB))\n    plt.axis('off')\n    plt.title(f'Pred: {y_pred[i]}')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-25T01:04:24.901202Z","iopub.execute_input":"2025-09-25T01:04:24.901456Z","iopub.status.idle":"2025-09-25T01:04:26.621852Z","shell.execute_reply.started":"2025-09-25T01:04:24.901438Z","shell.execute_reply":"2025-09-25T01:04:26.621205Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 8. Modelin Kaydedilmesi\n\nBu bölümde, eğitilen model **kalıcı olarak saklanır** ve ileride tekrar kullanılmak üzere hazır hâle getirilir.\n\n---\n\n### 🔹 Amaç\n- Modeli yeniden eğitmeye gerek kalmadan tekrar kullanabilmek.  \n- Test, deployment veya uygulama aşamalarında kolaylık sağlamak.\n\n---\n\n### 🔹 İşleyiş\n- `final_model.save(\"kedi_kopek_model_final.h5\")`  \n  - Modelin ağırlıkları, yapısı ve eğitim bilgileri `.h5` formatında kaydedilir.  \n- `print` ile modelin başarıyla kaydedildiği kullanıcıya bildirilir.\n\n---\n\n✅ **Özet:**  \nBu aşamada, eğitilen CNN modeli `.h5` formatında saklanmış ve artık **kullanıma hazır** hâle gelmiştir. Model, ileride tekrar yüklenip test edilebilir veya uygulamalarda kullanılabilir.\n","metadata":{}},{"cell_type":"code","source":"final_model.save(\"kedi_kopek_model_final.h5\")\nprint(\"Model başarıyla kaydedildi: kedi_kopek_model_final.h5\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-25T01:04:26.622543Z","iopub.execute_input":"2025-09-25T01:04:26.622798Z","iopub.status.idle":"2025-09-25T01:04:26.815204Z","shell.execute_reply.started":"2025-09-25T01:04:26.622776Z","shell.execute_reply":"2025-09-25T01:04:26.814621Z"}},"outputs":[],"execution_count":null}]}