Utiliser LIT pour analyser des modèles gemma dans Keras

Point sur l'IA générative Exécuter dans Google Colab Afficher la source sur GitHub Apprendre dans des ateliers de programmation

Présentation

Les produits d'IA générative sont relativement nouveaux et les comportements d'une application peuvent varier plus que les formes précédentes de logiciels. Il est donc important de vérifier les modèles de machine learning utilisés, d'examiner des exemples de comportement des modèles et d'enquêter sur les surprises.

L'outil d'interprétation de l'apprentissage (LIT, site Web, GitHub) est une plate-forme de débogage et d'analyse des modèles de ML qui permet de comprendre pourquoi et comment ils se comportent de cette manière.

Dans cet atelier de programmation, vous allez apprendre à utiliser LIT pour tirer le meilleur parti du modèle Gemma de Google. Cet atelier de programmation explique comment utiliser la saillance de séquence, une technique d'interprétabilité, pour analyser différentes approches d'ingénierie des requêtes.

Objectifs de la formation :

  1. Comprendre la saillance des séquences et son utilisation dans l'analyse de modèles
  2. Configuration de LIT pour Gemma afin de calculer les sorties des requêtes et la saillance des séquences.
  3. Utilisez la saillance de la séquence via le module Silence LM pour comprendre l'impact de la conception de requêtes sur les résultats des modèles.
  4. Nous avons testé les suggestions d'améliorations de LIT et constaté leur impact.

Remarque: Cet atelier de programmation utilise l'implémentation Keras NLP de Gemma et TensorFlow v2 pour le backend. Il est vivement recommandé d'utiliser un noyau GPU pour suivre le processus.

Saillance des séquences et ses utilisations dans l'analyse de modèles

Les modèles génératifs texte-vers-texte, tels que Gemma, utilisent une séquence d'entrée sous la forme de texte tokenisé et génèrent de nouveaux jetons qui sont des suites ou des lectures complètes de cette entrée. Cette génération se produit un jeton à la fois, en ajoutant (dans une boucle) chaque jeton nouvellement généré à l'entrée et les générations précédentes jusqu'à ce que le modèle atteigne une condition d'arrêt. par exemple lorsque le modèle génère un jeton de fin de séquence (EOS) ou atteint la longueur maximale prédéfinie.

Les méthodes de saillance sont une classe de techniques Explainable AI (XAI) qui peuvent vous indiquer quelles parties d'une entrée sont importantes pour le modèle pour différentes parties de sa sortie. LIT est compatible avec les méthodes de saillance pour diverses tâches de classification, qui expliquent l'impact d'une séquence de jetons d'entrée sur l'étiquette prédite. La saillance de la séquence généralise ces méthodes aux modèles génératifs texte-vers-texte et explique l'impact des jetons précédents sur les jetons générés.

Vous allez utiliser ici la méthode Grad L2 Norm pour la saillance de la séquence, qui analyse les gradients du modèle et fournit l'amplitude de l'influence de chaque jeton précédent sur la sortie. Simple et efficace, cette méthode a été confirmée pour la classification et d'autres paramètres. Plus le score de saillance est élevé, plus l'influence est élevée. Cette méthode est utilisée dans LIT, car elle est bien comprise et largement utilisée au sein de la communauté des chercheurs sur l'interprétabilité.

Les méthodes de saillance plus avancées basées sur le dégradé incluent Grad ⋅ Entrée et dégradés intégrés. Il existe également des méthodes basées sur l'ablation, telles que LIME et SHAP, qui peuvent être plus robustes, mais beaucoup plus coûteuses à calculer. Reportez-vous à cet article pour obtenir une comparaison détaillée des différentes méthodes de saillance.

Pour en savoir plus sur les méthodes de saillance, consultez cette présentation interactive de la saillance.

Importations, environnement et autres codes de configuration

ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
bigframes 0.21.0 requires scikit-learn>=1.2.2, but you have scikit-learn 1.0.2 which is incompatible.
google-colab 1.0.0 requires ipython==7.34.0, but you have ipython 8.14.0 which is incompatible.

Vous pouvez les ignorer.

Installer LIT et Keras NLP

Pour cet atelier de programmation, vous aurez besoin d'une version récente de keras (3) keras-nlp (0.8.0) et lit-nlp (1.1), ainsi que d'un compte Kaggle pour télécharger le modèle de base.

