Transformers documentation

RWKV

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v5.22.1).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Ce modèle a été contribué à Hugging Face Transformers le 2023-05-09.

RWKV

Aperçu

Le modèle RWKV (version 4) a été proposé dans ce dépôt

Elle propose une modification de l’attention du Transformer traditionnel pour la rendre linéaire. De cette façon, le modèle peut être utilisé comme un réseau récurrent : transmettre les entrées des horodatages 0 et 1 ensemble est équivalent à transmettre d’abord les entrées de l’horodatage 0, puis les entrées de l’horodatage 1 accompagnées de l’état de l’horodatage 0 (voir l’exemple ci-dessous).

Cela peut être plus efficace qu'un Transformer classique et peut traiter des phrases de n'importe quelle longueur (même si le modèle utilise une longueur de contexte fixe pour l'entraînement).

Ce modèle a été contribué par sgugger. Le code d'origine peut être trouvé ici.

Exemple d'utilisation

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)

Si vous souhaitez vous assurer que le modèle cesse de générer lorsque '\n\n' est détecté, nous recommandons d'utiliser les critères d'arrêt suivants :

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()])

Notes

  • Utilisez le padding à gauche pour la génération par lots. Voir Padding side.

RwkvConfig

classe transformers.RwkvConfig

< >

( transformers_version: str | None = Nonearchitectures: list[str] | None = Noneoutput_hidden_states: bool | None = Falsereturn_dict: bool | None = Truedtype: str | torch.dtype | None = Nonechunk_size_feed_forward: int = 0is_encoder_decoder: bool = Falseid2label: dict[int, str] | dict[str, str] | None = Nonelabel2id: dict[str, int] | dict[str, str] | None = Noneproblem_type: Literal['regression', 'single_label_classification', 'multi_label_classification'] | None = Nonevocab_size: int = 50277context_length: int = 1024hidden_size: int = 4096num_hidden_layers: int = 32attention_hidden_size: int | None = Noneintermediate_size: int | None = Nonelayer_norm_epsilon: float = 1e-05bos_token_id: int | None = 0eos_token_id: int | list[int] | None = 0rescale_every: int = 6tie_word_embeddings: bool = Falseuse_cache: bool = True )

Paramètres

  • vocab_size (int, facultatif, par défaut 50277) — Taille du vocabulaire du modèle. Définit le nombre de jetons différents qui peuvent être représentés par input_ids.
  • context_length (int, facultatif, valeur par défaut 1024) — La longueur de séquence maximale avec laquelle ce modèle peut être utilisé lors d'un seul passage avant (son utilisation en mode RNN permet d'utiliser n'importe quelle longueur de séquence).
  • hidden_size (int, facultatif, par défaut 4096) — Dimension des représentations cachées.
  • num_hidden_layers (int, facultatif, par défaut 32) — Nombre de couches cachées dans le décodeur Transformer.
  • attention_hidden_size (int, facultatif) — Dimension des états cachés de l'attention. Par défaut, elle est égale à hidden_size si non définie.
  • intermediate_size (int, facultatif) — Dimension des représentations du MLP.
  • layer_norm_epsilon (float, facultatif, par défaut 1e-05) — L'épsilon utilisé par les couches de normalisation de couche.
  • bos_token_id (int, facultatif, par défaut 0) — Identifiant du jeton utilisé pour le début de flux dans le vocabulaire.
  • eos_token_id (Union[int, list[int]], facultatif, par défaut 0) — Identifiant du jeton utilisé pour la fin de flux dans le vocabulaire.
  • rescale_every (int, facultatif, valeur par défaut 6) — Lors de l'inférence, les états cachés (ainsi que les poids des couches de sortie correspondantes) sont divisés par 2 toutes les rescale_every couches. Si la valeur est définie sur 0 ou un nombre négatif, aucun rééchelonnement n'est effectué.
  • tie_word_embeddings (bool, facultatif, valeur par défaut False) — Indique s'il faut lier les embeddings de poids selon la correspondance tied_weights_keys du modèle.
  • use_cache (bool, facultatif, valeur par défaut True) — Indique si le modèle doit retourner les dernières attentions clés/valeurs (non utilisé par tous les modèles). N’est pertinent que si config.is_decoder=True ou si le modèle est un modèle génératif uniquement décodeur.

