Skip to content

feat(axes): basculer estimate_key sur les profils modaux, poids recalibrés - #23

Merged
klodynlov merged 1 commit into
mainfrom
feat/bascule-modale
Jul 27, 2026
Merged

feat(axes): basculer estimate_key sur les profils modaux, poids recalibrés#23
klodynlov merged 1 commit into
mainfrom
feat/bascule-modale

Conversation

@klodynlov

Copy link
Copy Markdown
Owner

Empilée sur #22 (base feat/profils-modaux). ⚠ À merger en retargetant celle-ci sur main AVANT de merger #22 — un squash de la PR parente supprime sa branche et ferme la fille sans possibilité de la rouvrir (c'est ce qui est arrivé à #20).

#22 validait les profils sans les brancher. Ceci les branche, et mesure le prix avant de le faire.

Le changement

  • estimate_key prend MODAL_PROFILES par défaut. KEY_PROFILES reste nommé : c'est le témoin de toutes les mesures antérieures, et il suffit de le passer pour retrouver l'ancien comportement.
  • Les axes 9 et 14, seuls à déduire une gamme du mode, passent par PARENT_MODE — un mixolydien s'analyse sur la gamme majeure, pas sur la mineure. Les cinq autres consommateurs n'utilisent que la tonique (vérifié un par un ; l'axe 11 collecte le mode mais ne le compare jamais).
  • loop_index groupe les familles sur le mode parent : depuis que l'estimateur connaît le dorien, deux boucles du même kit peuvent sortir l'une « min » et l'autre « dorien », et grouper sur la chaîne exacte scinderait la famille sur une nuance qui ne les empêche pas de jouer ensemble. Même raison pour l'emprunt mélodique de forge_loops.

Ce que ça achète

Deux graines de contrôle fraîches, 311 morceaux non modulants : tonique juste 0.743 → 0.809 et 0.667 → 0.730. Dorien 45/58 → 58/58, mixolydien 9/54 → 21/54, mineur inchangé, majeur 96/97 → 91/97.

Ce que ça coûte — mesuré avant de basculer

La question qui décide : mieux nommer la tonalité dégrade-t-il la tâche que le moteur sait faire, distinguer un original de sa version dégradée ? Trois graines de corpus généré (40 morceaux chacune), calibration complète des deux côtés :

graine validation croisée, KK seul avec les modes AUC 11_modulation_count
7 0.944 0.938 0.604 → 0.650
23 0.916 0.925 0.548 → 0.581
31 0.944 0.934 0.616 → 0.603

Écart moyen −0.002 : rien de mesurable. 11_modulation_count gagne 0.022 en moyenne.

Poids recalibrés

Avec les commandes qui les avaient produits, retrouvées dans l'historique :

  • weights_songs.jsoncalibrate examples --variants 4 --iters 8000 : accuracy calibrée 0.833 → 0.896, validation croisée 0.771 inchangée (corpus de 3 fichiers, le dépôt le signale lui-même comme surappris) ;
  • weights_sloopy.json — 49 loops : calibrée 0.898 → 0.902, validation croisée 0.873 → 0.858, dans son propre écart-type (± 0.05).

scripts/check.sh → CHECK OK, aucun axe ne repasse sous le plancher AUC. 236 passed, 40 subtests passed.

Ce qui reste ouvert

Le mixolydien reste à moitié manqué (21/54). Les modes plus rares (phrygien, lydien) sont absents faute de vérité terrain — make_corpus n'en écrit pas. Et le vrai plafond est ailleurs : l'histogramme sur lequel le moteur appuie sa tonalité reste moins bon que les notes brutes (0.567 contre 0.783), ce qu'aucun profil ne corrige.

🤖 Generated with Claude Code

@klodynlov
klodynlov changed the base branch from feat/profils-modaux to main July 27, 2026 16:24
…ibrés

Le vocabulaire par défaut passe de deux profils à quatre. `KEY_PROFILES`
reste nommé — c'est le témoin de toutes les mesures antérieures. Les axes
9 et 14, seuls à déduire une gamme du mode, passent par `PARENT_MODE` :
un mixolydien s'analyse sur la gamme majeure, pas sur la mineure.

Ce que ça achète, sur deux graines de contrôle fraîches (311 morceaux) :
tonique juste 0.743 → 0.809 et 0.667 → 0.730. Dorien 45/58 → 58/58,
mixolydien 9/54 → 21/54, mineur inchangé, majeur 96/97 → 91/97.

Ce que ça coûte, mesuré avant de basculer : rien. Trois graines de corpus
généré (40 morceaux chacune), calibration complète des deux côtés —
validation croisée 0.944/0.916/0.944 contre 0.938/0.925/0.934, écart
moyen −0.002. `11_modulation_count` gagne 0.022 en moyenne.

Poids publiés recalibrés avec les commandes qui les avaient produits :
weights_songs.json (calibrate examples --variants 4 --iters 8000,
accuracy calibrée 0.833 → 0.896) et weights_sloopy.json (49 loops,
0.898 → 0.902, validation croisée 0.873 → 0.858, dans son écart-type).

L'index de loops groupe les familles sur le mode PARENT : depuis que
l'estimateur connaît le dorien, deux boucles du même kit peuvent sortir
l'une « min » et l'autre « dorien », et grouper sur la chaîne exacte
scinderait la famille sur une nuance qui ne les empêche pas de jouer
ensemble. Même raison pour l'emprunt mélodique de forge_loops.

check.sh → CHECK OK, aucun axe ne repasse sous le plancher.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@klodynlov
klodynlov force-pushed the feat/bascule-modale branch from 1418aad to 046cae7 Compare July 27, 2026 16:26
@klodynlov
klodynlov merged commit 5fd0dc5 into main Jul 27, 2026
10 checks passed
@klodynlov
klodynlov deleted the feat/bascule-modale branch July 27, 2026 16:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant