Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,14 @@
"print(\"Vocabulaire caractères :\", sorted(vocab_chars))"
]
},
{
"cell_type": "markdown",
"id": "86f9854d",
"metadata": {},
"source": [
"**Lecture chiffree — les deux extremes en deux lignes de tableau.** `vocabulaire = 188 | tokens/texte ~ 299` contre `vocabulaire = 33 | tokens/texte ~ 1313 | en moyenne 4.39 token/mot`. Le tokenizer-mots coupe la sequence par 4.39 (1313/299) mais paie 188 symboles — et un vocabulaire OUVERT qui grandira a chaque mot nouveau du monde reel. Le tokenizer-caracteres paie 33 symboles fermes mais 1313 tokens : chaque mot devient 4.39 unites que le modele doit traiter une par une. Ces 33 symboles se lisent dans la liste triee : 24 lettres (pas de `k` ni `w` — aucun mot du corpus ne les contient), les 7 accents francais (`à`, `è`, `é`, `ê`, `î`, `ô`, `û`), l'apostrophe et le trait d'union — la fingerprint exacte d'un corpus francais en minuscules. BPE va se placer ENTRE ces deux bornes : quelques dizaines a quelques centaines de symboles, pour un cout par mot proche du tokenizer-mots.\n"
]
},
{
"cell_type": "markdown",
"id": "01ae7f06",
Expand Down Expand Up @@ -287,6 +295,14 @@
" print(f\" {i:>2}. {a!r} + {b!r} -> {a+b!r}\")"
]
},
{
"cell_type": "markdown",
"id": "6e402ba9",
"metadata": {},
"source": [
"**Lecture chiffree — l'ordre des 60 fusions EST la statistique du corpus.** Les trois premieres lignes : `1. 'e' + '</w>' -> 'e</w>'`, `2. 't' + '</w>' -> 't</w>'`, `3. 's' + '</w>' -> 's</w>'` — les terminaisons francaises les plus courantes partent en premier. Puis les digrammes (`'e' + 'n' -> 'en'`, `'o' + 'u' -> 'ou'`, `'a' + 'u' -> 'au'`), puis `12. 'e' + 't</w>' -> 'et</w>'` reconstruit un mot fonction. A l'autre bout de la liste : `57. 'ren' + 'ard</w>' -> 'renard</w>'` et `60. 'or' + 'beau</w>' -> 'orbeau</w>'` — des mots ENTIERS du corpus n'emergent qu'en toutes dernieres fusions, parce qu'un mot entier doit battre la somme des frequences de ses parties. La lecture : BPE apprend d'abord ce qui est TRANSVERSAL (terminaisons, digrammes — utile pour tous les mots), et seulement a la fin ce qui est SPECIFIQUE (les mots frequents de ce corpus precis). C'est un extracteur de morphologie gratuit, par simple comptage de paires.\n"
]
},
{
"cell_type": "markdown",
"id": "c67bdd0d",
Expand Down Expand Up @@ -385,6 +401,14 @@
" print(f\" {w!r:>14} -> {BPE_encode(w)}\")"
]
},
{
"cell_type": "markdown",
"id": "8785506f",
"metadata": {},
"source": [
"**Lecture chiffree — l'inversibilite prouvee, et le gradient frequent/rare en un echantillon.** `decode(encode(mot)) == mot sur 8 mots : True` — la propriete tient par construction (chaque fusion est une concatenation, le decodage recolle). Mais l'echantillon dessous est la vraie lecon : `'vous' -> ['vous']` et `'renard' -> ['renard']` tiennent en UN token (les mots les plus frequents du corpus), `'corbeau' -> ['c', 'orbeau']` en deux, `'fromage' -> ['f', 'ro', 'm', 'age']` en quatre, `'dépourvue' -> ['dé', 'p', 'our', 'v', 'ue']` en cinq (rare, vu une fois). Le cout par mot suit la frequence : c'est la propriete qui rend le BPE economique sur les vraies langues (loi de Zipf — peu de mots tres frequents couvrent beaucoup de texte) et prudent sur le rare : le mot inconnu retombe sur des fragments, jamais sur un echec.\n"
]
},
{
"cell_type": "markdown",
"id": "1dab2e5a",
Expand Down Expand Up @@ -449,6 +473,14 @@
" print(f\" {m:>3} | {v:.3f}\")"
]
},
{
"cell_type": "markdown",
"id": "dad7ebc0",
"metadata": {},
"source": [
"**Lecture chiffree — la courbe du compromis, rendements decroissants chiffres.** `0 | 5.391`, `10 | 4.264`, `60 | 2.997`, `80 | 2.739`. Le premier bloc de 10 fusions gagne 5.391 - 4.264 = 1.127 tokens/mot, soit 0.113 par fusion ; le dernier palier (60 -> 80) gagne 2.997 - 2.739 = 0.258, soit 0.013 par fusion — pres de NEUF fois moins par symbole ajoute au vocabulaire. Chaque fusion coute la meme chose (un symbole a stocker, une ligne d'embedding) mais rapporte de moins en moins : les paires frequentes sont fusionnees en premier, il ne reste que des paires rares. La courbe est concave, et le choix de 60 fusions dans ce notebook tombe au genou : 2.997 tokens/mot, moitie du tokenizer-caracteres (5.391), pour 60+33 symboles seulement. La taille du vocabulaire est une decision d'ingenierie, pas un reglage par defaut.\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
Expand Down Expand Up @@ -564,6 +596,14 @@
"print(f\"{'Qwen (réel)':<22}{qwen.vocab_size:>8} | {tot_qwen}\")"
]
},
{
"cell_type": "markdown",
"id": "2d355f3e",
"metadata": {},
"source": [
"**Lecture chiffree — le jouet contre le reel : 46 contre 21 tokens, pour un vocabulaire 2 667 fois plus petit.** `notre BPE (60) 93 | 46` et `Qwen (réel) 248044 | 21`, avec `mots 188 | 18` comme borne basse mecanique. Trois lectures. (1) Sur ces trois phrases francaises courantes, le Qwen reel est a 3 tokens du decoupage-mots (21 contre 18) : son vocabulaire de 248 044 symboles contient quasi chaque mot francais courant entier. (2) Notre BPE a 93 symboles doit fragmenter les memes mots : 46 tokens, x2.2 le reel, pour un rapport de vocabulaire de 248 044 / 93 = 2 667. (3) La lecon d'echelle : la compacite s'achete en TAILLE de vocabulaire — le jouet montre la MECANIQUE (compter, fusionner), le reel montre le RESULTAT a l'echelle (des annees de corpus, des centaines de milliers de fusions). L'ecart se creuserait sur les mots rares et les noms propres, que le Qwen connait et que le jouet decompose en caracteres.\n"
]
},
{
"cell_type": "markdown",
"id": "ce8205f3",
Expand Down Expand Up @@ -629,6 +669,14 @@
" print(f\"{name:<22}{len(toks):>9}{n_chunks(toks, MAX_TOKENS):>12}\")"
]
},
{
"cell_type": "markdown",
"id": "51090ac3",
"metadata": {},
"source": [
"**Lecture chiffree — la facture RAG du choix de tokenizer : 9 chunks contre 4, a document identique.** `mots 299 3`, `BPE 20 1145 9`, `BPE 80 819 7`, `Qwen (réel) 419 4` (tokens, puis chunks a budget `MAX_TOKENS = 128` fixe). Le document ne change pas d'un mot — seul le tokenizer varie — et le nombre de chunks passe de 4 (Qwen) a 9 (BPE jouet a 20 fusions) : x2.25 sur TOUT le cout aval du RAG (stockage vectoriel, embeddings a calculer, retrieval, contexte consomme). Deuxieme lecture interne : passer le jouet de 20 a 80 fusions economise 1 145 - 819 = 326 tokens, soit exactement 2 chunks de moins (9 -> 7) — la courbe concave de la section 6, convertie en euros d'infrastructure. Et la ligne `mots 3` est un piege a lire honnetement : le plus compact ici, mais vocabulaire ouvert et hors-vocabulaire garanti sur tout texte reel — la borne basse n'est pas une option.\n"
]
},
{
"cell_type": "markdown",
"id": "fe279c5e",
Expand Down Expand Up @@ -694,6 +742,14 @@
"print(\"→ compter les lettres « à l'œil » (10) ne se retrouve PAS dans la découpe, car le mot est fragmenté.\")"
]
},
{
"cell_type": "markdown",
"id": "910f175e",
"metadata": {},
"source": [
"**Lecture chiffree — les cas pathologiques, token par token.** `'strawberry' | [485, 654, 14911] | 10` : trois tokens pour dix lettres, d'ou l'echec celebre du comptage de lettres — les lettres ne sont pas des unites de la representation, la question « combien de r » est mal posee pour un modele. `'élève' | [236940] | 5` : le francais accentue tient en UN token — le vocabulaire Qwen couvre la langue courante mieux que l'intuition ne le suggerre. `'1234' | [16, 17, 18, 19]` : chaque CHIFFRE est un token atomique ; et la coherence se verifie en croisant les lignes — dans `'aérodrome 42' -> [64, 933, 22771, 6439, 220, 19, 17]`, le `42` reprend exactement les ids `19` et `17` du `1234` — chaque chiffre porte un id fixe ('2' = 17, '4' = 19), et l'id d'un chiffre ne code pas sa valeur positionnelle. Consequence directe : l'arithmetique sur grands nombres est difficile pour un LLM non parce qu'il « sait mal compter » mais parce que ses nombres n'ont pas de representation positionnelle — 1234 est quatre symboles independants, pas mille-deux-cent-trente-quatre.\n"
]
},
{
"cell_type": "markdown",
"id": "51c1fbf0",
Expand Down
Loading