Il s’agit de la classe de configuration destinée à stocker la configuration d’un RwkvModel. Elle est utilisée pour instancier un modèle Rwkv en fonction des arguments spécifiés, en définissant l’architecture du modèle. L’instanciation d’une configuration avec les valeurs par défaut produira une configuration similaire à celle de RWKV/rwkv-4-169m-pile

Les objets de configuration héritent de PreTrainedConfig et peuvent être utilisés pour contrôler les sorties du modèle. Consultez la documentation de PreTrainedConfig pour plus d’informations.

Exemple :

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

classe transformers.RwkvModel

< >

( config: RwkvConfig )

Paramètres

  • config (RwkvConfig) — Classe de configuration du modèle contenant tous les paramètres du modèle. L'initialisation à partir d'un fichier de configuration ne charge pas les poids associés au modèle, uniquement la configuration. Consultez la méthode from_pretrained() pour charger les poids du modèle.

Le modèle Rwkv brut, qui produit des états cachés bruts sans aucune tête spécifique au sommet.

Ce modèle hérite de PreTrainedModel. Consultez la documentation de la classe parente pour les méthodes génériques que la bibliothèque implémente pour tous ses modèles (tels que le téléchargement ou l'enregistrement, le redimensionnement des embeddings d'entrée, la taille des têtes, etc.)

Ce modèle est également une sous-classe de torch.nn.Module de PyTorch. Utilisez-le comme un module PyTorch standard et consultez la documentation de PyTorch pour tout ce qui concerne l'utilisation et le comportement généraux.

forward

< >

( input_ids: typing.Optional[torch.LongTensor] = Noneattention_mask: typing.Optional[torch.LongTensor] = Noneinputs_embeds: typing.Optional[torch.FloatTensor] = Nonestate: list[torch.FloatTensor] | None = Noneuse_cache: bool | None = Noneoutput_attentions: bool | None = Noneoutput_hidden_states: bool | None = Nonereturn_dict: bool | None = None**kwargs ) → RwkvOutput or tuple(torch.FloatTensor)

Paramètres

  • input_ids (torch.LongTensor de forme (batch_size, input_ids_length)) — input_ids_length = sequence_length si past_key_values est None sinon past_key_values.get_seq_length() (sequence_length des états de clés et de valeurs passés en entrée). Indices des jetons de la séquence d'entrée dans le vocabulaire.

    Si past_key_values est utilisé, seuls les input_ids dont le passé n’a pas encore été calculé doivent être passés en tant que input_ids.

    Les indices peuvent être obtenus à l'aide de AutoTokenizer. Consultez PreTrainedTokenizer.encode() et PreTrainedTokenizer.call() pour plus de détails.

    Qu'est-ce que les identifiants d'entrée ?

  • attention_mask (torch.LongTensor de forme (batch_size, sequence_length), facultatif) — Masque pour éviter d'appliquer l'attention aux indices des jetons de bourrage. Les valeurs du masque sont choisies dans [0, 1]:
    • 1 pour les jetons qui ne sont pas masqués,
    • 0 pour les jetons masqués.

    Qu'est-ce que les masques d'attention ?

  • inputs_embeds (torch.FloatTensor de forme (batch_size, sequence_length, hidden_size), facultatif) — Facultativement, au lieu de passer input_ids, vous pouvez choisir de passer directement une représentation intégrée. Cela est utile si vous souhaitez un meilleur contrôle sur la manière de convertir les indices input_ids en vecteurs associés que la matrice de recherche d’intégration interne du modèle.
  • state (tuple de cinq torch.FloatTensor de forme (batch_size, hidden_size, num_hidden_layers), facultatif) — S’il est fourni, le modèle utilise l’état précédent dans tous les blocs (ce qui produira la sortie pour les input_ids fournis comme si le modèle avait ajouté state_input_ids + input_ids comme contexte).
  • use_cache (bool, facultatif) — Si défini sur True, l'état final est renvoyé et peut être utilisé pour générer rapidement les logits suivants.
  • output_attentions (bool, facultatif) — Indique s'il faut ou non retourner les tenseurs d'attention de toutes les couches d'attention. Consultez attentions sous les tenseurs retournés pour plus de détails.
  • output_hidden_states (bool, facultatif) — Indique s'il faut retourner les états cachés de toutes les couches. Voir hidden_states sous les tenseurs retournés pour plus de détails.
  • return_dict (bool, facultatif) — Indique s'il faut retourner un ModelOutput plutôt qu'un simple tuple.

