# RWKV

## 概要

RWKVモデル（バージョン4）は、[このリポジトリ](https://github.com/BlinkDL/RWKV-LM)で提案されました。

従来の Transformer の注意機構を調整して線形化することを提案しています。これにより、モデルを再帰型ネットワークとして使用できます。タイムスタンプ 0 とタイムスタンプ 1 の入力を同時に渡すことは、まずタイムスタンプ 0 の入力を渡し、次にタイムスタンプ 0 の状態とともにタイムスタンプ 1 の入力を渡すことと同等です（以下の例を参照）。

これは通常の Transformer よりも効率的であり、任意の長さの文を処理できます（モデルが学習時に固定のコンテキスト長を使用する場合でも）。

このモデルは [sgugger](https://huggingface.co/sgugger) によって提供されました。元のコードは [こちら](https://github.com/BlinkDL/RWKV-LM) で確認できます。

## 使用例

```python
import torch

from transformers import AutoTokenizer, RwkvModel

model = RwkvModel.from_pretrained("sgugger/rwkv-430M-pile", device_map="auto")
tokenizer = AutoTokenizer.from_pretrained("sgugger/rwkv-430M-pile")

inputs = tokenizer("This is an example.", return_tensors="pt").to(model.device)
# Feed everything to the model
outputs = model(inputs["input_ids"])
output_whole = outputs.last_hidden_state

outputs = model(inputs["input_ids"][:, :2])
output_one = outputs.last_hidden_state

# Using the state computed on the first inputs, we will get the same output
outputs = model(inputs["input_ids"][:, 2:], state=outputs.state)
output_two = outputs.last_hidden_state

torch.allclose(torch.cat([output_one, output_two], dim=1), output_whole, atol=1e-5)
```

`'\n\n'` が検出された時点でモデルの生成を停止させたい場合は、以下の停止条件の使用を推奨します。

```python
from transformers import StoppingCriteria

class RwkvStoppingCriteria(StoppingCriteria):
    def __init__(self, eos_sequence = [187,187], eos_token_id = 537):
        self.eos_sequence = eos_sequence
        self.eos_token_id = eos_token_id

    def __call__(self, input_ids: torch.LongTensor, scores: torch.FloatTensor, **kwargs) -> bool:
        last_2_ids = input_ids[:,-2:].tolist()
        return self.eos_sequence in last_2_ids

output = model.generate(inputs["input_ids"], max_new_tokens=64, stopping_criteria = [RwkvStoppingCriteria()])
```

## 注記

- バッチ生成には左パディングを使用します。[Padding side](../llm_tutorial#padding-side)を参照してください。

## RwkvConfig[[transformers.RwkvConfig]]

#### transformers.RwkvConfig[[transformers.RwkvConfig]]

```python
transformers.RwkvConfig(transformers_version: str | None = None, architectures: list[str] | None = None, output_hidden_states: bool | None = False, return_dict: bool | None = True, dtype: str | torch.dtype | None = None, chunk_size_feed_forward: int = 0, is_encoder_decoder: bool = False, id2label: dict[int, str] | dict[str, str] | None = None, label2id: dict[str, int] | dict[str, str] | None = None, problem_type: Literal['regression', 'single_label_classification', 'multi_label_classification'] | None = None, vocab_size: int = 50277, context_length: int = 1024, hidden_size: int = 4096, num_hidden_layers: int = 32, attention_hidden_size: int | None = None, intermediate_size: int | None = None, layer_norm_epsilon: float = 1e-05, bos_token_id: int | None = 0, eos_token_id: int | list[int] | None = 0, rescale_every: int = 6, tie_word_embeddings: bool = False, use_cache: bool = True)
```

[ソース](https://github.com/huggingface/transformers/blob/main/src/transformers/models/rwkv/configuration_rwkv.py#L25)

**パラメータ:**

vocab_size (`int`、*任意*、デフォルトは`50277`) : モデルの語彙サイズ。`input_ids`で表現できるトークンの種類数を定義します。

context_length (`int`、*optional*、デフォルトは 1024) : このモデルを単一の forward で使用できる最大シーケンス長です（RNN モードで使用する場合は、任意のシーケンス長を使用できます）。

hidden_size (`int`、*任意*、デフォルトは`4096`) : 隠れ表現の次元数。

num_hidden_layers (`int`、*任意*、デフォルトは`32`) : Transformerデコーダーの隠れ層の数。

attention_hidden_size (`int`, *optional*) : 注意機構の隠れ状態の次元数。未設定の場合は `hidden_size` がデフォルトになります。

intermediate_size (`int`, *任意*) : MLP 表現の次元数。

layer_norm_epsilon (`float`、*任意*、デフォルトは`1e-05`) : Layer Normalization 層で使用する epsilon。

bos_token_id (`int`, *optional*, デフォルトは `0`) : 語彙内でストリームの開始に使用されるトークン ID。

eos_token_id (`Union[int, list[int]]`、*任意*、デフォルトは`0`) : 語彙内でストリーム終了に使用されるトークン ID。

rescale_every (`int`, *optional*, デフォルトは 6) : 推論時、隠れ状態（および対応する出力層の重み）は、`rescale_every` 層ごとに 2 で割られます。0 または負の数を設定した場合、リスケールは行われません。

tie_word_embeddings (`bool`, *任意*, デフォルトは `False`) : モデルの `tied_weights_keys` マッピングに従って重み埋め込みを共有するかどうか。

use_cache (`bool`、*任意*、デフォルトは `True`) : モデルが最後のキー/バリューアテンションを返すかどうか（すべてのモデルで利用されるわけではありません）。`config.is_decoder=True` の場合、またはモデルがデコーダー専用の生成モデルである場合にのみ関連します。

これはRwkvModelの設定を保存するための設定クラスです。指定された引数に基づいてRwkvモデルをインスタンス化し、モデルのアーキテクチャを定義するために使用されます。デフォルト値で設定をインスタンス化すると、[RWKV/rwkv-4-169m-pile](https://huggingface.co/RWKV/rwkv-4-169m-pile) と同様の設定が得られます。

設定オブジェクトは [PreTrainedConfig](/docs/transformers/main/ja/main_classes/configuration#transformers.PreTrainedConfig) を継承し、モデルの出力を制御するために使用できます。詳細については、[PreTrainedConfig](/docs/transformers/main/ja/main_classes/configuration#transformers.PreTrainedConfig) のドキュメントを参照してください。

例:

```python
>>> from transformers import RwkvConfig, RwkvModel

>>> # Initializing a Rwkv configuration
>>> configuration = RwkvConfig()

>>> # Initializing a model (with random weights) from the configuration
>>> model = RwkvModel(configuration)

>>> # Accessing the model configuration
>>> configuration = model.config
```

## RwkvModel[[transformers.RwkvModel]]

#### transformers.RwkvModel[[transformers.RwkvModel]]

```python
transformers.RwkvModel(config: RwkvConfig)
```

[ソース](https://github.com/huggingface/transformers/blob/main/src/transformers/models/rwkv/modeling_rwkv.py#L487)

**パラメータ:**

config ([RwkvConfig](/docs/transformers/main/ja/model_doc/rwkv#transformers.RwkvConfig)) : モデルのパラメータをすべて含むモデル設定クラスです。設定ファイルで初期化しても、モデルに関連する重みは読み込まれず、設定のみが読み込まれます。モデルの重みをロードするには、[from_pretrained()](/docs/transformers/main/ja/main_classes/model#transformers.PreTrainedModel.from_pretrained) メソッドを確認してください。

特定のヘッドを付加せず、生の隠れ状態を出力する素のRwkvモデル。

このモデルは [PreTrainedModel](/docs/transformers/main/ja/main_classes/model#transformers.PreTrainedModel) を継承しています。ライブラリがすべてのモデルに対して実装している汎用的なメソッド（ダウンロードや保存、入力埋め込みのリサイズ、ヘッドのプルーニングなど）については、スーパークラスのドキュメントを参照してください。

このモデルは、PyTorchの[torch.nn.Module](https://pytorch.org/docs/stable/nn.html#torch.nn.Module)のサブクラスでもあります。通常のPyTorch Moduleとして使用し、一般的な使用方法や動作に関する詳細については、PyTorchのドキュメントを参照してください。

#### forward[[transformers.RwkvModel.forward]]

```python
forward(input_ids: typing.Optional[torch.LongTensor] = None, attention_mask: typing.Optional[torch.LongTensor] = None, inputs_embeds: typing.Optional[torch.FloatTensor] = None, state: list[torch.FloatTensor] | None = None, use_cache: bool | None = None, output_attentions: bool | None = None, output_hidden_states: bool | None = None, return_dict: bool | None = None, **kwargs)
```

[ソース](https://github.com/huggingface/transformers/blob/main/src/transformers/models/rwkv/modeling_rwkv.py#L508)

**パラメータ:**

input_ids (`torch.LongTensor`、shape `(batch_size, input_ids_length)`) : `input_ids_length` = `past_key_values` が `None` の場合は `sequence_length`、それ以外の場合は `past_key_values.get_seq_length()`（入力された past key value states の `sequence_length`）。語彙における入力シーケンスのトークンインデックスです。 `past_key_values` を使用する場合、過去が計算されていない `input_ids` のみを `input_ids` として渡す必要があります。 インデックスは [AutoTokenizer](/docs/transformers/main/ja/model_doc/auto#transformers.AutoTokenizer) を使用して取得できます。 詳細は [PreTrainedTokenizer.encode()](/docs/transformers/main/ja/internal/tokenization_utils#transformers.PreTrainedTokenizerBase.encode) および [PreTrainedTokenizer.__call__()](/docs/transformers/main/ja/internal/tokenization_utils#transformers.PreTrainedTokenizerBase.__call__) を参照してください。 [input ID とは何か？](../glossary#input-ids)

attention_mask (`torch.LongTensor`、shape `(batch_size, sequence_length)`、*任意*) : padding トークンインデックスに対する attention を行わないためのマスク。`[0, 1]` から選択されるマスク値:  - **マスクされない**トークンは 1、- **マスクされる**トークンは 0。  [attention マスクとは?](../glossary#attention-mask)

inputs_embeds (`torch.FloatTensor`、shape `(batch_size, sequence_length, hidden_size)`、*任意*) : `input_ids` を渡す代わりに、埋め込み表現を直接渡すこともできます。これは、モデル内部の埋め込み参照行列よりも、`input_ids` のインデックスを対応するベクトルに変換する方法をより細かく制御したい場合に有用です。

state (`tuple` of five `torch.FloatTensor` of shape `(batch_size, hidden_size, num_hidden_layers)`, *optional*) : 渡された場合、モデルはすべてのブロックで以前の状態を使用します（`input_ids` が、モデルが `state_input_ids + input_ids` をコンテキストとして追加したかのように出力されるようになります）。

use_cache (`bool`, *任意*) : `True`に設定すると、最後の状態が返され、次のlogitsを迅速に生成するために使用できます。

output_attentions (`bool`, *任意*) : すべてのアテンション層のアテンションテンソルを返すかどうか。詳細は、返されるテンソルの `attentions` を参照してください。

output_hidden_states (`bool`, *任意*) : 全レイヤーの hidden states を返すかどうかを指定します。詳細は、返されるテンソルの `hidden_states` を参照してください。

return_dict (`bool`, *任意*) : プレーンなタプルではなく [ModelOutput](/docs/transformers/main/ja/main_classes/output#transformers.utils.ModelOutput) を返すかどうか。

**戻り値:** `RwkvOutput` または `tuple(torch.FloatTensor)`

`RwkvOutput` または `torch.FloatTensor` のタプル（`return_dict=False` が渡された場合、または `config.return_dict=False` の場合）。[RwkvConfig](/docs/transformers/main/ja/model_doc/rwkv#transformers.RwkvConfig) および入力に応じて、さまざまな要素で構成されます。

[RwkvModel](/docs/transformers/main/ja/model_doc/rwkv#transformers.RwkvModel)のforwardメソッドは、`__call__`特殊メソッドをオーバーライドします。

この関数内でフォワードパスの手順を定義する必要がありますが、その後、この関数ではなく`Module`インスタンスを呼び出すべきです。前者は前処理と後処理の実行を適切に処理するのに対し、後者はそれらを無視してしまいます。

- **last_hidden_state** (`torch.FloatTensor`、shape `(batch_size, sequence_length, hidden_size)`、*optional*) -- モデルの最終層の出力における隠れ状態のシーケンス。
- **state**（shape が `(batch_size, hidden_size, num_hidden_layers)` の `torch.FloatTensor` 5 つからなる `list`）-- 最終タイムステップにおけるモデルの状態です。次の`input_ids`を forward メソッドで使用することで、古い`input_ids`を指定せずに済みます。
- **hidden_states** (`tuple[torch.FloatTensor, ...]`、*optional*、`output_hidden_states=True` が渡された場合または `config.output_hidden_states=True` の場合に返されます) -- `torch.FloatTensor` のタプル（埋め込み層を持つモデルの場合、埋め込みの出力用が 1 つ、各層の出力用が 1 つずつ）で、形状は `(batch_size, sequence_length, hidden_size)` です。

  各層の出力におけるモデルのHidden-states、および任意の初期埋め込み出力。
- **attentions** (`tuple[torch.FloatTensor, ...]`、*optional*、`output_attentions=True` が渡された場合または `config.output_attentions=True` の場合に返されます) -- `torch.FloatTensor` のタプル（レイヤーごとに1つ）で、形状は `(batch_size, num_heads, sequence_length, sequence_length)` です。

  アテンションのsoftmax後のアテンション重み。自己アテンションヘッド内で加重平均を計算するために使用されます。

## RwkvLMHeadModel[[transformers.RwkvForCausalLM]]

#### transformers.RwkvForCausalLM[[transformers.RwkvForCausalLM]]

```python
transformers.RwkvForCausalLM(config: RwkvConfig)
```

[ソース](https://github.com/huggingface/transformers/blob/main/src/transformers/models/rwkv/modeling_rwkv.py#L667)

**パラメータ:**

config ([RwkvConfig](/docs/transformers/main/ja/model_doc/rwkv#transformers.RwkvConfig)) : モデルのパラメータをすべて含むモデル設定クラスです。設定ファイルで初期化しても、モデルに関連する重みは読み込まれず、設定のみが読み込まれます。モデルの重みをロードするには、[from_pretrained()](/docs/transformers/main/ja/main_classes/model#transformers.PreTrainedModel.from_pretrained) メソッドを確認してください。

入力埋め込みの重みと共有される線形層を上部に備えた言語モデリングヘッドを持つ、RWKV Modelトランスフォーマー。

このモデルは [PreTrainedModel](/docs/transformers/main/ja/main_classes/model#transformers.PreTrainedModel) を継承しています。ライブラリがすべてのモデルに対して実装している汎用的なメソッド（ダウンロードや保存、入力埋め込みのリサイズ、ヘッドのプルーニングなど）については、スーパークラスのドキュメントを参照してください。

このモデルは、PyTorchの[torch.nn.Module](https://pytorch.org/docs/stable/nn.html#torch.nn.Module)のサブクラスでもあります。通常のPyTorch Moduleとして使用し、一般的な使用方法や動作に関する詳細については、PyTorchのドキュメントを参照してください。

#### forward[[transformers.RwkvForCausalLM.forward]]

```python
forward(input_ids: typing.Optional[torch.LongTensor] = None, attention_mask: typing.Optional[torch.LongTensor] = None, inputs_embeds: typing.Optional[torch.FloatTensor] = None, state: list[torch.FloatTensor] | None = None, labels: typing.Optional[torch.LongTensor] = None, use_cache: bool | None = None, output_attentions: bool | None = None, output_hidden_states: bool | None = None, return_dict: bool | None = None, logits_to_keep: typing.Union[int, torch.Tensor] = 0, **kwargs)
```

[ソース](https://github.com/huggingface/transformers/blob/main/src/transformers/models/rwkv/modeling_rwkv.py#L684)

**パラメータ:**

input_ids (`torch.LongTensor`、shape `(batch_size, input_ids_length)`) : `input_ids_length` = `past_key_values` が `None` の場合は `sequence_length`、それ以外の場合は `past_key_values.get_seq_length()`（入力された past key value states の `sequence_length`）。語彙における入力シーケンスのトークンインデックスです。 `past_key_values` を使用する場合、過去が計算されていない `input_ids` のみを `input_ids` として渡す必要があります。 インデックスは [AutoTokenizer](/docs/transformers/main/ja/model_doc/auto#transformers.AutoTokenizer) を使用して取得できます。 詳細は [PreTrainedTokenizer.encode()](/docs/transformers/main/ja/internal/tokenization_utils#transformers.PreTrainedTokenizerBase.encode) および [PreTrainedTokenizer.__call__()](/docs/transformers/main/ja/internal/tokenization_utils#transformers.PreTrainedTokenizerBase.__call__) を参照してください。 [input ID とは何か？](../glossary#input-ids)

attention_mask (`torch.LongTensor`、shape `(batch_size, sequence_length)`、*任意*) : padding トークンインデックスに対する attention を行わないためのマスク。`[0, 1]` から選択されるマスク値:  - **マスクされない**トークンは 1、- **マスクされる**トークンは 0。  [attention マスクとは?](../glossary#attention-mask)

inputs_embeds (`torch.FloatTensor`、shape `(batch_size, sequence_length, hidden_size)`、*任意*) : `input_ids` を渡す代わりに、埋め込み表現を直接渡すこともできます。これは、モデル内部の埋め込み参照行列よりも、`input_ids` のインデックスを対応するベクトルに変換する方法をより細かく制御したい場合に有用です。

state (`tuple` of five `torch.FloatTensor` of shape `(batch_size, hidden_size, num_hidden_layers)`, *optional*) : 渡された場合、モデルはすべてのブロックで以前の状態を使用します（`input_ids` が、モデルが `state_input_ids + input_ids` をコンテキストとして追加したかのように出力されるようになります）。

labels (`torch.LongTensor`、shape `(batch_size, sequence_length)`、*任意*) : 言語モデリング用のラベル。モデル内部でラベルは**シフト**されるため、`labels = input_ids` と設定できます。インデックスは `[-100, 0, ..., config.vocab_size]` から選択されます。`-100` に設定されたすべてのラベルは無視（マスク）され、損失は `[0, ..., config.vocab_size]` 内のラベルに対してのみ計算されます。

use_cache (`bool`, *任意*) : `True`に設定すると、最後の状態が返され、次のlogitsを迅速に生成するために使用できます。

output_attentions (`bool`, *任意*) : すべてのアテンション層のアテンションテンソルを返すかどうか。詳細は、返されるテンソルの `attentions` を参照してください。

output_hidden_states (`bool`, *任意*) : 全レイヤーの hidden states を返すかどうかを指定します。詳細は、返されるテンソルの `hidden_states` を参照してください。

return_dict (`bool`, *任意*) : プレーンなタプルではなく [ModelOutput](/docs/transformers/main/ja/main_classes/output#transformers.utils.ModelOutput) を返すかどうか。

logits_to_keep (`Union[int, torch.Tensor]`、*任意*、デフォルトは `0`) : `int` の場合、最後の `logits_to_keep` トークンについて logits を計算します。`0` の場合、すべての `input_ids` について logits を計算します（特殊ケース）。生成には最後のトークンの logits だけで十分であり、そのトークンのみについて計算することでメモリを節約できます。これは、長いシーケンスや大規模な語彙サイズの場合に特に顕著な効果があります。`torch.Tensor` の場合、シーケンス長次元で保持するインデックスに対応する 1 次元である必要があります。これは、パックされたテンソル形式（バッチとシーケンス長を単一の次元にまとめる形式）を使用する場合に有用です。

**戻り値:** `RwkvCausalLMOutput` または `tuple(torch.FloatTensor)`

`RwkvCausalLMOutput` または `torch.FloatTensor` のタプル（`return_dict=False` が渡された場合、または `config.return_dict=False` の場合）。設定（[RwkvConfig](/docs/transformers/main/ja/model_doc/rwkv#transformers.RwkvConfig)）や入力に応じて、さまざまな要素で構成されます。

[RwkvForCausalLM](/docs/transformers/main/ja/model_doc/rwkv#transformers.RwkvForCausalLM) の forward メソッドは、`__call__` という特殊メソッドをオーバーライドします。

この関数内でフォワードパスの手順を定義する必要がありますが、その後、この関数ではなく`Module`インスタンスを呼び出すべきです。前者は前処理と後処理の実行を適切に処理するのに対し、後者はそれらを無視してしまいます。

- **loss** (`torch.FloatTensor`、shape `(1,)`、*optional*、`labels` が指定された場合に返されます) -- 言語モデリングの損失(次のトークンの予測用)。
- **logits** (`torch.FloatTensor`、shape `(batch_size, sequence_length, config.vocab_size)`) -- 言語モデリングヘッドの予測スコア（SoftMax 適用前の各語彙トークンのスコア）。
- **state** (`list` of five `torch.FloatTensor` of shape `(batch_size, hidden_size, num_hidden_layers)`) -- The state of the model at the last time step. Can be used in a forward method with the next `input_ids` to avoid providing the old `input_ids`.
- **hidden_states** (`tuple[torch.FloatTensor, ...]`、*optional*、`output_hidden_states=True` が渡された場合または `config.output_hidden_states=True` の場合に返されます) -- `torch.FloatTensor` のタプル（埋め込み層を持つモデルの場合、埋め込みの出力用が 1 つ、各層の出力用が 1 つずつ）で、形状は `(batch_size, sequence_length, hidden_size)` です。

  各層の出力におけるモデルのHidden-states、および任意の初期埋め込み出力。
- **attentions** (`tuple[torch.FloatTensor, ...]`、*optional*、`output_attentions=True` が渡された場合または `config.output_attentions=True` の場合に返されます) -- `torch.FloatTensor` のタプル（レイヤーごとに1つ）で、形状は `(batch_size, num_heads, sequence_length, sequence_length)` です。

  アテンションのsoftmax後のアテンション重み。自己アテンションヘッド内で加重平均を計算するために使用されます。

例:

```python
```

## Rwkvのattentionと再帰式

従来の自己回帰型Transformerでは、アテンションは以下のように記述されます

$$O = \hbox{softmax}(QK^{T} / \sqrt{d}) V$$

ここで、`seq_len x hidden_size` の形状を持つ行列 $Q$、$K$、$V$ は、それぞれクエリ、キー、バリューと呼ばれます（実際にはバッチ次元とアテンションヘッド次元を持つより大きな行列ですが、行列積が計算される最後の2次元にのみ注目するため、簡略化のためにこれら2次元のみを考慮します）。積 $QK^{T}$ の形状は `seq_len x seq_len` となり、$V$ との行列積を取ることで、他の行列と同じ形状の出力 $O$ を得ることができます。

softmaxをその値で置き換えると、次のようになります。

$$O_{i} = \frac{\sum_{j=1}^{i} e^{Q_{i} K_{j}^{T} / \sqrt{d}} V_{j}}{\sum_{j=1}^{i} e^{Q_{i} K_{j}^{T} / \sqrt{d}}}$$

$j > i$ に対応する $QK^{T}$ のエントリはマスクされています（合計は j で停止します）。これは、アテンションが将来のトークンを見ることは許可されておらず（過去のトークンのみ）、そのためです。

これに対し、RWKVの注意機構は以下のように与えられます

$$O_{i} = \sigma(R_{i}) \frac{\sum_{j=1}^{i} e^{W_{i-j} + K_{j}} V_{j}}{\sum_{j=1}^{i} e^{W_{i-j} + K_{j}}}$$

ここで、$R$ は著者が受容性（receptance）と呼ぶ新しい行列、$K$ と $V$ は引き続きキーとバリュー（$\sigma$ はここではシグモイド関数）です。$W$ はトークンの位置を表す新しいベクトルであり、以下のように与えられます

$$W_{0} = u \hbox{ かつ  } W_{k} = (k-1)w \hbox{ （} k \geq 1 \hbox{）}$$

with $u$ and $w$ learnable parameters called in the code `time_first` and `time_decay` respectively. The numerator and denominator can both be expressed recursively. Naming them $N_{i}$ and $D_{i}$ we have:

$$N_{i} = e^{u + K_{i}} V_{i} + \hat{N}_{i} \hbox{  where  } \hat{N}_{i} = e^{K_{i-1}} V_{i-1} + e^{w + K_{i-2}} V_{i-2} \cdots + e^{(i-2)w + K_{1}} V_{1}$$

したがって、`numerator_state` と呼ばれる `numerator_state` は、

$$\hat{N}_{0} = 0 \hbox{  and  } \hat{N}_{j+1} = e^{K_{j}} V_{j} + e^{w} \hat{N}_{j}$$

および

$$D_{i} = e^{u + K_{i}} + \hat{D}_{i} \hbox{  where  } \hat{D}_{i} = e^{K_{i-1}} + e^{w + K_{i-2}} \cdots + e^{(i-2)w + K_{1}}$$

したがって、`denominator_state` と呼ばれる `denominator_state` は、

$$\hat{D}_{0} = 0 \hbox{  and  } \hat{D}_{j+1} = e^{K_{j}} + e^{w} \hat{D}_{j}$$

実際に使用される再帰式はわずかに複雑ですが、これは数値的安定性の観点から、大きな数の指数を計算したくないためです。通常、softmax はそのまま計算されるのではなく、最大項の指数が分子と分母から割り引かれます：

$$\frac{e^{x_{i}}}{\sum_{j=1}^{n} e^{x_{j}}} = \frac{e^{x_{i} - M}}{\sum_{j=1}^{n} e^{x_{j} - M}}$$

ここで $M$ はすべての $x_{j}$ の最大値です。したがって、ここでは分子の状態（$\hat{N}$）と分母の状態（$\hat{D}$）を保存するだけでなく、指数関数で遭遇したすべての項の最大値も追跡します。つまり、実際には

$$\tilde{N}_{i} = e^{-M_{i}} \hat{N}_{i} \hbox{  and  } \tilde{D}_{i} = e^{-M_{i}} \hat{D}_{i}$$

以下の再帰式によって定義されます:

$$\tilde{N}_{0} = 0 \hbox{  かつ  } \tilde{N}_{j+1} = e^{K_{j} - q} V_{j} + e^{w + M_{j} - q} \tilde{N}_{j} \hbox{  ただし  } q = \max(K_{j}, w + M_{j})$$

および

$$\tilde{D}_{0} = 0 \hbox{  and  } \tilde{D}_{j+1} = e^{K_{j} - q} + e^{w + M_{j} - q} \tilde{D}_{j} \hbox{  where  } q = \max(K_{j}, w + M_{j})$$

そして$M_{j+1} = q$です。これらを用いて、次に計算できます

$$N_{i} = e^{u + K_{i} - q} V_{i} + e^{M_{i}} \tilde{N}_{i} \hbox{  where  } q = \max(u + K_{i}, M_{i})$$

および

$$D_{i} = e^{u + K_{i} - q} + e^{M_{i}} \tilde{D}_{i} \hbox{  where  } q = \max(u + K_{i}, M_{i})$$

最終的に得られるのは

$$O_{i} = \sigma(R_{i}) \frac{N_{i}}{D_{i}}$$

