{
 "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 · Kayıp fonksiyonları ve optimize ediciler\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. Kayıp fonksiyonları"
   ],
   "id": "c03"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from torch import nn\n",
    "logits = torch.tensor([[2.0, 0.5, -1.0]]); target = torch.tensor([0])\n",
    "ce = nn.CrossEntropyLoss()(logits, target)\n",
    "manual = -torch.log_softmax(logits, dim=1)[0, 0]\n",
    "print('CE', ce.item(), '| elle', manual.item())\n",
    "print('çift softmax (yanlış):', nn.CrossEntropyLoss()(torch.softmax(logits, 1), target).item())\n",
    "print('BCEWithLogits', nn.BCEWithLogitsLoss()(torch.tensor([1.2]), torch.tensor([1.0])).item())"
   ],
   "id": "c04"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. Dar bir vadide optimize ediciler\n",
    "$f(x, y) = 0{,}04x^2 + y^2$"
   ],
   "id": "c05"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "def run(make, steps=100):\n",
    "    xy = torch.tensor([-8.0, 1.6], requires_grad=True); opt = make([xy]); path = [xy.detach().clone()]\n",
    "    for _ in range(steps):\n",
    "        opt.zero_grad(); f = 0.04 * xy[0] ** 2 + xy[1] ** 2; f.backward(); opt.step(); path.append(xy.detach().clone())\n",
    "    return torch.stack(path)\n",
    "opts = {'SGD': lambda p: torch.optim.SGD(p, lr=0.05), 'Momentum': lambda p: torch.optim.SGD(p, lr=0.05, momentum=0.9),\n",
    "        'RMSprop': lambda p: torch.optim.RMSprop(p, lr=0.3), 'Adam': lambda p: torch.optim.Adam(p, lr=0.3)}\n",
    "X, Y = np.meshgrid(np.linspace(-10, 10, 200), np.linspace(-3, 3, 100))\n",
    "plt.contour(X, Y, 0.04 * X ** 2 + Y ** 2, levels=20, cmap='gray')\n",
    "for name, make in opts.items():\n",
    "    p = run(make); plt.plot(p[:, 0], p[:, 1], label=name)\n",
    "plt.legend(); plt.title('Optimize edici yarışı'); plt.show()"
   ],
   "id": "c06"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. Öğrenme oranı taraması"
   ],
   "id": "c07"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "for lr in [0.001, 0.01, 0.1, 0.5, 1.0, 1.1]:\n",
    "    p = run(lambda q: torch.optim.SGD(q, lr=lr))\n",
    "    f = (0.04 * p[-1, 0] ** 2 + p[-1, 1] ** 2).item()\n",
    "    print(f'lr={lr:<6} f={f:.3e}')                                   # 1,0 üstünde ıraksar"
   ],
   "id": "c08"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4. Zamanlayıcı"
   ],
   "id": "c09"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "w = torch.zeros(1, requires_grad=True)\n",
    "opt = torch.optim.SGD([w], lr=0.1)\n",
    "sched = torch.optim.lr_scheduler.CosineAnnealingLR(opt, T_max=20)\n",
    "lrs = []\n",
    "for _ in range(20):\n",
    "    opt.step(); sched.step(); lrs.append(opt.param_groups[0]['lr'])\n",
    "plt.plot(lrs); plt.title('CosineAnnealingLR'); plt.show()"
   ],
   "id": "c10"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Alıştırmalar\n",
    "1. Rosenbrock fonksiyonunda (`(1-x)^2 + 10(y-x^2)^2`) aynı yarışı yap.\n",
    "2. Momentumu 0,5 ve 0,99 yap; yörüngeyi karşılaştır.\n",
    "3. `OneCycleLR` ile öğrenme oranı eğrisini çiz."
   ],
   "id": "c11"
  }
 ]
}