Retourne

RwkvOutput ou tuple(torch.FloatTensor)

Un RwkvOutput ou un tuple de torch.FloatTensor (si return_dict=False est passé ou si config.return_dict=False) comprenant divers éléments selon la configuration (RwkvConfig) et les entrées.

La méthode forward de RwkvModel redéfinit la méthode spéciale __call__.

Bien que la recette de la passe avant doive être définie dans cette fonction, il faut ensuite appeler l'instance Module plutôt que celle-ci, car la première gère l'exécution des étapes de prétraitement et de post-traitement, tandis que la seconde les ignore silencieusement.

  • last_hidden_state (torch.FloatTensor de forme (batch_size, sequence_length, hidden_size), facultatif) — Séquence d'états cachés à la sortie de la dernière couche du modèle.

  • state (list de cinq torch.FloatTensor de forme (batch_size, hidden_size, num_hidden_layers)) — L'état du modèle à la dernière étape temporelle. Peut être utilisé dans une méthode forward avec les input_ids suivants pour éviter de fournir les anciens input_ids.

  • hidden_states (tuple[torch.FloatTensor, ...], facultatif, renvoyé lorsque output_hidden_states=True est passé ou lorsque config.output_hidden_states=True) — Tuple de torch.FloatTensor (un pour la sortie des embeddings, si le modèle possède une couche d’embedding, + un pour la sortie de chaque couche) de forme (batch_size, sequence_length, hidden_size).

    États cachés du modèle à la sortie de chaque couche, ainsi que les sorties d'incorporation initiales facultatives.

  • attentions (tuple[torch.FloatTensor, ...], facultatif, renvoyé lorsque output_attentions=True est passé ou lorsque config.output_attentions=True) — Tuple de torch.FloatTensor (un par couche) de forme (batch_size, num_heads, sequence_length, sequence_length).

    Poids des attentions après le softmax d'attention, utilisés pour calculer la moyenne pondérée dans les têtes d'auto-attention.

RwkvLMHeadModel

classe transformers.RwkvForCausalLM

< >

( config: RwkvConfig )

Paramètres

  • config (RwkvConfig) — Classe de configuration du modèle contenant tous les paramètres du modèle. L'initialisation à partir d'un fichier de configuration ne charge pas les poids associés au modèle, uniquement la configuration. Consultez la méthode from_pretrained() pour charger les poids du modèle.

Le modèle RWKV Model, un transformer doté d'une tête de modélisation de langage au sommet (couche linéaire dont les poids sont liés aux embeddings d'entrée).

Ce modèle hérite de PreTrainedModel. Consultez la documentation de la classe parente pour les méthodes génériques que la bibliothèque implémente pour tous ses modèles (tels que le téléchargement ou l'enregistrement, le redimensionnement des embeddings d'entrée, la taille des têtes, etc.)

Ce modèle est également une sous-classe de torch.nn.Module de PyTorch. Utilisez-le comme un module PyTorch standard et consultez la documentation de PyTorch pour tout ce qui concerne l'utilisation et le comportement généraux.

forward

< >

