Files
pyRBM/context33.ipynb
T
jensandClaude Sonnet 4.6 bbc03d37e1 [context33] - 200-char sentence, auto-uppercase, adaptive tick spacing
SENTENCE now accepts mixed case and strips non-vocab chars automatically.
Extended to ~200 chars using the Moby Dick opening passage.
Visualisation cells use adaptive tick spacing (max 40 labels) to handle
longer sequences without crowding.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-31 16:15:01 +02:00

510 lines
79 KiB
Plaintext

{
"cells": [
{
"cell_type": "code",
"id": "c33-0001",
"metadata": {
"execution": {
"iopub.execute_input": "2026-05-31T13:42:50.031812Z",
"iopub.status.busy": "2026-05-31T13:42:50.031636Z",
"iopub.status.idle": "2026-05-31T13:42:50.946668Z",
"shell.execute_reply": "2026-05-31T13:42:50.945911Z"
},
"ExecuteTime": {
"end_time": "2026-05-31T13:57:38.398527610Z",
"start_time": "2026-05-31T13:57:37.908008067Z"
}
},
"source": [
"# context33.prj → pyRBM\n",
"#\n",
"# Architecture: shared-weights StackRnn (1 entity, reused every time step)\n",
"# visible = [context(128) | x_t(40)] = 168 hidden = 128\n",
"#\n",
"# All hyperparameters taken verbatim from context33.prj.\n",
"# Training data: 20-character sentence, encoded with the moby vocabulary.\n",
"\n",
"import numpy as np_cpu\n",
"import matplotlib.pyplot as plt\n",
"from rbm.stack_rnn import StackRnn\n",
"from rbm.matrix import np, convert\n",
"from rbm.entity import EntityParams, TrainingParams\n",
"from rbm.status import CheckpointStatus"
],
"outputs": [],
"execution_count": 1
},
{
"cell_type": "code",
"id": "c33-0002",
"metadata": {
"execution": {
"iopub.execute_input": "2026-05-31T13:42:50.949289Z",
"iopub.status.busy": "2026-05-31T13:42:50.948998Z",
"iopub.status.idle": "2026-05-31T13:42:50.953268Z",
"shell.execute_reply": "2026-05-31T13:42:50.952461Z"
},
"ExecuteTime": {
"end_time": "2026-05-31T13:57:38.447434185Z",
"start_time": "2026-05-31T13:57:38.399226980Z"
}
},
"source": [
"# ── Config from context33.prj ──────────────────────────────────────────────\n",
"SENSORY_SIZE = 40 # numVisibleX * numVisibleY = 1 * 40\n",
"CONTEXT_SIZE = 128 # numContext = numHidden\n",
"LEARNING_RATE = 0.05 # learningRate\n",
"MOMENTUM = 0.5 # momentum\n",
"NUM_EPOCHS = 1000 # numEpochs\n",
"MINI_BATCH = 100 # miniBatchSize\n",
"NUM_GIBBS = 3 # numGibbs\n",
"RAO_BLACKWELL = True # doRaoBlackwell\n",
"L2_LAMBDA = 0.0 # weightDecay\n",
"PRJ_NAME = \"context33\"\n",
"WORK_DIR = \"results\"\n",
"\n",
"# Vocabulary (40 chars, matching numVisibleY=40 in context33.prj)\n",
"# Same encoding as moby_rnn.ipynb\n",
"ALLOWED = set(' .!?ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789')\n",
"chars = sorted(ALLOWED)\n",
"idx_to_char = {i: c for i, c in enumerate(chars)}\n",
"char_to_idx = {c: i for i, c in enumerate(chars)}"
],
"outputs": [],
"execution_count": 2
},
{
"cell_type": "code",
"id": "c33-0003",
"metadata": {
"execution": {
"iopub.execute_input": "2026-05-31T13:42:50.955004Z",
"iopub.status.busy": "2026-05-31T13:42:50.954814Z",
"iopub.status.idle": "2026-05-31T13:42:50.959397Z",
"shell.execute_reply": "2026-05-31T13:42:50.958632Z"
},
"ExecuteTime": {
"end_time": "2026-05-31T13:57:38.505581964Z",
"start_time": "2026-05-31T13:57:38.448366492Z"
}
},
"source": "# ── Training sentence ──────────────────────────────────────────────────────\nSENTENCE = (\n \"Call me Ishmael. Some years ago, never mind how long precisely, \"\n \"having little money in my pocket and nothing particular to interest \"\n \"me on shore, I thought I would sail about a little.\"\n)\n\n# Convert to uppercase, keep only in-vocab characters\nSENTENCE = ''.join(c for c in SENTENCE.upper() if c in ALLOWED)\nN_SAMPLES = len(SENTENCE)\n\nsensory_np = np_cpu.zeros((N_SAMPLES, SENSORY_SIZE), dtype=np_cpu.float64)\nfor i, c in enumerate(SENTENCE):\n sensory_np[i, char_to_idx[c]] = 1.0\n\ndecoded = SENTENCE\nprint(f\"Sentence : '{decoded}'\")\nprint(f\"Length : {N_SAMPLES} chars\")",
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Sentence : 'CALL ME ISHMAEL. SOME YEARS AGO NEVER MIND HOW LONG PRECISELY HAVING LITTLE MONEY IN MY POCKET AND NOTHING PARTICULAR TO INTEREST ME ON SHORE I THOUGHT I WOULD SAIL ABOUT A LITTLE.'\n",
"Length : 180 chars\n"
]
}
],
"execution_count": 3
},
{
"cell_type": "code",
"id": "c33-0004",
"metadata": {
"execution": {
"iopub.execute_input": "2026-05-31T13:42:50.961020Z",
"iopub.status.busy": "2026-05-31T13:42:50.960862Z",
"iopub.status.idle": "2026-05-31T13:42:51.208274Z",
"shell.execute_reply": "2026-05-31T13:42:51.207444Z"
},
"ExecuteTime": {
"end_time": "2026-05-31T13:57:38.858778350Z",
"start_time": "2026-05-31T13:57:38.506823556Z"
}
},
"source": "# ── Visualise one-hot encoding ─────────────────────────────────────────────\nstep = max(1, N_SAMPLES // 40) # show at most 40 tick labels\ntick_pos = range(0, N_SAMPLES, step)\n\nplt.figure(figsize=(16, 3))\nplt.imshow(sensory_np.T, aspect='auto', cmap='Blues', vmin=0, vmax=1)\nplt.colorbar(label='activation')\nplt.xlabel('Position')\nplt.ylabel('Vocab index')\nplt.title(f'One-hot encoding ({N_SAMPLES} chars)')\nplt.xticks(tick_pos, [decoded[i] for i in tick_pos], fontsize=8)\nplt.tight_layout()\nplt.show()",
"outputs": [
{
"data": {
"text/plain": [
"<Figure size 1600x300 with 2 Axes>"
],
"image/png": "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6tSpY5uNLklNmza1Hc9JTEyMpKvPWX545JFHVKJECT366KN2y2DkdRmXTMYY/fTTT/rpp5/08ssva+jQoRo7dqxat25t99oKCwvT5cuX9Z///Cdf4gcAAEDBwLIVAADA7d555x1dvHhRn3zySZZE4PXXX6+PP/5YFy5c0DvvvOP0tRcuXKiMjAyNGDEi2+OZ/cXGxmrVqlW2sm7dOqf7+uGHH9S0aVPdddddtrpSpUqpT58+io2N1a5duyRdXQdZksqUKZPrNa9cuaIFCxaoU6dOuvXWW7Mcd2UN2S1btigmJkaDBg3KsjxBphMnTmjr1q3q3r27XZtbb71VDzzwgH744QdbfMuXL1eHDh1044032trVrl1bDz74oNOx5WTVqlVKT0/XP//5T7v6/v37X9N1o6OjVa9ePQUEBLh0/v79+3X58mU9+eSTdvVVqlRRy5YttXXrVlvd4sWLlZaWpsjISLu2ffv21dGjRx2+5hITE/XLL7+oV69eduPsqsyZyX+d2R0cHKyePXvm+RrZzdjOTID/fXmOxo0ba+fOnUpKSnIhWgAAABRUzDwGAABut3//fnXv3l2zZ8/Wjh07NH36dMXGxuqmm25S7969Vb58eXXt2tU2+9IZMTExGj58uMaPH6+bbrpJixYtUnJyssLCwtSxY0dNmzZN7777br7cx/jx49W1a1ctXbpU77//vk6fPq3u3bsrLCxMnTp1ss04PnDggM6cOaO+ffsqOTlZFy5c0Pr16+1m1P7VkCFD1Lp1a61fv16ffvqpdu3apbJly6pRo0a67777VK5cOafiNMbon//8p5YsWaJt27YpKipKx48fV+3atXXrrbeqTZs2kqTBgwdr6dKlio6O1vTp01WyZEkNGDBA586ds1viY8SIEWrTpo3Wrl2rDz/8UP7+/howYIB27typ+vXruzSWf5eQkKD33ntPr7zyihYvXqxly5apfv36euihh3Ty5EmX19JdvHix3nzzTYWHh2vFihV2x/r166cyZcqocuXKkq7O1r3hhhskXd2oLykpSYmJifr888/13HPPadWqVVq4cKGCgoIUGRmpkiVL2tYQlqS4uDhNnjxZr776qooVK6aNGzeqQ4cOuueee9StWze7ZR6y88ILL+jXX3/Vli1bNG3aNNt7pF27dmrYsKFT9/3jjz8qNTVVS5Ys0SeffKLrrrtO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fHguAd/GdwEABQGfRQAKGovFIouDDLGjYwXF3r17VatWLR06dEjbt2/X888/r4MHD6pv3746fvy4S9f0avL474s39+jRQydPnlTjxo21du1aBQcHq3fv3urWrZt+/vlnSVLPnj21Z88eNW3aVOvXr/dG2AAAAAAAAACKED+LRX4OEsSOjhUU7733nipVqiRJGjlypJYtW6annnpKaWlp6tGjh0vXvKbk8Q033CBJOnr06LVcxqZ06dKSpNOnT0uSGjdurICAAK1cudLWZu/evTp06JCaNWuWbfI4ICBAxYsXtz0OCgrKl9gAAAAAAAAAFE0Wi2Qt5BvmzZ492/bzli1bVK1aNdWuXVuHDx/WqVOnXLqm02se+/n5adSoUTp79qwOHjyogwcP6uzZsxo9erT8/V3PRVssFk2ePFm//vqrdu7cKUkKDQ1Vamqqzp07Z9c2Pj5eoaGh2V5n6NChSkpKspW4uDiXYwIAAAAAAABQ9FktuZeCrkWLFnaPL126pK1bt7qcOJZcSB5/8MEH6tOnj1599VU1bNhQDRs21KuvvqrevXvr/fffdzmQqVOnql69eurSpYvL15CkcePGKTg42FaqVKlyTdcDAAAAAAAAULRlrnnsqBR0P/30k2JiYvT222+rTp06+XJNp6cKd+vWTV26dNGyZctsdTt27NCRI0c0Z84cRUZGOh3EBx98oIcfflj33HOP3UzhEydOqHjx4ipdurTd7OOQkBCdOHEi22ulpaUpLS3N6RgAAAAAAAAA+CY/69Xi6HhBV7lyZXXp0kVdu3bVkCFD9Mcff2j27NmaM2eOy6szWCQZZ06Ij49XeHi49uzZY1dfu3ZtrVmzRhUrVnQqgA8++EAdO3ZUq1attH//frtjwcHBOnnypLp27aqFCxdKkm655Rbt3btXd911V542zAsKClJSUpJSMpwKq0jLaVdbdrQF3IsdpcFrAIAr+OwACpei+p715H0V1TEEPKWE/9WcWnJysrdDKRQyc4cjftyv1IwrObYr7m/VyAdqFpqxvemmm9StWzd17drVlreNiIhw+jpO58ynTJmiN954QwEBAba6gIAAvf7665oyxbkP8alTp+rpp59Wt27dlJycrJCQEIWEhKhEiRKSpKSkJE2fPl0TJ05Uq1at1KhRI0VFRWndunV5ShwDAAAAAAAAQG6seSiFycGDBzV+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uHFjBQQEaOXKlbY2e/fu1aFDh9SsWbMcrxMQEKCgoCC7AgAAAAAAAAA5seThP1/k9eRxvXr1lJycrNTUVH388cfq2LGjdu/erdDQUKWmpurcuXN27ePj4xUaGprj9YYOHaqkpCRbiYuLc/ctAAAAAAAAACjMLP/bNC+74qO5Y+8nj/fu3asGDRqoadOm+uijjzRz5kzVqVPH5euNGzdOwcHBtlKlSpV8jBYAAAAAAABAUcOGednz93YA6enpOnDggCRpy5YtatKkiQYOHKh58+apePHiKl26tN3s45CQEJ04cSLH66WlpSktLc3tcQMAAAAAAAAoInLLDvto9tjryeO/s1qtKl68uDZv3qy0tDRFRERo4cKFkqRbbrlF1apVU3R0tJejBPLX9U3653jszMYpHoyk4GOsig6eSwAo+gr7Z31O8ReG2F3li/dcEBT29woAFAVWi+PssNVHk8deXbZi7NixatmypapVq6Z69epp7NixatWqlWbPnq2kpCRNnz5dEydOVKtWrdSoUSNFRUVp3bp1Wr9+vTfDBgAAAAAAAFCEuGvZisjISMXGxurSpUv6/fff1aRJkxzb/uMf/9CaNWt0+vRpnT59WitWrHDY3hO8mjyuWLGivvjiC+3du1erVq1SkyZN9OCDD2rlypWSpBdffFHfffedFixYoDVr1ujEiRN67LHHvBkyAAAAAAAAgKLGDdnjzp07a+LEiRo5cqQaNWqk7du3a/ny5apQoUK27Vu1aqU5c+aodevWatasmY4cOaIff/xRlStXdvGmrp1Xl634xz/+4fB4amqq+vfvr/79c/4nPAAAAAAAAABwLSyyOMwPuzLz+KWXXtKnn36qGTNmSJL69u2rdu3aqVevXpowYUKW9k8//bTd43/84x/q1KmTIiIiNGvWLBciuHZenXkMAAAAAAAAAN5mteReJCkoKMiuBAQEZHu9YsWKqXHjxrYVFiTJGKOVK1eqWbNmeYqpVKlSKlasmE6fPn3N9+eqArdhHvJHUd1woajel6PYi+o9u8oX77mo8uRzyfsIALyjsH/GFvb4XeHKPfvi79n8vueiOk5wPza5BPJRblOL/3s8Li7Orvqtt97SyJEjszQvX768/P39FR8fb1cfHx+v2rVr5ymkCRMm6NixY3YJaE8jeQwAAAAAAADAp+V12YoqVaooOTnZVp+amuqW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mUWLFrkt0VRUx84bY+ipvmJjY82zzz5rjhw5YkqWLGkkzySPJZnff//dPP7444X6vmrWrGkuXLhgypYta1f/0EMPmUOHDhXavnJ6ztavX286derklr5y6tMd5cEHHzR//vmnqVmzpjl69Kjb/jLS39/fxMfH2yXopk6dat555x233p+niqeSx5GRkea7774zkkxwcLDZt2+fGTVqVL4njz352vBG8eT72ZPJ46L2We/J+/pr8cT3Dk9/r/fk9w5PlqKYiPR0qV+/vjlx4oS57rrreM5cKDVr1jTnz583119/vcefu6KWPPb0a9ETheQxhVKwik8sW9GoUSPt27dPp06d8nYohVqdOnV04403avny5Zo+fbp69+7t7ZDyzbx58+z+CViJEiXc0o8nx9DTz9f27dv1888/68UXX3RrP39Vq1YtlStXTqtXr3ZbH564r4YNG2rfvn06ffq0XX10dLSqVq2q8uXLF8q+slOvXj3Vrl1b27dvd2s/nrB8+XKtXbtWGzdu1KhRoxQbG+uWfjIyMjRr1iz16tVLklS8eHF17dpV06dPd0t/RdVvv/2mm266SZUqVVLXrl311Vdf6fLly27py1OvDW/zxPvZU7+fi9pnfSZP/m721PcOb36v98T3Dk/y1PurqPrjjz/066+/6tChQ1q4cKFeeeUVVa5c2a19FqXnrGHDhtq/f7/OnDnj7VAKPW+8FgH4Fp9IHiN/9O7dW1988YWuXLmiH374QWFhYapdu7a3w8oXTz75pBo2bGgrKSkpbunHk2PojefrjTfe0MCBA1W2bFm39jNv3jzt2rVLu3bt0gcffKDExES39uep+yrKMv+w88knn6hXr17av3+/t0PKF++8846sVqumTZvm1n6mT5+up556SsWKFdNjjz2m3bt3a8+ePW7tsyiaNWuWevTooV69eunzzz93a1+eem14gyffz576/SwV3c96T91XUf6e6OnvHZ7iyfdXUWSM0eOPP67mzZtr2bJlatGihXbu3KkaNWq4rc+i/JxVr17dtra4u39He4sxxm3X9fRr0VvcNYYAHPOJ5PGWLVt08803F7k/DHiSv7+/nnnmGXXv3l2xsbHav3+/SpUqVaRmH7ubJ8fQW8/XoUOH9OWXX2r48OFu7efJJ59U3bp19cADD2j8+PFu3eBQcv99bd26NdvPqGbNmunw4cP5+odUT/b1V5l/2GnRooUWLFjglj684fLly7py5Yrb+9m9e7f279+vRx55RL169WLWsYu++OILvfDCC0pJSXH7X2B46rXhDUX1/VyUPuv/yhO/mz35vcMb3+s9/b0DhcvevXs1bdo0dezYUb///rseffRRb4dUKGzdulU1a9ZUmTJlJEkxMTFq2LChxo0bp+uvv967wV2jhIQElStXzq6ufPnySkhIcGu/Rem16K0xBJA9n0geHzhwQAsWLND06dPtdux87LHHFBYW5sXICo9HH31UMTExuuGGGxQWFqawsDDdddddeuaZZ+x2r0fOPDmG3ny+xowZo6efftoj/1Rq1apV+uijjzRmzBi39+XO+9q/f7+WLFmiadOmqWTJkpKkatWq6d1339Xo0aMLbV/IX9OnT9ewYcN05513at68ed4Op1A6fvy4hg4dqtdee83boaCAKiqf9X/n7t/Nnvze4c3v9Z783oGCr3LlymrevLntcZkyZRQWFqYDBw54MarCY//+/Vq8eHGW93JgYKAXo8ofy5cv1/PPP297/MwzzygmJkYnTpxwS39F8bXo6TEE4JhPJI8lqVevXtq+fbvWr1+vP//8U7t27dIDDzyQZd05ZK93796aPXu2Xd2ePXsUFxenRx55xEtR5Z+/rx/WqlWrfO/Dk2Pozefr1KlTev/99z22ztbo0aN19913q1GjRm7tx9339eyzzyomJkY7duzQrl279N133+mdd97RZ599Vqj7Qv6ZN2+eatWqpa+++koXLlzwdjiF1owZM/T77797OwzkkSd+P/9VUfqs/yt335env3d483u9p753eIKn319Fjb+/v958803t3btXW7du1dq1azVz5kx9++23buuzqD1nPXr00I4dO2zv5bVr1+q+++7ThAkTvB3aNRk0aJAqVaqk7du3a+vWrerWrZueeOIJt/Xnjdeiu3l6DAE4ZtHVnfMAAAAAAAAAALDxmZnHAAAAAAAAAIC8I3kMAAAAAAAAAMiC5DEAAAAAAAAAIAuSxwAAAAAAAACALEgeAwAAAAAAAACyIHkMAAAAAAAAAMiC5DEAAAAAAAAAIAuSxwAAAMg34eHhMsaodOnSDtvFxsZq4MCBHooKAAAAgCtIHgMAAPigqKgoGWNkjFFqaqr27dunN954Q35+ftd03XXr1ik0NFTnzp2TJHXv3l1nzpzJ0q5JkyaaNm3aNfUFAAAAwL38vR0AAAAAvGPp0qXq2bOnihcvrrZt22rq1KlKT0/X+PHjXb5menq64uPjc22XmJjoch8AAAAAPIOZxwAAAD4qNTVV8fHxOnz4sD7++GOtXLlSjz76qMqUKaOZM2fq9OnTunDhgn744QfVrFnTdl7VqlX17bff6vTp0zp//rz+/PNPPfTQQ5Lsl60IDw/XjBkzVKZMGdss5xEjRkjKumzFjTfeqEWLFik5OVnnzp3TvHnzVLFiRdvxESNGaOvWrXr66acVGxurs2fPas6cObruuus8NFoAAACA7yF5DAAAAEnSpUuXFBAQoBkzZuiOO+7Qo48+qmbNmsliseiHH36Qv//Vf7Q2depUFS9eXPfcc49uu+02vfbaazp//nyW661bt04DBw7UuXPnFBoaqtDQUP3rX//K0s5isWjx4sUqW7aswsPDdf/996t69eqaN2+eXbsaNWqoQ4cOevjhh/Xwww8rPDxcQ4YMcc9gAAAAAGDZCgAAAEgRERF68MEHtXTpUnXs2FHNmzdXdHS0JOmpp57SkSNH1KFDB3399deqWrWqFixYoD///FPS1VnE2UlPT9e5c+dkjHG4lEVERIRuu+02hYWF6ejRo5KkZ599Vrt27dIdd9yhTZs2SZKsVqt69OhhS1TPmjVLERERGj58eL6NAwAAAID/YeYxAACAj3r44YeVnJyslJQULV26VPPmzdOMGTOUnp6u9evX29qdPn1ae/fuVZ06dSRJ77//voYPH65ff/1Vb731lm677bZriqNOnTo6cuSILXEsSbt379aZM2dsfUrSwYMH7WY4Hz9+3G5pCwAAAAD5i+QxAACAj/r555/VoEED3XzzzSpZsqR69OghY0yu502fPl3Vq1fXrFmzdNttt2nTpk3q37+/2+NNT0+3e2yMkdXK11kAAADAXfi2DQAA4KMuXLigAwcO6MiRI7p8+bKkqzN+ixUrpqZNm9ralS1bVrVq1dKuXbtsdUePHtUnn3yiTp066d1339Vzzz2XbR9paWny8/NzGMfu3bt144036oYbbrDV1alTR9dff71dnwAAAAA8i+QxAAAAbPbv369Fixbp008/VYsWLXT77bfr3//+t+Li4rR48WJJ0qRJk/TAAw/opptuUsOGDdW6dWvt3r072+sdPHhQQUFBuvfee1WuXDmVLFkyS5uVK1dqx44dmj17tho2bKgmTZroiy++0OrVq7V582a33i8AAACAnJE8BgAAgJ2ePXtq8+bN+u677xQdHS2LxaK2bdsqIyNDkuTn56epU6dq9+7dWrZsmf7zn/8oMjIy22tFR0fro48+0rx585SYmKhXX30123bt27fXmTNntGbNGq1cuVIxMTF68skn3XaPAAAAAHJnkZT7wnYAAAAAAAAAAJ/CzGMAAAAAAAAAQBYkjwEAAAAAAAAAWZA8BgAAAAAAAABkQfIYAAAAAAAAAJAFyWMAAAAAAAAAQBYkjwEAAAAAAAAAWZA8BgAAAAAAAABkQfIYAAAAAAAAAJAFyWMAAAAAAAAAQBYkjwEAAAAAAAAAWZA8BgAAAAAAAABkQfIYAAAAAAAAAJDF/wPj7l1jjhTaQgAAAABJRU5ErkJggg=="
},
"metadata": {},
"output_type": "display_data",
"jetTransient": {
"display_id": null
}
}
],
"execution_count": 4
},
{
"cell_type": "code",
"id": "c33-0005",
"metadata": {
"execution": {
"iopub.execute_input": "2026-05-31T13:42:51.209939Z",
"iopub.status.busy": "2026-05-31T13:42:51.209737Z",
"iopub.status.idle": "2026-05-31T13:42:51.213230Z",
"shell.execute_reply": "2026-05-31T13:42:51.212592Z"
},
"ExecuteTime": {
"end_time": "2026-05-31T13:57:38.915386126Z",
"start_time": "2026-05-31T13:57:38.861262921Z"
}
},
"source": [
"# ── Prepare sequences for StackRnn ─────────────────────────────────────────\n",
"sequences = sensory_np[np_cpu.newaxis, :, :] # (1, 20, 40)\n",
"print(f\"sequences shape : {sequences.shape} → 1 sequence of {N_SAMPLES} chars\")"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"sequences shape : (1, 180, 40) → 1 sequence of 180 chars\n"
]
}
],
"execution_count": 5
},
{
"cell_type": "code",
"id": "c33-0006",
"metadata": {
"execution": {
"iopub.execute_input": "2026-05-31T13:42:51.215346Z",
"iopub.status.busy": "2026-05-31T13:42:51.215163Z",
"iopub.status.idle": "2026-05-31T13:42:51.319714Z",
"shell.execute_reply": "2026-05-31T13:42:51.319006Z"
},
"ExecuteTime": {
"end_time": "2026-05-31T13:57:39.033277512Z",
"start_time": "2026-05-31T13:57:38.916167712Z"
}
},
"source": [
"# ── Build model ────────────────────────────────────────────────────────────\n",
"rnn = StackRnn(PRJ_NAME, WORK_DIR)\n",
"rnn.append(StackRnn.make_layer(\n",
" \"layer0\",\n",
" sensory_size=SENSORY_SIZE,\n",
" h_size=CONTEXT_SIZE,\n",
" entity_params=EntityParams(\n",
" do_gaussian_visible=False,\n",
" do_gaussian_hidden=False,\n",
" num_gibbs_samples=NUM_GIBBS,\n",
" ),\n",
" training_params=TrainingParams(\n",
" learning_rate=LEARNING_RATE,\n",
" momentum=MOMENTUM,\n",
" num_epochs=NUM_EPOCHS,\n",
" mini_batch_size=MINI_BATCH,\n",
" num_gibbs_samples=NUM_GIBBS,\n",
" do_rao_blackwell=RAO_BLACKWELL,\n",
" l2_lambda=L2_LAMBDA,\n",
" ),\n",
"))\n",
"\n",
"rnn.state_init(0.01)\n",
"rnn.state_load()\n",
"\n",
"e = rnn.from_index(0).entity\n",
"print(f\"Mode : {'shared' if rnn.is_shared else 'unrolled'}\")\n",
"print(f\"Visible : {rnn.h_size()} (context) + {rnn.sensory_size()} (sensory) = {e.shape[0]}\")\n",
"print(f\"Hidden : {rnn.h_size()}\")\n",
"print(f\"Parameters : {e.shape[0] * e.shape[1]:,}\")"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Mode : shared\n",
"Visible : 128 (context) + 40 (sensory) = 168\n",
"Hidden : 128\n",
"Parameters : 21,504\n"
]
}
],
"execution_count": 6
},
{
"cell_type": "code",
"id": "c33-0007",
"metadata": {
"execution": {
"iopub.execute_input": "2026-05-31T13:42:51.321630Z",
"iopub.status.busy": "2026-05-31T13:42:51.321423Z",
"iopub.status.idle": "2026-05-31T13:44:35.697232Z",
"shell.execute_reply": "2026-05-31T13:44:35.696410Z"
},
"ExecuteTime": {
"end_time": "2026-05-31T14:13:33.465818984Z",
"start_time": "2026-05-31T13:57:39.034495646Z"
}
},
"source": [
"# ── Train: predict next character from current context ─────────────────────\n",
"# Pairs used: (h_t, x_{t+1})\n",
"# Step 1 — advance context: h_t = forward([h_{t-1} | x_t]) (no weight update)\n",
"# Step 2 — CD update on visible = [h_t | x_{t+1}] (predict next)\n",
"from rbm.train import cd_binary_binary, _to_gpu\n",
"from rbm.matrix import rms_error_accu\n",
"\n",
"entity = rnn.from_index(0).entity\n",
"h_sz = rnn.h_size()\n",
"num_seq, T, s_sz = sequences.shape\n",
"\n",
"rnn.state_init(0.01) # fresh weights for the new training objective\n",
"entity.grad_zero()\n",
"\n",
"d_progress = 100.0 / NUM_EPOCHS\n",
"progress = 0.0\n",
"status = CheckpointStatus(rnn.state_save, update_interval=10)\n",
"status.on_change(entity)\n",
"\n",
"for epoch in range(NUM_EPOCHS):\n",
" h = np.zeros((num_seq, h_sz))\n",
" err_total = 0.0\n",
"\n",
" for t in range(T - 1):\n",
" x_t = _to_gpu(sequences[:, t, :]) # current char x_t\n",
" x_tp1 = _to_gpu(sequences[:, t+1, :]) # next char x_{t+1}\n",
"\n",
" # Step 1: advance context to h_t (no training)\n",
" h = entity.forward(np.concatenate([h, x_t], axis=1))\n",
"\n",
" # Step 2: train on [h_t | x_{t+1}]\n",
" vis = np.concatenate([h, x_tp1], axis=1)\n",
" dwhv, dbv, dbh = cd_binary_binary(entity, vis)\n",
" grad = entity.grad_compute(dbv, dbh, dwhv)\n",
" entity.state_adjust(grad, 1.0 / num_seq)\n",
" err_total += rms_error_accu(vis - entity.reconstruct(entity.forward(vis)))\n",
"\n",
" progress += d_progress\n",
" if status.want_report(round(progress)):\n",
" if not status.on_change(entity, {\n",
" \"progress\": {\"value\": round(progress), \"unit\": \"%\"},\n",
" \"err_rms\": {\"value\": err_total / (T - 1), \"unit\": \"\"},\n",
" }):\n",
" break\n",
"\n",
"rnn.state_save()"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"-------------------------------------------\n",
"Entity-168x128: progress : 0%\n",
"Entity-168x128: err_rms : 0.005378640847885016\n",
"Entity-168x128: l2_norm : 0.3832858163328573\n",
"-------------------------------------------\n",
"Entity-168x128: progress : 10%\n",
"Entity-168x128: err_rms : 0.004888029606164829\n",
"Entity-168x128: l2_norm : 37.943563674580545\n",
"-------------------------------------------\n",
"Entity-168x128: progress : 20%\n",
"Entity-168x128: err_rms : 0.004586658254152343\n",
"Entity-168x128: l2_norm : 62.68289402335654\n",
"-------------------------------------------\n",
"Entity-168x128: progress : 30%\n",
"Entity-168x128: err_rms : 0.0029227696643319935\n",
"Entity-168x128: l2_norm : 77.592210060179\n",
"-------------------------------------------\n",
"Entity-168x128: progress : 40%\n",
"Entity-168x128: err_rms : 0.0033848746808303183\n",
"Entity-168x128: l2_norm : 87.52545196132891\n",
"-------------------------------------------\n",
"Entity-168x128: progress : 50%\n",
"Entity-168x128: err_rms : 0.0031435271125311573\n",
"Entity-168x128: l2_norm : 94.6793236343037\n",
"-------------------------------------------\n",
"Entity-168x128: progress : 60%\n",
"Entity-168x128: err_rms : 0.002912863154656583\n",
"Entity-168x128: l2_norm : 101.0458096406675\n",
"-------------------------------------------\n",
"Entity-168x128: progress : 70%\n",
"Entity-168x128: err_rms : 0.0026133215611993344\n",
"Entity-168x128: l2_norm : 108.17102558067306\n",
"-------------------------------------------\n",
"Entity-168x128: progress : 80%\n",
"Entity-168x128: err_rms : 0.0023368766544820717\n",
"Entity-168x128: l2_norm : 114.27352128254557\n",
"-------------------------------------------\n",
"Entity-168x128: progress : 90%\n",
"Entity-168x128: err_rms : 0.0033621059271795742\n",
"Entity-168x128: l2_norm : 118.8790801434613\n",
"-------------------------------------------\n",
"Entity-168x128: progress : 100%\n",
"Entity-168x128: err_rms : 0.0028362015980278044\n",
"Entity-168x128: l2_norm : 123.1840443378905\n"
]
}
],
"execution_count": 7
},
{
"cell_type": "code",
"id": "c33-0008",
"metadata": {
"execution": {
"iopub.execute_input": "2026-05-31T13:44:35.698954Z",
"iopub.status.busy": "2026-05-31T13:44:35.698747Z",
"iopub.status.idle": "2026-05-31T13:44:35.743964Z",
"shell.execute_reply": "2026-05-31T13:44:35.743294Z"
},
"ExecuteTime": {
"end_time": "2026-05-31T14:13:33.829642525Z",
"start_time": "2026-05-31T14:13:33.467124588Z"
}
},
"source": [
"# ── Reconstruction: teacher-forced ─────────────────────────────────────────\n",
"# Step through each sample, reconstruct, compare to input.\n",
"rnn.reset(batch_size=1)\n",
"recons = []\n",
"for i in range(N_SAMPLES):\n",
" x_t = np.array(sensory_np[i][np_cpu.newaxis, :])\n",
" h = rnn.step(x_t)\n",
" rec = convert(rnn.reconstruct(h))[0] # (40,)\n",
" recons.append(rec)\n",
"\n",
"recons_np = np_cpu.array(recons) # (12, 40)\n",
"decoded_recon = ''.join(idx_to_char[int(np_cpu.argmax(recons_np[i]))] for i in range(N_SAMPLES))\n",
"\n",
"print(f\"Input : '{decoded}'\")\n",
"print(f\"Reconstruction: '{decoded_recon}'\")\n",
"\n",
"correct = sum(decoded[i] == decoded_recon[i] for i in range(N_SAMPLES))\n",
"print(f\"Char accuracy : {correct}/{N_SAMPLES} = {100*correct/N_SAMPLES:.0f}%\")"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Input : 'CALL ME ISHMAEL. SOME YEARS AGO NEVER MIND HOW LONG PRECISELY HAVING LITTLE MONEY IN MY POCKET AND NOTHING PARTICULAR TO INTEREST ME ON SHORE I THOUGHT I WOULD SAIL ABOUT A LITTLE.'\n",
"Reconstruction: 'CALL ME ISHMAEL. SOME YEARS AGO NEVER MIND HOW LONG PRECISELY HAVING LITTLE MONEY IN MY POCKET AND NOTHING PARTICULARETO INTEREST ME ON SHORE I THOUGHT I WOULD SAIL ABOUT A LITTLE.'\n",
"Char accuracy : 179/180 = 99%\n"
]
}
],
"execution_count": 8
},
{
"cell_type": "code",
"id": "c33-0009",
"metadata": {
"execution": {
"iopub.execute_input": "2026-05-31T13:44:35.745972Z",
"iopub.status.busy": "2026-05-31T13:44:35.745781Z",
"iopub.status.idle": "2026-05-31T13:44:36.051662Z",
"shell.execute_reply": "2026-05-31T13:44:36.050823Z"
},
"ExecuteTime": {
"end_time": "2026-05-31T14:13:34.318617319Z",
"start_time": "2026-05-31T14:13:33.830853549Z"
}
},
"source": "# ── Visualise reconstruction ───────────────────────────────────────────────\nstep = max(1, N_SAMPLES // 40)\ntick_pos = range(0, N_SAMPLES, step)\n\nfig, axes = plt.subplots(1, 2, figsize=(16, 3))\n\naxes[0].imshow(sensory_np.T, aspect='auto', cmap='Blues', vmin=0, vmax=1)\naxes[0].set_title(f'Input ({N_SAMPLES} chars)')\naxes[0].set_xticks(tick_pos)\naxes[0].set_xticklabels([decoded[i] for i in tick_pos], fontsize=8)\naxes[0].set_ylabel('Vocab index')\n\naxes[1].imshow(recons_np.T, aspect='auto', cmap='Blues', vmin=0, vmax=1)\naxes[1].set_title(f'Reconstruction (acc {100*correct/N_SAMPLES:.0f}%)')\naxes[1].set_xticks(tick_pos)\naxes[1].set_xticklabels([decoded_recon[i] for i in tick_pos], fontsize=8)\n\nplt.tight_layout()\nplt.show()",
"outputs": [
{
"data": {
"text/plain": [
"<Figure size 1600x300 with 2 Axes>"
],
"image/png": "iVBORw0KGgoAAAANSUhEUgAABjUAAAEiCAYAAACx91CkAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjgsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvwVt1zgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAU5dJREFUeJzt3Xl8THf///9nIoQysYutXJbSRamqra3ybbXVq4u12upC+XyuqlJa1V66oPSi6lKt0F1j+VwtWktVi24opaTWEFuINQRJJFORROL9+6O/zGWSYCYzmTMzedxvt/ft5pyc5XnOnJk5L+8554RIMgIAAAAAAAAAAPBzoVYHAAAAAAAAAAAAcAWdGgAAAAAAAAAAICDQqQEAAAAAAAAAAAICnRoAAAAAAAAAACAg0KkBAAAAAAAAAAACAp0aAAAAAAAAAAAgINCpAQAAAAAAAAAAAgKdGgAAAAAAAAAAICDQqQEAAAAAAAAAAAICnRoAAK96+OGHlZycrPLly1sdxWPGGEVFRVkdw+HLL7/UvHnzrI4BAAAAWKpjx44yxqhjx46WrD8kJESxsbF69dVXLVl/ILnuuut0/vx53XDDDVZHARBE6NQAAD/Rt29fGWPUqlUrq6NIksqVK6fRo0e7VSiEhobqzTffVFRUlM6ePesYf/fdd+uzzz5TbGyscnJylJCQcMll1KxZUx9//LEOHDigjIwMxcfHa/LkyapSpUqBaa+99lotW7ZMdrtdycnJmj17tqpVq+behgaQiRMnqmfPnmrevLnVUQAAAEqcvPP1vHb+/HkdPXpU0dHRql27ttXxvO7ZZ59V3759S3yGwjz22GO6+uqrNW3aNKujFOq5555TXFycMjMzdfToUU2ePFlXXXVVgekaNWqkr776SikpKTp79qzWrFmjTp06FZiua9eu2rVrl86cOaMlS5aoVq1aBab55ptv9PHHHxcYv2vXLn333XcaO3asV7YNAPIYGo1Go1nf+vbta4wxplWrVpZnkWSqVq1qjDFm9OjRLs/TtWtXk5uba2rXru00Pjo62mRkZJi1a9eaw4cPm4SEhELnL1++vElISDAnT540Y8aMMQMGDDBTp041WVlZZvPmzSYkJMQxbZ06dczJkyfNvn37zJAhQ8zIkSNNcnKy2bJliyldurRX9oExxkRFRVn+Wlzcfv/9dzNr1izLc9BoNBqNRqOVtJZ3vv7666+bxx9/3AwYMMB8+umn5vz582bfvn0mPDzc8ozebLGxsWblypV+mSEkJMSEh4c71Qe+bFu2bDEfffSR5a9RYe3tt982xhgzf/5888wzz5j333/fZGdnm+XLlztNV7duXXPy5Elz/PhxM3LkSPP888+bLVu2mOzsbNOhQwfHdA0aNDCZmZlm1qxZZuDAgWb37t0FlnXPPfeY1NRUU61atUIzdenSxRhjTMOGDS3fPzQaLWia5QFoNBqNpuDo1Fi8eLH59ddfC4yvVauWCQsLM5LMt99+e8lOjccee8wYY8zf//53p/Fjxowxxhhz0003OcZNnz7dnD171lx99dWOcXfddZcxxpj//d//9co+8EWnxlVXXeXW9C+++KKx2+2mfPnylh8jNBqNRqPRaCWpXep8fcKECcYYYx5++GHLM3qzudOp4e45bXFk8FW76aabjDHG3HnnnZZnyd9q1qxpsrOzC/wI6rnnnjPGGPPAAw84xk2bNs1kZ2ebJk2aOMaVK1fOHDp0yPzxxx+Occ8884yJj493DHfs2NHk5uY6OvFKlSpldu7caV544YVL5goLCzPJycnmzTfftHwf0Wi04GjcfgoA/Fh0dLTsdrtq166tRYsWyW636+TJk5o0aZJCQ//7EV6/fn0ZYzR8+HANGzZMBw8eVEZGhlatWlXg3qUrV67UypUrC11X3m2h6tevr9OnT0uSxowZ47jEfvTo0ZfMGh4eri5duuinn34q8Lfjx48rJyfnitsbEREhSUpKSiowvySdO3fOMa5nz55aunSpjhw54hj3888/a8+ePerdu/cV1xUSEqLnn39e27dv17lz53Ty5EktW7as0Nt/de3aVbGxscrMzNSOHTt07733Ov29Xr16mj59unbv3q2MjAydPn1a8+fPV/369Z2my7tlwR133KHp06crKSlJR48elSRVqFBBU6ZMUUJCgjIzM5WUlKQffvhBLVu2dFrGjz/+qAoVKujuu+++4jYCAACg+K1Zs0bSX7fyuVjTpk311VdfKTk5WefOnVNMTIwefPDBAvNXrFhR7777ruM88MiRI5o1a5aqVq3qmKZ69er67LPPdOLECZ07d05bt27VU0895bSci2uC//3f/1V8fLwyMzO1ceNG3XLLLU7TRkZG6vPPP9eRI0eUmZmpxMRELV682HH+mpCQoGbNmqlTp06OWiCvhrjcOe3FNcXFRo8eLWNMgfGPP/64NmzYoLNnzyolJUWrV692nOdeLsOlnqnRq1cv/fHHH8rIyNCpU6c0Z86cArcGc7XGupRu3bopKytLv/76q9N4V2sCybXXPDw8XKNHj9aePXt07tw5JSYmasGCBWrYsOEls7Vv316lS5fW3LlzncbnDT/66KOOcR06dNCWLVu0d+9ex7hz585pyZIlatWqlRo3bizpr9sSnzlzxjFNSkqKQkNDVa5cOUnS4MGDVapUqcs+izAnJ0erVq1S165dLzkNALgjzOoAAIDLK1WqlFasWKENGzbopZdeUufOnfXSSy9p//79+uijj5ymfeqpp2Sz2TR9+nSVLVtWQ4cO1S+//KIbb7xRJ0+edHmdp06d0sCBA/XRRx9p4cKFWrhwoSRp+/btl5ynVatWCg8P1+bNm4u2oZJ+/fVX5ebm6v3339fw4cN19OhRNW/eXK+99poWLVqkPXv2SJJq166tyMhI/fHHHwWWsXHjRv3973+/4rpmzJihp59+Wt9//70+++wzhYWFqUOHDmrXrp02bdrkmO72229Xjx499MEHH8hut+v555/XggULVK9ePaWkpEiSWrdurVtvvVVz587V0aNH9be//U3PPvusVq1apeuvv96pM0aSPvjgA506dUpjx451PFD9o48+Uq9evTRt2jTFxcWpatWquv3223Xddddpy5Ytjnnj4uKUkZGh2267TYsXL3Z7HwMAAMC7/va3v0mSUlNTHeOuv/56/fbbbzp27JjefvttnT17Vr1799bixYvVs2dPx3lc+fLltWbNGl133XX6/PPPtXnzZlWrVk0PPfSQ6tatq+TkZJUtW1arVq1S48aNNW3aNCUkJOjhhx/WrFmzVKlSJU2dOtUpT58+fWSz2fTxxx/LGKOXX35ZCxcuVMOGDR0/NFqwYIFuuOEGRUVF6eDBg6pRo4buvvtu1atXT4cOHdKwYcMUFRWlP//8U//6178kFfzhUWHntO4YNWqU3nzzTf32228aNWqUsrOz1bZtW91555368ccfXcpwsb59+2rmzJnauHGjRo4cqcjISA0dOlS33XabWrZsqbS0NMe07tRY+d16663asWNHgR9tuVoTuPKah4aGaunSpercubO+/PJLvf/++7LZbLr77rvVrFkzHThwoNBs4eHhklSg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Bmnz5s3avXu3WrRoURwZAQAAAAAAAAAAFObuDAcOHNBtt92m9957T8uXL1dubq769u2ruXPnFkc+AAAAAAAAAAAASUV8UPj999+vRx99VOvXr9eZM2c0YMAA1apVy9vZAAAAAAAAAAAAHNzu1Pjoo4/01VdfaeLEierQoYOaN2+u7OxsxcbG6uGHHy6OjAAAAAAAAAAAAAqRZNyZITY2Vo8//ri2b9/uNH7QoEGaOHGibDabN/N5zGazKT09XZk5VicBAAAASqayYVJERITsdrvVUS6L2gEAAACwliu1g9udGmXKlFF2dnahf2vSpIn27t3rVsjiVlhhUrn1YKdpUmOm+TiV+/JnlgIjd36e7vtAfO3gPzh+cLFgPR58vV3B8v0EuCMQzmf87TMukDs1/G1fuiJYPpsD4b2G4MXxg4tVbjPEaTh1Y5RFSbyL2gEofh6fz7R/0Xn+9e96nKnAOvzsO8+V2sHt209lZ2erYcOGGjdunL744gtVr15dktSlSxeFhbn93HEAAAAAAAAAAACXuN2pcccddyg2NlZt27ZVjx49VKFCBUlSixYt9Oabb3o9IAAAAAAAAAAAgFSETo23335br7/+uu655x6n21D98ssvateunVfDAQAAAAAAAAAA5HG7U+PGG2/UokWLCow/efKkqlWr5tayOnTooCVLlujYsWMyxqhr165Of4+OjpYxxqktW7bM3cgAAAAAAhy1AwAAAACpCA8KP3LkiHr37q3169crPT1dLVq0UEJCgrp166Z///vfaty4scvL6tKli2677TZt2rRJixYtUrdu3fTNN984/h4dHa3IyEg9/fTTjnFZWVk6c+aMy+so7GF/AAAAgL/wtwfzFQdvPCic2gEAAAAlHbXDX9x+svfcuXM1ceJEPfzwwzLGKDQ0VLfeeqv+/e9/a/bs2W4ta/ny5Vq+fPllp8nKylJSUpK7MQEAAAAEEWoHAAAAAFIRbj/16quvavfu3Tpy5IgqVKiguLg4/frrr1q3bp3eeustrwfs1KmTkpKStHv3bn3wwQeqUqWK19cBAAAAIPBROwAAAADBz+0rNc6fP69//OMfGjdunJo1a6YKFSpoy5Ytio+P93q45cuXa+HChUpISFCjRo00fvx4LVu2TO3bt9eFCxcKnadMmTIKDw93DNtsNq/nAgAAAOBfqB0AAACAksHtTo08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"
},
"metadata": {},
"output_type": "display_data",
"jetTransient": {
"display_id": null
}
}
],
"execution_count": 9
},
{
"cell_type": "code",
"id": "c33-0010",
"metadata": {
"execution": {
"iopub.execute_input": "2026-05-31T13:44:36.053484Z",
"iopub.status.busy": "2026-05-31T13:44:36.053314Z",
"iopub.status.idle": "2026-05-31T13:44:36.198793Z",
"shell.execute_reply": "2026-05-31T13:44:36.197851Z"
},
"ExecuteTime": {
"end_time": "2026-05-31T14:13:35.558819364Z",
"start_time": "2026-05-31T14:13:34.319986996Z"
}
},
"source": [
"# ── Next-step prediction ───────────────────────────────────────────────────\n",
"# Given h_t (context after seeing x_t), predict x_{t+1} via clamped Gibbs.\n",
"def predict_next(rnn, context, n_gibbs=NUM_GIBBS, temperature=1.0):\n",
" entity = rnn.next_entity()\n",
" h_sz, s_sz = rnn.h_size(), rnn.sensory_size()\n",
" x_init = (np.random.rand(1, s_sz) > 0.5).astype(float)\n",
" visible = np.concatenate([context, x_init], axis=1)\n",
" for _ in range(n_gibbs):\n",
" h = entity.forward(visible)\n",
" visible = entity.reconstruct(h)\n",
" visible[:, :h_sz] = context\n",
" probs = convert(visible[:, h_sz:])[0]\n",
" probs = np_cpu.power(np_cpu.clip(probs, 1e-10, 1.0), 1.0 / temperature)\n",
" probs /= probs.sum()\n",
" return probs\n",
"\n",
"rnn.reset(batch_size=1)\n",
"h = np.zeros((1, CONTEXT_SIZE))\n",
"predicted = ''\n",
"\n",
"for i in range(N_SAMPLES - 1):\n",
" x_t = np.array(sensory_np[i][np_cpu.newaxis, :])\n",
" h = rnn.step(x_t) # advance to h_t\n",
" probs = predict_next(rnn, h.copy()) # predict x_{t+1} from h_t\n",
" predicted += idx_to_char[int(np_cpu.argmax(probs))]\n",
"\n",
"print(f\"Input (t+1) : '{decoded[1:]}'\")\n",
"print(f\"Predicted from h_t : '{predicted}'\")\n",
"correct = sum(decoded[i+1] == predicted[i] for i in range(N_SAMPLES - 1))\n",
"print(f\"Next-step accuracy : {correct}/{N_SAMPLES-1} = {100*correct/(N_SAMPLES-1):.0f}%\")"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Input (t+1) : 'ALL ME ISHMAEL. SOME YEARS AGO NEVER MIND HOW LONG PRECISELY HAVING LITTLE MONEY IN MY POCKET AND NOTHING PARTICULAR TO INTEREST ME ON SHORE I THOUGHT I WOULD SAIL ABOUT A LITTLE.'\n",
"Predicted from h_t : 'AOEGML ONIOAEL.OSEMATOOLRT RGE IEVRR NDOHOWHAENG PRECO EEY HALARTAI TTEE MONEYHIN MY PACKEY EID HR.HIPE PROKHC.MORE.S IIDARETTLME ON EHOTE NTHHUGESOITWIU D EAIL ABOOT H LROTLE.'\n",
"Next-step accuracy : 101/179 = 56%\n"
]
}
],
"execution_count": 10
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.3"
}
},
"nbformat": 4,
"nbformat_minor": 5
}