# RWKV

## Visão geral

O modelo RWKV (versão 4) foi proposto em [este repositório](https://github.com/BlinkDL/RWKV-LM)

Isso sugere um ajuste na atenção do Transformer tradicional para torná-la linear. Dessa forma, o modelo pode ser usado como uma rede recorrente: passar as entradas do timestamp 0 e do timestamp 1 juntos é o mesmo que passar as entradas no timestamp 0 e, em seguida, as entradas no timestamp 1 junto com o estado do timestamp 0 (veja o exemplo abaixo).

Isso pode ser mais eficiente do que um Transformer regular e pode lidar com frases de qualquer comprimento (mesmo que o modelo use um comprimento de contexto fixo para o treinamento).

Este modelo foi contribuído por [sgugger](https://huggingface.co/sgugger). O código original pode ser encontrado [aqui](https://github.com/BlinkDL/RWKV-LM).

## Exemplo de uso

```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)
```

Se você quiser garantir que o modelo pare de gerar quando `'\n\n'` for detectado, recomendamos usar os seguintes critérios de parada:

```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.Tensor, **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()])
```

## Observações

- Use padding à esquerda para geração em lote. Consulte [Lado do padding](../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)
```

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

**Parâmetros:**

vocab_size (`int`, *opcional*, padrão `50277`) : Tamanho do vocabulário do modelo. Define o número de tokens diferentes que podem ser representados pelos `input_ids`.

context_length (`int`, *opcional*, padrão 1024) : O comprimento máximo de sequência com o qual este modelo pode ser usado em um único forward (usá-lo em modo RNN permite usar qualquer comprimento de sequência).

hidden_size (`int`, *opcional*, padrão `4096`) : Dimensão das representações ocultas.

num_hidden_layers (`int`, *opcional*, padrão `32`) : Número de camadas ocultas no decodificador do Transformer.

attention_hidden_size (`int`, *opcional*) : Dimensionalidade dos estados ocultos da atenção. Se não definido, o padrão será `hidden_size`.

intermediate_size (`int`, *opcional*) : Dimensão das representações do MLP.

layer_norm_epsilon (`float`, *opcional*, padrão `1e-05`) : O epsilon usado pelas camadas de normalização de camada.

bos_token_id (`int`, *opcional*, padrão `0`) : ID do token usado para o início do fluxo no vocabulário.

eos_token_id (`Union[int, list[int]]`, *opcional*, padrão `0`) : ID do token usado para o fim do fluxo no vocabulário.

rescale_every (`int`, *opcional*, padrão 6) : Na inferência, os estados ocultos (e os pesos das camadas de saída correspondentes) são divididos por 2 a cada `rescale_every` camada. Se definido como 0 ou um número negativo, nenhum rescale é realizado.

tie_word_embeddings (`bool`, *opcional*, padrão `False`) : Se deve vincular as embeddings de pesos de acordo com o mapeamento `tied_weights_keys` do modelo.

use_cache (`bool`, *opcional*, padrão `True`) : Indica se o modelo deve retornar as últimas atenções de chave/valor (não utilizado por todos os modelos). Relevante apenas se `config.is_decoder=True` ou quando o modelo for um modelo generativo somente de decodificador.

Esta é a classe de configuração para armazenar a configuração de um RwkvModel. Ela é usada para instanciar um modelo Rwkv de acordo com os argumentos especificados, definindo a arquitetura do modelo. Instanciar uma configuração com os padrões resultará em uma configuração semelhante à do [RWKV/rwkv-4-169m-pile](https://huggingface.co/RWKV/rwkv-4-169m-pile)

Os objetos de configuração herdam de [PreTrainedConfig](/docs/transformers/main/pt/main_classes/configuration#transformers.PreTrainedConfig) e podem ser usados para controlar as saídas do modelo. Leia a documentação de [PreTrainedConfig](/docs/transformers/main/pt/main_classes/configuration#transformers.PreTrainedConfig) para mais informações.

Exemplo:

```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)
```

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

**Parâmetros:**

config ([RwkvConfig](/docs/transformers/main/pt/model_doc/rwkv#transformers.RwkvConfig)) : Classe de configuração do modelo com todos os parâmetros do modelo. Inicializar com um arquivo de configuração não carrega os pesos associados ao modelo, apenas a configuração. Consulte o método [from_pretrained()](/docs/transformers/main/pt/main_classes/model#transformers.PreTrainedModel.from_pretrained) para carregar os pesos do modelo.

O modelo Rwkv puro, que produz estados ocultos brutos sem nenhum cabeçalho específico no topo.

Este modelo herda de [PreTrainedModel](/docs/transformers/main/pt/main_classes/model#transformers.PreTrainedModel). Consulte a documentação da classe pai para os métodos genéricos que a biblioteca implementa para todos os seus modelos (como download ou salvamento, redimensionamento dos embeddings de entrada, poda de cabeças, etc.).

Este modelo também é uma subclasse de [torch.nn.Module](https://pytorch.org/docs/stable/nn.html#torch.nn.Module) do PyTorch. Use-o como um Módulo PyTorch regular e consulte a documentação do PyTorch para todos os assuntos relacionados ao uso e comportamento gerais.

#### 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.Tensor] = None, state: list[torch.Tensor] | None = None, use_cache: bool | None = None, output_attentions: bool | None = None, output_hidden_states: bool | None = None, return_dict: bool | None = None, **kwargs)
```

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

**Parâmetros:**

input_ids (`torch.LongTensor` de forma `(batch_size, input_ids_length)`) : `input_ids_length` = `sequence_length` se `past_key_values` for `None`, caso contrário `past_key_values.get_seq_length()` (`sequence_length` dos estados de chave e valor passados). Índices dos tokens da sequência de entrada no vocabulário. Se `past_key_values` for usado, apenas os `input_ids` que ainda não têm seu passado calculado devem ser passados como `input_ids`. Os índices podem ser obtidos usando [AutoTokenizer](/docs/transformers/main/pt/model_doc/auto#transformers.AutoTokenizer). Consulte [PreTrainedTokenizer.encode()](/docs/transformers/main/pt/internal/tokenization_utils#transformers.PreTrainedTokenizerBase.encode) e [PreTrainedTokenizer.__call__()](/docs/transformers/main/pt/internal/tokenization_utils#transformers.PreTrainedTokenizerBase.__call__) para mais detalhes. [O que são IDs de entrada?](../glossary#input-ids)

attention_mask (`torch.LongTensor` de forma `(batch_size, sequence_length)`, *opcional*) : Máscara para evitar a execução de atenção nos índices de tokens de preenchimento. Valores de máscara selecionados em `[0, 1]`:  - 1 para tokens que **não estão mascarados**, - 0 para tokens que **estão mascarados**.  [O que são máscaras de atenção?](../glossary#attention-mask)

inputs_embeds (`torch.Tensor` de forma `(batch_size, sequence_length, hidden_size)`, *opcional*) : Opcionalmente, em vez de passar `input_ids`, você pode escolher passar diretamente uma representação incorporada. Isso é útil se você quiser ter mais controle sobre como converter os índices de `input_ids` nos vetores associados do que a matriz de busca de incorporação interna do modelo.

state (`tuple` de cinco `torch.Tensor` de forma `(batch_size, hidden_size, num_hidden_layers)`, *opcional*) : Se fornecido, o modelo usa o estado anterior em todos os blocos (o que resultará na saída para os `input_ids` fornecidos como se o modelo adicionasse `state_input_ids + input_ids` como contexto).

use_cache (`bool`, *opcional*) : Se definido como `True`, o último estado é retornado e pode ser usado para gerar rapidamente os próximos logits.

output_attentions (`bool`, *opcional*) : Indica se os tensores de atenção de todas as camadas de atenção devem ser retornados. Consulte `attentions` nos tensores retornados para mais detalhes.

output_hidden_states (`bool`, *opcional*) : Indica se os estados ocultos de todas as camadas devem ser retornados. Consulte `hidden_states` em tensores retornados para mais detalhes.

return_dict (`bool`, *opcional*) : Se deve ou não retornar um [ModelOutput](/docs/transformers/main/pt/main_classes/output#transformers.utils.ModelOutput) em vez de uma tupla simples.

**Retorna:** `RwkvOutput` ou `tuple(torch.Tensor)`

Um `RwkvOutput` ou uma tupla de `torch.Tensor` (se `return_dict=False` for passado ou quando `config.return_dict=False`) contendo vários elementos, dependendo da configuração ([RwkvConfig](/docs/transformers/main/pt/model_doc/rwkv#transformers.RwkvConfig)) e das entradas.

O método forward de [RwkvModel](/docs/transformers/main/pt/model_doc/rwkv#transformers.RwkvModel) substitui o método especial `__call__`.

Embora a receita para a passagem direta precise ser definida dentro desta função, deve-se chamar a instância de `Module` em seguida, em vez desta, pois a primeira cuida da execução das etapas de pré e pós-processamento, enquanto a segunda as ignora silenciosamente.

- **last_hidden_state** (`torch.Tensor` de forma `(batch_size, sequence_length, hidden_size)`, *opcional*) -- Sequência de hidden-states na saída da última camada do modelo.
- **state** (`list` de cinco `torch.Tensor` de forma `(batch_size, hidden_size, num_hidden_layers)`) -- O estado do modelo no último passo de tempo. Pode ser usado em um método forward com o próximo `input_ids` para evitar fornecer os antigos `input_ids`.
- **hidden_states** (`tuple[torch.Tensor, ...]`, *opcional*, retornado quando `output_hidden_states=True` é passado ou quando `config.output_hidden_states=True`) -- Tupla de `torch.Tensor` (uma para a saída dos embeddings, se o modelo tiver uma camada de embedding, + uma para a saída de cada camada) de forma `(batch_size, sequence_length, hidden_size)`.

  Estados ocultos do modelo na saída de cada camada, além das saídas opcionais do embedding inicial.
- **attentions** (`tuple[torch.Tensor, ...]`, *opcional*, retornado quando `output_attentions=True` é passado ou quando `config.output_attentions=True`) -- Tupla de `torch.Tensor` (uma para cada camada) de forma `(batch_size, num_heads, sequence_length, sequence_length)`.

  Pesos de atenção após o softmax de atenção, usados para calcular a média ponderada nas cabeças de autoatenção.

## RwkvLMHeadModel[[transformers.RwkvForCausalLM]]

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

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

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

**Parâmetros:**

config ([RwkvConfig](/docs/transformers/main/pt/model_doc/rwkv#transformers.RwkvConfig)) : Classe de configuração do modelo com todos os parâmetros do modelo. Inicializar com um arquivo de configuração não carrega os pesos associados ao modelo, apenas a configuração. Consulte o método [from_pretrained()](/docs/transformers/main/pt/main_classes/model#transformers.PreTrainedModel.from_pretrained) para carregar os pesos do modelo.

O transformer do modelo RWKV com uma cabeça de modelagem de linguagem no topo (camada linear com pesos vinculados aos embeddings de entrada).

Este modelo herda de [PreTrainedModel](/docs/transformers/main/pt/main_classes/model#transformers.PreTrainedModel). Consulte a documentação da classe pai para os métodos genéricos que a biblioteca implementa para todos os seus modelos (como download ou salvamento, redimensionamento dos embeddings de entrada, poda de cabeças, etc.).

Este modelo também é uma subclasse de [torch.nn.Module](https://pytorch.org/docs/stable/nn.html#torch.nn.Module) do PyTorch. Use-o como um Módulo PyTorch regular e consulte a documentação do PyTorch para todos os assuntos relacionados ao uso e comportamento gerais.

#### 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.Tensor] = None, state: list[torch.Tensor] | 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)
```

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

**Parâmetros:**

input_ids (`torch.LongTensor` de forma `(batch_size, input_ids_length)`) : `input_ids_length` = `sequence_length` se `past_key_values` for `None`, caso contrário `past_key_values.get_seq_length()` (`sequence_length` dos estados de chave e valor passados). Índices dos tokens da sequência de entrada no vocabulário. Se `past_key_values` for usado, apenas os `input_ids` que ainda não têm seu passado calculado devem ser passados como `input_ids`. Os índices podem ser obtidos usando [AutoTokenizer](/docs/transformers/main/pt/model_doc/auto#transformers.AutoTokenizer). Consulte [PreTrainedTokenizer.encode()](/docs/transformers/main/pt/internal/tokenization_utils#transformers.PreTrainedTokenizerBase.encode) e [PreTrainedTokenizer.__call__()](/docs/transformers/main/pt/internal/tokenization_utils#transformers.PreTrainedTokenizerBase.__call__) para mais detalhes. [O que são IDs de entrada?](../glossary#input-ids)

attention_mask (`torch.LongTensor` de forma `(batch_size, sequence_length)`, *opcional*) : Máscara para evitar a execução de atenção nos índices de tokens de preenchimento. Valores de máscara selecionados em `[0, 1]`:  - 1 para tokens que **não estão mascarados**, - 0 para tokens que **estão mascarados**.  [O que são máscaras de atenção?](../glossary#attention-mask)

inputs_embeds (`torch.Tensor` de forma `(batch_size, sequence_length, hidden_size)`, *opcional*) : Opcionalmente, em vez de passar `input_ids`, você pode escolher passar diretamente uma representação incorporada. Isso é útil se você quiser ter mais controle sobre como converter os índices de `input_ids` nos vetores associados do que a matriz de busca de incorporação interna do modelo.

state (`tuple` de cinco `torch.Tensor` de forma `(batch_size, hidden_size, num_hidden_layers)`, *opcional*) : Se fornecido, o modelo usa o estado anterior em todos os blocos (o que resultará na saída para os `input_ids` fornecidos como se o modelo adicionasse `state_input_ids + input_ids` como contexto).

labels (`torch.LongTensor` de forma `(batch_size, sequence_length)`, *opcional*) : Rótulos para modelagem de linguagem. Observe que os rótulos **são deslocados** dentro do modelo, ou seja, você pode definir `labels = input_ids` Os índices são selecionados em `[-100, 0, ..., config.vocab_size]` Todos os rótulos definidos como `-100` são ignorados (mascarados); a perda é calculada apenas para rótulos em `[0, ..., config.vocab_size]`

use_cache (`bool`, *opcional*) : Se definido como `True`, o último estado é retornado e pode ser usado para gerar rapidamente os próximos logits.

output_attentions (`bool`, *opcional*) : Indica se os tensores de atenção de todas as camadas de atenção devem ser retornados. Consulte `attentions` nos tensores retornados para mais detalhes.

output_hidden_states (`bool`, *opcional*) : Indica se os estados ocultos de todas as camadas devem ser retornados. Consulte `hidden_states` em tensores retornados para mais detalhes.

return_dict (`bool`, *opcional*) : Se deve ou não retornar um [ModelOutput](/docs/transformers/main/pt/main_classes/output#transformers.utils.ModelOutput) em vez de uma tupla simples.

logits_to_keep (`Union[int, torch.Tensor]`, *opcional*, padrão `0`) : Se for um `int`, calcula os logits para os últimos `logits_to_keep` tokens. Se for `0`, calcula os logits para todos os `input_ids` (caso especial). Apenas os logits do último token são necessários para a geração, e calculá-los apenas para esse token pode economizar memória, o que se torna bastante significativo para sequências longas ou tamanho de vocabulário grande. Se for um `torch.Tensor`, deve ser 1D, correspondendo aos índices a serem mantidos na dimensão de comprimento da sequência. Isso é útil ao usar o formato de tensor empacotado (uma única dimensão para lote e comprimento da sequência).

**Retorna:** `RwkvCausalLMOutput` ou `tuple(torch.Tensor)`

Um `RwkvCausalLMOutput` ou uma tupla de `torch.Tensor` (se `return_dict=False` for passado ou quando `config.return_dict=False`) contendo vários elementos, dependendo da configuração ([RwkvConfig](/docs/transformers/main/pt/model_doc/rwkv#transformers.RwkvConfig)) e das entradas.

O método forward de [RwkvForCausalLM](/docs/transformers/main/pt/model_doc/rwkv#transformers.RwkvForCausalLM) substitui o método especial `__call__`.

Embora a receita para a passagem direta precise ser definida dentro desta função, deve-se chamar a instância de `Module` em seguida, em vez desta, pois a primeira cuida da execução das etapas de pré e pós-processamento, enquanto a segunda as ignora silenciosamente.

- **loss** (`torch.Tensor` de forma `(1,)`, *opcional*, retornado quando `labels` é fornecido) -- Perda de modelagem de linguagem (para previsão do próximo token).
- **logits** (`torch.Tensor` de forma `(batch_size, sequence_length, config.vocab_size)`) -- Pontuações de previsão da cabeça de modelagem de linguagem (pontuações para cada token do vocabulário antes do SoftMax).
- **state** (`list` de cinco `torch.Tensor` de forma `(batch_size, hidden_size, num_hidden_layers)`) -- O estado do modelo no último passo de tempo. Pode ser usado em um método forward com o próximo `input_ids` para evitar fornecer os antigos `input_ids`.
- **hidden_states** (`tuple[torch.Tensor, ...]`, *opcional*, retornado quando `output_hidden_states=True` é passado ou quando `config.output_hidden_states=True`) -- Tupla de `torch.Tensor` (uma para a saída dos embeddings, se o modelo tiver uma camada de embedding, + uma para a saída de cada camada) de forma `(batch_size, sequence_length, hidden_size)`.

  Estados ocultos do modelo na saída de cada camada, além das saídas opcionais do embedding inicial.
- **attentions** (`tuple[torch.Tensor, ...]`, *opcional*, retornado quando `output_attentions=True` é passado ou quando `config.output_attentions=True`) -- Tupla de `torch.Tensor` (uma para cada camada) de forma `(batch_size, num_heads, sequence_length, sequence_length)`.

  Pesos de atenção após o softmax de atenção, usados para calcular a média ponderada nas cabeças de autoatenção.

Exemplo:

```python
```

## Atenção Rwkv e as fórmulas recorrentes

Em um Transformer auto-regressivo tradicional, a atenção é escrita como

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

em que $Q$, $K$ e $V$ são matrizes de forma `seq_len x hidden_size` chamadas query, key e value (na verdade, são matrizes maiores com uma dimensão de lote e uma dimensão de cabeça de atenção, mas estamos interessados apenas nas duas últimas, onde o produto de matrizes é realizado, então, por simplicidade, consideramos apenas essas duas). O produto $QK^{T}$ então tem a forma `seq_len x seq_len` e podemos tomar o produto de matrizes com $V$ para obter a saída $O$ da mesma forma que as outras.

Substituindo o softmax pelo seu valor, obtemos:

$$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}}}$$

Observe que as entradas em $QK^{T}$ correspondentes a $j > i$ são mascaradas (a soma para em j) porque a atenção não é permitida a olhar para tokens futuros (apenas passados).

Em comparação, a atenção do RWKV é dada por

$$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}}}$$

onde $R$ é uma nova matriz chamada receptância pelo autor, $K$ e $V$ ainda são a chave e o valor ($\sigma$ aqui é a função sigmoide). $W$ é um novo vetor que representa a posição do token e é dado por

$$W_{0} = u \hbox{  e  } W_{k} = (k-1)w \hbox{ para } k \geq 1$$

com $u$ e $w$ como parâmetros aprendíveis, chamados no código de `time_first` e `time_decay`, respectivamente. O numerador e o denominador podem ambos ser expressos recursivamente. Denominando-os $N_{i}$ e $D_{i}$, temos:

$$N_{i} = e^{u + K_{i}} V_{i} + \hat{N}_{i} \hbox{  onde  } \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}$$

somente $\hat{N}_{i}$ (chamado de `numerator_state` no código) satisfaz

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

e

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

somente $\hat{D}_{i}$ (chamado de `denominator_state` no código) satisfaz

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

A fórmula recorrente real usada é um pouco mais complexa, pois, por estabilidade numérica, não queremos calcular exponenciais de números grandes. Normalmente, o softmax não é calculado como está, mas o exponencial do termo máximo é dividido do numerador e do denominador:

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

com $M$ sendo o máximo de todos os $x_{j}$. Portanto, aqui, além de salvar o estado do numerador ($\hat{N}$) e o estado do denominador ($\hat{D}$), também mantemos o registro do máximo de todos os termos encontrados nos exponenciais. Portanto, na verdade, usamos

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

definidas pelas seguintes fórmulas recorrentes:

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

e

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

e $M_{j+1} = q$. Com isso, podemos então calcular

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

e

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

o que finalmente nos dá

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

