Un test que le modèle a déjà vu
L’entraînement, la validation et le test sont trois tas d’exemples séparés. Le modèle apprend sur le premier, vous réglez avec le deuxième et vous jugez avec le troisième.
Si un cas de test se trouve aussi dans le tas d’entraînement, le modèle peut simplement s’en souvenir. Le score paraît alors bon et ne vaut rien.
À la fin de cette leçon
Remarque
Je peux garder les cas de test hors des données d’entraînement.
Mots clés
| Mot | Ce que ça veut dire |
|---|---|
| Jeu d’entraînement | les exemples sur lesquels le modèle apprend |
| Jeu de validation | des exemples qui servent à régler les choix |
| Jeu de test | des exemples gardés de côté pour juger le résultat |
| Fuite | un cas de test qui se trouve aussi dans l’entraînement |
| Doublon | un exemple qui apparaît deux fois |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Trois tas, trois rôles
Découpez votre fichier contrôlé avant d’entraîner. La plupart des exemples vont au jeu d’entraînement. Un tas plus petit, le jeu de validation, sert à comparer vos choix en route. Le jeu de test ne se touche qu’une fois, à la fin.
Découpez selon une règle fixe, comme la position, pour que les mêmes lignes tombent toujours dans le même tas.
Exemple : dix lignes, trois tas
| Tas | Lignes | Sert à |
|---|---|---|
| Entraînement | 1 à 6 | Apprendre |
| Validation | 7 et 8 | Choisir entre des versions |
| Test | 9 et 10 | Un seul jugement final |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Une quasi-copie est une fuite aussi
La ligne 1 dit « Où est mon colis ». La ligne 7 dit « Où est mon colis ? ». Les mots sont les mêmes : le modèle a donc vu la réponse.
Pour attraper ces cas, rendez d’abord les deux textes simples. Passez en minuscules, enlevez la ponctuation et réduisez les espaces. Puis comparez.
Une erreur courante
Attention
Beaucoup pensent qu’un mélange au hasard protège le jeu de test. Un mélange répartit les copies d’un même exemple dans des tas différents. Retirez d’abord les doublons, puis découpez.
Écrire l’assistant du modèle, partie 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' '// Les jetons d’une réponse, ou null si elle n’en donne pas.' 'function compter(donnees, nom) {' ' return donnees.usage && typeof donnees.usage[nom] === \"number\" ? donnees.usage[nom] : null;' '}' > model.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire l’assistant du modèle, partie 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function demander(messages, echantillon, max) {' ' try {' ' const res = await fetch(base + \"/v1/chat/completions\", {' ' method: \"POST\",' ' headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' ' body: JSON.stringify({ model: \"lab\", messages: messages, max_tokens: max || 100 }),' ' signal: AbortSignal.timeout(30000),' ' });' ' if (res.ok === false) throw new Error(\"statut \" + res.status);' ' const d = await res.json();' ' return { texte: d.choices[0].message.content, entree: compter(d, \"prompt_tokens\"), sortie: compter(d, \"completion_tokens\"), enregistre: false };' ' } catch (erreur) {' ' console.log(\"Échantillon enregistré : aucun modèle n’a répondu (\" + erreur.message + \").\");' ' return { texte: echantillon, entree: null, sortie: null, enregistre: true };' ' }' '}' 'module.exports = { demander };' >> model.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire le chercheur de fuites, partie 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { demander } = require(\"./model\");' 'const lignes = [' ' \"Où est mon colis\", \"J’ai été débité deux fois\", \"Annulez ma commande\",' ' \"Le carton est arrivé écrasé\", \"Montant de facture faux\", \"Puis-je changer d’adresse\",' ' \"Où est mon colis ?\", \"Super boutique\", \"Mon remboursement n’est pas arrivé\", \"La boutique ouvre-t-elle le dimanche\",' '];' > adapt3.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire le chercheur de fuites, partie 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function normal(texte) {' ' let sortie = \"\";' ' for (const c of texte.toLowerCase()) {' ' const lettre = c.toLowerCase() === c.toUpperCase() === false;' ' if (lettre || (c >= \"0\" && c <= \"9\") || c === \" \") sortie = sortie + c;' ' }' ' return sortie.split(\" \").filter(function (m) { return m.length > 0; }).join(\" \");' '}' 'const entrainement = lignes.slice(0, 6);' 'const validation = lignes.slice(6, 8);' 'const test = lignes.slice(8);' >> adapt3.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire le chercheur de fuites, partie 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function fuites(depuis, vers) {' ' const vus = depuis.map(normal);' ' return vers.filter(function (t) { return vus.includes(normal(t)); });' '}' 'async function main() {' ' console.log(\"entraînement \" + entrainement.length + \", validation \" + validation.length + \", test \" + test.length);' ' console.log(\"fuites vers la validation : \" + fuites(entrainement, validation).join(\" | \"));' ' console.log(\"fuites vers le test : \" + fuites(entrainement, test).length);' ' const q = \"En une phrase, pourquoi un cas de test ne doit-il jamais figurer dans les données d’entraînement ?\";' ' const echantillon = \"Un modèle peut répéter un exemple déjà vu : un cas de test qui a fui fait paraître le score meilleur qu’il n’est.\";' ' const reponse = await demander([{ role: \"user\", content: q }], echantillon, 60);' ' console.log(\"le modèle dit : \" + reponse.texte);' '}' 'main();' >> adapt3.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Lancer le chercheur de fuites
docker exec -w /home/node/project agent node adapt3.jsAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Ce que le chercheur a signalé
Le Run découpe dix phrases inventées par position et compare le texte simple de chacune. Il trouve une fuite, vers le tas de validation, et aucune vers le tas de test.
La dernière ligne est un court appel au modèle, ou un Échantillon enregistré.