{
 "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 · Diziler: RNN, LSTM ve dikkat\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. Görev: dizinin başındaki işareti hatırla\n",
    "Dizinin ilk adımındaki değerin işareti etiketi belirler; arası gürültü. Uzun dizilerde RNN zorlanır."
   ],
   "id": "c03"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from torch import nn\n",
    "def veri(n, T):\n",
    "    x = torch.randn(n, T, 1) * 0.5\n",
    "    y = (x[:, 0, 0] > 0).long()\n",
    "    x[:, 0, 0] = torch.where(y == 1, 1.0, -1.0)\n",
    "    return x, y\n",
    "class Model(nn.Module):\n",
    "    def __init__(self, kind='lstm', h=32):\n",
    "        super().__init__()\n",
    "        self.rnn = (nn.LSTM if kind == 'lstm' else nn.RNN)(1, h, batch_first=True); self.fc = nn.Linear(h, 2)\n",
    "    def forward(self, x):\n",
    "        out, _ = self.rnn(x)\n",
    "        return self.fc(out[:, -1])"
   ],
   "id": "c04"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. RNN ve LSTM karşılaştırması"
   ],
   "id": "c05"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def egit(kind, T, steps=300):\n",
    "    torch.manual_seed(0); m = Model(kind).to(device); opt = torch.optim.Adam(m.parameters(), lr=3e-3)\n",
    "    for _ in range(steps):\n",
    "        x, y = veri(64, T); x, y = x.to(device), y.to(device)\n",
    "        opt.zero_grad(); l = nn.functional.cross_entropy(m(x), y); l.backward()\n",
    "        nn.utils.clip_grad_norm_(m.parameters(), 1.0); opt.step()\n",
    "    x, y = veri(500, T)\n",
    "    with torch.no_grad():\n",
    "        return (m(x.to(device)).argmax(1).cpu() == y).float().mean().item()\n",
    "for T in [10, 50, 100]:\n",
    "    print(f'T={T:3d}  RNN {egit(\"rnn\", T):.2f}  LSTM {egit(\"lstm\", T):.2f}')"
   ],
   "id": "c06"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. Ölçekli nokta çarpımı dikkati"
   ],
   "id": "c07"
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch.nn.functional as F\n",
    "Q = K_ = V = torch.randn(1, 5, 16)\n",
    "w = torch.softmax(Q @ K_.transpose(-2, -1) / 16 ** 0.5, dim=-1)\n",
    "print(w.sum(-1))\n",
    "print(torch.allclose(w @ V, F.scaled_dot_product_attention(Q, K_, V), atol=1e-6))\n",
    "mha = nn.MultiheadAttention(16, num_heads=4, batch_first=True)\n",
    "out, att = mha(Q, K_, V)\n",
    "print(out.shape, att.shape)"
   ],
   "id": "c08"
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Alıştırmalar\n",
    "1. `nn.GRU` ile aynı karşılaştırmayı yap.\n",
    "2. Gradyan kırpmayı kaldır; RNN'de ne oldu?\n",
    "3. Dikkat ağırlıklarını ısı haritası olarak çiz."
   ],
   "id": "c09"
  }
 ]
}