pip install -q -U lit-nlp
pip uninstall -y umap-learn
pip install -q -U keras-nlp
pip install -q -U keras

Kaggle Access

Pour vous connecter à Kaggle, vous pouvez stocker votre fichier d'identifiants kaggle.json sur ~/.kaggle/kaggle.json ou exécuter la commande suivante dans un environnement Colab. Pour en savoir plus, consultez la documentation du package kagglehub.

import kagglehub

kagglehub.login()

Assurez-vous également d'accepter le contrat de licence de Gemma.

Configurer LIT pour Gemma

Configurer des modèles LIT

import os

os.environ["KERAS_BACKEND"] = "tensorflow"
import keras
import keras_nlp

# Run at half precision.
keras.config.set_floatx("bfloat16")
model_name = 'gemma_instruct_2b_en'
gemma_model = keras_nlp.models.GemmaCausalLM.from_preset(model_name)

Le code suivant initialise les wrappers LIT pour permettre la saillance du modèle Gemma. Le framework LIT les appelle des modèles, mais dans le cas présent, il s'agit simplement de points de terminaison différents pour le même gemma_model sous-jacent que vous avez chargé ci-dessus. Cela permet à LIT de calculer les générations, la tokenisation et la saillance à la demande.

from lit_nlp.examples.models import instrumented_keras_lms

batch_size = 1
max_sequence_length = 512
init_models = instrumented_keras_lms.initialize_model_group_for_salience
models = init_models(model_name, gemma_model,
                     batch_size=batch_size,
                     max_length=max_sequence_length)

Configurer des ensembles de données LIT

Gemma est un modèle génératif texte-vers-texte qui génère du texte en entrée et en génère. Les modèles de LIT supposent que les ensembles de données fourniront les champs suivants pour permettre la génération:

  • prompt: entrée d'un objet KerasGenerationModel.
  • target: séquence cible facultative, telle qu'une réponse de type "vérité terrain" (or) ou une réponse prégénérée du modèle.

LIT inclut un petit ensemble de sample_prompts avec des exemples provenant de différentes sources, telles que:

  • [GSM8K][GSM8K]: résoudre des problèmes de maths en classe à l'aide d'exemples concrets.
  • [Gigaword Benchmark][gigaword]: génération de titres pour un ensemble d'articles courts.
  • [Requête constitutionnelle][requête constitutionnelle]: génération de nouvelles idées sur l'utilisation d'objets avec des consignes/limites

Vous pouvez également charger facilement vos propres données, soit sous forme de fichier .jsonl contenant des enregistrements avec les champs prompt et éventuellement target ([example][jsonl-example]), soit depuis n'importe quel format à l'aide de l'API Dataset de LIT.

Exécutez la cellule ci-dessous pour charger les exemples de requêtes.

from lit_nlp.examples.datasets import lm as lm_data

datasets = {
  'sample_prompts': lm_data.PromptExamples(
      lm_data.PromptExamples.SAMPLE_DATA_PATH
  ),
}

Configurer l'UI LIT

LIT est un outil interactif de compréhension de modèle qui permet une évaluation humaine et une vérification du comportement du modèle. L'interface utilisateur LIT facilite cette interaction en vous permettant de:

  • visualiser vos ensembles de données et les résultats des modèles en direct,
  • Exécuter des méthodes de saillance pour comprendre les jetons d'entrée qui pilotent le comportement du modèle
  • créer des contrefacteurs pour tester des hypothèses.

Le LIT permet tout cela dans la même interface, ce qui permet de passer d'un outil à l'autre plus facilement. Cela est particulièrement utile pour des tâches telles que l'ingénierie des requêtes, que vous étudierez plus tard dans cet atelier de programmation.

Cette mise en page d'interface utilisateur peut être utilisée pour tout autre modèle de langage génératif. Si d'autres fonctionnalités vous intéressent, consultez la liste complète.

from lit_nlp.api import layout
modules = layout.LitModuleName

LM_SALIENCE_LAYOUT = layout.LitCanonicalLayout(
    left={
        'Data Table': [modules.DataTableModule],
        'Datapoint Editor': [modules.DatapointEditorModule],
    },
    upper={  # if 'lower' not specified, this fills the right side
        'Salience': [modules.LMSalienceModule],
    },
    layoutSettings=layout.LayoutSettings(leftWidth=40),
    description='Custom layout for language model salience.',
)

