import { Arrow, FigBox, FILL, LoopFigure, type LoopStop } from "./LoopFigure"; const STOPS: LoopStop[] = [ { x: 150, y: 90, ids: ["unroll"], inspect: "unroll", title: "Input x_t", note: "A new token (or frame) arrives. The same weights will process it as every other step.", }, { x: 150, y: 200, ids: ["cell"], inspect: "cell", title: "Shared cell", note: "h_t = tanh(W_h h_{t−1} + W_x x_t). One cell, reused across time.", }, { x: 150, y: 330, ids: ["hidden"], inspect: "hidden", title: "Hidden state h_t", note: "The running summary of the past. The next step reads this vector as memory.", }, { x: 370, y: 200, ids: ["unroll", "cell"], inspect: "unroll", title: "Unroll t−1", note: "Training unrolls the loop into a deep net. Gradients flow back through every step (BPTT).", }, { x: 540, y: 200, ids: ["cell", "hidden"], inspect: "cell", title: "Unroll t", note: "The same cell at the current time. Hidden state arrives from the left.", }, { x: 710, y: 200, ids: ["unroll", "hidden"], inspect: "hidden", title: "Unroll t+1", note: "Long-range signals must survive every multiply. Then the loop returns to a new x_t.", }, { x: 710, y: 400, ids: ["hidden"], inspect: "hidden", title: "Carry memory", note: "h_{t+1} is written for the next step. The rolled cell on the left is the same weights.", }, { x: 150, y: 400, ids: ["hidden", "unroll"], inspect: "unroll", title: "Next step", note: "The loop returns to a new x_t with the updated hidden state.", }, ]; export function RnnLoop({ onSelect }: { onSelect: (id: string) => void }) { return ( {({ on, markerId }) => ( Recurrent Neural Network Rolled Unrolled through time onSelect("unroll")} /> onSelect("cell")} /> h onSelect("hidden")} /> {[ { x: 300, t: "t−1", xid: "x_{t-1}", hid: "h_{t-1}" }, { x: 470, t: "t", xid: "x_t", hid: "h_t" }, { x: 640, t: "t+1", xid: "x_{t+1}", hid: "h_{t+1}" }, ].map((col, i) => ( {col.t} onSelect("unroll")} /> onSelect("cell")} /> onSelect("hidden")} /> {i < 2 ? ( ) : null} ))} )} ); }