| """Recurrent models, 1-D and N-D under one name. |
| |
| ``td.LSTM(d_model, n_layers)`` with no lattice is an ordinary sequence model. |
| Give it a ``lattice`` and the same class becomes N-dimensional. There is no |
| separate ``LSTMND`` because there is no separate mechanism: a lattice with no |
| spatial axes has an identity permutation, so the 1-D case is the N-D case with |
| nothing to fold. |
| |
| How the extra axes are handled is ``nd_method``'s business, not this class's. |
| The default sweeps them with the RNN itself; a kernel-family method instead |
| mixes across the lattice and leaves the RNN to run along time. |
| |
| A multi-layer stack here is pre-norm and residual, which ``nn.LSTM(num_layers=k)`` |
| is not. One layer with ``norm=False, residual=False`` reproduces ``nn.LSTM`` |
| exactly; beyond that these are modern defaults, not a drop-in reimplementation. |
| """ |
|
|
| from __future__ import annotations |
|
|
| from torch_dimensions.mixers.rnn import GRUMixer, LSTMMixer |
| from torch_dimensions.models.base import LatticeModel |
|
|
| __all__ = ["GRU", "LSTM"] |
|
|
|
|
| class LSTM(LatticeModel): |
| """LSTM over a sequence, or over an N-D lattice. |
| |
| Args: |
| d_model: feature width the model works in, and the output width. |
| d_input: width of the incoming features, when it differs from |
| ``d_model``. Adds a single input projection; omit it and the input |
| is expected to already be ``d_model`` wide. |
| n_layers: how many sweeps. With a lattice, layers cycle through its |
| axes unless ``plan`` says otherwise. |
| lattice: omit for an ordinary 1-D sequence model. |
| nd_method: how the extra axes are handled — a registered name or any |
| callable with the strategy signature. Defaults to |
| :func:`~torch_dimensions.axial_scan`, which sweeps every axis with |
| the RNN. Supplying your own function is the supported way to add a |
| traversal the library has never heard of. |
| bidirectional: ``True``/``False``, or the axes to sweep both ways, so a |
| time axis can stay causal while spatial axes do not. Off by |
| default: an implicit direction schedule should be stated, not |
| assumed. |
| |
| ``bidirectional`` is a property of the *schedule*, not of the underlying |
| ``nn.LSTM`` — a backward sweep arrives pre-flipped, and the feature width |
| never doubles. |
| """ |
|
|
| _mixer = LSTMMixer |
|
|
|
|
| class GRU(LatticeModel): |
| """GRU over a sequence, or over an N-D lattice. See :class:`LSTM`.""" |
|
|
| _mixer = GRUMixer |
|
|