Created
November 17, 2025 10:32
-
-
Save AhmedCoolProjects/572dd81226fccaeec8805bc6dad5d130 to your computer and use it in GitHub Desktop.
RNN Application.ipynb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "nbformat": 4, | |
| "nbformat_minor": 0, | |
| "metadata": { | |
| "colab": { | |
| "provenance": [], | |
| "authorship_tag": "ABX9TyPJ0J6hVNon7X83DA1z7njz", | |
| "include_colab_link": true | |
| }, | |
| "kernelspec": { | |
| "name": "python3", | |
| "display_name": "Python 3" | |
| }, | |
| "language_info": { | |
| "name": "python" | |
| } | |
| }, | |
| "cells": [ | |
| { | |
| "cell_type": "markdown", | |
| "metadata": { | |
| "id": "view-in-github", | |
| "colab_type": "text" | |
| }, | |
| "source": [ | |
| "<a href=\"https://colab.research.google.com/gist/AhmedCoolProjects/572dd81226fccaeec8805bc6dad5d130/rnn-application.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 1, | |
| "metadata": { | |
| "id": "bzmI0Aq_TRYO" | |
| }, | |
| "outputs": [], | |
| "source": [ | |
| "import numpy as np\n", | |
| "\n", | |
| "class RNN:\n", | |
| " def __init__(self, hidden_size, vocab_size, learning_rate=0.01):\n", | |
| " '''\n", | |
| " Initialize the RNN layer.\n", | |
| " hidden_size: Number of neurons in the hidden state.\n", | |
| " vocab_size: Number of unique tokens in the input data.\n", | |
| " '''\n", | |
| "\n", | |
| " self.hidden_size = hidden_size\n", | |
| " self.vocab_size = vocab_size\n", | |
| " self.lr = learning_rate\n", | |
| "\n", | |
| " # 1. Initialize weights and biases\n", | |
| " # we use small random values * 0.01 to avoid exploding gradients\n", | |
| " # W_xh: From input x to hidden h, the input x is one-hot encoded\n", | |
| " self.Wxh = np.random.randn(hidden_size, vocab_size) * 0.01\n", | |
| " # W_hh: From hidden h(t-1) to hidden h(t)\n", | |
| " self.Whh = np.random.randn(hidden_size, hidden_size) * 0.01\n", | |
| " # W_hy: From hidden h to output y\n", | |
| " self.Why = np.random.randn(vocab_size, hidden_size) * 0.01\n", | |
| "\n", | |
| " # Biases\n", | |
| " self.bh = np.zeros((hidden_size, 1))\n", | |
| " self.by = np.zeros((vocab_size, 1))\n", | |
| "\n", | |
| " def _softmax(self, x):\n", | |
| " e_x = np.exp(x - np.max(x))\n", | |
| " return e_x / e_x.sum(axis=0)\n", | |
| "\n", | |
| " def forward(self, inputs, h_prev):\n", | |
| " '''\n", | |
| " For a full sequence.\n", | |
| "\n", | |
| " inputs: List of token indices for the sequence.\n", | |
| " h_prev: Previous hidden state (initially zeros).\n", | |
| "\n", | |
| " Returns:\n", | |
| " y_preds: List of softmax probabilities for each time step.\n", | |
| " h_final: The final hidden state after processing the sequence.\n", | |
| " cache: Values needed for backpropagation.\n", | |
| " '''\n", | |
| "\n", | |
| " xs, hs, ys, y_preds = {}, {}, {}, {} # these are x: input, h: hidden state, y: output before softmax, y_pred: after softmax\n", | |
| " hs[-1] = np.copy(h_prev) # initial hidden state at t=-1\n", | |
| " for t in range(len(inputs)):\n", | |
| " # 1. One-hot encode input\n", | |
| " xs[t] = np.zeros((self.vocab_size, 1))\n", | |
| " xs[t][inputs[t]] = 1\n", | |
| "\n", | |
| " # 2. Compute hidden state\n", | |
| " # h_t = tanh(W_xh * x_t + W_hh * h_(t-1) + b_h)\n", | |
| " zt = np.dot(self.Wxh, xs[t]) + np.dot(self.Whh, hs[t-1]) + self.bh # dimensions: (hidden_size, 1)\n", | |
| " hs[t] = np.tanh(zt)\n", | |
| "\n", | |
| " # 3. Compute output\n", | |
| " # y_t = W_hy * h_t + b_y\n", | |
| " ys[t] = np.dot(self.Why, hs[t]) + self.by\n", | |
| "\n", | |
| " # 4. Softmax to get probabilities\n", | |
| " y_preds[t] = self._softmax(ys[t])\n", | |
| "\n", | |
| " cache = (xs, hs, y_preds)\n", | |
| " return y_preds, hs[len(inputs)-1], cache # hs[len(inputs)-1] is the final hidden state\n", | |
| "\n", | |
| " def compute_cost(self, y_preds, targets):\n", | |
| " '''\n", | |
| " Calculate the total cross-entropy for the sequence.\n", | |
| " y_preds: Predicted probabilities for each time step.\n", | |
| " targets: True token indices for the sequence.\n", | |
| " '''\n", | |
| "\n", | |
| " total_cost = 0\n", | |
| " for t in range(len(targets)):\n", | |
| " prob_of_correct_class = y_preds[t][targets[t], 0]\n", | |
| " total_cost += -np.log(prob_of_correct_class + 1e-9) # add small value to avoid log(0)\n", | |
| "\n", | |
| " return total_cost / len(targets) # average cost per time step\n", | |
| "\n", | |
| " def backpropagation(self, targets, cache):\n", | |
| " '''\n", | |
| " Performs BPTT to compute gradients.\n", | |
| " targets: True token indices for the sequence.\n", | |
| " cache: (xs, hs, y_preds) from forward pass.\n", | |
| " '''\n", | |
| " xs, hs, y_preds = cache\n", | |
| " # Initialize gradients\n", | |
| " self.dWxh, self.dWhh, self.dWhy = np.zeros_like(self.Wxh), np.zeros_like(self.Whh), np.zeros_like(self.Why)\n", | |
| " self.dbh, self.dby = np.zeros_like(self.bh), np.zeros_like(self.by)\n", | |
| "\n", | |
| " # Gradient of the hidden state\n", | |
| " dh_next = np.zeros((self.hidden_size, 1))\n", | |
| "\n", | |
| " # --- Loop backward through time steps ---\n", | |
| " for t in reversed(range(len(targets))):\n", | |
| " # 1. Output gradients\n", | |
| " # Gradient of softmax + cross-entropy loss (AL - Y)\n", | |
| " dy = np.copy(y_preds[t])\n", | |
| " dy[targets[t]] -= 1 # derivative of loss w.r.t. y before softmax\n", | |
| "\n", | |
| " # 2. Gradients for output layer Why and by\n", | |
| " self.dWhy += np.dot(dy, hs[t].T) # vocab x hidden\n", | |
| " self.dby += dy\n", | |
| "\n", | |
| " # 3. Gradient for hidden state dh_t\n", | |
| " dh = np.dot(self.Why.T, dy) + dh_next # dh_next is from next time step\n", | |
| " # 4. Tanh Activation Zht\n", | |
| " # dtanh = 1 - tanh^2(zt) = 1 - h_t^2\n", | |
| " dzt = (1 - hs[t] * hs[t]) * dh # element-wise multiplication (hidden, 1)\n", | |
| " # 5. Gradients for Recurrent Layer dWhh, dWxh, dbh\n", | |
| " self.dbh += dzt\n", | |
| " self.dWhh += np.dot(dzt, hs[t-1].T)\n", | |
| " self.dWxh += np.dot(dzt, xs[t].T)\n", | |
| "\n", | |
| " # 6. Pass gradient to next (previous) time step\n", | |
| " dh_next = np.dot(self.Whh.T, dzt)\n", | |
| "\n", | |
| " # Clip gradients to prevent exploding gradients\n", | |
| " for grad in [self.dWxh, self.dWhh, self.dWhy, self.dbh, self.dby]:\n", | |
| " np.clip(grad, -5, 5, out=grad)\n", | |
| "\n", | |
| " def update_parameters(self):\n", | |
| " '''\n", | |
| " Performs a single gradient descent update.\n", | |
| " '''\n", | |
| " self.Wxh -= self.lr * self.dWxh\n", | |
| " self.Whh -= self.lr * self.dWhh\n", | |
| " self.Why -= self.lr * self.dWhy\n", | |
| " self.bh -= self.lr * self.dbh\n", | |
| " self.by -= self.lr * self.dby\n", | |
| "\n", | |
| " def sample(self, seed_idx, h_prev, length=20):\n", | |
| " '''\n", | |
| " This function generates a sequence of indices given a seed index and initial hidden state.\n", | |
| " '''\n", | |
| " x = np.zeros((self.vocab_size, 1))\n", | |
| " x[seed_idx] = 1\n", | |
| " indices = []\n", | |
| "\n", | |
| " for t in range(length):\n", | |
| " h = np.tanh(np.dot(self.Wxh, x) + np.dot(self.Whh, h_prev) + self.bh)\n", | |
| " z = np.dot(self.Why, h) + self.by\n", | |
| " y = self._softmax(z)\n", | |
| "\n", | |
| " idx = np.random.choice(range(self.vocab_size), p=y.ravel())\n", | |
| "\n", | |
| " x = np.zeros((self.vocab_size, 1))\n", | |
| " x[idx] = 1\n", | |
| " indices.append(idx)\n", | |
| " h_prev = h\n", | |
| " return indices" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "import matplotlib.pyplot as plt" | |
| ], | |
| "metadata": { | |
| "id": "6A-LOnqGTT0V" | |
| }, | |
| "execution_count": 2, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "# 1. prepare data\n", | |
| "data = \"helloahmed\"\n", | |
| "chars = list(set(data))\n", | |
| "vocab_size = len(chars)\n", | |
| "char_to_idx = { ch:i for i,ch in enumerate(chars)}\n", | |
| "idx_to_char = { i:ch for i,ch in enumerate(chars)}\n", | |
| "\n", | |
| "print(f\"Data: {data}\")\n", | |
| "print(f\"Vocabulary: {chars}\")\n", | |
| "print(f\"Vocab Size: {vocab_size}\")\n" | |
| ], | |
| "metadata": { | |
| "colab": { | |
| "base_uri": "https://localhost:8080/" | |
| }, | |
| "id": "opIE4GOsV7gu", | |
| "outputId": "46336f47-aed5-4e52-8a7a-b0a0496e695b" | |
| }, | |
| "execution_count": 7, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": [ | |
| "Data: helloahmed\n", | |
| "Vocabulary: ['d', 'h', 'a', 'e', 'l', 'o', 'm']\n", | |
| "Vocab Size: 7\n" | |
| ] | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "# 2. create model\n", | |
| "hidden_size = 25\n", | |
| "learning_rate = 0.01\n", | |
| "epochs = 3000\n", | |
| "\n", | |
| "rnn = RNN(hidden_size, vocab_size, learning_rate)" | |
| ], | |
| "metadata": { | |
| "id": "-zau4rHTWS4e" | |
| }, | |
| "execution_count": 30, | |
| "outputs": [] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "# 3. training loop\n", | |
| "print(\"Training RNN...\")\n", | |
| "costs = []\n", | |
| "h_prev = np.zeros((hidden_size, 1))\n", | |
| "inputs = [char_to_idx[ch] for ch in data[:-1]] # all chars except last\n", | |
| "targets = [char_to_idx[ch] for ch in data[1:]] # all chars except first\n", | |
| "\n", | |
| "for epoch in range(epochs):\n", | |
| " # Forward pass\n", | |
| " y_preds, h_prev, cache = rnn.forward(inputs, h_prev)\n", | |
| "\n", | |
| " # Compute cost\n", | |
| " cost = rnn.compute_cost(y_preds, targets)\n", | |
| " costs.append(cost)\n", | |
| "\n", | |
| " # Backpropagation\n", | |
| " rnn.backpropagation(targets, cache)\n", | |
| "\n", | |
| " # Update parameters\n", | |
| " rnn.update_parameters()\n", | |
| "\n", | |
| " if epoch % 200 == 0:\n", | |
| " print(f\"Epoch {epoch}, Cost: {cost}\")\n", | |
| "\n", | |
| "print(\"Training complete.\")" | |
| ], | |
| "metadata": { | |
| "colab": { | |
| "base_uri": "https://localhost:8080/" | |
| }, | |
| "id": "QdvuNWGjV_rG", | |
| "outputId": "ee4f4392-f3dd-4278-c10c-490dc68e65bd" | |
| }, | |
| "execution_count": 31, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": [ | |
| "Training RNN...\n", | |
| "Epoch 0, Cost: 1.9459309991147857\n", | |
| "Epoch 200, Cost: 1.706202022211689\n", | |
| "Epoch 400, Cost: 0.12627818855498268\n", | |
| "Epoch 600, Cost: 0.0324479532281581\n", | |
| "Epoch 800, Cost: 0.017277991429821452\n", | |
| "Epoch 1000, Cost: 0.011609467854989664\n", | |
| "Epoch 1200, Cost: 0.00869695286268516\n", | |
| "Epoch 1400, Cost: 0.006935226399796615\n", | |
| "Epoch 1600, Cost: 0.005758547578169212\n", | |
| "Epoch 1800, Cost: 0.004918524861098574\n", | |
| "Epoch 2000, Cost: 0.004289487960648133\n", | |
| "Epoch 2200, Cost: 0.00380120066255434\n", | |
| "Epoch 2400, Cost: 0.003411396816110657\n", | |
| "Epoch 2600, Cost: 0.0030931462666720904\n", | |
| "Epoch 2800, Cost: 0.0028284911266208226\n", | |
| "Training complete.\n" | |
| ] | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "# --- 5. Plot the Cost ---\n", | |
| "plt.plot(np.squeeze(costs))\n", | |
| "plt.ylabel('Cost')\n", | |
| "plt.xlabel('Epochs (per 100)')\n", | |
| "plt.title(f\"Learning rate = {learning_rate}\")\n", | |
| "plt.show()" | |
| ], | |
| "metadata": { | |
| "colab": { | |
| "base_uri": "https://localhost:8080/", | |
| "height": 472 | |
| }, | |
| "id": "tfGODTX4WE91", | |
| "outputId": "3eb80fcb-2953-4be2-c656-1716144bbead" | |
| }, | |
| "execution_count": 32, | |
| "outputs": [ | |
| { | |
| "output_type": "display_data", | |
| "data": { | |
| "text/plain": [ | |
| "<Figure size 640x480 with 1 Axes>" | |
| ], | |
| "image/png": "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WwA4c+YMACAoKMisn4eHh9S3JZqqvzXn4FoZGRkQQmDhwoVYuHBho31yc3ObDUB33HHHdX9OSzg4OAAAKisrG6yrqKiQ1je3fVVVVaPrWrI9kSVjACKycEajEQDw0EMPISYmptE+prkrn376KaZPn47o6Gg888wz8Pb2hkajQXx8PE6dOtVgu+b+AJpGUa4lhLhuzTezbWs0Vn9rz8G1TOf76aefRmRkZKN9rg1u18rLy2vRHCBnZ2c4Ozs3ud7X1xcAcPHixQbrLl68CD8/v2b37+vri9raWuTm5sLb21tqr6qqQn5+/nW3J7JkDEBEFs7LywsuLi6ora1FREREs32/+uor9OjRAxs3bjS7BLV48eL2LrNVAgICANSNtlw9KpOfny+NEt2olp6Dq9ddzXRZytbW9rrnuym33XabNMrVnMWLFzd7yW/AgAGwsbHB/v378eCDD0rtVVVVSEtLM2trjGnS+/79+3HvvfdK7fv374fRaGwwKZ7ImjAAEVk4jUaD+++/H59//jmOHTuGAQMGmK3Py8uT5sGYRl6EENIf+L179yI1NbXBZSk5jR49GjY2Nli5ciXuueceqf2999676X239ByY7r4qLCw0297b2xt33303/v3vf2PBggXSKIzJ1ee7KW01B0in0yEiIgKffvopFi5cKN2m/p///AclJSVmD0MsKytDVlYWPD094enpCQD405/+BA8PD6xcudIsAK1cuRKOjo4YN27cdWskslQMQEQWYs2aNUhKSmrQ/sQTT+DVV1/F9u3bERYWhlmzZqFfv34oKCjAwYMH8eOPP6KgoAAAcN9992Hjxo2YOHEixo0bh8zMTCQmJqJfv36tenVCe/Px8cETTzyBt956C3/+858RFRWFw4cPY8uWLfD09GxydKYlWnoOHBwc0K9fP6xfvx69e/eGh4cHBgwYgAEDBiAhIQEjRozAwIEDMWvWLPTo0QM5OTlITU3FuXPncPjw4WZraKs5QADwyiuvYPjw4bjrrrswe/ZsnDt3Dm+99RbGjBmDqKgoqd++ffswatQos1ElBwcHvPzyy5g3bx4eeOABREZGYteuXfj000/xyiuvmD32oKioSHpFxk8//QSgLpC6ubnBzc0N8+fPb7NjIuoQMt6BRkQtYLp1vKnl7NmzQgghcnJyxLx584S/v7+wtbUVer1ejB49WqxatUra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\n" | |
| }, | |
| "metadata": {} | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "# Test the model (sampling)\n", | |
| "# Get the index for our seed character 'h'\n", | |
| "seed_char_idx = char_to_idx['h']\n", | |
| "h_sample = np.zeros((hidden_size, 1))\n", | |
| "generated_indices = rnn.sample(seed_char_idx, h_sample, length=10)\n", | |
| "generated_text = 'h' + ''.join(idx_to_char[idx] for idx in generated_indices)\n", | |
| "\n", | |
| "print(f\"Generated text: {generated_text}\")" | |
| ], | |
| "metadata": { | |
| "colab": { | |
| "base_uri": "https://localhost:8080/" | |
| }, | |
| "id": "ofzVKsPFWFa0", | |
| "outputId": "cb126bd2-a98f-40f8-f5ba-94604c4916d6" | |
| }, | |
| "execution_count": 33, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": [ | |
| "Generated text: hmedlloahme\n" | |
| ] | |
| } | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [], | |
| "metadata": { | |
| "id": "cwnN0wfTWJ9X" | |
| }, | |
| "execution_count": null, | |
| "outputs": [] | |
| } | |
| ] | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment