feat(axes): l'estimation tonale part des notes — et l'axe 13 resserré derrière - #24
Conversation
…tation `_pc_hist` remplaçait les notes par une reconstruction — fondamentale de chaque accord détecté ×2, notes de l'accord ×0.5, voix supérieure ×1 — c'est-à-dire qu'elle faisait passer par une détection d'accords à un accord par mesure une information que les notes portaient déjà. Le builder calculait pourtant déjà un chroma pondéré durée × vélocité, percussions exclues, mesure par mesure : il ne le gardait pas. `Section.pc_weights` le conserve, `_pc_hist` le préfère, et retombe sur les accords pour un Score écrit à la main, qui n'a pas de notes. Le mélange a été essayé avant de trancher — réglage sur une graine tenue à part (11), vérification sur deux autres (23, 31) : histogramme graine 11 graine 23 graine 31 notes brutes 0.834 0.783 0.723 notes + basses ×3 0.803 0.743 0.704 notes + 0.25 × accords 0.783 0.743 0.692 notes + 1.0 × accords 0.688 0.691 0.579 accords seuls (ancien) 0.561 0.605 0.491 Chaque cuillerée d'accords dégrade le résultat, sur les trois graines : le réglage optimal était de ne rien mélanger. Bout en bout, l'estimateur du moteur passe de 0.605 à 0.783 (graine 23) et de 0.491 à 0.723 (graine 31). Ce que ça coûte, et ce n'est pas nul : la validation croisée contrastive perd 0.012 en moyenne sur trois graines (les trois dans le même sens), et la perte se concentre sur 13_tonal_contrast — 0.030 d'AUC en moyenne, 0.49 sur une graine. Au-dessus du plancher du gate (0.42), check.sh passe, mais l'axe rejoint la liste des sous-0.5. Explication la plus économique : son ancrage sature dès que la moitié des sections partagent la tonique, et avec une estimation plus nette l'original comme le dégradé y arrivent plus souvent. Ce sont ses bandes qu'il faudrait resserrer — sur une graine, validé sur d'autres. Constaté, pas corrigé. Poids recalibrés (weights_songs 1.000 sur 3 fichiers, surappris et signalé comme tel ; weights_sloopy 0.881, validation croisée 0.853). Un fixture de test gagne une basse : quatre triades plaquées sans basse ne désignent pas leur fondamentale — do-mi-sol et mi-sol-si partagent assez de matière pour qu'un histogramme de hauteurs lise le relatif mineur. L'ancien histogramme s'en sortait parce que la détection d'accords, elle, nomme la fondamentale. La basse manquait au fixture, pas à l'axe. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…turait Le passage aux notes brutes avait coûté 0.030 d'AUC à 13_tonal_contrast. Le diagnostic tenait : sa bande d'ancrage créditait pleinement dès que la moitié des sections partageaient la tonique — réglage fait quand la tonalité était estimée sur les accords détectés, donc bruitée. Avec une estimation nette, l'original comme sa version dégradée franchissent ce seuil, saturent tous les deux, et l'axe cesse de les distinguer. Plus de plateau : band(ancrage, 0.35, 1.0, 1.01, 1.01). Le crédit plein n'est donné qu'à une pièce dont TOUTES les sections partagent la tonique. Réglé sur une graine tenue à part (11 : 0.567 → 0.619), sur un plateau stable de 0.30 à 0.45 — d'où le 0.35 pris au milieu et non le maximum de la grille. Vérifié sur trois graines jamais consultées pour choisir, à travers la calibration complète : AUC 13_tonal_contrast graine 7 graine 23 graine 31 moyenne accords (avant tout) 0.559 0.567 0.509 0.545 notes brutes, bande v3 0.488 0.536 0.522 0.515 notes brutes, bande v4 0.584 0.696 0.584 0.621 L'axe ne récupère pas seulement : il dépasse de 0.076 ce qu'il valait avant qu'on touche à l'histogramme, et quitte la liste des axes sous 0.5. La validation croisée regagne 0.005 et s'établit à 0.007 sous son niveau d'origine — ce qui reste tient à l'histogramme, plus à l'axe. Poids recalibrés. check.sh → CHECK OK. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
L'axe 13 est resserré — le coût est non seulement remboursé, mais dépassé
Sa bande d'ancrage créditait pleinement dès que la moitié des sections partageaient la tonique — réglage fait quand la tonalité était estimée sur les accords détectés, donc bruitée. Avec une estimation nette, l'original comme sa version dégradée franchissent ce seuil, saturent tous les deux, et l'axe cesse de les distinguer. Plus de plateau : Réglé sur une graine tenue à part (11 : 0.567 → 0.619), sur un plateau stable de 0.30 à 0.45 — d'où le 0.35 pris au milieu de l'intervalle et non le maximum de la grille, qui n'aurait mesuré que le bruit de cette graine. Vérifié sur trois graines jamais consultées pour choisir, à travers la calibration complète :
L'axe ne récupère pas seulement les 0.030 perdus : il dépasse de 0.076 ce qu'il valait avant qu'on touche à l'histogramme, et quitte la liste des axes sous 0.5 sur le corpus de validation. La validation croisée contrastive regagne 0.005 et s'établit à 0.007 sous son niveau d'origine (0.932 → 0.920 → 0.925). Ce qui reste tient à l'histogramme lui-même, plus à l'axe — et se paie contre +0.18 de justesse tonale. Poids recalibrés une seconde fois. |
_pc_histne partait pas des notes. Elle les remplaçait par une reconstruction — fondamentale de chaque accord détecté ×2, notes de l'accord ×0.5, voix supérieure ×1 — c'est-à-dire qu'elle faisait passer par une détection d'accords à un accord par mesure une information que les notes portaient déjà.Le builder calculait pourtant déjà, mesure par mesure, un chroma pondéré durée × vélocité et sans percussions. Il ne le gardait pas.
Section.pc_weightsle conserve,_pc_histle préfère, et retombe sur les accords pour unScoreécrit à la main — qui n'a pas de notes.Le mélange a été essayé avant de trancher
Réglage sur une graine tenue à part (11), vérification sur deux autres (23, 31) :
Chaque cuillerée d'accords dégrade le résultat, sur les trois graines. Le réglage optimal était de ne rien mélanger. Bout en bout, l'estimateur du moteur passe de 0.605 à 0.783 (graine 23) et de 0.491 à 0.723 (graine 31) — il rejoint les notes brutes mesurées à part.
Ce que ça coûte — et ce n'est pas nul
Trois graines de corpus généré, calibration complète des deux côtés :
13_tonal_contrast−0.012 de validation croisée en moyenne, les trois graines dans le même sens, et la perte se concentre sur un seul axe :
13_tonal_contrast, −0.030 d'AUC, jusqu'à 0.49. Il reste au-dessus du plancher du gate (0.42),check.shpasse, mais il rejoint la liste des axes sous 0.5 — un axe que le dépôt avait réparé de 0.36 à 0.56, donc ça mérite d'être dit franchement.Explication la plus économique : son ancrage sature dès que la moitié des sections partagent la tonique, et avec une estimation plus nette l'original comme sa version dégradée y arrivent plus souvent. Ce sont ses bandes qu'il faudrait resserrer — réglées sur une graine, validées sur d'autres. Constaté, pas corrigé : c'est le chantier suivant, pas une retouche à glisser ici.
Un fixture a gagné une basse
Quatre triades plaquées sans basse ne désignent pas leur fondamentale : do-mi-sol et mi-sol-si partagent assez de matière pour qu'un histogramme de hauteurs lise le relatif mineur (vérifié : KK seul répond
E mincomme les profils modaux, ce n'est pas un effet de la PR précédente). L'ancien histogramme s'en sortait parce que la détection d'accords, elle, nomme la fondamentale. La basse manquait au fixture, pas à l'axe — elle est là dans toute musique, et dans les autres fixtures du même fichier. Avec elle : ancré 1.000 contre errant 0.182, l'axe discrimine franchement.Divers
weights_songs.json(3 fichiers, accuracy 1.000 — surappris et signalé comme tel par l'outil),weights_sloopy.json(49 loops, 0.881, validation croisée 0.853).236 passed, 40 subtests passed·scripts/check.sh→ CHECK OK.🤖 Generated with Claude Code