Skip to content

Instantly share code, notes, and snippets.

@AhmedCoolProjects
Created November 17, 2025 10:32
Show Gist options
  • Select an option

  • Save AhmedCoolProjects/572dd81226fccaeec8805bc6dad5d130 to your computer and use it in GitHub Desktop.

Select an option

Save AhmedCoolProjects/572dd81226fccaeec8805bc6dad5d130 to your computer and use it in GitHub Desktop.
RNN Application.ipynb
Display the source blob
Display the rendered blob
Raw
{
"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+wtbUVer1ejB49WqxatUral9FoFP/3f/8nAgIChFarFYMHDxabN28WMTExIiAgQOpnuo38jTfeaFCP6Tb4vLy8Ruu8+tbopm6Dv/aW/u3btwsAYvv27VJbTU2NWLhwodDr9cLBwUH86U9/EidOnBBdunQRc+bMafacNVd/S8+BEEL8/PPPYsiQIcLOzq7BbemnTp0S06ZNE3q9Xtja2oquXbuK++67T3z11VfN1tYedu3aJYYPHy7s7e2Fl5eXmDdvnjAYDGZ9TOe4sVvrV61aJYKDg4WdnZ3o2bOnePvtt80eUyDElXPa2HLteSOyBCoh2njWIRFROyksLIS7uzuWLVuGF154Qe5yiMiC8VUYRNQpNTZHZsWKFQCAu+++u2OLISKrwzlARNQprV+/HmvXrsW9994LZ2dn7N69G1988QXGjBnTpnNoiEiZGICIqFMKCQmBjY0NXn/9dRgMBmli9LJly+QujYisAOcAERERkeJwDhAREREpDgMQERERKQ7nADXCaDTiwoULcHFxuakHrhEREVHHEUKguLgYfn5+UKubH+NhAGrEhQsX4O/vL3cZREREdAPOnj2LW265pdk+DECNML1P5+zZs3B1dZW5GiIiImoJg8EAf39/6e94cxiAGmG67OXq6soAREREZGFaMn1F1knQ8fHxuO222+Di4gJvb29ER0cjPT39uttt2LABffr0gb29PQYOHIjvv//ebL0QAosWLYKvry8cHBwQERGBkydPttdhEBERkYWRNQDt2LED8+bNw549e7B161ZUV1djzJgxKC0tbXKbn3/+GVOmTMHMmTNx6NAhREdHIzo6GseOHZP6vP7663jnnXeQmJiIvXv3wsnJCZGRkaioqOiIwyIiIqJOrlM9CDEvLw/e3t7YsWMH7rzzzkb7TJo0CaWlpdi8ebPUdvvttyM0NBSJiYkQQsDPzw9PPfUUnn76aQBAUVERfHx8sHbtWkyePPm6dRgMBuh0OhQVFfESGBERkYVozd/vTvUcoKKiIgCAh4dHk31SU1MRERFh1hYZGYnU1FQAQGZmJrKzs8366HQ6hIWFSX2IiIhI2TrNJGij0Ygnn3wSd9xxBwYMGNBkv+zsbPj4+Ji1+fj4IDs7W1pvamuqz7UqKytRWVkpfTYYDDd0DERERGQZOs0I0Lx583Ds2DGsW7euw392fHw8dDqdtPAZQERERNatUwSg+fPnY/Pmzdi+fft1H1yk1+uRk5Nj1paTkwO9Xi+tN7U11edacXFxKCoqkpazZ8/e6KEQERGRBZA1AAkhMH/+fHzzzTfYtm0bAgMDr7tNeHg4kpOTzdq2bt2K8PBwAEBgYCD0er1ZH4PBgL1790p9rqXVaqVn/vDZP0RERNZP1jlA8+bNw+eff45vv/0WLi4u0hwdnU4HBwcHAMC0adPQtWtXxMfHAwCeeOIJ3HXXXXjrrbcwbtw4rFu3Dvv378eqVasA1D386Mknn8SyZcvQq1cvBAYGYuHChfDz80N0dLQsx0lERESdi6wBaOXKlQCAu+++26z9o48+wvTp0wEAWVlZZi80Gz58OD7//HO8+OKLeP7559GrVy9s2rTJbOL0s88+i9LSUsyePRuFhYUYMWIEkpKSYG9v3+7HRERERJ1fp3oOUGfB5wARERFZHot9DhARERFRR2AA6mB7/8hHSWWN3GUQEREpGgNQB4r//gQmrdqD97ZlyF0KERGRojEAdaBhgXWv+Fi9+w9kXmr6ha9ERETUvhiAOtCf+njj7mAvVNcKLPr2GIxGzj8nIiKSAwNQB1KpVFh0Xz9obdTYdfISVu/OlLskIiIiRWIA6mA9vJyxaHw/AMBrSb9h18k8mSsiIiJSHgYgGfxtWDf8eZAfaowCj/3nAPZlFshdEhERkaIwAMlApVLhjQdCMLKXJ8qqavHQh3vx9YFzcpdFRESkGAxAMtHaaLDq4aGI6q9HVa0RT204jLmfHkCOoULu0oiIiKweA5CMHOw0eH/qrXgyohds1CpsOZaNO1/fjmWbjzMIERERtSO+C6wRcrwL7NcLRVj07a84cOYyAECjViGyvw8eCgtAeM8uUKlUHVIHERGRpWrN328GoEbI9TJUIQRSfs/D+9sz8Mvpy1J7kLczYsIDMPHWW+CstemweoiIiCwJA9BN6gxvg/8t24BP95zBNwfPo7SqFgDgrLXBpNv8MW9UEDyc7GSpi4iIqLNiALpJnSEAmRRXVOPrA+fwSeoZ/FH/+gwXexvE3tMbMeHdoVbz0hgRERHAAHTTOlMAMjEaBXaczMMbSek4ftEAABjZyxP/mjyYo0FERERo3d9v3gVmIdRqFUYFe2PzghF4OXoA7G3rXqfx18Sfce5ymdzlERERWRQGIAujVqvw8O0B+O/8EfDT2eOPvFJM/XAv8ksq5S6NiIjIYjAAWajePi74+u/D4e/hgDP5ZZj9nwOorjXKXRYREZFFYACyYL46B3w0fRhc7G1w4MxlvLctQ+6SiIiILAIDkIUL8nbGKxMHAgDe3XYSJ+onSBMREVHTGICswJ8H+WHsAD2MAlj23XHwxj4iIqLmMQBZiefv7Qs7jRo/ZeQj5fc8ucshIiLq1BiArIS/hyOmhQcAABJTTslcDRERUefGAGRFZo4MhI1ahb2ZBUg7Wyh3OURERJ0WA5AV8dU5YEJoVwDA2p8yZa6GiIio82IAsjIP3d4NAJD0azaKK6plroaIiKhzYgCyMqH+bujp5YSKaiO2HM2WuxwiIqJOiQHIyqhUKtw/5BYAwNcHz8lcDRERUefEAGSFxof4AQB+OV2Ay6VVMldDRETU+TAAWSF/D0f00bvAKIBtv+XKXQ4REVGnwwBkpcb08wEAbD2eI3MlREREnQ8DkJWKqA9AO0/moaqGb4knIiK6mqwBaOfOnRg/fjz8/PygUqmwadOmZvtPnz4dKpWqwdK/f3+pz5IlSxqs79OnTzsfSeczwE8HDyc7lFXV4si5QrnLISIi6lRkDUClpaUYNGgQEhISWtT/X//6Fy5evCgtZ8+ehYeHBx544AGzfv379zfrt3v37vYov1NTq1UI79EFAPDzqXyZqyEiIupcbOT84WPHjsXYsWNb3F+n00Gn00mfN23ahMuXL2PGjBlm/WxsbKDX69usTkt1e88u+O7oRfx86hIeH91L7nKIiIg6DYueA7R69WpEREQgICDArP3kyZPw8/NDjx49MHXqVGRlZTW7n8rKShgMBrPFGgzvWTcCdPBMISqqa2WuhoiIqPOw2AB04cIFbNmyBY8++qhZe1hYGNauXYukpCSsXLkSmZmZGDlyJIqLi5vcV3x8vDS6pNPp4O/v397ld4genk7wdtGiqtbIl6MSERFdxWID0Mcffww3NzdER0ebtY8dOxYPPPAAQkJCEBkZie+//x6FhYX48ssvm9xXXFwcioqKpOXs2bPtXH3HUKlUuLWbOwAwABEREV1F1jlAN0oIgTVr1uDhhx+GnZ1ds33d3NzQu3dvZGRkNNlHq9VCq9W2dZmdQmg3NyT9mo20rEK5SyEiIuo0LHIEaMeOHcjIyMDMmTOv27ekpASnTp2Cr69vB1TW+YT6uwHgCBAREdHVZA1AJSUlSEtLQ1paGgAgMzMTaWlp0qTluLg4TJs2rcF2q1evRlhYGAYMGNBg3dNPP40dO3bg9OnT+PnnnzFx4kRoNBpMmTKlXY+lswq5RQe1Csg2VCC7qELucoiIiDoFWQPQ/v37MXjwYAwePBgAEBsbi8GDB2PRokUAgIsXLza4g6uoqAhff/11k6M/586dw5QpUxAcHIwHH3wQXbp0wZ49e+Dl5dW+B9NJOdrZIFjvCgBIO3tZ5mqIiIg6B5UQQshdRGdjMBig0+lQVFQEV1dXucu5aXEbj+KLfVmYc1dPPDdWeU/FJiIiZWjN32+LnANErdPfr+6X4MRF63i+ERER0c1iAFKAvr4MQERERFdjAFKAPnoXqFRAbnEl8ksq5S6HiIhIdgxACuCktUGAhyMA4MTFpp+ITUREpBQMQArBy2BERERXMAApRB89AxAREZEJA5BC9PV1AQAcZwAiIiJiAFIK0wjQH5dKUWvko5+IiEjZGIAUoqu7A+xs1KiqMeLc5TK5yyEiIpIVA5BCaNQq9PB0AgCcyiuRuRoiIiJ5MQApSE9vZwDAqdxSmSshIiKSFwOQgvT0qg9AHAEiIiKFYwBSkJ5edZfAMnIZgIiISNkYgBSEI0BERER1GIAUxBSALpdVo6C0SuZqiIiI5MMApCAOdhp0dXMAwFEgIiJSNgYghblyJxgDEBERKRcDkMJ071L3VvgzBXwYIhERKRcDkMJ086gLQFn5DEBERKRcDEAKE9Cl7lb4MwV8GCIRESkXA5DCBJgugeWXQQi+FJWIiJSJAUhh/N3rAlBxRQ0Ky6plroaIiEgeDEAK42CngbeLFgCQxYnQRESkUAxAChTAO8GIiEjhGIAUqJtH3UTorHxOhCYiImViAFKgqydCExERKREDkALxEhgRESkdA5ACmR6GeJYBiIiIFIoBSIG6ute9EDXHUIHqWqPM1RAREXU8BiAF8nTSws5GDaMAsosq5C6HiIiowzEAKZBarYKfzh4AcKGwXOZqiIiIOh4DkEL5udVdBjvPAERERAokawDauXMnxo8fDz8/P6hUKmzatKnZ/ikpKVCpVA2W7Oxss34JCQno3r077O3tERYWhn379rXjUVgmUwDiCBARESmRrAGotLQUgwYNQkJCQqu2S09Px8WLF6XF29tbWrd+/XrExsZi8eLFOHjwIAYNGoTIyEjk5ua2dfkWras0AsQ5QEREpDw2cv7wsWPHYuzYsa3eztvbG25ubo2uW758OWbNmoUZM2YAABITE/Hdd99hzZo1eO65526mXKvSlZfAiIhIwSxyDlBoaCh8fX1xzz334KeffpLaq6qqcODAAUREREhtarUaERERSE1NbXJ/lZWVMBgMZou14yUwIiJSMosKQL6+vkhMTMTXX3+Nr7/+Gv7+/rj77rtx8OBBAMClS5dQW1sLHx8fs+18fHwazBO6Wnx8PHQ6nbT4+/u363F0Bn5uV+4CE0LIXA0REVHHkvUSWGsFBwcjODhY+jx8+HCcOnUKb7/9Nv7zn//c8H7j4uIQGxsrfTYYDFYfgkwjQGVVtSgqr4abo53MFREREXUciwpAjRk2bBh2794NAPD09IRGo0FOTo5Zn5ycHOj1+ib3odVqodVq27XOzsbeVgNPZztcKqnCucvlDEBERKQoFnUJrDFpaWnw9fUFANjZ2WHIkCFITk6W1huNRiQnJyM8PFyuEjstzgMiIiKlknUEqKSkBBkZGdLnzMxMpKWlwcPDA926dUNcXBzOnz+PTz75BACwYsUKBAYGon///qioqMCHH36Ibdu24YcffpD2ERsbi5iYGAwdOhTDhg3DihUrUFpaKt0VRlf46uxx5FwRAxARESmOrAFo//79GDVqlPTZNA8nJiYGa9euxcWLF5GVlSWtr6qqwlNPPYXz58/D0dERISEh+PHHH832MWnSJOTl5WHRokXIzs5GaGgokpKSGkyMJkDvWjcROre4UuZKiIiIOpZK8BagBgwGA3Q6HYqKiuDq6ip3Oe0mYXsG3vh/6bj/1lvw1oOD5C6HiIjoprTm77fFzwGiG+cjjQDxadBERKQsDEAK5uNad+dbroGXwIiISFkYgBTMNAKUwxEgIiJSGAYgBfNxqQtAhWXVqKiulbkaIiKijsMApGCuDjbQ2tT9CuTxTjAiIlIQBiAFU6lU8K6fB5Rj4GUwIiJSDgYghTNdBsvhRGgiIlIQBiCFkyZCcwSIiIgUhAFI4UyXwPg0aCIiUhIGIIXzduHDEImISHkYgBSui7MdAKCgtErmSoiIiDoOA5DCdXGqC0D5JQxARESkHAxACtfFuW4OUH4J5wAREZFyMAApnDQCVFoFIYTM1RAREXUMBiCFM80BqqwxorSKr8MgIiJlYABSOEc7GzjYagAABZwHRERECsEARPCovwx2qZTzgIiISBkYgAiezrwTjIiIlIUBiKQ7wQo4AkRERArBAERXLoFxBIiIiBSCAYikO8F4CYyIiJSCAYikZwHxEhgRESkFAxDBzbEuABWWV8tcCRERUcdgACLoHGwBAIVlDEBERKQMDEAEt/oAZOAIEBERKQQDEPESGBERKQ4DEEmXwIrKq/lCVCIiUgQGIIKbY10AqjUKlFTWyFwNERFR+2MAItjbamBnU/erUMTLYEREpAAMQATgykRo3glGRERKwABEAK7MA+KdYEREpAQMQATgyjwg3glGRERKIGsA2rlzJ8aPHw8/Pz+oVCps2rSp2f4bN27EPffcAy8vL7i6uiI8PBz/7//9P7M+S5YsgUqlMlv69OnTjkdhHa6+E4yIiMjayRqASktLMWjQICQkJLSo/86dO3HPPffg+++/x4EDBzBq1CiMHz8ehw4dMuvXv39/XLx4UVp2797dHuVbFZ1D/bOAOAeIiIgUwEbOHz527FiMHTu2xf1XrFhh9vn//u//8O233+J///sfBg8eLLXb2NhAr9e3VZmKwBEgIiJSEoueA2Q0GlFcXAwPDw+z9pMnT8LPzw89evTA1KlTkZWV1ex+KisrYTAYzBalcXWoy8LFFQxARERk/Sw6AL355psoKSnBgw8+KLWFhYVh7dq1SEpKwsqVK5GZmYmRI0eiuLi4yf3Ex8dDp9NJi7+/f0eU36k4a+sCEB+ESERESmCxAejzzz/H0qVL8eWXX8Lb21tqHzt2LB544AGEhIQgMjIS33//PQoLC/Hll182ua+4uDgUFRVJy9mzZzviEDoVUwAqZQAiIiIFkHUO0I1at24dHn30UWzYsAERERHN9nVzc0Pv3r2RkZHRZB+tVgutVtvWZVoUZ3vTJTAGICIisn4WNwL0xRdfYMaMGfjiiy8wbty46/YvKSnBqVOn4Ovr2wHVWS5eAiMiIiWRdQSopKTEbGQmMzMTaWlp8PDwQLdu3RAXF4fz58/jk08+AVB32SsmJgb/+te/EBYWhuzsbACAg4MDdDodAODpp5/G+PHjERAQgAsXLmDx4sXQaDSYMmVKxx+gBXGxZwAiIiLlkHUEaP/+/Rg8eLB0C3tsbCwGDx6MRYsWAQAuXrxodgfXqlWrUFNTg3nz5sHX11dannjiCanPuXPnMGXKFAQHB+PBBx9Ely5dsGfPHnh5eXXswVkYJ9MIEC+BERGRAqiEEELuIjobg8EAnU6HoqIiuLq6yl1Ohzh3uQwjXtsOrY0a6cta/mwmIiKizqI1f78tbg4QtQ8Xbd2DECtrjKiqMcpcDRERUftiACIAgJNWI33PW+GJiMjaMQARAMBGo4aDbV0I4kRoIiKydgxAJDFNhOazgIiIyNoxAJHEdCt8aRUDEBERWTcGIJI481Z4IiJSCAYgkpgCUDHnABERkZVjACIJH4ZIRERKwQBEkiuvw6iWuRIiIqL2xQBEEge7utvgy6pqZa6EiIiofTEAkcSx/jlA5QxARERk5RiASOLIESAiIlIIBiCSONjVzQFiACIiImvHAEQS0whQeTXvAiMiIuvGAEQS0yRozgEiIiJrxwBEEtPLUHkJjIiIrB0DEEmuXAJjACIiIuvGAEQSPgeIiIiUggGIJI71d4FxDhAREVk7BiCSXHkOEO8CIyIi68YARBJOgiYiIqVgACKJaQSossYIo1HIXA0REVH7YQAiiWkSNMA7wYiIyLoxAJHE3uZKAOJlMCIismYMQCRRq1XSPCDeCUZERNaMAYjMSHeC8X1gRERkxRiAyAwfhkhERErAAERmHPlCVCIiUoAbCkAvvfQSysrKGrSXl5fjpZdeuumiSD4O9U+D5ggQERFZsxsKQEuXLkVJSUmD9rKyMixduvSmiyL5ONryadBERGT9bigACSGgUqkatB8+fBgeHh43XRTJxzQHqLLaKHMlRERE7cemNZ3d3d2hUqmgUqnQu3dvsxBUW1uLkpISzJkzp82LpI5jCkB8ECIREVmzVo0ArVixAsuXL4cQAkuXLsXbb78tLYmJidi9ezcSEhJavL+dO3di/Pjx8PPzg0qlwqZNm667TUpKCm699VZotVoEBQVh7dq1DfokJCSge/fusLe3R1hYGPbt29eKo1Q2vg+MiIiUoFUjQDExMQCAwMBA3HHHHbCxadXmDZSWlmLQoEF45JFH8Je//OW6/TMzMzFu3DjMmTMHn332GZKTk/Hoo4/C19cXkZGRAID169cjNjYWiYmJCAsLw4oVKxAZGYn09HR4e3vfVL1KID0IkSNARERkxW5oDpCLiwtOnDghff72228RHR2N559/HlVVVS3ez9ixY7Fs2TJMnDixRf0TExMRGBiIt956C3379sX8+fPx17/+FW+//bbUZ/ny5Zg1axZmzJiBfv36ITExEY6OjlizZk3LD1DBTJfAKhiAiIjIit1QAHrsscfw+++/AwD++OMPTJo0CY6OjtiwYQOeffbZNi3waqmpqYiIiDBri4yMRGpqKgCgqqoKBw4cMOujVqsREREh9WlMZWUlDAaD2aJU9nwVBhERKcANBaDff/8doaGhAIANGzbgrrvuwueff461a9fi66+/bsv6zGRnZ8PHx8eszcfHBwaDAeXl5bh06RJqa2sb7ZOdnd3kfuPj46HT6aTF39+/Xeq3BLwERkRESnDDt8EbjXW3Sf/444+49957AQD+/v64dOlS21XXQeLi4lBUVCQtZ8+elbsk2TjY1v1KMAAREZE1u6FZzEOHDsWyZcsQERGBHTt2YOXKlQDqJilfO/rSlvR6PXJycszacnJy4OrqCgcHB2g0Gmg0mkb76PX6Jver1Wqh1WrbpWZLI80B4iUwIiKyYjc0ArRixQocPHgQ8+fPxwsvvICgoCAAwFdffYXhw4e3aYFXCw8PR3Jyslnb1q1bER4eDgCws7PDkCFDzPoYjUYkJydLfah59rwERkRECnBDI0AhISE4evRog/Y33ngDGo2mxfspKSlBRkaG9DkzMxNpaWnw8PBAt27dEBcXh/Pnz+OTTz4BAMyZMwfvvfcenn32WTzyyCPYtm0bvvzyS3z33XfSPmJjYxETE4OhQ4di2LBhWLFiBUpLSzFjxowbOVTFcax/FxgDEBERWbObepDPgQMHpNvh+/Xrh1tvvbVV2+/fvx+jRo2SPsfGxgKoe97Q2rVrcfHiRWRlZUnrAwMD8d133+Ef//gH/vWvf+GWW27Bhx9+KD0DCAAmTZqEvLw8LFq0CNnZ2QgNDUVSUlK7XpqzJg68C4yIiBRAJYQQrd0oNzcXkyZNwo4dO+Dm5gYAKCwsxKhRo7Bu3Tp4eXm1dZ0dymAwQKfToaioCK6urnKX06EOnCnA/StT0b2LI1KeGXX9DYiIiDqJ1vz9vqE5QAsWLEBJSQl+/fVXFBQUoKCgAMeOHYPBYMDjjz9+Q0VT52DPV2EQEZEC3NAlsKSkJPz444/o27ev1NavXz8kJCRgzJgxbVYcdTw+B4iIiJTghkaAjEYjbG1tG7Tb2tpKzwciy8RXYRARkRLcUAD605/+hCeeeAIXLlyQ2s6fP49//OMfGD16dJsVRx3PNAJUXStQXcswS0RE1umGAtB7770Hg8GA7t27o2fPnujZsycCAwNhMBjw7rvvtnWN1IFMc4AAjgIREZH1uqE5QP7+/jh48CB+/PFH/PbbbwCAvn37NnhRKVkerY0aKhUgRN08IBf7hpc6iYiILF2rRoC2bduGfv36wWAwQKVS4Z577sGCBQuwYMEC3Hbbbejfvz927drVXrVSB1CpVNJlsIoqXgIjIiLr1KoAtGLFCsyaNavRe+t1Oh0ee+wxLF++vM2KI3k42vFOMCIism6tCkCHDx9GVFRUk+vHjBmDAwcO3HRRJC++D4yIiKxdqwJQTk5Oo7e/m9jY2CAvL++miyJ58XUYRERk7VoVgLp27Ypjx441uf7IkSPw9fW96aJIXg7SJbAamSshIiJqH60KQPfeey8WLlyIioqKBuvKy8uxePFi3HfffW1WHMlDugTGSdBERGSlWnUb/IsvvoiNGzeid+/emD9/PoKDgwEAv/32GxISElBbW4sXXnihXQqljsPXYRARkbVrVQDy8fHBzz//jLlz5yIuLg6mF8mrVCpERkYiISEBPj4+7VIodRwGICIisnatfhBiQEAAvv/+e1y+fBkZGRkQQqBXr15wd3dvj/pIBtL7wDgJmoiIrNQNPQkaANzd3XHbbbe1ZS3USfA2eCIisnY39C4wsm58ECIREVk7BiBqgM8BIiIia8cARA1Ic4A4AkRERFaKAYga4BwgIiKydgxA1AAvgRERkbVjAKIGHOzqfi04AkRERNaKAYga4AgQERFZOwYgaoBzgIiIyNoxAFEDfBUGERFZOwYgasDRru4B4XwVBhERWSsGIGqAk6CJiMjaMQBRA5wDRERE1o4BiBowzQGqqDbCaBQyV0NERNT2GICoAdOrMACgssYoYyVERETtgwGIGrC3uRKAeBmMiIisEQMQNaBWq6C1qfvVKKuqkbkaIiKittcpAlBCQgK6d+8Oe3t7hIWFYd++fU32vfvuu6FSqRos48aNk/pMnz69wfqoqKiOOBSrwTfCExGRNbORu4D169cjNjYWiYmJCAsLw4oVKxAZGYn09HR4e3s36L9x40ZUVVVJn/Pz8zFo0CA88MADZv2ioqLw0UcfSZ+1Wm37HYQVcrDVoBDVKK/iHCAiIrI+so8ALV++HLNmzcKMGTPQr18/JCYmwtHREWvWrGm0v4eHB/R6vbRs3boVjo6ODQKQVqs16+fu7t4Rh2M1TCNAnANERETWSNYAVFVVhQMHDiAiIkJqU6vViIiIQGpqaov2sXr1akyePBlOTk5m7SkpKfD29kZwcDDmzp2L/Pz8Nq3d2vF1GEREZM1kvQR26dIl1NbWwsfHx6zdx8cHv/3223W337dvH44dO4bVq1ebtUdFReEvf/kLAgMDcerUKTz//PMYO3YsUlNTodFoGuynsrISlZWV0meDwXCDR2Q9+EZ4IiKyZrLPAboZq1evxsCBAzFs2DCz9smTJ0vfDxw4ECEhIejZsydSUlIwevToBvuJj4/H0qVL271eS8JJ0EREZM1kvQTm6ekJjUaDnJwcs/acnBzo9fpmty0tLcW6deswc+bM6/6cHj16wNPTExkZGY2uj4uLQ1FRkbScPXu25Qdhpfg6DCIismayBiA7OzsMGTIEycnJUpvRaERycjLCw8Ob3XbDhg2orKzEQw89dN2fc+7cOeTn58PX17fR9VqtFq6urmaL0vESGBERWTPZ7wKLjY3FBx98gI8//hgnTpzA3LlzUVpaihkzZgAApk2bhri4uAbbrV69GtHR0ejSpYtZe0lJCZ555hns2bMHp0+fRnJyMiZMmICgoCBERkZ2yDFZA06CJiIiayb7HKBJkyYhLy8PixYtQnZ2NkJDQ5GUlCRNjM7KyoJabZ7T0tPTsXv3bvzwww8N9qfRaHDkyBF8/PHHKCwshJ+fH8aMGYOXX36ZzwJqBc4BIiIia6YSQvB139cwGAzQ6XQoKipS7OWwV7f8hsQdpzBzRCAW3tdP7nKIiIiuqzV/v2W/BEadk2P9CFAZ5wAREZEVYgCiRpkCUDlfhkpERFaIAYga5WJfNz2suIIBiIiIrA8DEDXKWWsLACiuZAAiIiLrwwBEjeIIEBERWTMGIGqUc30AKqmslrkSIiKitscARI1y0XIEiIiIrBcDEDXKxb5uDlBJRQ34qCgiIrI2DEDUKNMlsBqjQGWNUeZqiIiI2hYDEDXKyU4Dlarue0MF5wEREZF1YQCiRqlUKjjXzwMq4TwgIiKyMgxA1CTX+nlAnAhNRETWhgGImiSNAPFhiEREZGUYgKhJztLDEDkHiIiIrAsDEDWJT4MmIiJrxQBETXLmwxCJiMhKMQBRk1w4CZqIiKwUAxA1ydWhbgSIzwEiIiJrwwBETXJ3tAMAXC6rkrkSIiKitsUARE1yc6i7BFZUxhEgIiKyLgxA1CQ3jgAREZGVYgCiJrk71o0AFXIEiIiIrAwDEDXJNAJUWM4ARERE1oUBiJp0ZQSoCkajkLkaIiKitsMARE3S1Qcgo+CzgIiIyLowAFGTtDYaONppAACF5ZwITURE1oMBiJp15VlAnAdERETWgwGImuVWfxmMt8ITEZE1YQCiZpkCEB+GSERE1oQBiJrFhyESEZE1YgCiZrlLl8A4AkRERNaDAYiaJU2CLuUIEBERWQ8GIGqWp7MWAJBfWilzJURERG2nUwSghIQEdO/eHfb29ggLC8O+ffua7Lt27VqoVCqzxd7e3qyPEAKLFi2Cr68vHBwcEBERgZMnT7b3YVglL5e6AJRXzABERETWQ/YAtH79esTGxmLx4sU4ePAgBg0ahMjISOTm5ja5jaurKy5evCgtZ86cMVv/+uuv45133kFiYiL27t0LJycnREZGoqKior0Px+qYRoAYgIiIyJrIHoCWL1+OWbNmYcaMGejXrx8SExPh6OiINWvWNLmNSqWCXq+XFh8fH2mdEAIrVqzAiy++iAkTJiAkJASffPIJLly4gE2bNnXAEVkX0wjQpRLOASIiIushawCqqqrCgQMHEBERIbWp1WpEREQgNTW1ye1KSkoQEBAAf39/TJgwAb/++qu0LjMzE9nZ2Wb71Ol0CAsLa3KflZWVMBgMZgvV8XSumwRdUlmD8qpamashIiJqG7IGoEuXLqG2ttZsBAcAfHx8kJ2d3eg2wcHBWLNmDb799lt8+umnMBqNGD58OM6dOwcA0nat2Wd8fDx0Op20+Pv73+yhWQ1nrQ3sbet+TS6V8DIYERFZB9kvgbVWeHg4pk2bhtDQUNx1113YuHEjvLy88O9///uG9xkXF4eioiJpOXv2bBtWbNlUKpV0GSyX84CIiMhKyBqAPD09odFokJOTY9aek5MDvV7fon3Y2tpi8ODByMjIAABpu9bsU6vVwtXV1WyhKzgRmoiIrI2sAcjOzg5DhgxBcnKy1GY0GpGcnIzw8PAW7aO2thZHjx6Fr68vACAwMBB6vd5snwaDAXv37m3xPsmcl7NpIjQDEBERWQcbuQuIjY1FTEwMhg4dimHDhmHFihUoLS3FjBkzAADTpk1D165dER8fDwB46aWXcPvttyMoKAiFhYV44403cObMGTz66KMA6i7ZPPnkk1i2bBl69eqFwMBALFy4EH5+foiOjpbrMC2aJ58FREREVkb2ADRp0iTk5eVh0aJFyM7ORmhoKJKSkqRJzFlZWVCrrwxUXb58GbNmzUJ2djbc3d0xZMgQ/Pzzz+jXr5/U59lnn0VpaSlmz56NwsJCjBgxAklJSQ0emEgtYxoByuMIEBERWQmVEELIXURnYzAYoNPpUFRUxPlAAD7fm4XnvzmK0X28sXr6bXKXQ0RE1KjW/P22uLvAqOP5udWNnJ0vLJe5EiIiorbBAETX5efmAAC4WMRXiRARkXVgAKLr8tXVjQAVlVejrKpG5mqIiIhuHgMQXZeLvS1ctHXz5S8UchSIiIgsHwMQtYhv/Tygi0WcB0RERJaPAYhaxFdXNw/oAidCExGRFWAAohYxTYTmJTAiIrIGDEDUIn46XgIjIiLrwQBELeLLW+GJiMiKMABRi0gPQ7zMESAiIrJ8DEDUIgFdnAAAZy+XodbIt6cQEZFlYwCiFvF1tYedjRrVtYJ3ghERkcVjAKIWUatV8Hevmwd0Jr9M5mqIiIhuDgMQtVj3+stgp/NLZa6EiIjo5jAAUYuZ5gFlFXAEiIiILBsDELVYd09HAMDpSxwBIiIiy8YARC3WzaMuAHEOEBERWToGIGox0xygMwWlMPJWeCIismAMQNRiXd0dYKtRoaLaiAt8JQYREVkwBiBqMVuNGj08nQEAv+cUy1wNERHRjWMAolbp5WMKQCUyV0JERHTjGICoVYJ9XABwBIiIiCwbAxC1Sq/6AHSSI0BERGTBGICoVXrXXwI7mVvMO8GIiMhiMQBRqwR0cYKdjRoV1UacvcznARERkWViAKJW0ahVCPLiRGgiIrJsDEDUan186+YB/XqhSOZKiIiIbgwDELVaSFcdAODoOQYgIiKyTAxA1GoDb3EDABw5XwQhOBGaiIgsDwMQtVo/X1do1CrkFVcix1ApdzlEREStxgBEreZgp0Ev77qJ0EfOFcpbDBER0Q1gAKIbEnJL/Tyg85wHRERElqdTBKCEhAR0794d9vb2CAsLw759+5rs+8EHH2DkyJFwd3eHu7s7IiIiGvSfPn06VCqV2RIVFdXeh6EopnlAaWcLZa2DiIjoRsgegNavX4/Y2FgsXrwYBw8exKBBgxAZGYnc3NxG+6ekpGDKlCnYvn07UlNT4e/vjzFjxuD8+fNm/aKionDx4kVp+eKLLzricBTj1m5uAIBDWYWoqTXKWwwREVEryR6Ali9fjlmzZmHGjBno168fEhMT4ejoiDVr1jTa/7PPPsPf//53hIaGok+fPvjwww9hNBqRnJxs1k+r1UKv10uLu7t7RxyOYvTRu8LF3gYllTU4cZEvRiUiIssiawCqqqrCgQMHEBERIbWp1WpEREQgNTW1RfsoKytDdXU1PDw8zNpTUlLg7e2N4OBgzJ07F/n5+U3uo7KyEgaDwWyh5mnUKtzWve6c781s+twSERF1RrIGoEuXLqG2thY+Pj5m7T4+PsjOzm7RPv75z3/Cz8/PLERFRUXhk08+QXJyMl577TXs2LEDY8eORW1tbaP7iI+Ph06nkxZ/f/8bPygFGRZYF4D2ZRbIXAkREVHr2MhdwM149dVXsW7dOqSkpMDe3l5qnzx5svT9wIEDERISgp49eyIlJQWjR49usJ+4uDjExsZKnw0GA0NQC5gC0C+nC2A0CqjVKpkrIiIiahlZR4A8PT2h0WiQk5Nj1p6TkwO9Xt/stm+++SZeffVV/PDDDwgJCWm2b48ePeDp6YmMjIxG12u1Wri6upotdH0Du+rgYKvB5bJqnMjmZUMiIrIcsgYgOzs7DBkyxGwCs2lCc3h4eJPbvf7663j55ZeRlJSEoUOHXvfnnDt3Dvn5+fD19W2TuqmOrUaNO4K6AABS0vNkroaIiKjlZL8LLDY2Fh988AE+/vhjnDhxAnPnzkVpaSlmzJgBAJg2bRri4uKk/q+99hoWLlyINWvWoHv37sjOzkZ2djZKSkoAACUlJXjmmWewZ88enD59GsnJyZgwYQKCgoIQGRkpyzFas7uCvQEAOxiAiIjIgsg+B2jSpEnIy8vDokWLkJ2djdDQUCQlJUkTo7OysqBWX8lpK1euRFVVFf7617+a7Wfx4sVYsmQJNBoNjhw5go8//hiFhYXw8/PDmDFj8PLLL0Or1XbosSnB3b29AAAHsi6jqLwaOgdbmSsiIiK6PpXg67wbMBgM0Ol0KCoq4nygFhj9VgpO5ZUi4W+3YlwILzMSEZE8WvP3W/ZLYGT5RvetG61L+rVljy4gIiKSGwMQ3bRxA+tGfZJP5KC8qvFnLREREXUmDEB000Ju0eEWdweUVdVie3rj73AjIiLqTBiA6KapVCpp7s93Ry7KXA0REdH1MQBRmxgf4gcA+PFEDorKqmWuhoiIqHkMQNQm+vu5oo/eBZU1Rmw8dE7ucoiIiJrFAERtQqVS4W9h3QAAn+/NAp+uQEREnRkDELWZ6MFd4WCrwcncEuw/c1nucoiIiJrEAERtxtXeFhNC6+YCrdr5h8zVEBERNY0BiNrUoyN7QKUCth7PQXp2sdzlEBERNYoBiNpUkLczxg7QAwDeT8mQuRoiIqLGMQBRm/v73UEAgP8evoDjFwwyV0NERNQQAxC1uQFddRgX4gshgFe+P847woiIqNNhAKJ28VxUH9hp1PgpIx9bj+fIXQ4REZEZBiBqF/4ejnh0ZCAA4MVNx/h0aCIi6lQYgKjdPD66F3p4OSG3uBJL//er3OUQERFJGICo3djbavDmA4OgVgEbD53HVwf4igwiIuocGICoXd3azR1PjO4NAHj+m6M4cq5Q3oKIiIjAAEQdYMGfghDR1xtVNUY8snY//sgrkbskIiJSOAYgandqtQrLJ4Wir68rLpVU4qEP9+JsQZncZRERkYIxAFGHcLW3xX9mDkMPLydcKKrA/St/xq8XiuQui4iIFIoBiDqMp7MWnz96O3r7OCO3uBIPJqYi6Vi23GUREZECMQBRh9Lr7LFhznCE9+iC0qpazPn0ABZuOoaK6lq5SyMiIgVhAKIOp3OwxcePDMNjd/YAAPxnzxmMeXsnkk/widFERNQxGIBIFnY2asTd2xcfPzIMeld7ZBWUYebH+zFtzT4czLosd3lERGTlVIJvqmzAYDBAp9OhqKgIrq6ucpdj9Uora/DOtpNYvSsTNca6X8eRvTwRE94do/p4Q6NWyVwhERFZgtb8/WYAagQDkDzO5JciYXsGvj54HrX1QchPZ4+/DvXHuIG+6O3jDJWKYYiIiBrHAHSTGIDklZVfhv/sOY0NB86h8KqXqPbwckJkfz1GBnni1gB32NtqZKySiIg6Gwagm8QA1DlUVNci6Vg2Nh+5gJ2/X0JVrVFap7VRY2h3dwwN8MAgfx1CbnGDp7NWxmqJiEhuDEA3iQGo8ymuqMa233KRkp6HnzIuIbe4skGfrm4O6OfniiBvZwR5OSPI2xk9vZ3hrLWRoWIiIupoDEA3iQGocxNCICO3BD+fysfhs4U4fK4Qf1wqRVO/yd4uWnR1d0BXNwd0dXfALfVffXUO8HLRwt3RjhOtiYisQGv+fvM/jcniqFQq9PJxQS8fF6mtuKIax84b8HtOMTJyS5CRW4KTuSW4VFKJ3OK65VBWYaP7U6sADyctPJ3t4OWihZezFp4uWrg52sLV3hY6hyuLq+mrvQ1sNHyKBBGRpeoUI0AJCQl44403kJ2djUGDBuHdd9/FsGHDmuy/YcMGLFy4EKdPn0avXr3w2muv4d5775XWCyGwePFifPDBBygsLMQdd9yBlStXolevXi2qhyNA1qOorBpnCkpx/nI5zheW41z91/OXy5FtqEBBadUN79tZawMXexs42mngpK3/amcDR60NHG01cNSaPtd/tdPA0c4GWhs1tLZqaG00Db63t61vs1EzYBERtZJFjQCtX78esbGxSExMRFhYGFasWIHIyEikp6fD29u7Qf+ff/4ZU6ZMQXx8PO677z58/vnniI6OxsGDBzFgwAAAwOuvv4533nkHH3/8MQIDA7Fw4UJERkbi+PHjsLe37+hDJBnpHG0R4uiGkFvcGl1fU2tEQWkVcosrcamkEpdKquq+FleiqLzabDHUfy2tqnttR0llDUoqa9qtdo1aJYUhrY0GWls17DR1wchWo4KtRg0bdf3X+s+2GhVs1PWf1WrY2tR9ttWo6raT+pv6qmBrU7cftUoFjfqq5arP6vrPNqbv6/vbXP295qp9qFTQaOq+qtWo31Zd9/01++ejDYhIDrKPAIWFheG2227De++9BwAwGo3w9/fHggUL8NxzzzXoP2nSJJSWlmLz5s1S2+23347Q0FAkJiZCCAE/Pz889dRTePrppwEARUVF8PHxwdq1azF58uTr1sQRIGpOda0RxRU1Uigqq6pFWVWN9LW0sv5rVS3Kq2pRWlm3rrSqBmWVtaisNaKyuhZVNUZU1hhRWVOLyuq676++001J1CpAraoLUCrpe1z5XB+y1Kq6S6AqwOyzWt3c9ub7uvqzusHnxreva7vSB3X/J9WiuuZz3XrVVe1Xfa7v0Oi6+n3gqnZ1/TYt2nf9ho3vt+G+G9sHmjquluzfdGIgfbnyM6XPMKvh6jZcb5tr+l+7Hk2ub7qGq/fb4tqb+Dm4bp1tXH+T56+JOhppb20NZsfbYNurzmUjdV3b7lI/xaAtWcwIUFVVFQ4cOIC4uDipTa1WIyIiAqmpqY1uk5qaitjYWLO2yMhIbNq0CQCQmZmJ7OxsRERESOt1Oh3CwsKQmpraaACqrKxEZeWVu4oMBsPNHBZZOVuNGh5OdvBwsmvzfRuNAlW1xvpAVCsFpIrqK2GpplagutaI6lqBGqMRNbV129TUf66uX19zVZ8rbXWfq2rMt601CtQaBYxCoKZWoFYIGI11X03rpPXGq9bVmvqgflsjjAJ1/a/a9rrHLeq2B2S/Ik9EHeTvd/fEs1F9ZPv5sgagS5cuoba2Fj4+PmbtPj4++O233xrdJjs7u9H+2dnZ0npTW1N9rhUfH4+lS5fe0DEQtSW1WgV7tab+IY9t+19GcjIa64OTKRRdFZ6MQgDiSggyCgEhfY/6z3Xfixb0MRrr+6KJPsYrbdJ+cfXnK30abF9/LKL++/rSYRpIF1f9XHHNZ9T3M60zXvU9zPbXcHtc9XOa3XcT+wDqjum6+77mmOo3vbJdE/tucB5gqgnXfDYPuFfWC/PPTbVLGza//np1oMn1TdXRyvqbqAMtrrPxOtDa7a5Zj9aer2vrb/DB/OPV58e8/er+Vz7YyHz3rexzgDqDuLg4s1Elg8EAf39/GSsisi5qtQp2fNQAEXUist5m4unpCY1Gg5ycHLP2nJwc6PX6RrfR6/XN9jd9bc0+tVotXF1dzRYiIiKyXrIGIDs7OwwZMgTJyclSm9FoRHJyMsLDwxvdJjw83Kw/AGzdulXqHxgYCL1eb9bHYDBg7969Te6TiIiIlEX2S2CxsbGIiYnB0KFDMWzYMKxYsQKlpaWYMWMGAGDatGno2rUr4uPjAQBPPPEE7rrrLrz11lsYN24c1q1bh/3792PVqlUA6maqP/nkk1i2bBl69eol3Qbv5+eH6OhouQ6TiIiIOhHZA9CkSZOQl5eHRYsWITs7G6GhoUhKSpImMWdlZUGtvjJQNXz4cHz++ed48cUX8fzzz6NXr17YtGmT9AwgAHj22WdRWlqK2bNno7CwECNGjEBSUhKfAUREREQAOsFzgDojPgeIiIjI8rTm7zeftU9ERESKwwBEREREisMARERERIrDAERERESKwwBEREREisMARERERIrDAERERESKwwBEREREisMARERERIoj+6swOiPTw7ENBoPMlRAREVFLmf5ut+QlFwxAjSguLgYA+Pv7y1wJERERtVZxcTF0Ol2zffgusEYYjUZcuHABLi4uUKlUbbpvg8EAf39/nD17lu8Zuw6eq5bjuWo5nquW47lqOZ6r1mmv8yWEQHFxMfz8/MxepN4YjgA1Qq1W45ZbbmnXn+Hq6sp/JC3Ec9VyPFctx3PVcjxXLcdz1Trtcb6uN/JjwknQREREpDgMQERERKQ4DEAdTKvVYvHixdBqtXKX0unxXLUcz1XL8Vy1HM9Vy/FctU5nOF+cBE1ERESKwxEgIiIiUhwGICIiIlIcBiAiIiJSHAYgIiIiUhwGoA6UkJCA7t27w97eHmFhYdi3b5/cJXW4JUuWQKVSmS19+vSR1ldUVGDevHno0qULnJ2dcf/99yMnJ8dsH1lZWRg3bhwcHR3h7e2NZ555BjU1NR19KG1u586dGD9+PPz8/KBSqbBp0yaz9UIILFq0CL6+vnBwcEBERAROnjxp1qegoABTp06Fq6sr3NzcMHPmTJSUlJj1OXLkCEaOHAl7e3v4+/vj9ddfb+9Da3PXO1fTp09v8HsWFRVl1kcp5yo+Ph633XYbXFxc4O3tjejoaKSnp5v1aat/dykpKbj11luh1WoRFBSEtWvXtvfhtamWnKu77767we/WnDlzzPoo4VytXLkSISEh0oMMw8PDsWXLFmm9RfxOCeoQ69atE3Z2dmLNmjXi119/FbNmzRJubm4iJydH7tI61OLFi0X//v3FxYsXpSUvL09aP2fOHOHv7y+Sk5PF/v37xe233y6GDx8ura+pqREDBgwQERER4tChQ+L7778Xnp6eIi4uTo7DaVPff/+9eOGFF8TGjRsFAPHNN9+YrX/11VeFTqcTmzZtEocPHxZ//vOfRWBgoCgvL5f6REVFiUGDBok9e/aIXbt2iaCgIDFlyhRpfVFRkfDx8RFTp04Vx44dE1988YVwcHAQ//73vzvqMNvE9c5VTEyMiIqKMvs9KygoMOujlHMVGRkpPvroI3Hs2DGRlpYm7r33XtGtWzdRUlIi9WmLf3d//PGHcHR0FLGxseL48ePi3XffFRqNRiQlJXXo8d6Mlpyru+66S8yaNcvsd6uoqEhar5Rz9d///ld899134vfffxfp6eni+eefF7a2tuLYsWNCCMv4nWIA6iDDhg0T8+bNkz7X1tYKPz8/ER8fL2NVHW/x4sVi0KBBja4rLCwUtra2YsOGDVLbiRMnBACRmpoqhKj7w6dWq0V2drbUZ+XKlcLV1VVUVla2a+0d6do/6kajUej1evHGG29IbYWFhUKr1YovvvhCCCHE8ePHBQDxyy+/SH22bNkiVCqVOH/+vBBCiPfff1+4u7ubnat//vOfIjg4uJ2PqP00FYAmTJjQ5DZKPVdCCJGbmysAiB07dggh2u7f3bPPPiv69+9v9rMmTZokIiMj2/uQ2s2150qIugD0xBNPNLmNUs+VEEK4u7uLDz/80GJ+p3gJrANUVVXhwIEDiIiIkNrUajUiIiKQmpoqY2XyOHnyJPz8/NCjRw9MnToVWVlZAIADBw6gurra7Dz16dMH3bp1k85TamoqBg4cCB8fH6lPZGQkDAYDfv311449kA6UmZmJ7Oxss3Oj0+kQFhZmdm7c3NwwdOhQqU9ERATUajX27t0r9bnzzjthZ2cn9YmMjER6ejouX77cQUfTMVJSUuDt7Y3g4GDMnTsX+fn50joln6uioiIAgIeHB4C2+3eXmppqtg9TH0v+37hrz5XJZ599Bk9PTwwYMABxcXEoKyuT1inxXNXW1mLdunUoLS1FeHi4xfxO8WWoHeDSpUuora01+380APj4+OC3336TqSp5hIWFYe3atQgODsbFixexdOlSjBw5EseOHUN2djbs7Ozg5uZmto2Pjw+ys7MBANnZ2Y2eR9M6a2U6tsaO/epz4+3tbbbexsYGHh4eZn0CAwMb7MO0zt3dvV3q72hRUVH4y1/+gsDAQJw6dQrPP/88xo4di9TUVGg0GsWeK6PRiCeffBJ33HEHBgwYAABt9u+uqT4GgwHl5eVwcHBoj0NqN42dKwD429/+hoCAAPj5+eHIkSP45z//ifT0dGzcuBGAss7V0aNHER4ejoqKCjg7O+Obb75Bv379kJaWZhG/UwxA1KHGjh0rfR8SEoKwsDAEBATgyy+/tJh/9NT5TZ48Wfp+4MCBCAkJQc+ePZGSkoLRo0fLWJm85s2bh2PHjmH37t1yl9LpNXWuZs+eLX0/cOBA+Pr6YvTo0Th16hR69uzZ0WXKKjg4GGlpaSgqKsJXX32FmJgY7NixQ+6yWoyXwDqAp6cnNBpNgxnwOTk50Ov1MlXVObi5uaF3797IyMiAXq9HVVUVCgsLzfpcfZ70en2j59G0zlqZjq253yG9Xo/c3Fyz9TU1NSgoKFD8+evRowc8PT2RkZEBQJnnav78+di8eTO2b9+OW265RWpvq393TfVxdXW1uP+4aepcNSYsLAwAzH63lHKu7OzsEBQUhCFDhiA+Ph6DBg3Cv/71L4v5nWIA6gB2dnYYMmQIkpOTpTaj0Yjk5GSEh4fLWJn8SkpKcOrUKfj6+mLIkCGwtbU1O0/p6enIysqSzlN4eDiOHj1q9sdr69atcHV1Rb9+/Tq8/o4SGBgIvV5vdm4MBgP27t1rdm4KCwtx4MABqc+2bdtgNBql/5EODw/Hzp07UV1dLfXZunUrgoODLfKSTkudO3cO+fn58PX1BaCscyWEwPz58/HNN99g27ZtDS7rtdW/u/DwcLN9mPpY0v/GXe9cNSYtLQ0AzH63lHCuGmM0GlFZWWk5v1NtMpWarmvdunVCq9WKtWvXiuPHj4vZs2cLNzc3sxnwSvDUU0+JlJQUkZmZKX766ScREREhPD09RW5urhCi7tbJbt26iW3bton9+/eL8PBwER4eLm1vunVyzJgxIi0tTSQlJQkvLy+ruA2+uLhYHDp0SBw6dEgAEMuXLxeHDh0SZ86cEULU3Qbv5uYmvv32W3HkyBExYcKERm+DHzx4sNi7d6/YvXu36NWrl9mt3YWFhcLHx0c8/PDD4tixY2LdunXC0dHR4m7tbu5cFRcXi6efflqkpqaKzMxM8eOPP4pbb71V9OrVS1RUVEj7UMq5mjt3rtDpdCIlJcXs1u2ysjKpT1v8uzPdsvzMM8+IEydOiISEBIu7tft65yojI0O89NJLYv/+/SIzM1N8++23okePHuLOO++U9qGUc/Xcc8+JHTt2iMzMTHHkyBHx3HPPCZVKJX744QchhGX8TjEAdaB3331XdOvWTdjZ2Ylhw4aJPXv2yF1Sh5s0aZLw9fUVdnZ2omvXrmLSpEkiIyNDWl9eXi7+/ve/C3d3d+Ho6CgmTpwoLl68aLaP06dPi7FjxwoHBwfh6ekpnnrqKVFdXd3Rh9Lmtm/fLgA0WGJiYoQQdbfCL1y4UPj4+AitVitGjx4t0tPTzfaRn58vpkyZIpydnYWrq6uYMWOGKC4uNutz+PBhMWLECKHVakXXrl3Fq6++2lGH2GaaO1dlZWVizJgxwsvLS9ja2oqAgAAxa9asBv+xoZRz1dh5AiA++ugjqU9b/bvbvn27CA0NFXZ2dqJHjx5mP8MSXO9cZWVliTvvvFN4eHgIrVYrgoKCxDPPPGP2HCAhlHGuHnnkEREQECDs7OyEl5eXGD16tBR+hLCM3ymVEEK0zVgSERERkWXgHCAiIiJSHAYgIiIiUhwGICIiIlIcBiAiIiJSHAYgIiIiUhwGICIiIlIcBiAiIiJSHAYgIup0VCoVNm3a1Kb7zM/Ph7e3N06fPt2m++1skpKSEBoaCqPRKHcpRJ0aAxARSaZPnw6VStVgiYqKkru0m/bKK69gwoQJ6N69uyw/f+fOnRg/fjz8/PyaDHhCCCxatAi+vr5wcHBAREQETp48adanoKAAU6dOhaurK9zc3DBz5kyUlJRI66OiomBra4vPPvusvQ+JyKIxABGRmaioKFy8eNFs+eKLL+Qu66aUlZVh9erVmDlzZrv/rKqqqkbbS0tLMWjQICQkJDS57euvv4533nkHiYmJ2Lt3L5ycnBAZGYmKigqpz9SpU/Hrr79i69at2Lx5M3bu3InZs2eb7Wf69Ol455132uaAiKxVm71Ug4gsXkxMjJgwYUKzfQCI999/X0RFRQl7e3sRGBgoNmzYYNbnyJEjYtSoUcLe3l54eHiIWbNmNXjP1urVq0W/fv2EnZ2d0Ov1Yt68eWY/44MPPhDR0dHCwcFBBAUFiW+//VZaX1BQIP72t78JT09PYW9vL4KCgsSaNWuarHnDhg3Cy8vLrM30PrHNmzeLgQMHCq1WK8LCwsTRo0fN+u3atUuMGDFC2Nvbi1tuuUUsWLBAlJSUSOsDAgLESy+9JB5++GHh4uIivbvteufwm2++MWszGo1Cr9eLN954Q2orLCwUWq1WfPHFF0IIIY4fPy4AiF9++UXqs2XLFqFSqcT58+eltjNnzggAZu/ZIyJzHAEiolZbuHAh7r//fhw+fBhTp07F5MmTceLECQB1Ix2RkZFwd3fHL7/8gg0bNuDHH3/E/Pnzpe1XrlyJefPmYfbs2Th69Cj++9//IigoyOxnLF26FA8++CCOHDmCe++9F1OnTkVBQYH0848fP44tW7bgxIkTWLlyJTw9PZusd9euXRgyZEij65555hm89dZb+OWXX+Dl5YXx48ejuroaAHDq1ClERUXh/vvvx5EjR7B+/Xrs3r3b7FgA4M0338SgQYNw6NAhLFy4sPUnFEBmZiays7MREREhtel0OoSFhSE1NRUAkJqaCjc3NwwdOlTqExERAbVajb1790pt3bp1g4+PD3bt2nVDtRApgtwJjIg6j5iYGKHRaISTk5PZ8sorr0h9AIg5c+aYbRcWFibmzp0rhBBi1apVwt3d3WyU5LvvvhNqtVp6I7ufn5944YUXmqwDgHjxxRelzyUlJQKA2LJlixBCiPHjx4sZM2a0+LgmTJggHnnkEbM20wjQunXrpLb8/Hzh4OAg1q9fL4QQYubMmWL27Nlm2+3atUuo1WpRXl4uhKgbAYqOjm5xLabju3YE6KeffhIAxIULF8zaH3jgAfHggw8KIYR45ZVXRO/evRvsz8vLS7z//vtmbYMHDxZLlixpVV1ESmIjZ/gios5n1KhRWLlypVmbh4eH2efw8PAGn9PS0gAAJ06cwKBBg+Dk5CStv+OOO2A0GpGeng6VSoULFy5g9OjRzdYREhIife/k5ARXV1fk5uYCAObOnYv7778fBw8exJgxYxAdHY3hw4c3ua/y8nLY29s3uu7qY/Hw8EBwcLA0mnX48GEcOXLEbEKxEAJGoxGZmZno27cvAJiNyHQWDg4OKCsrk7sMok6LAYiIzDg5OTW4HNWWHBwcWtTP1tbW7LNKpZJu7R47dizOnDmD77//Hlu3bsXo0aMxb948vPnmm43uy9PTE5cvX251rSUlJXjsscfw+OOPN1jXrVs36furw96N0uv1AICcnBz4+vpK7Tk5OQgNDZX6mEKgSU1NDQoKCqTtTQoKCuDl5XXTdRFZK84BIqJW27NnT4PPptGQvn374vDhwygtLZXW//TTT1Cr1QgODoaLiwu6d++O5OTkm6rBy8sLMTEx+PTTT7FixQqsWrWqyb6DBw/G8ePHr3ssly9fxu+//y4dy6233orjx48jKCiowWJnZ3dT9V8rMDAQer3e7LwYDAbs3btXGqUKDw9HYWEhDhw4IPXZtm0bjEYjwsLCpLaKigqcOnUKgwcPbtMaiawJR4CIyExlZSWys7PN2mxsbMwmGW/YsAFDhw7FiBEj8Nlnn2Hfvn1YvXo1gLrbtBcvXoyYmBgsWbIEeXl5WLBgAR5++GH4+PgAAJYsWYI5c+bA29sbY8eORXFxMX766ScsWLCgRTUuWrQIQ4YMQf/+/VFZWYnNmzdLoaUxkZGRiIuLw+XLl+Hu7m627qWXXkKXLl3g4+ODF154AZ6enoiOjgYA/POf/8Ttt9+O+fPn49FHH4WTkxOOHz+OrVu34r333mtRrSYlJSXIyMiQPmdmZiItLQ0eHh7o1q0bVCoVnnzySSxbtgy9evVCYGAgFi5cCD8/P6mevn37IioqCrNmzUJiYiKqq6sxf/58TJ48GX5+ftK+9+zZA61W2+BSJRFdRe5JSETUecTExAgADZbg4GCpDwCRkJAg7rnnHqHVakX37t2lScMmLbkNPjExUQQHBwtbW1vh6+srFixYYPYzrp0krNPpxEcffSSEEOLll18Wffv2FQ4ODsLDw0NMmDBB/PHHH80e27Bhw0RiYqL02TQJ+n//+5/o37+/sLOzE8OGDROHDx82227fvn3innvuEc7OzsLJyUmEhISYTQoPCAgQb7/9drM/++qfd+1y9W3zRqNRLFy4UPj4+AitVitGjx4t0tPTzfaTn58vpkyZIpydnYWrq6uYMWNGg3M7e/Zs8dhjj123JiIlUwkhhCzJi4gskkqlwjfffCONSliK7777Ds888wyOHTsGtVqNlJQUjBo1CpcvX4abm5vc5bWZS5cuITg4GPv370dgYKDc5RB1WrwERkSKMG7cOJw8eRLnz5+Hv7+/3OW0m9OnT+P9999n+CG6DgYgIlKMJ598Uu4S2t3QoUM75W35RJ0NL4ERERGR4vA2eCIiIlIcBiAiIiJSHAYgIiIiUhwGICIiIlIcBiAiIiJSHAYgIiIiUhwGICIiIlIcBiAiIiJSHAYgIiIiUpz/Dz7HtAVxqPtjAAAAAElFTkSuQmCC\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