Example 28
intermediate
28
Tensors
Neural Networks

Recurrent Neural Network Layers

Demonstrates RNN, LSTM, and GRU layers for sequence modeling tasks. This example uses deepbox/ndarray, deepbox/nn and focuses on tensor, GradTensor; RNN, LSTM, GRU.

Deepbox Modules Used

deepbox/ndarraydeepbox/nn

What You Will Learn

  • Use deepbox/ndarray for tensor, GradTensor.
  • Use deepbox/nn for RNN, LSTM, GRU.
  • Demonstrates RNN, LSTM, and GRU layers for sequence modeling tasks.

Source Files

index.ts
1/**2 * Example 28: Recurrent Neural Network Layers3 *4 * Demonstrates RNN, LSTM, and GRU layers for sequence modeling.5 * Recurrent layers process sequential data by maintaining hidden state across time steps.6 */78import { GradTensor, tensor } from "deepbox/ndarray";9import { GRU, LSTM, RNN } from "deepbox/nn";1011console.log("=== Recurrent Neural Network Layers ===\n");1213// ---------------------------------------------------------------------------14// Part 1: Simple RNN15// ---------------------------------------------------------------------------16console.log("--- Part 1: Simple RNN ---");1718// RNN(inputSize, hiddenSize, options)19// Input shape (batchFirst=true): (batch, seqLen, inputSize)20const rnn = new RNN(4, 8, { batchFirst: true });21console.log("RNN(inputSize=4, hiddenSize=8, batchFirst=true)");2223// Batch of 2 sequences, each with 3 time steps and 4 features24const rnnInput = tensor([25  [26    [1, 2, 3, 4],27    [5, 6, 7, 8],28    [9, 10, 11, 12],29  ],30  [31    [13, 14, 15, 16],32    [17, 18, 19, 20],33    [21, 22, 23, 24],34  ],35]);36console.log(`Input shape:  [${rnnInput.shape.join(", ")}]`);3738const rnnResult = rnn.forward(rnnInput);39const rnnOut = rnnResult instanceof GradTensor ? rnnResult.tensor : rnnResult;40console.log(`Output shape: [${rnnOut.shape.join(", ")}]`);41console.log("  Output contains hidden states for all time steps\n");4243// ---------------------------------------------------------------------------44// Part 2: LSTM (Long Short-Term Memory)45// ---------------------------------------------------------------------------46console.log("--- Part 2: LSTM ---");4748// LSTM adds cell state for better long-range dependencies49const lstm = new LSTM(4, 8, { batchFirst: true });50console.log("LSTM(inputSize=4, hiddenSize=8, batchFirst=true)");51console.log(`Input shape:  [${rnnInput.shape.join(", ")}]`);5253const lstmResult = lstm.forward(rnnInput);54const lstmOut = lstmResult instanceof GradTensor ? lstmResult.tensor : lstmResult;55console.log(`Output shape: [${lstmOut.shape.join(", ")}]`);56console.log("  LSTM uses forget/input/output gates for selective memory\n");5758// ---------------------------------------------------------------------------59// Part 3: GRU (Gated Recurrent Unit)60// ---------------------------------------------------------------------------61console.log("--- Part 3: GRU ---");6263// GRU is a simplified version of LSTM with fewer parameters64const gru = new GRU(4, 8, { batchFirst: true });65console.log("GRU(inputSize=4, hiddenSize=8, batchFirst=true)");66console.log(`Input shape:  [${rnnInput.shape.join(", ")}]`);6768const gruResult = gru.forward(rnnInput);69const gruOut = gruResult instanceof GradTensor ? gruResult.tensor : gruResult;70console.log(`Output shape: [${gruOut.shape.join(", ")}]`);71console.log("  GRU uses reset/update gates — fewer params than LSTM\n");7273// ---------------------------------------------------------------------------74// Part 4: Multi-layer RNN75// ---------------------------------------------------------------------------76console.log("--- Part 4: Multi-Layer Stacking ---");7778const deepRnn = new RNN(4, 16, { numLayers: 2, batchFirst: true });79console.log("RNN(inputSize=4, hiddenSize=16, numLayers=2)");80console.log(`Input shape:  [${rnnInput.shape.join(", ")}]`);8182const deepResult = deepRnn.forward(rnnInput);83const deepOut = deepResult instanceof GradTensor ? deepResult.tensor : deepResult;84console.log(`Output shape: [${deepOut.shape.join(", ")}]`);85console.log("  2-layer RNN extracts higher-level sequential patterns\n");8687// ---------------------------------------------------------------------------88// Part 5: Unbatched (single sequence) input89// ---------------------------------------------------------------------------90console.log("--- Part 5: Unbatched Input ---");9192const singleSeq = tensor([93  [1, 2, 3, 4],94  [5, 6, 7, 8],95  [9, 10, 11, 12],96]);97console.log("Single sequence (no batch dim):");98console.log(`Input shape:  [${singleSeq.shape.join(", ")}]`);99100const singleResult = rnn.forward(singleSeq);101const singleOut = singleResult instanceof GradTensor ? singleResult.tensor : singleResult;102console.log(`Output shape: [${singleOut.shape.join(", ")}]`);103console.log("  2D input is treated as unbatched sequence\n");104105// ---------------------------------------------------------------------------106// Part 6: Parameter counts107// ---------------------------------------------------------------------------108console.log("--- Part 6: Parameter Comparison ---");109const rnnParams = Array.from(rnn.parameters()).length;110const lstmParams = Array.from(lstm.parameters()).length;111const gruParams = Array.from(gru.parameters()).length;112console.log(`RNN  parameters: ${rnnParams}`);113console.log(`LSTM parameters: ${lstmParams} (4x gates)`);114console.log(`GRU  parameters: ${gruParams} (3x gates)`);115116console.log("\n=== Recurrent Layers Complete ===");117

Console Output

$ npx tsx 28-rnn-lstm-gru/index.ts
Console output showing sequence processing with different recurrent architectures
Parameter count comparison between RNN, LSTM, and GRU