( input_ids: typing.Optional[torch.LongTensor] = Noneattention_mask: typing.Optional[torch.LongTensor] = Noneinputs_embeds: typing.Optional[torch.FloatTensor] = Nonestate: list[torch.FloatTensor] | None = Nonelabels: typing.Optional[torch.LongTensor] = Noneuse_cache: bool | None = Noneoutput_attentions: bool | None = Noneoutput_hidden_states: bool | None = Nonereturn_dict: bool | None = Nonelogits_to_keep: typing.Union[int, torch.Tensor] = 0**kwargs ) → RwkvCausalLMOutput or tuple(torch.FloatTensor)

Paramètres

  • input_ids (torch.LongTensor de forme (batch_size, input_ids_length)) — input_ids_length = sequence_length si past_key_values est None sinon past_key_values.get_seq_length() (sequence_length des états de clés et de valeurs passés en entrée). Indices des jetons de la séquence d'entrée dans le vocabulaire.

    Si past_key_values est utilisé, seuls les input_ids dont le passé n’a pas encore été calculé doivent être passés en tant que input_ids.

    Les indices peuvent être obtenus à l'aide de AutoTokenizer. Consultez PreTrainedTokenizer.encode() et PreTrainedTokenizer.call() pour plus de détails.

    Qu'est-ce que les identifiants d'entrée ?

  • attention_mask (torch.LongTensor de forme (batch_size, sequence_length), facultatif) — Masque pour éviter d'appliquer l'attention aux indices des jetons de bourrage. Les valeurs du masque sont choisies dans [0, 1]:
    • 1 pour les jetons qui ne sont pas masqués,
    • 0 pour les jetons masqués.

    Qu'est-ce que les masques d'attention ?

  • inputs_embeds (torch.FloatTensor de forme (batch_size, sequence_length, hidden_size), facultatif) — Facultativement, au lieu de passer input_ids, vous pouvez choisir de passer directement une représentation intégrée. Cela est utile si vous souhaitez un meilleur contrôle sur la manière de convertir les indices input_ids en vecteurs associés que la matrice de recherche d’intégration interne du modèle.
  • state (tuple de cinq torch.FloatTensor de forme (batch_size, hidden_size, num_hidden_layers), facultatif) — S’il est transmis, le modèle utilise l’état précédent dans tous les blocs (ce qui produira la sortie pour les input_ids fournis comme si le modèle avait ajouté state_input_ids + input_ids comme contexte).
  • labels (torch.LongTensor de forme (batch_size, sequence_length), facultatif) — Étiquettes pour le modélisation du langage. Notez que les étiquettes sont décalées à l'intérieur du modèle, c'est-à-dire que vous pouvez définir labels = input_ids Les indices sont sélectionnés dans [-100, 0, ..., config.vocab_size] Toutes les étiquettes définies sur -100 sont ignorées (masquées), la perte n'est calculée que pour les étiquettes dans [0, ..., config.vocab_size]
  • use_cache (bool, facultatif) — Si défini sur True, l'état final est renvoyé et peut être utilisé pour générer rapidement les logits suivants.
  • output_attentions (bool, facultatif) — Indique s'il faut ou non retourner les tenseurs d'attention de toutes les couches d'attention. Consultez attentions sous les tenseurs retournés pour plus de détails.
  • output_hidden_states (bool, facultatif) — Indique s'il faut retourner les états cachés de toutes les couches. Voir hidden_states sous les tenseurs retournés pour plus de détails.
  • return_dict (bool, facultatif) — Indique s'il faut retourner un ModelOutput plutôt qu'un simple tuple.
  • logits_to_keep (Union[int, torch.Tensor], facultatif, valeur par défaut 0) — Si c'est un int, calcule les logits pour les logits_to_keep derniers jetons. Si 0, calcule les logits pour tous les input_ids (cas particulier). Seuls les logits du dernier jeton sont nécessaires pour la génération, et les calculer uniquement pour ce jeton peut économiser de la mémoire, ce qui devient assez significatif pour les séquences longues ou les tailles de vocabulaire importantes. Si c'est un torch.Tensor, il doit être 1D et correspondre aux indices à conserver dans la dimension de la longueur de la séquence. Cela est utile lors de l'utilisation du format de tenseurs empilés (une seule dimension pour le lot et la longueur de la séquence).

