Skip to content

feat(axes): l'estimation tonale part des notes — et l'axe 13 resserré derrière - #24

Merged
klodynlov merged 2 commits into
mainfrom
feat/histogramme-brut
Jul 27, 2026
Merged

feat(axes): l'estimation tonale part des notes — et l'axe 13 resserré derrière#24
klodynlov merged 2 commits into
mainfrom
feat/histogramme-brut

Conversation

@klodynlov

Copy link
Copy Markdown
Owner

_pc_hist ne 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_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 pondérées ×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) — 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 :

graine 7 graine 23 graine 31
validation croisée, accords → notes 0.938 → 0.925 0.925 → 0.909 0.934 → 0.925
AUC 13_tonal_contrast 0.56 → 0.49 0.57 → 0.54 0.50 → 0.52

−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.sh passe, 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 min comme 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

  • Poids recalibrés : 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).
  • Sur les packs de loops, aucun changement : 0.400 avant, 0.400 après. Une boucle de quatre mesures ne contient pas de quoi trancher, et ça ne dépend pas de l'histogramme.
  • 236 passed, 40 subtests passed · scripts/check.sh → CHECK OK.

🤖 Generated with Claude Code

klodynlov and others added 2 commits July 27, 2026 18:39
…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>
@klodynlov klodynlov changed the title feat(axes): l'estimation tonale part des notes, plus de leur interprétation feat(axes): l'estimation tonale part des notes — et l'axe 13 resserré derrière Jul 27, 2026
@klodynlov

Copy link
Copy Markdown
Owner Author

L'axe 13 est resserré — le coût est non seulement remboursé, mais dépassé

9aea45e, sur la même branche. La PR portait le diagnostic sans le correctif ; il est mesuré.

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) — crédit plein réservé à 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 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 :

AUC 13_tonal_contrast graine 7 graine 23 graine 31 moyenne
accords (avant toute cette PR) 0.559 0.567 0.509 0.545
notes brutes, bande d'origine 0.488 0.536 0.522 0.515
notes brutes, bande resserrée 0.584 0.696 0.584 0.621

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. 236 passed · check.sh → CHECK OK, seuls 03/04/06 restent sous 0.5, comme avant cette PR.

@klodynlov
klodynlov merged commit cb2c631 into main Jul 27, 2026
10 checks passed
@klodynlov
klodynlov deleted the feat/histogramme-brut branch July 27, 2026 18:05
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