Source code for fynance.models.rnn

#!/usr/bin/env python3
# coding: utf-8

""" Single-step Elman-style recurrent cell.

Defines :class:`RecurrentNeuralNetwork`, an Elman-style cell: it
concatenates an input row with a supplied hidden-state row, applies one
linear layer plus activation, and projects to the output. Each of the
``T`` rows of the input is processed **independently** — the class does
**not** thread a hidden state across a time axis, so it is a *stateless*
gated feed-forward cell rather than a sequence model. The caller is
responsible for any state threading (e.g. by looping over time steps and
feeding the returned ``H`` back in).

For genuine sequence modeling with temporal state, use a dedicated
sequence architecture such as :class:`~fynance.models.tcn.TemporalConvNet`
or :class:`~fynance.models.transformer.Transformer`, which enforce
causality over an explicit time axis.

Main entry points
-----------------
- :class:`RecurrentNeuralNetwork` — single-step Elman cell ready for
  training via :meth:`~fynance.models._base.BaseNeuralNet.set_optimizer`.

References
----------
.. [1] Elman, J.L. (1990). Finding Structure in Time. Cognitive Science.

"""

from __future__ import annotations

# Third-party packages
from torch import nn

# Local packages
from fynance.models._recurrent_base import _OutputLayerMixin, _RecurrentBase

__all__ = ['RecurrentNeuralNetwork']


[docs] class RecurrentNeuralNetwork(_OutputLayerMixin, _RecurrentBase): # type: ignore[misc] """ Single-step Elman-style gated cell. A single linear layer (over the input concatenated with a supplied hidden state) followed by an output projection. Each call to :meth:`forward` consumes ``X`` of shape ``(T, N)`` and ``H`` of shape ``(T, H)`` and returns ``(Y, H_new)`` with the same leading dimension ``T``; **every row is processed independently** and no state is threaded across rows. This is therefore a *stateless* gated feed-forward cell, not a sequence model — the caller must perform any temporal state threading explicitly. For sequence modeling with built-in temporal state and causality, prefer :class:`~fynance.models.tcn.TemporalConvNet` or :class:`~fynance.models.transformer.Transformer`. Parameters ---------- X, y : array-like or int - If it's an array-like, respectively inputs and outputs data. - If it's an integer, respectively dimension of inputs and outputs. drop : float, optional Probability of an element to be zeroed. bias : bool, optional If ``True`` (default), the linear layers learn an additive bias. forward_activation, hidden_activation : torch.nn.Module, optional Activation functions, default is respectively Identity and Tanh function. The output activation defaults to Identity so the cell produces unconstrained regression outputs (pass ``nn.Softmax`` for a probability-simplex output). hidden_state_size : int, optional Size of hidden states, default is the same size than input. Attributes ---------- criterion : torch.nn.modules.loss A loss function. optimizer : torch.optim An optimizer algorithm. W_h, W_y : torch.nn.Linear Respectively recurrent and forward weights. f_y, f_h : torch.nn.Module Respectively forward and hidden activation functions. Examples -------- >>> import torch >>> from fynance.models.rnn import RecurrentNeuralNetwork >>> _ = torch.manual_seed(0) >>> model = RecurrentNeuralNetwork(4, 1, hidden_state_size=3) >>> X = torch.zeros(5, 4) >>> H = torch.zeros(5, 3) >>> Y, H_new = model(X, H) >>> Y.shape, H_new.shape (torch.Size([5, 1]), torch.Size([5, 3])) See Also -------- fynance.models.gru.GatedRecurrentUnit, fynance.models.lstm.LongShortTermMemory """ def __init__( self, X, y, drop=None, x_type=None, y_type=None, bias=True, forward_activation=nn.Identity, hidden_activation=nn.Tanh, hidden_state_size=None, ): _RecurrentBase.__init__( self, X, y, drop=drop, x_type=x_type, y_type=y_type, bias=bias, hidden_activation=hidden_activation, hidden_state_size=hidden_state_size, ) _OutputLayerMixin.__init__(self, forward_activation=forward_activation)
[docs] def forward(self, X, H): """ Forward method. Parameters ---------- X, H : torch.Tensor Respectively input data and hidden state. Returns ------- torch.Tensor Output data. torch.Tensor Hidden state. """ H = super().forward(X, H) Y = self.f_y(self.W_y(self.drop(H))) return Y, H