lstm_forward
Builtin index · Statistics & ML
result = lstm_forward(x_sequence, h0, c0, weights)
Input: x_sequence, h0, c0, weights · Output: result
What it is
Unrolls lstm_cell over a whole sequence: x_sequence an (input_size, seq_len) matrix (one column per timestep), h0/c0 length-hidden_size initial states, weights the same gate-weights Record as lstm_cell.
Overloads
One call shape — this function is not overloaded.
| Code | Input | Output | Description |
result = lstm_forward(x_sequence, h0, c0, weights) | x_sequence matrix or Recordnot documented yeth0 matrix or Recordnot documented yetc0 matrix or Recordnot documented yetweights matrix or Recordnot documented yet | result vector | Returns a length-seq_len list of length-hidden_size hidden-state vectors, one per timestep; the cell state threads through internally and is not returned. |
Examples
From the documentation, and run by the build -- the output and the figure below are what the engine actually produced. Simplest first.
raw = lstm_init(2, 3, seed = 1)
w = {wf=param(raw.wf), uf=param(raw.uf), bf=param(raw.bf),
wi=param(raw.wi), ui=param(raw.ui), bi=param(raw.bi),
wo=param(raw.wo), uo=param(raw.uo), bo=param(raw.bo),
wg=param(raw.wg), ug=param(raw.ug), bg=param(raw.bg)}
Xseq = [0.5, -0.3, 0.8; 0.2, 0.4, -0.1] # (input_size, seq_len)
hs = lstm_forward(Xseq, [0.0, 0.0, 0.0], [0.0, 0.0, 0.0], w)
h_last = hs[length(hs) - 1]
loss = sum(h_last .^ 2)
g = grad(loss, wrt = w.wf) # through time, on the same tape
print("loss: {round(loss, 4)}")
print("dL/dwf: {round(g, 4)}")
loss: 0.0027 dL/dwf: [0.0001, 0; 0.0005, 0; 0.0021, -0.0002]
from statistics-ml
How it works
lstm_forward(x_sequence, h0, c0, weights) — unrolls lstm_cell across a whole sequence, mirroring gru_forward's own structure and x_sequence shape contract exactly (a Value::Mat of shape (input_size, seq_len), one COLUMN per timestep, or a Value::List of per-timestep batched Mats — see gru_forward's own doc comment for why batching rides on Matrix::matmul's own rayon parallelism rather than a hand-rolled thread fan-out here, which applies identically to LSTM's tape-mutating &mut self cell calls). Returns a Value::List of every timestep's HIDDEN state only (h_t, not c_t) — the same "one value per timestep, caller slices hs[length(hs)-1] for the last one" contract gru_forward already established, so any code built against gru_forward's return shape (e.g. a dense readout on the last hidden state) works unchanged against lstm_forward. c_t still threads through the loop below (lstm_cell's own {h, c} record is unpacked each step via lstm_field), it's just not part of what's handed back to the caller — matching most high-level LSTM APIs (PyTorch's nn.LSTM also returns only the hidden-state sequence by default, with the final cell state as a separate secondary output most sequence- classification callers never touch).
From the note above this builtin in the interpreter, where the reasoning was written down as it was built.