Cette cellule initialise le serveur LIT. Cette opération peut prendre quelques secondes, car elle exécute également le modèle selon les requêtes d'exemple et met en cache le résultat.

from lit_nlp import notebook as lit_notebook

lit_widget = lit_notebook.LitWidget(
    models=models,
    datasets=datasets,
    layouts={'default': LM_SALIENCE_LAYOUT},
    default_layout='default',
)

Vous pouvez maintenant afficher l'interface utilisateur:

lit_widget.render(height=800)
<IPython.core.display.Javascript object>

Vous pouvez également ouvrir LIT en tant que page complète dans un nouvel onglet. Exécutez cette cellule et cliquez sur le lien qu'elle affiche:

lit_widget.render(open_in_new_tab=True)
<IPython.core.display.Javascript object>

Analyser quelques invites de plans pour Gemma dans LIT

Aujourd'hui, les requêtes constituent autant de l'art que de la science, et LIT peut vous aider à améliorer empiriquement les requêtes pour les grands modèles de langage, tels que Gemma. Vous verrez ensuite un exemple d'utilisation de LIT pour explorer les comportements de Gemma, anticiper les problèmes potentiels et améliorer sa sécurité.

Identifier les erreurs dans les requêtes complexes

Deux des techniques de requête les plus importantes pour les prototypes et applications basés sur des LLM de haute qualité sont les requêtes few-shot (incluant des exemples du comportement souhaité dans la requête) et la chaîne de pensée (y compris une forme d'explication ou de raisonnement avant la sortie finale du LLM). Mais créer une requête efficace reste souvent difficile.

Prenons l'exemple d'aider quelqu'un à évaluer s'il aimera la nourriture en fonction de ses goûts. Un modèle initial de requête de chaîne de pensée du prototype pourrait ressembler à ceci:

def analyze_menu_item_template(food_likes, food_dislikes, menu_item):
  return f"""Analyze a menu item in a restaurant.

## For example:

Taste-likes: I've a sweet-tooth
Taste-dislikes: Don't like onions or garlic
Suggestion: Onion soup
Analysis: it has cooked onions in it, which you don't like.
Recommendation: You have to try it.

Taste-likes: I've a sweet-tooth
Taste-dislikes: Don't like onions or garlic
Suggestion: Baguette maison au levain
Analysis: Home-made leaven bread in france is usually great
Recommendation: Likely good.

Taste-likes: I've a sweet-tooth
Taste-dislikes: Don't like onions or garlic
Suggestion: Macaron in france
Analysis: Sweet with many kinds of flavours
Recommendation: You have to try it.

## Now analyze one more example:

Taste-likes: {food_likes}
Taste-dislikes: {food_dislikes}
Suggestion: {menu_item}
Analysis:"""

Avez-vous repéré les problèmes liés à cette invite ? LIT vous aidera à examiner la requête à l'aide du module LM Salience.

Utiliser la saillance de la séquence pour le débogage

Ce module met en évidence les parties de l'invite auxquelles le modèle tient compte lorsqu'il génère sa réponse. La saillance est calculée au plus petit niveau possible (c'est-à-dire pour chaque jeton d'entrée), mais LIT peut agréger la saillance des jetons dans des intervalles plus grands plus interprétables, tels que des lignes, des phrases ou des mots. Pour en savoir plus sur la saillance et sur la façon de l'utiliser pour identifier les biais inconscients, consultez la page Saliency Explorable.

Commençons par donner à l'invite un nouvel exemple d'entrée pour les variables du modèle d'invite:

food_likes = """Cheese"""
food_dislikes = """Can't eat eggs"""
menu_item = """Quiche Lorraine"""

prompt = analyze_menu_item_template(food_likes, food_dislikes, menu_item)
print(prompt)

fewshot_mistake_example = {'prompt': prompt}  # you'll use this below
Analyze a menu item in a restaurant.

## For example:

Taste-likes: I've a sweet-tooth
Taste-dislikes: Don't like onions or garlic
Suggestion: Onion soup
Analysis: it has cooked onions in it, which you don't like.
Recommendation: You have to try it.

Taste-likes: I've a sweet-tooth
Taste-dislikes: Don't like onions or garlic
Suggestion: Baguette maison au levain
Analysis: Home-made leaven bread in france is usually great
Recommendation: Likely good.

Taste-likes: I've a sweet-tooth
Taste-dislikes: Don't like onions or garlic
Suggestion: Macaron in france
Analysis: Sweet with many kinds of flavours
Recommendation: You have to try it.

## Now analyze one more example:

Taste-likes: Cheese
Taste-dislikes: Can't eat eggs
Suggestion: Quiche Lorraine
Analysis:

Si l'interface utilisateur de LIT est ouverte dans la cellule ci-dessus ou dans un onglet distinct, vous pouvez utiliser l'éditeur de points de données de LIT pour ajouter l'invite suivante:

1_Éditeur de points de données.png

Vous pouvez également afficher à nouveau le widget directement avec l'invite qui vous intéresse:

lit_widget.render(data=[fewshot_mistake_example])
<IPython.core.display.Javascript object>

Notez que le modèle est terminé, ce qui est surprenant:

Taste-likes: Cheese
Taste-dislikes: Can't eat eggs
Suggestion: Quiche Lorraine
Analysis: A savoury tart with cheese and eggs
Recommendation: You might not like it, but it's worth trying.

Pourquoi le modèle vous suggère-t-il de manger quelque chose que vous ne pouvez pas manger ?

La saillance de la séquence peut aider à mettre en évidence le problème racine, comme le montre nos exemples few-shot. Dans le premier exemple, le raisonnement en chaîne de pensée de la section d'analyse it has cooked onions in it, which you don't like ne correspond pas à la recommandation finale You have to try it.

Dans le module LM Salience, sélectionnez "Phrases", puis la ligne de recommandation. L'interface utilisateur doit maintenant se présenter comme suit:

3_few_shots_mistake..png

Correction de la "Recommendation" du premier exemple par Avoid, puis réessayons. Cet exemple est préchargé dans les exemples de requêtes de LIT. Vous pouvez donc utiliser cette petite fonction utilitaire pour le récupérer:

def get_fewshot_example(source: str) -> str:
  for example in datasets['sample_prompts'].examples:
    if example['source'] == source:
      return example['prompt']
  raise ValueError(f'Source "{source}" not found in the dataset.')
lit_widget.render(data=[{'prompt': get_fewshot_example('fewshot-fixed')}])
<IPython.core.display.Javascript object>

Le modèle se termine maintenant comme suit:

Taste-likes: Cheese
Taste-dislikes: Can't eat eggs
Suggestion: Quiche Lorraine
Analysis: This dish contains eggs and cheese, which you don't like.
Recommendation: Avoid.

Il est important de retenir que le prototypage précoce permet de détecter les risques auxquels vous ne pensez peut-être pas à l'avance, et la nature sujette aux erreurs des modèles de langage signifie qu'il faut concevoir de manière proactive pour éviter les erreurs. Pour en savoir plus à ce sujet, consultez notre Guide People + AI sur la conception avec l'IA.

Bien que l'invite de quelques plans corrigée soit meilleure, elle n'est pas tout à fait correcte: elle indique correctement à l'utilisateur d'éviter les œufs, mais le raisonnement n'est pas correct, elle indique qu'il n'aime pas les œufs, alors qu'en fait l'utilisateur a déclaré qu'il ne pouvait pas en manger. Dans la section suivante, vous découvrirez comment améliorer vos performances.

Tester des hypothèses pour améliorer le comportement du modèle

La fonctionnalité LIT vous permet de tester les modifications apportées aux requêtes dans la même interface. Dans ce cas, vous allez tester l'ajout d'une constitution pour améliorer le comportement du modèle. Les constitutions font référence aux requêtes de conception dotées de principes pour guider la génération du modèle. Des méthodes récentes permettent même de dériver de manière interactive des principes constitutionnels.

Utilisons cette idée pour améliorer encore davantage la requête. Ajoutez une section avec les principes de génération en haut de notre invite, qui commence désormais comme suit:

Analyze a menu item in a restaurant.

* The analysis should be brief and to the point.
* The analysis and recommendation should both be clear about the suitability for someone with a specified dietary restriction.

## For example:

Taste-likes: I've a sweet-tooth
Taste-dislikes: Don't like onions or garlic
Suggestion: Onion soup
Analysis: it has cooked onions in it, which you don't like.
Recommendation: Avoid.

...

lit_widget.render(data=[{'prompt': get_fewshot_example('fewshot-constitution')}])
<IPython.core.display.Javascript object>

Avec cette mise à jour, l'exemple peut être réexécuté et observer un résultat très différent:

Taste-likes: Cheese
Taste-dislikes: Can't eat eggs
Suggestion: Quiche Lorraine
Analysis: This dish containts eggs, which you can't eat.
Recommendation: Not suitable for you.

La saillance de l'invite peut ensuite être réexaminée pour aider à comprendre pourquoi ce changement se produit:

3_few_shot_constitution.png

Notez que cette recommandation est beaucoup plus sûre. De plus, la catégorie "Ne convient pas à vos besoins" est influencée par le principe d'adéquation avec la restriction alimentaire, ainsi que par l'analyse (ce que l'on appelle la chaîne de pensée). Cela permet de s'assurer que le résultat se produit pour la bonne raison.

Inclure des équipes non techniques dans la vérification et l'exploration des modèles

L'interprétabilité est un travail d'équipe qui couvre l'expertise des spécialistes de l'IA, de la politique, du droit, etc.

L'interaction avec les modèles au tout début du développement exigeait traditionnellement une grande expertise technique, ce qui rendait plus difficile l'accès à ces modèles et leur vérification pour certains collaborateurs. Les outils n'ont historiquement pas existé pour permettre à ces équipes de participer aux premières phases de prototypage.

Grâce à LIT, nous espérons que ce paradigme peut changer. Comme vous l'avez vu dans cet atelier de programmation, le support visuel et la capacité interactive de LIT à examiner la saillance et à explorer des exemples peuvent aider différents partenaires à partager et communiquer leurs conclusions. Cela peut vous permettre d'élargir la diversité de vos collègues pour l'exploration, la vérification et le débogage du modèle. Leur exposition à ces méthodes techniques peut améliorer leur compréhension du fonctionnement des modèles. En outre, un ensemble d'expertise plus diversifié lors des premiers tests de modèles peut également aider à identifier des résultats indésirables susceptibles d'être améliorés.

Récapitulatif

En résumé :

  • L'UI LIT fournit une interface pour l'exécution interactive du modèle, ce qui permet aux utilisateurs de générer directement des sorties et de tester des scénarios de type "Et si ?". Cela s'avère particulièrement utile pour tester différentes variantes de requête.
  • Le module Saillance du LMS fournit une représentation visuelle de la saillance et fournit une précision contrôlable des données. Vous pouvez ainsi communiquer sur les constructions centrées sur l'humain (par exemple, les phrases et les mots) plutôt que sur les constructions centrées sur le modèle (par exemple, les jetons).

Lorsque vous trouvez des exemples problématiques dans les évaluations de votre modèle, importez-les dans LIT pour le débogage. Commencez par analyser la plus grande unité de contenu sensible à laquelle vous pouvez penser et qui est liée logiquement à la tâche de modélisation, utilisez les visualisations pour voir où le modèle assiste correctement ou incorrectement au contenu de la requête, puis affichez le détail dans des unités de contenu plus petites pour décrire plus en détail le comportement incorrect que vous observez afin d'identifier les solutions possibles.

Enfin, Lit s'améliore constamment. Pour en savoir plus sur nos fonctionnalités et partager vos suggestions, cliquez ici.

Annexe: Comment LIT calcule la saillance des séquences

LIT calcule la saillance de la séquence dans un processus en plusieurs étapes.

  1. À l'aide d'une chaîne d'entrée (requête et séquence cible "gold" ou de génération du modèle), tokenisez-la pour l'entrée du modèle.
  2. Calculez une séquence "cible" en effectuant un lancer les jetons d'entrée d'une position à gauche.
  3. Extrayez les représentations vectorielles continues de la séquence de génération et calculez la perte par jeton entre la séquence de génération et la séquence "cible".
  4. Masquez la perte pour isoler les jetons que vous souhaitez expliquer.
  5. Utilisez la fonction tf.GradientTape.gradient() pour calculer les gradients des représentations vectorielles continues d'entrée par rapport à la perte masquée.
  6. Traiter les gradients pour attribuer un score unique à chaque jeton d'entrée Prenons l'exemple de la norme L2 du dégradé à chaque position.

Annexe: Calculer saillance de manière programmatique

Il est possible de calculer les scores de saillance directement à partir de Python, en suivant les étapes ci-dessus que l'outil LIT s'exécute en interne. Pour cela, vous devez suivre trois étapes:

  1. Préparer un exemple et exécuter la fonction de tokenisation du modèle
  2. Préparer un masque qui sélectionne les jetons (prédits) à expliquer,
  3. Appelez le wrapper de salience.

Créer un exemple de saisie pour LIT

{'prompt': 'Keras is a',
 'target': ' deep learning library for Python that provides a wide range of tools and functionalities for building, training, and evaluating deep learning models.\n\n**'}

Remarque sur les conventions d'appel: La fonction de tokenisation et le wrapper de saillance utilisent l'API Model de LIT, où la fonction .predict() prend une liste d'exemples (dicts) et renvoie un générateur de réponses (dicts). Cette méthode est beaucoup plus flexible lorsque vous travaillez avec des ensembles de données plus volumineux ou des modèles plus lents, mais si vous ne souhaitez obtenir que des prédictions sur un seul exemple, vous devez maintenant l'encapsuler avec un élément comme: list(model.predict([example])[0]

Obtenir des jetons vous permettant de sélectionner des cibles d'explication

array(['<bos>', 'K', 'eras', '▁is', '▁a', '▁deep', '▁learning',
       '▁library', '▁for', '▁Python', '▁that', '▁provides', '▁a', '▁wide',
       '▁range', '▁of', '▁tools', '▁and', '▁functionalities', '▁for',
       '▁building', ',', '▁training', ',', '▁and', '▁evaluating', '▁deep',
       '▁learning', '▁models', '.', '\n\n', '**'], dtype='<U16')

Pour calculer la saillance, vous devez créer un masque cible qui spécifie les jetons (prédits) à expliquer. Le masque cible sera un tableau de la même longueur que les jetons, avec des 1 aux positions des jetons que vous voulez expliquer. Utilisons ▁training et ▁evaluating comme cibles:

Préparer le masque cible

{'prompt': 'Keras is a',
 'target': ' deep learning library for Python that provides a wide range of tools and functionalities for building, training, and evaluating deep learning models.\n\n**',
 'target_mask': array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,
        0., 0., 0., 0., 0., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0.],
       dtype=float32)}

Appeler le modèle de saillance

{'grad_l2': array([45.75, 36.75, 61, 5.40625, 4.09375, 5.625, 6.46875, 7.3125, 3.375,
        5.03125, 3.23438, 4.5625, 2.375, 3.40625, 2.75, 1.97656, 3.95312,
        3.42188, 14.125, 4.53125, 11.375, 12.625, 18.5, 4.5625, 6.5, 0, 0,
        0, 0, 0, 0, 0], dtype=bfloat16),
 'grad_dot_input': array([-4.03125, 3.04688, -7.03125, -0.800781, 0.769531, -0.679688,
        -0.304688, 2.04688, 0.275391, -1.25781, -0.376953, -0.0664062,
        -0.0405273, -0.357422, 0.355469, -0.145508, -0.333984, 0.0181885,
        -5.0625, 0.235352, -0.470703, 2.25, 3.90625, -0.199219, 0.929688,
        0, 0, 0, 0, 0, 0, 0], dtype=bfloat16),
 'tokens': array(['<bos>', 'K', 'eras', '▁is', '▁a', '▁deep', '▁learning',
        '▁library', '▁for', '▁Python', '▁that', '▁provides', '▁a', '▁wide',
        '▁range', '▁of', '▁tools', '▁and', '▁functionalities', '▁for',
        '▁building', ',', '▁training', ',', '▁and', '▁evaluating', '▁deep',
        '▁learning', '▁models', '.', '\n\n', '**'], dtype='<U16')}

Et voilà ! Les scores des champs grad_l2 et grad_dot_input sont alignés sur tokens et sont identiques à ceux de l'UI LIT.

Notez que les derniers scores sont de 0: comme notre modèle de langage est de gauche à droite, les jetons situés à droite de notre segment cible n'ont aucune influence sur la prédiction.