Transformers documentation
Personnalisation des tokenizers
Personnalisation des tokenizers
Les tokenizers sont découplés de leurs vocabulaires appris. Cela vous permet d'initialiser un tokenizer vide pour l'entraînement ou d'en créer un directement avec votre propre vocabulaire. Le pipeline de tokenisation sous-jacent reste le même (normaliseur, pré-tokeniseur, algorithme de tokenisation), vous n'avez donc pas besoin de le recréer de zéro.
Ce guide montre comment entraîner et créer un tokeniseur personnalisé.
Aidez l'utilisateur à choisir comment créer ou adapter un tokenizer Transformers. Commencez par déterminer s'il doit entraîner un nouveau vocabulaire, définir un vocabulaire personnalisé ou modifier le pipeline de tokenisation. Utilisez ce guide pour sélectionner l'approche correspondante.
- Demandez la langue ou le domaine, la source et la taille du corpus, le tokenizer de départ, la taille de vocabulaire souhaitée, le modèle cible et l’usage prévu. Posez des questions complémentaires uniquement si les détails manquants influencent le choix, et indiquez vos hypothèses.
- Choisissez le workflow correspondant. Pour ajouter des jetons à un tokenizer existant, utilisez
add_tokenspour les jetons réguliers ouadd_special_tokenslorsqu’ils nécessitent un comportement de jeton spécial. Si vous ajoutez des jetons à un tokenizer associé à un modèle, redimensionnez les embeddings de jetons du modèle avecresize_token_embeddings(len(tokenizer)). Pour un nouveau vocabulaire qui conserve un pipeline de tokenizer existant, utiliseztrain_new_from_iteratoravec des lots de texte représentatifs. Pour un vocabulaire fourni et des règles de fusion, vérifiez si le tokenizer prend en charge ces entrées. N’utilisez un backend personnalisé que si le pipeline existant ne peut pas exprimer le comportement requis. - Vérifiez la compatibilité avec le modèle cible. Un nouveau vocabulaire peut modifier les identifiants de jetons, il ne faut donc pas supposer qu’il correspond aux plongements d’un modèle pré-entraîné. Précisez si le modèle nécessite des plongements correspondants ou une formation supplémentaire.
- Validez le résultat. Enregistrez et rechargez le tokenizer, puis testez l’encodage et le décodage sur des textes représentatifs du domaine ainsi que sur des jetons spéciaux. Signalez les fichiers créés, le tokenizer de départ, la taille du vocabulaire, les résultats des tests et les questions de compatibilité non résolues.
Entraîner un tokenizer
Un tokenizer entraînable vide remplace le vocabulaire par un nouveau vocabulaire cible. Cela est utile pour s'adapter à un nouveau domaine comme la finance, une langue à faibles ressources, ou le code.
Créez un tokenizer vide et chargez un jeu de données.
from datasets import load_dataset
from transformers import GemmaTokenizer
tokenizer = GemmaTokenizer()
dataset = load_dataset("Josephgflowers/Finance-Instruct-500k", split="train")Utilisez la méthode TokenizersBackend.train_new_from_iterator() pour entraîner le tokeniseur. Cette méthode accepte une fonction génératrice pour retourner des blocs de texte depuis le jeu de données, au lieu de tout charger en mémoire d'un coup. L'argument vocab_size définit la taille du vocabulaire des tokeniseurs.
def batch_iterator(batch_size=1000):
for i in range(0, len(dataset), batch_size):
yield dataset[i : i + batch_size]["assistant"]
trained_tokenizer = tokenizer.train_new_from_iterator(
batch_iterator(),
vocab_size=32000,
)
encoded = trained_tokenizer("The stock market rallied today.")
print(encoded["input_ids"])
[5866, 11503, 98, 5885, 8617, 13381, 30]Ajoutez de nouveaux jetons spéciaux avec l’argument new_special_tokens ou utilisez special_tokens_map pour renommer les anciens jetons spéciaux en nouveaux jetons spéciaux.
Enregistrez le nouveau finance tokenizer avec save_pretrained() ou enregistrez-le et téléchargez-le sur le Hub avec push_to_hub(). Cela crée un fichier tokenizer.json qui capture le vocabulaire nouvellement entraîné, les règles de fusion et la configuration complète du pipeline.
trained_tokenizer.save_pretrained("./finance-gemma-tokenizer")
trained_tokenizer.push_to_hub("finance-gemma-tokenizer")Vocabulaire personnalisé
Un tokenizer vide prend en charge un vocabulaire personnalisé grâce aux arguments vocab et merges.
vocabest l'ensemble complet des jetons que le tokeniseur connaît et chaque entrée associe un jeton à son identifiant d'entrée.mergesdéfinit la manière dont l'algorithme BPE doit combiner les jetons adjacents.
from transformers import GemmaTokenizer
vocab={
"<pad>": 0,
"</s>": 1,
"<s>": 2,
"<unk>": 3,
"<mask>": 4,
"▁the": 5,
"▁stock": 6,
"▁market": 7,
"▁": 8,
"r": 9,
"a": 10,
"l": 11,
"i": 12,
"e": 13,
"d": 14,
"ra": 15,
"li": 16,
"lie": 17,
"lied": 18,
"ral": 19,
"ralli": 20,
"rallie": 21,
"rallied": 22,
}
merges=[
("r", "a"), # r + a → ra
("l", "i"), # l + i → li
("li", "e"), # li + e → lie
("lie", "d"), # lie + d → lied
("ra", "l"), # ra + l → ral
("ral", "li"), # ral + li → ralli
("ralli", "e"), # ralli + e → rallie
("rallie", "d"), # rallie + d → rallied
]
tokenizer = GemmaTokenizer(vocab=vocab, merges=merges)
encoded = tokenizer("the stock market rallied")
print(encoded["input_ids"])Sous-classer TokenizersBackend
Tokenizers prend en charge quatre backends différents. En général, vous devez utiliser TokenizersBackend pour définir un nouveau tokenizer, car il est plus rapide.
Le PythonBackend est un tokeniseur en Python pur qui ne s’appuie pas sur des backends tels que Rust, SentencePiece ou mistral-common. Vous ne devriez utiliser PythonBackend que si vous développez un tokeniseur très spécialisé qui ne peut pas être exprimé par le backend Rust.
- Sous-classez TokenizersBackend avec des attributs de classe tels que le côté de bourrage et l'algorithme de tokenisation à utiliser.
- Définissez le pipeline de tokenisation dans le
__init__. Cela inclut l'algorithme de tokenisation à utiliser, la manière de découper le texte brut avant l'algorithme, et la manière de décoder les jetons pour revenir au texte.
from tokenizers import Tokenizer, decoders, pre_tokenizers
from tokenizers.models import BPE
from transformers import TokenizersBackend
class NewTokenizer(TokenizersBackend):
padding_side = "left"
model = BPE
def __init__(
self,
vocab=None,
merges=None,
unk_token="<unk>",
bos_token="<s>",
eos_token="</s>",
pad_token="<pad>",
):
self._vocab = vocab or {
str(unk_token): 0,
str(bos_token): 1,
str(eos_token): 2,
str(pad_token): 3,
}
self._merges = merges or []
self._tokenizer = Tokenizer(
BPE(vocab=self._vocab, merges=self._merges, fuse_unk=True)
)
self._tokenizer.pre_tokenizer = pre_tokenizers.ByteLevel(add_prefix_space=False)
self._tokenizer.decoder = decoders.ByteLevel()
super().__init__(
unk_token=unk_token,
bos_token=bos_token,
eos_token=eos_token,
pad_token=pad_token,
)Entraînez ou enregistrez le nouveau tokenizer vide.
tokenizer = NewTokenizer()
# train on new corpus
corpus = ["The stock market rallied today.", "Bond yields fell sharply."]
trained_tokenizer = tokenizer.train_new_from_iterator(corpus, vocab_size=32000)
# save tokenizer
trained_tokenizer.save_pretrained("./new-tokenizer")