{
 "nbformat": 4,
 "nbformat_minor": 5,
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python"
  },
  "accelerator": "GPU",
  "colab": {
   "provenance": []
  }
 },
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# PyTorch ile Derin Öğrenme · Eğitim döngüsü ve doğrulama\n",
    "\n",
    "Macademia · Büyükler için"
   ],
   "id": "c00"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> **Colab'da çalıştırma:** Bu dosyayı [colab.research.google.com](https://colab.research.google.com) adresinde **Dosya → Not defteri yükle** ile aç. GPU için **Çalışma zamanı → Çalışma zamanı türünü değiştir → T4 GPU** seç. Hücreleri yukarıdan aşağı sırayla çalıştır (Shift + Enter). PyTorch Colab'da kuruludur; bilgisayarında çalıştırmak istersen `pip install torch torchvision`."
   ],
   "id": "c01"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch, random, numpy as np\n",
    "torch.manual_seed(0); random.seed(0); np.random.seed(0)          # tekrarlanabilirlik\n",
    "device = 'cuda' if torch.cuda.is_available() else 'cpu'\n",
    "print('PyTorch', torch.__version__, '| device:', device)"
   ],
   "id": "c02"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. Veri ve ayrım"
   ],
   "id": "c03"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from torch import nn\n",
    "from sklearn.datasets import make_moons\n",
    "def moons(n, seed):                                                  # eğitim ve doğrulama ayrı üretilir\n",
    "    X, y = make_moons(n, noise=0.2, random_state=seed)\n",
    "    return torch.tensor(X, dtype=torch.float32).to(device), torch.tensor(y, dtype=torch.float32).unsqueeze(1).to(device)\n",
    "Xtr, ytr = moons(300, 0)\n",
    "Xva, yva = moons(100, 1)\n",
    "print(Xtr.shape, Xva.shape)"
   ],
   "id": "c04"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. Dört adımlı döngü"
   ],
   "id": "c05"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def make_model(h=16):\n",
    "    return nn.Sequential(nn.Linear(2, h), nn.ReLU(), nn.Linear(h, h), nn.ReLU(), nn.Linear(h, 1)).to(device)\n",
    "\n",
    "def train(model, epochs=100, lr=0.01, bs=32):\n",
    "    opt = torch.optim.Adam(model.parameters(), lr=lr); loss_fn = nn.BCEWithLogitsLoss(); hist = []\n",
    "    for epoch in range(epochs):\n",
    "        model.train(); perm = torch.randperm(len(Xtr)); tot = 0.0\n",
    "        for i in range(0, len(Xtr), bs):\n",
    "            idx = perm[i:i + bs]\n",
    "            opt.zero_grad()                                          # 1) sıfırla\n",
    "            loss = loss_fn(model(Xtr[idx]), ytr[idx])                # 2) ileri + kayıp\n",
    "            loss.backward()                                          # 3) geri\n",
    "            opt.step()                                               # 4) güncelle\n",
    "            tot += loss.item() * len(idx)\n",
    "        model.eval()\n",
    "        with torch.no_grad():\n",
    "            va = loss_fn(model(Xva), yva).item(); acc = ((model(Xva) > 0).float() == yva).float().mean().item()\n",
    "        hist.append((tot / len(Xtr), va, acc))\n",
    "    return hist\n",
    "\n",
    "hist = train(make_model())\n",
    "print('son: train %.3f val %.3f acc %.3f' % hist[-1])"
   ],
   "id": "c06"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. Eğriler ve karar sınırı"
   ],
   "id": "c07"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "h = np.array(hist)\n",
    "plt.plot(h[:, 0], label='train'); plt.plot(h[:, 1], label='val'); plt.legend(); plt.xlabel('epoch'); plt.show()"
   ],
   "id": "c08"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4. Duman testi: tek yığını ezberle"
   ],
   "id": "c09"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "m = make_model(64); opt = torch.optim.Adam(m.parameters(), lr=0.01)\n",
    "xb, yb = Xtr[:32], ytr[:32]\n",
    "for _ in range(300):\n",
    "    opt.zero_grad(); l = nn.BCEWithLogitsLoss()(m(xb), yb); l.backward(); opt.step()\n",
    "print('tek yığın kaybı:', l.item())                     # ≈ 0 olmalı"
   ],
   "id": "c10"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Alıştırmalar\n",
    "1. Öğrenme oranını 0,001 ve 0,1 yap; eğrileri karşılaştır.\n",
    "2. Aynı tohumla iki kez çalıştır: sonuç aynı mı?\n",
    "3. En iyi doğrulama kaybındaki modeli kaydeden bir checkpoint ekle."
   ],
   "id": "c11"
  }
 ]
}