Pytorch
TensorFlow

#
Tout assembler

Dans les dernières sections, nous avons fait de notre mieux pour effectuer la plupart du travail manuellement. Nous avons exploré le fonctionnement des tokenizers et examiné la tokenisation, la conversion en identifiants d’entrée, le padding, la troncature et les masques d’attention.

Cependant, comme nous l’avons vu dans la section 2, l’API 🤗 Transformers peut gérer tout cela pour nous via une fonction dans laquelle nous allons nous plonger ici. Lorsque vous appelez votre `tokenizer` directement sur la phrase, vous récupérez des entrées qui sont prêtes à être passées dans votre modèle :

    from transformers import AutoTokenizer

    checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
    tokenizer = AutoTokenizer.from_pretrained(checkpoint)

    sequence = "I've been waiting for a HuggingFace course my whole life."
    # J'ai attendu un cours d’HuggingFace toute ma vie.

    model_inputs = tokenizer(sequence)

Ici, la variable `model_inputs` contient tout ce qui est nécessaire au bon fonctionnement d’un modèle. Pour DistilBERT, cela inclut les identifiants d’entrée ainsi que le masque d’attention. D’autres modèles qui acceptent des entrées supplémentaires sont également fournis par l’objet `tokenizer`.

Comme nous allons le voir dans les quelques exemples ci-dessous, cette méthode est très puissante. Premièrement, elle peut tokeniser une seule séquence :

    sequence = "I've been waiting for a HuggingFace course my whole life."
    # J'ai attendu un cours d’HuggingFace toute ma vie.

    model_inputs = tokenizer(sequence)

Elle gère également plusieurs séquences à la fois, sans modification de l’API :

    sequences = [
        "I've been waiting for a HuggingFace course my whole life.",
        "So have I!",
    ]  # « J'ai attendu un cours de HuggingFace toute ma vie. », « Moi aussi ! »

    model_inputs = tokenizer(sequences)

Il est possible de faire du padding selon plusieurs objectifs :

    # Remplit les séquences jusqu'à la longueur maximale de la séquence
    model_inputs = tokenizer(sequences, padding="longest")

    # Remplit les séquences jusqu'à la longueur maximale du modèle (512 pour BERT ou DistilBERT)
    model_inputs = tokenizer(sequences, padding="max_length")

    # Remplit les séquences jusqu'à la longueur maximale spécifiée
    model_inputs = tokenizer(sequences, padding="max_length", max_length=8)

La fonction peut également tronquer les séquences :

    sequences = [
        "I've been waiting for a HuggingFace course my whole life.",
        "So have I!",
    ]  # « J'ai attendu un cours de HuggingFace toute ma vie. », « Moi aussi ! »

    # Tronque les séquences qui sont plus longues que la longueur maximale du modèle
    # (512 pour BERT ou DistilBERT)
    model_inputs = tokenizer(sequences, truncation=True)

    # Tronque les séquences qui sont plus longues que la longueur maximale spécifiée
    model_inputs = tokenizer(sequences, max_length=8, truncation=True)

L’objet `tokenizer` peut gérer la conversion en des tenseurs de frameworks spécifiques. Ils peuvent ensuite être directement envoyés au modèle. Par exemple, dans le code suivant, nous demandons au tokenizer de retourner des tenseurs PyTorch lorsque l’on spécifie `"pt"`, de retourner des tenseurs TensorFlow lorsque l’on spécifie `"tf"` et des tableaux NumPy lorsque l’on indique `"np"` :

    sequences = [
        "I've been waiting for a HuggingFace course my whole life.",
        "So have I!",
    ]  # « J'ai attendu un cours de HuggingFace toute ma vie. », « Moi aussi ! »

    # Retourne des tenseurs PyTorch
    model_inputs = tokenizer(sequences, padding=True, return_tensors="pt")

    # Retourne des tenseurs TensorFlow
    model_inputs = tokenizer(sequences, padding=True, return_tensors="tf")

    # Retourne des tableaux NumPy
    model_inputs = tokenizer(sequences, padding=True, return_tensors="np")

##
Jetons spéciaux

Si nous jetons un coup d’œil aux identifiants d’entrée renvoyés par le tokenizer, nous verrons qu’ils sont un peu différents de ceux que nous avions précédemment :

    sequence = "I've been waiting for a HuggingFace course my whole life."
    # « J'ai attendu un cours de HuggingFace toute ma vie. »

    model_inputs = tokenizer(sequence)
    print(model_inputs["input_ids"])

    tokens = tokenizer.tokenize(sequence)
    ids = tokenizer.convert_tokens_to_ids(tokens)
    print(ids)

    [101, 1045, 1005, 2310, 2042, 3403, 2005, 1037, 17662, 12172, 2607, 2026, 2878, 2166, 1012, 102]
    [1045, 1005, 2310, 2042, 3403, 2005, 1037, 17662, 12172, 2607, 2026, 2878, 2166, 1012]

Un identifiant symbolique a été ajouté au début ainsi qu’un autre à la fin. Décodons les deux séquences d’identifiants ci-dessus pour voir de quoi il s’agit :

    print(tokenizer.decode(model_inputs["input_ids"]))
    print(tokenizer.decode(ids))

    "[CLS] i've been waiting for a huggingface course my whole life. [SEP]"
    "i've been waiting for a huggingface course my whole life."

Le tokenizer a ajouté le mot spécial `[CLS]` au début et le mot spécial `[SEP]` à la fin. C’est parce que le modèle a été pré-entraîné avec ces mots, donc pour obtenir les mêmes résultats pour l’inférence, nous devons également les ajouter. Notez que certains modèles n’ajoutent pas de mots spéciaux, ou en ajoutent des différents. Les modèles peuvent aussi ajouter ces mots spéciaux seulement au début, ou seulement à la fin. Dans tous les cas, le tokenizer sait lesquels sont attendus et s’en occupe pour vous.

##
Conclusion : du <i> tokenizer </i> au modèle

Maintenant que nous avons vu toutes les étapes individuelles que l’objet `tokenizer` utilise lorsqu’il est appliqué sur des textes, voyons une dernière fois comment il peut gérer plusieurs séquences (padding), de très longues séquences (troncation) et plusieurs types de tenseurs avec son API principale :

    import torch
    from transformers import AutoTokenizer, AutoModelForSequenceClassification

    checkpoint = "distilbert-base-uncased-finetuned-sst-2-english"
    tokenizer = AutoTokenizer.from_pretrained(checkpoint)
    model = AutoModelForSequenceClassification.from_pretrained(checkpoint)
    sequences = [
        "I've been waiting for a HuggingFace course my whole life.",
        "So have I!",
    ]  # « J'ai attendu un cours de HuggingFace toute ma vie. », « Moi aussi ! »

    tokens = tokenizer(sequences, padding=True, truncation=True, return_tensors="pt")
    output = model(**tokens)