Retourne

RwkvCausalLMOutput ou tuple(torch.FloatTensor)

Un RwkvCausalLMOutput ou un tuple de torch.FloatTensor (si return_dict=False est passé ou si config.return_dict=False) comprenant divers éléments en fonction de la configuration (RwkvConfig) et des entrées.

La méthode forward de RwkvForCausalLM redéfinit la méthode spéciale __call__.

Bien que la recette de la passe avant doive être définie dans cette fonction, il faut ensuite appeler l'instance Module plutôt que celle-ci, car la première gère l'exécution des étapes de prétraitement et de post-traitement, tandis que la seconde les ignore silencieusement.

  • loss (torch.FloatTensor de forme (1,), facultatif, renvoyé lorsque labels est fourni) — Perte de modélisation du langage (pour la prédiction du jeton suivant).

  • logits (torch.FloatTensor de forme (batch_size, sequence_length, config.vocab_size)) — Scores de prédiction de la tête de modélisation du langage (scores pour chaque jeton du vocabulaire avant SoftMax).

  • state (list de cinq torch.FloatTensor de forme (batch_size, hidden_size, num_hidden_layers)) — L'état du modèle à la dernière étape temporelle. Peut être utilisé dans une méthode forward avec les input_ids suivants pour éviter de fournir les anciens input_ids.

  • hidden_states (tuple[torch.FloatTensor, ...], facultatif, renvoyé lorsque output_hidden_states=True est passé ou lorsque config.output_hidden_states=True) — Tuple de torch.FloatTensor (un pour la sortie des embeddings, si le modèle possède une couche d’embedding, + un pour la sortie de chaque couche) de forme (batch_size, sequence_length, hidden_size).

    États cachés du modèle à la sortie de chaque couche, ainsi que les sorties d'incorporation initiales facultatives.

  • attentions (tuple[torch.FloatTensor, ...], facultatif, renvoyé lorsque output_attentions=True est passé ou lorsque config.output_attentions=True) — Tuple de torch.FloatTensor (un par couche) de forme (batch_size, num_heads, sequence_length, sequence_length).

    Poids des attentions après le softmax d'attention, utilisés pour calculer la moyenne pondérée dans les têtes d'auto-attention.

Exemple :

Attention Rwkv et formules récurrentes

Dans un Transformer auto-régressif traditionnel, l'attention est écrite sous la forme O=softmax(QKT/d)VO = \hbox{softmax}(QK^{T} / \sqrt{d}) V

avec $Q$, KK et VV sont des matrices de forme seq_len x hidden_size appelées requête, clé et valeur (elles sont en réalité des matrices plus grandes avec une dimension de lot et une dimension de tête d'attention, mais nous ne nous intéressons qu'aux deux dernières, c'est-à-dire celles où le produit matriciel est effectué, donc, pour simplifier, nous ne considérons que ces deux dimensions). Le produit QKTQK^{T} a alors la forme seq_len x seq_len et nous pouvons effectuer le produit matriciel avec VV pour obtenir la sortie OO de la même forme que les autres.

Le remplacement du softmax par sa valeur donne : Oi=∑j=1ieQiKjT/dVj∑j=1ieQiKjT/dO_{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}}}

