Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
2072dd5
Add: notebook 4.2e — détection from scratch, la Focal Loss (Bloc A.3 …
jsboige Sep 14, 2026
5821189
Fix(notebook,#16165): remove navlink to 4.2d (notebook absent de la b…
jsboige Sep 14, 2026
340c33c
Exec(notebook,#16165): Papermill CPU + align prose introductive §4 su…
jsboige Sep 14, 2026
e790625
fix(vision,#16057): focal loss — signe dérivé, sanity BCE pondéré, me…
jsboige Sep 14, 2026
c662cb0
fix(vision,#16165): focal20 source_list_missing_newlines (markdown-re…
jsboige Sep 14, 2026
5ea3d9b
fix(notebook,#16165): focal01/focal08 repr-quoted source entries + RE…
jsboige Sep 14, 2026
0a4a32f
fix(notebook,#16165): reparation 4 review findings — FL signe, p_t co…
jsboige Sep 14, 2026
fbeff49
fix(notebook,#16165): repair 4th review — model capture, honest grad …
jsboige Sep 14, 2026
d8c629c
Fix(#16057): cohérence README 04-Vision + ratio RetinaNet cellule foc…
jsboige Sep 15, 2026
ff62a65
fix(notebook,#16165): ré-alignement cellule focal20 — ratio RetinaNet…
jsboige Sep 15, 2026
5aeadf7
fix(notebook,#16165): empty trigger post-amend to refresh pr-gate ver…
jsboige Sep 15, 2026
7cd4aad
fix(pr,#16165): update body c.1178 — CHANGES_REQUESTED ai-01 review 5…
jsboige Sep 15, 2026
e67697f
Add: notebook 4.2e — détection from scratch, la Focal Loss (Bloc A.3 …
jsboige Sep 14, 2026
59e9a18
Fix(notebook,#16165): remove navlink to 4.2d (notebook absent de la b…
jsboige Sep 14, 2026
8d01e59
Exec(notebook,#16165): Papermill CPU + align prose introductive §4 su…
jsboige Sep 14, 2026
7417d0f
fix(vision,#16057): focal loss — signe dérivé, sanity BCE pondéré, me…
jsboige Sep 14, 2026
8551af9
fix(vision,#16165): focal20 source_list_missing_newlines (markdown-re…
jsboige Sep 14, 2026
1faba18
fix(notebook,#16165): focal01/focal08 repr-quoted source entries + RE…
jsboige Sep 14, 2026
32a52ff
fix(notebook,#16165): reparation 4 review findings — FL signe, p_t co…
jsboige Sep 14, 2026
25113fb
fix(notebook,#16165): repair 4th review — model capture, honest grad …
jsboige Sep 14, 2026
c74e62b
Fix(#16057): cohérence README 04-Vision + ratio RetinaNet cellule foc…
jsboige Sep 15, 2026
7d518a0
fix(notebook,#16165): ré-alignement cellule focal20 — ratio RetinaNet…
jsboige Sep 15, 2026
696e673
fix(notebook,#16165): empty trigger post-amend to refresh pr-gate ver…
jsboige Sep 15, 2026
485807f
fix(pr,#16165): update body c.1178 — CHANGES_REQUESTED ai-01 review 5…
jsboige Sep 15, 2026
afd2900
fix(pr,#16165): README 4.2e timings — 3,6 s CUDA focal11 + CPU 1,3 s …
jsboige Sep 16, 2026
4846734
fix(pr,#16165): C.5 retrait timings absolus README 4.2e — workload st…
jsboige Sep 16, 2026
2697f5e
Merge remote-tracking branch 'origin/main' into fix/16165-rebase-merge
jsboige Sep 17, 2026
acc21e3
Merge remote-tracking branch 'origin/main' into fix/16165-c1208-rebase
jsboige Sep 17, 2026
526200f
Merge remote-tracking branch 'origin/feature/16057-focal-loss' into f…
jsboige Sep 17, 2026
de60b8a
Merge remote-tracking branch 'origin/feature/16057-focal-loss' into f…
jsboige Sep 17, 2026
bd1aab0
fix(pr,#16165): README 04-Vision ligne 38 — cite issues #16241/#16251…
jsboige Sep 17, 2026
de67547
Merge branch 'main' into feature/16057-focal-loss
jsboige Sep 17, 2026
f409bc4
Merge branch 'main' into feature/16057-focal-loss
jsboige Sep 17, 2026
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

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Cette série suit la **même discipline que 03** : *from scratch PUIS framework,
| [4.2 — ConvNet profonde : pourquoi les résiduelles](4.2-ConvNet-Profonde-Residuelles.ipynb) | 20 conv2d empilées nues (effondrement du gradient), skip naïf (gradient réparé mais passe avant qui dérive), bloc pré-norme (les deux réparés), même protocole transposé à 20 blocs d'attention, puis accuracy CIFAR-10 sur 3 graines | **Le skip-connection n'est pas un détail architectural** : c'est le mécanisme qui rend les réseaux profonds entraînables. **C'est le même bloc que l'attention pré-norme dans [3.4](../03-DeepLearning/3.4-Attention-Transformer-From-Scratch.ipynb)** | rapport de gradients `g_0/g_19` : `plain` 2,16e-08 contre `prenorm` 1,01 ; effondrement exponentiel en la profondeur (D = 4 → 28 : 1,47e-01 → 2,02e-12) ; `res_naif` répare le gradient mais `\\|h\\|` dérive d'un facteur 88 et la perte initiale monte à 17,4 au lieu de `ln 5` ; attention nue : rapport **plat** (0,92) alors que `\\|h\\|` est divisé par 2,1e+07 ; CIFAR-10 (5 classes, 3 graines) : `prenorm` 62,0 % ± 2,8 contre `plain` 34,0 % ± 10,0, soit +28,0 points pour un bruit de ±10,4 (rapport 2,7) |
| [4.2b — Lean : le gradient qui meurt, le gradient qui survit](4.2b-Lean-GradientFlow-Vanishing.ipynb) | Companion kernel `lean4-wsl` du lake `learning_theory_lean` : la paire plafond/plancher `c ^ n` (pile plain) vs `(1-c) ^ n` (pile résiduelle) `#check`ée depuis le lake, anti-triangulaire au pire cas `t = ±2/5`, ancres numériques `norm_num`, balayage en profondeur rejoué en `Float`, 3 exercices | **La mesure du 4.2 devient un théorème** : `abs_deriv_plainStack_le` majore, `abs_deriv_residualStack_ge` minore — le raccourci identité garantit un plancher géométrique là où la pile nue a un plafond qui s'effondre | table `boundTable 0.4 [5,10,15,20]` : `c^n` 0,010240 → 0,000000 contre `(1-c)^n` 0,077760 → 0,000037 ; à n = 24 le plancher résiduel tient encore à 5e-06 ; exécution 19 cellules kernel lean4-wsl, 0 erreur (See #13106) |
| [4.2c — Détection d'objets from scratch : la grille d'anchors](4.2c-Detection-Anchor-From-Scratch.ipynb) | Terrain synthétique contrôlé (1-3 objets, largeurs 14-44 px, ratios 0,35-2,9, bruit gaussien + blobs de fond), grille d'anchors 5 184 (3 tailles × 3 ratios, stride 4), IoU vectorisée + garde-fous, assignation 0,5/0,35 + zone d'ombre + meilleur anchor par GT forcé, échantillonnage 1:3, encode/decode (dx, dy, dw, dh), loss BCE + 2×SmoothL1, NMS gloutonne, mAP VOC07/VOC10 calculé à la main, ablation grille carrée, 3 exercices | **Le réseau ne devine pas des boîtes, il corrige des hypothèses** : la détection anchor-based réduit la localisation à une régression de petits décalages contre des priors géométriques — et l'ablation mesure que la diversité des ratios y est absorbée par l'assignation forcée et la plage log ±3 | aller-retour encode/decode à 7,63e-06 px près ; 1,2 % des anchors ≥ 0,5 (le déséquilibre que le 1:3 compense) ; AnchorNet 74 717 paramètres ; 12 époques en 79 s GPU, loss 13,1 → 1,12 ; mAP@0.5 (400 images / 817 GT) : VOC07 0,853 / VOC10 0,914 ; ablation : grille carrée 0,864/0,926 contre complète 0,853/0,914 — écart de l'ordre du point (See #16057) |
| [4.2e — Détection d'objets from scratch : la Focal Loss](4.2e-Detection-FocalLoss-From-Scratch.ipynb) | Dérivation mathématique de $FL(p_t) = -\alpha_t (1 - p_t)^\gamma \log p_t$ depuis la BCE pondérée, implémentation PyTorch vectorisée sans lib, preuve numérique sur le régime 1000:1 (950 easy negatives + 50 hard negatives + 1 positif) que la contribution des easy negatives passe de 29 % du total BCE à 0,0 % en FL (γ=2), comparaison d'entraînement BCE vs focal sur classifieur binaire pathologique (80 positifs vs 8000 négatifs), 3 exercices (gradient analytique vs autograd, focal multi-classe, mini-détecteur avec focal) | **Le déséquilibre pos:neg n'est pas qu'un problème de ratio — c'est un problème de loss** : la BCE pondère tous les exemples pareillement, et les easy negatives continuent d'accumuler leur contribution. Le modulateur $(1-p_t)^\gamma$ écrase les easy examples et préserve les hard — c'est la troisième voie après le sous-échantillonnage (4.2c) et la heatmap gaussienne (4.2d anchor-free). | sur batch pathologique 1000:1, BCE = 64,8 (29 % easy neg / 70 % hard neg / 0,2 % pos) vs FL(γ=2) = 8,2 (0,0 % easy neg / 99,9 % hard neg / 0,0 % pos) — easy neg **entièrement éliminés** ; entraînement 30 époques sur MLP 2→32→1 (2 entraînements, workload stable : batch 80 positifs / 8 000 négatifs, MLP 2→32→1, BCE vs FL(γ=2, α=0,5), torch 2.14.0+cu126, lr 1e-2, Adam, mesure cellule `focal11` post-c.1165 incluant `grad_class_metric` + `loss_share_per_class` — mesure exacte voir cellule `focal11` du notebook) : BCE → rappel sur positifs **= 0,00** (classifieur prédit tout comme négatif), FL(γ=2, α=0,5) → rappel **= 0,84** — la loss seule, sans aucun sous-échantillonnage, suffit à détecter la classe rare (See #16057) |
| [4.2f — Détection SOTA : fine-tuner torchvision](4.2f-Detection-SOTA-Torchvision.ipynb) | Le terrain exact du 4.2c (générateur et graines repris verbatim : mêmes images, mêmes 817 GT de validation), trois familles `torchvision.models.detection` fine-tunées (Faster R-CNN two-stage, RetinaNet one-stage anchors, FCOS anchor-free) via le pattern d'usine uniforme (`num_classes=2, weights=None, weights_backbone=ImageNet`, seuils 0,5/0,45 posés à la construction, `min_size=320` commun), gris → RGB, cibles xyxy/labels, `ap_voc` et matching glouton repris verbatim, comparatif final contre AnchorNet (nombres committés), 3 exercices | **Le pré-entraînement transfère hors domaine** : sur des images grises synthétiques jamais vues d'ImageNet, la moitié du budget du from scratch (1 000 img × 6 ép. contre 2 000 × 12) achète un mAP essentiellement complet — le vrai livrable est le pattern d'usine, vocabulaire de tout pipeline réel | Faster R-CNN 18,9 M · RetinaNet 32,2 M · FCOS 32,1 M paramètres (contre 75 k) ; mAP@0.5 sur les mêmes 400 images : 0,909/0,997 · 0,997/1,000 · 0,909/0,998 contre AnchorNet 0,853/0,914 ; latence 17,7-36,3 ms/img GPU ; fine-tuning 73 s / 109 s / 107 s (See #16057) |
| [4.2g — Détection SOTA : YOLO sous ultralytics](4.2g-Detection-SOTA-Ultralytics.ipynb) | Terrain et protocole du 4.2c inchangés, conversion au format YOLO imposé par le pipeline (images uint8 + labels normalisés + `data.yaml`, répertoire temporaire, décomptes imprimés sans chemin machine), YOLO11n et YOLO11s fine-tunés au budget exact du 4.2f (1 000 × 6, `imgsz=96`, `workers=0`), évaluation `ap_voc` maison à seuils 0,5/0,45 (jamais le mAP auto-rapporté seul), **tableau final bloc A vs B** (AnchorNet, 3 torchvision, 2 YOLO : mAP, latence, paramètres, GFLOPs à 96, lignes de code), 3 exercices | **Le wrapper est un choix d'ingénieur, pas un raccourci** : ~267 lignes effectives contre ~404 au from scratch pour le même terrain ; le nano signe le meilleur rapport latence/précision du comparatif — en échange : format de données imposé, hyperparamètres enfouis, mAP auto-rapporté à protocole interne (l'exercice 3 le confronte au nôtre) | YOLO11n 2,59 M · YOLO11s 9,43 M paramètres ; mAP@0.5 mêmes 400 images : 0,909/0,989 · 0,909/0,993 ; latence 10,3 / 10,8 ms/img GPU (les plus rapides du comparatif) ; GFLOPs à `imgsz=96` : 0,1 / 0,5 ; fine-tuning 57 s / 54 s (See #16057) |
| [4.3 — Transfer learning : réutiliser un ResNet18 pré-entraîné](4.3-TransferLearning-ResNet.ipynb) | Charger ResNet18 pré-entraîné ImageNet, greffer une tête (5 130 params), comparer gelé vs fine-tuné sur EuroSAT (Sentinel-2, 10 classes d'occupation du sol, 80+30 imgs/classe), 3 graines appariées + test de permutation des signes | **Le feature extractor pré-entraîné est réutilisable — et le prix de ne pas l'adapter se mesure** : le gelé fait déjà ~89 % ; le fine-tuné ajoute ~6 points, mais seulement avec un taux décroissant (à taux constants, l'optimiseur oscille et finit sous le gelé) | backbone gelé 11,18 M params (99,95 % du réseau) ; gelé 89,3 % ± 1,3 (5 130 params entraînés) vs fine-tuné 95,6 % ± 0,8 (Adam différencié 3e-4/3e-3, décroissance x0,3/époque, batch 64, 5 époques) ; écart apparié +6,2 pts sur 3 graines (rapport signal/bruit 3,2, p = 0,250 au test de permutation — plancher 0,125 à n = 3) |
Expand All @@ -34,7 +35,7 @@ Cette série suit la **même discipline que 03** : *from scratch PUIS framework,
pip install numpy matplotlib torch torchvision pillow
```

L'entraînement des deux notebooks concernés (4.2 et 4.3) reste **borné CPU** (sous-ensemble CIFAR-10 pour 4.2 ; EuroSAT ~94 Mo au premier run pour 4.3 — cache partagé `~/.cache/coursia-datasets` ; < 10 min/notebook). Les seuils d'entraînement sont calibrés pour la démonstration pédagogique, pas pour la performance ImageNet — voir les notebooks pour les budgets exacts par époque et par taille de sous-ensemble. Mesure sur 4.2 : exécution complète des 48 cellules en 2 min 20 s sur CPU ; mesure sur 4.3 : exécution complète des 35 cellules en 6 min 29 s sur CPU (dont 4 min 45 s d'entraînements) ; mesure sur 4.2c : exécution complète des 33 cellules en 3 min 02 s sur GPU CUDA (dont 1 min 19 s d'entraînement principal + l'ablation), le même budget restant exécutable sur CPU en quelques dizaines de minutes ; mesure sur 4.2f : exécution complète des 30 cellules en 5 min 51 s sur GPU CUDA (dont 4 min 49 s de fine-tuning des trois familles + évaluation sur 400 images), CPU exécutable pour l'inférence mais l'entraînement passe en dizaines de minutes par modèle ; mesure sur 4.2g : exécution complète des 27 cellules en 2 min 19 s sur GPU CUDA (dont 1 min 51 s de fine-tuning YOLO11n + YOLO11s, plus la conversion du dataset au format YOLO) — le nano reste entraînable sur CPU en quelques minutes.
L'entraînement des deux notebooks concernés (4.2 et 4.3) reste **borné CPU** (sous-ensemble CIFAR-10 pour 4.2 ; EuroSAT ~94 Mo au premier run pour 4.3 — cache partagé `~/.cache/coursia-datasets` ; < 10 min/notebook). Les seuils d'entraînement sont calibrés pour la démonstration pédagogique, pas pour la performance ImageNet — voir les notebooks pour les budgets exacts par époque et par taille de sous-ensemble. Mesure sur 4.2 : exécution complète des 48 cellules en 2 min 20 s sur CPU ; mesure sur 4.3 : exécution complète des 35 cellules en 6 min 29 s sur CPU (dont 4 min 45 s d'entraînements) ; mesure sur 4.2c : exécution complète des 33 cellules en 3 min 02 s sur GPU CUDA (dont 1 min 19 s d'entraînement principal + l'ablation), le même budget restant exécutable sur CPU en quelques dizaines de minutes ; mesure sur 4.2e : exécution CPU pour 2 entraînements × 30 époques (workload stable : batch 80 positifs / 8 000 négatifs, MLP 2→32→1, torch 2.14.0+cu126, notebook conçu CPU-first — aucune cellule ne requiert de GPU dédié ; la cellule `focal11` du notebook documente le résumé CUDA de l'entraînement principal ; les deux passages first-hand CPU #16251 (1,3 s, c.1210) et #16241 (3,15 s, c.1204) sont documentés comme **evidence externe** dans les issues respectives — l'écart imputable à la différence de build torch/CPU exact, non réconcilié hors rerun CPU dédié) ; mesure sur 4.2f : exécution complète des 30 cellules en 5 min 51 s sur GPU CUDA (dont 4 min 49 s de fine-tuning des trois familles + évaluation sur 400 images), CPU exécutable pour l'inférence mais l'entraînement passe en dizaines de minutes par modèle ; mesure sur 4.2g : exécution complète des 27 cellules en 2 min 19 s sur GPU CUDA (dont 1 min 51 s de fine-tuning YOLO11n + YOLO11s, plus la conversion du dataset au format YOLO) — le nano reste entraînable sur CPU en quelques minutes.

## Lien avec les autres séries

Expand All @@ -46,6 +47,9 @@ L'entraînement des deux notebooks concernés (4.2 et 4.3) reste **borné CPU**
L'Epic #12422 *« Série Vision 04 (à décider) — Évolution des architectures CNN »* est livrée par cette série :
- 4.1 — [le neurone convolutif from scratch](4.1-Conv-NumPy-Torch-Allclose.ipynb) (livré)
- 4.2 — [pourquoi la profondeur échoue sans résiduelles](4.2-ConvNet-Profonde-Residuelles.ipynb) (livré)
- 4.2b — [companion Lean : le gradient qui meurt, le gradient qui survit](4.2b-Lean-GradientFlow-Vanishing.ipynb) (livré)
- 4.2c — [détection anchor-based from scratch](4.2c-Detection-Anchor-From-Scratch.ipynb) (livré, See #16057)
- 4.2e — [détection from scratch : la Focal Loss](4.2e-Detection-FocalLoss-From-Scratch.ipynb) (livré, See #16057 — bloc A.3 trilogie anchor / anchor-free / focal)
- 4.3 — [transfer learning ResNet](4.3-TransferLearning-ResNet.ipynb) (livré)

La famille **détection d'objets** poursuit sur l'Epic #16057 (même terrain, même protocole d'évaluation) :
Expand Down
Loading