[refactor] move rbm.stack* + rbm.rnn_helper → stack/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-02 08:10:03 +02:00
co-authored by Claude Sonnet 4.6
parent b0d370a56b
commit 2da2262368
12 changed files with 56 additions and 58 deletions
+17 -17
View File
@@ -25,7 +25,7 @@
"\n",
"import numpy as np_cpu\n",
"import matplotlib.pyplot as plt\n",
"from rbm.stack_rnn import StackRnn\n",
"from stack.rnn import StackRnn\n",
"from rbm.matrix import np, convert\n",
"from rbm.entity import EntityParams, TrainingParams\n",
"from rbm.status import CheckpointStatus"
@@ -49,7 +49,7 @@
}
},
"source": [
"# ── Config ─────────────────────────────────────────────────────────────────\n",
"# \u2500\u2500 Config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n",
"SENSORY_SIZE = 40 # numVisibleX * numVisibleY = 1 * 40\n",
"CONTEXT_SIZE = 256 # numContext = numHidden\n",
"UNROLL_DEPTH = 1 # number of time-step entities (1 = shared weights)\n",
@@ -88,7 +88,7 @@
}
},
"source": [
"# ── Training sentence ──────────────────────────────────────────────────────\n",
"# \u2500\u2500 Training sentence \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n",
"SENTENCE = (\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",
@@ -135,7 +135,7 @@
}
},
"source": [
"# ── Visualise one-hot encoding ─────────────────────────────────────────────\n",
"# \u2500\u2500 Visualise one-hot encoding \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n",
"step = max(1, N_SAMPLES // 40) # show at most 40 tick labels\n",
"tick_pos = range(0, N_SAMPLES, step)\n",
"\n",
@@ -182,19 +182,19 @@
}
},
"source": [
"# ── Prepare sequences for StackRnn ─────────────────────────────────────────\n",
"# \u2500\u2500 Prepare sequences for StackRnn \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n",
"# Tile the single sentence N_REPEAT times to form a real batch so GPU/CPU\n",
"# matrix ops are (N_REPEAT, 168) instead of (1, 168).\n",
"N_REPEAT = 500\n",
"sequences = np_cpu.tile(sensory_np[np_cpu.newaxis, :, :], (N_REPEAT, 1, 1))\n",
"print(f\"sequences shape : {sequences.shape} {N_REPEAT} × {N_SAMPLES} chars\")"
"print(f\"sequences shape : {sequences.shape} \u2192 {N_REPEAT} \u00d7 {N_SAMPLES} chars\")"
],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"sequences shape : (500, 180, 40) → 500 × 180 chars\n"
"sequences shape : (500, 180, 40) \u2192 500 \u00d7 180 chars\n"
]
}
],
@@ -216,7 +216,7 @@
}
},
"source": [
"# ── Build model ────────────────────────────────────────────────────────────\n",
"# \u2500\u2500 Build model \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n",
"rnn = StackRnn(PRJ_NAME, WORK_DIR)\n",
"for layer in StackRnn.make_unrolled(\n",
" UNROLL_DEPTH,\n",
@@ -247,7 +247,7 @@
"print(f\"Layers : {rnn.num_layers()} (alternating t % {rnn.num_layers()})\")\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] * rnn.num_layers():,} ({rnn.num_layers()} × {e.shape[0] * e.shape[1]:,})\")"
"print(f\"Parameters : {e.shape[0] * e.shape[1] * rnn.num_layers():,} ({rnn.num_layers()} \u00d7 {e.shape[0] * e.shape[1]:,})\")"
],
"outputs": [
{
@@ -258,7 +258,7 @@
"Layers : 1 (alternating t % 1)\n",
"Visible : 256 (context) + 40 (sensory) = 296\n",
"Hidden : 256\n",
"Parameters : 75,776 (1 × 75,776)\n"
"Parameters : 75,776 (1 \u00d7 75,776)\n"
]
}
],
@@ -279,10 +279,10 @@
}
},
"source": [
"# ── Train: predict next character from current context ─────────────────────\n",
"# \u2500\u2500 Train: predict next character from current context \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n",
"# Unrolled layers alternate: layer[t % num_layers] owns each time-step position.\n",
"# Step 1 advance context: h_t = layer[t%D].forward([h_{t-1} | x_t])\n",
"# Step 2 CD on [h_t | x_{t+1}] using the same layer[t%D]\n",
"# Step 1 \u2014 advance context: h_t = layer[t%D].forward([h_{t-1} | x_t])\n",
"# Step 2 \u2014 CD on [h_t | x_{t+1}] using the same layer[t%D]\n",
"from rbm.train import cd_binary_binary, _to_gpu\n",
"from rbm.matrix import rms_error_accu\n",
"\n",
@@ -354,7 +354,7 @@
}
},
"source": [
"# ── Reconstruction: teacher-forced ─────────────────────────────────────────\n",
"# \u2500\u2500 Reconstruction: teacher-forced \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n",
"# Step through each sample, reconstruct, compare to input.\n",
"rnn.reset(batch_size=1)\n",
"recons = []\n",
@@ -388,7 +388,7 @@
}
},
"source": [
"# ── Visualise reconstruction ───────────────────────────────────────────────\n",
"# \u2500\u2500 Visualise reconstruction \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n",
"step = max(1, N_SAMPLES // 40)\n",
"tick_pos = range(0, N_SAMPLES, step)\n",
"\n",
@@ -430,7 +430,7 @@
}
},
"source": [
"# ── Next-step prediction ───────────────────────────────────────────────────\n",
"# \u2500\u2500 Next-step prediction \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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",
@@ -486,4 +486,4 @@
},
"nbformat": 4,
"nbformat_minor": 5
}
}