Notez que les éléments de QKTQK^{T} correspondant à $j > i$ sont masqués (la somme s'arrête à j) car l'attention n'est pas autorisée à consulter les jetons futurs (uniquement les jetons passés).

En comparaison, l'attention RWKV est donnée par Oi=σ(Ri)∑j=1ieWi−j+KjVj∑j=1ieWi−j+KjO_{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}}}

où RR est une nouvelle matrice appelée réceptance par l'auteur, KK et VV sont toujours la clé et la valeur ($\sigma$ désigne ici la fonction sigmoïde). WW est un nouveau vecteur qui représente la position du jeton et est donné par W0=u and Wk=(k−1)w for k≥1W_{0} = u \hbox{ and } W_{k} = (k-1)w \hbox{ for } k \geq 1

avec uu et ww des paramètres apprenables nommés dans le code time_first et time_decay respectivement. Le numérateur et le dénominateur peuvent tous deux être exprimés de manière récursive. En les nommant NiN_{i} et DiD_{i} nous avons : Ni=eu+KiVi+N^i where N^i=eKi−1Vi−1+ew+Ki−2Vi−2⋯+e(i−2)w+K1V1N_{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}

de sorte que N^i\hat{N}_{i} (appelé numerator_state dans le code) satisfait N^0=0 and N^j+1=eKjVj+ewN^j\hat{N}_{0} = 0 \hbox{ and } \hat{N}_{j+1} = e^{K_{j}} V_{j} + e^{w} \hat{N}_{j}

et Di=eu+Ki+D^i where D^i=eKi−1+ew+Ki−2⋯+e(i−2)w+K1D_{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}}

de sorte que D^i\hat{D}_{i} (appelée denominator_state dans le code) satisfait D^0=0 and D^j+1=eKj+ewD^j\hat{D}_{0} = 0 \hbox{ and } \hat{D}_{j+1} = e^{K_{j}} + e^{w} \hat{D}_{j}

La formule récurrente réellement utilisée est légèrement plus complexe, car, pour des raisons de stabilité numérique, nous ne souhaitons pas calculer des exponentielles de grands nombres. En général, le softmax n'est pas calculé tel quel, mais l'exponentielle du terme maximal est divisée au numérateur et au dénominateur : exi∑j=1nexj=exi−M∑j=1nexj−M\frac{e^{x_{i}}}{\sum_{j=1}^{n} e^{x_{j}}} = \frac{e^{x_{i} - M}}{\sum_{j=1}^{n} e^{x_{j} - M}}

avec MM le maximum de tous les $x_{j}$. Ici, en plus de sauvegarder l'état du numérateur ($\hat{N}$) et l'état du dénominateur ($\hat{D}$), nous suivons également le maximum de tous les termes rencontrés dans les exponentielles. Nous utilisons donc en réalité N~i=e−MiN^i and D~i=e−MiD^i\tilde{N}_{i} = e^{-M_{i}} \hat{N}_{i} \hbox{ and } \tilde{D}_{i} = e^{-M_{i}} \hat{D}_{i}

définies par les formules récurrentes suivantes : N~0=0 and N~j+1=eKj−qVj+ew+Mj−qN~j where q=max⁡(Kj,w+Mj)\tilde{N}_{0} = 0 \hbox{ and } \tilde{N}_{j+1} = e^{K_{j} - q} V_{j} + e^{w + M_{j} - q} \tilde{N}_{j} \hbox{ where } q = \max(K_{j}, w + M_{j})

et D~0=0 and D~j+1=eKj−q+ew+Mj−qD~j where q=max⁡(Kj,w+Mj)\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})

et $M_{j+1} = q$. Avec celles-ci, nous pouvons ensuite calculer Ni=eu+Ki−qVi+eMiN~i where q=max⁡(u+Ki,Mi)N_{i} = e^{u + K_{i} - q} V_{i} + e^{M_{i}} \tilde{N}_{i} \hbox{ where } q = \max(u + K_{i}, M_{i})

et Di=eu+Ki−q+eMiD~i where q=max⁡(u+Ki,Mi)D_{i} = e^{u + K_{i} - q} + e^{M_{i}} \tilde{D}_{i} \hbox{ where } q = \max(u + K_{i}, M_{i})

ce qui nous donne finalement Oi=σ(Ri)NiDiO_{i} = \sigma(R_{i}) \frac{N_{i}}{D_{i}}

Update on GitHub