Amar Merabti · carnet EN
← Retour au carnet

Exp. 01 · 2026 · projet personnel

Un modèle de langue pour le kabyle, entraîné de zéro

Peut-on entraîner un modèle de langue pour une langue qui n'a presque pas de données ?

36,3 M
paramètres, architecture de type Llama
107 M
tokens de pré-entraînement, en 46 minutes sur une T4
1,977
bits par caractère en validation, −3,3 %
40
tests de régression sur le pipeline de données
01 · Le problème

Une langue qui tient dans un disque dur

Le kabyle est une langue berbère, ma langue maternelle. Tout le texte kabyle exploitable représente environ 40 millions de tokens : trois à quatre ordres de grandeur de moins que ce qu'il faut pour entraîner un modèle généraliste. Une partie dort dans quelque 600 PDF publiés par la communauté, souvent composés avec des polices d'avant Unicode.

Même les modèles multilingues le lisent mal. J'ai mesuré combien de tokens il faut en moyenne pour écrire un mot kabyle avec leurs tokenizers, sur 400 000 caractères :

Tokenizertokens par mot
Qwen3 (1,7B / 4B)2,77
SmolLM3-3B2,96
Mistral-7B v0.33,03
NLLB-200, entraîné avec du kabyle2,26

Un texte anglais tourne autour de 1,3 token par mot : le kabyle coûte donc environ 2,1 fois plus à Qwen3, en calcul comme en contexte. Contrairement à ce que je pensais, les lettres spéciales (ɣ, ḍ, ɛ) n'y sont presque pour rien (pénalité de 1,06) : c'est la morphologie qui coûte.

02 · Premier essai

Un modèle qui apprend par cœur

Ma première version était un GPT classique de 43,27 M de paramètres (8 couches, contexte de 128 tokens), entraîné sur 2 GPU T4 avec les 995 159 tokens de Wikipédia en kabyle. Le tokenizer découpait sur les tirets et mettait tout en minuscules : 35 000 mots distincts, dont 42 % n'apparaissaient qu'une fois, et 6,5 % de mots inconnus.

Résultat : une perte de 1,33 à l'entraînement et 6,21 en validation. Le modèle n'était pas sous-entraîné, il avait mémorisé son corpus. D'après la loi de Chinchilla, 1 M de tokens justifie un modèle d'environ 50 000 paramètres : le mien était près de 800 fois trop gros.

03 · Les données

Déchiffrer avant d'entraîner

La plus grosse partie du travail a été de rendre le texte utilisable. Trois problèmes propres au kabyle :

Des lettres qui ont plusieurs formes. Le ɛ latin, le ε grec et le ԑ cyrillique désignent la même lettre ; ɤ remplace souvent ɣ. Chaque variante crée des mots en double dans le vocabulaire. Le pipeline les normalise au lieu de les rejeter.

Des polices qui chiffrent le texte. Les livres anciens sont composés avec des polices où $ veut dire ɣ et î veut dire ṭ. C'est un chiffrement par substitution, différent pour chaque police, et parfois entre le romain et l'italique d'un même livre. J'ai écrit un décodeur qui travaille police par police, et un solveur qui retrouve automatiquement la table d'une police inconnue en minimisant le taux de mots absents d'un dictionnaire kabyle.

Des mots qui portent une phrase. Le kabyle est agglutinant : yenna-yas (« il lui a dit ») contient sujet, verbe et complément. Le pipeline conserve ces clitiques au lieu de les couper.

Chaque bug rencontré est devenu un test : 40 tests de régression, tous tirés de cas réels.

04 · Le modèle

Pré-entraîner sur les livres, affiner sur les messages

La deuxième version est un Transformer décodeur de type Llama, entraîné de zéro en deux étapes sur une seule T4 de Kaggle.

Architecturedécodeur seul · RMSNorm · RoPE · SwiGLU (1 408)
Taille10 couches · dmodel 512 · 8 têtes de 64 · contexte 512 tokens
TokenizerBPE au niveau de l'octet, 8 192 tokens
Paramètres36 317 696
Étape 1pré-entraînement sur 1,0 M de lignes (120 M de caractères) converties à l'orthographe des messages : 6 548 pas × 16 384 tokens = 107,3 M de tokens, 46 min
Étape 2fine-tuning sur un corpus de discussion privé : 300 pas, 20 % de corpus rejoué dans chaque lot, 1 min 36 s
Courbes de perte. À gauche, pré-entraînement : la perte sur le corpus descend de 9 à 3,6 tandis que celle sur la discussion stagne autour de 7,4. À droite, fine-tuning : la perte de validation sur la discussion descend de 7,4 à 4,24.
Fig. 2 — À gauche, le pré-entraînement fait baisser la perte sur le corpus, mais celle sur la discussion stagne vers 7,4 : les livres ne ressemblent pas à des messages. À droite, 300 pas de fine-tuning la font tomber à 4,24, et elle baissait encore à la fin.
05 · Résultats

Un gain réel, mais modeste

Pour comparer des modèles aux tokenizers différents, je mesure les bits par caractère sur les mêmes 6 600 messages de validation (plus bas, c'est mieux) :

Modèlebits par caractère
11,4 M de paramètres, entraîné sur la discussion seule2,046
36,3 M, pré-entraîné seulement (n'a jamais vu la discussion)3,445
36,3 M, pré-entraîné puis affiné1,977

Le pré-entraînement seul ne suffit pas : le style des messages est trop loin de celui des livres. Combiné au fine-tuning, il bat le modèle entraîné sur la discussion seule de 3,3 %. C'est une amélioration mesurable, pas une percée.

06 · La suite

Adapter plutôt que tout réapprendre

Avec 40 M de tokens, un modèle entraîné de zéro ne saura jamais raisonner. La voie suivante est d'adapter un modèle multilingue : lui apprendre la langue, et garder ce qu'il sait du monde. Le pipeline est écrit et testé : décodage des PDF, corpus filtré et dédoublonné, extension du vocabulaire (cible autour de 1,9 token par mot), pré-entraînement continu, instruction tuning, évaluation et export GGUF pour tourner sur un ordinateur portable. Le budget est estimé à 28 heures de GPU, environ une semaine de quota Kaggle ; comme une T4 ne gère ni le bf16 ni FlashAttention-2, le code détecte la carte et bascule en fp16 avec l'attention SDPA.

Les corpus viennent en grande partie de la communauté NLP kabyle (Imsidag-community, boffire), de Tatoeba, de Common Voice et de Wikipédia. Rendre à cette communauté un corpus fusionné et normalisé serait sans doute plus utile que le modèle lui-même.