Skip to content
Merged
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,16 @@
" print(f' sparsite {s:.2f} : conserve {int(mask.sum() / mask.size * 100)}% des poids')"
]
},
{
"cell_type": "markdown",
"id": "a3b1799d",
"metadata": {},
"source": [
"### Lecture du résultat\n",
"\n",
"La conservation suit exactement la règle `round((1 - s) × n)` : sur les 10 000 poids du tensor, `s = 0.50` en garde 5 000 (50 %), `s = 0.90` en garde 1 000 (10 %), `s = 0.99` en garde 100 (1 %). Deux détails d'implémentation comptent ici : `np.partition` extrait le seuil (le k-ième plus grand `|w|`) en O(n) sans trier tout le tensor ; et le garde-fou `k = max(1, ...)` garantit qu'au moins un poids survit, même si l'on poussait la sparsité vers 1. Le masque obtenu est *unstructured* : les poids conservés sont éparpillés — le stockage peut être compressé, mais un matmul dense classique n'y gagne rien.\n"
]
},
{
"cell_type": "markdown",
"id": "c623ccdb",
Expand Down Expand Up @@ -245,6 +255,16 @@
" print(f' sparsite {s:.2f} : garde {keep.sum()}/{len(keep)} neurones de sortie')"
]
},
{
"cell_type": "markdown",
"id": "6895cea8",
"metadata": {},
"source": [
"### Lecture du résultat\n",
"\n",
"Deux enseignements dans cette sortie. D'abord le niveau des norms : sur un kernel gaussien i.i.d., les 16 L1-norms tiennent dans l'étroit intervalle **43.82–68.50** (facteur 1,56 entre extrêmes seulement) — sur du bruit, le critère « plus petite norme » discrimine peu. C'est l'entraînement qui écarte les norms (les filtres utiles grossissent), et c'est là que ce critère devient significatif. Ensuite l'effet du pruning structured : `s = 0.25` supprime 4 filtres entiers (12/16 conservés), `s = 0.50` la moitié (8/16) — chaque filtre retiré disparaît **du calcul** de la convolution, et sur le `Linear` 64×128 chaque colonne supprimée retire une unité cachée (48/64 puis 32/64). C'est la différence économique avec le unstructured : ici l'accélération est réelle, sans noyau sparse dédié.\n"
]
},
{
"cell_type": "markdown",
"id": "3e4ff705",
Expand Down Expand Up @@ -518,6 +538,16 @@
"print(f'Train : {len(train_ds)} images, Test : {len(test_ds)} images.')"
]
},
{
"cell_type": "markdown",
"id": "5a1298a1",
"metadata": {},
"source": [
"### Lecture du résultat\n",
"\n",
"L'information utile est la dernière ligne : **20 000 images d'entraînement, 10 000 de test**. Le reste de la sortie n'est que les barres de progression du premier téléchargement de MNIST (9.91 Mo d'images d'entraînement, etc.) — il disparaît des exécutions suivantes une fois le cache `./data` en place. Le sous-ensemble de 20 000 est tiré sans remise par `default_rng(42)` : le tirage est reproductible, et les quatre protocoles de la section 5 comparent leurs accuracies **sur les mêmes données**. Dernier réglage visible : les batchs de test (512) sont 4× plus gros que ceux d'entraînement (128) — sans rétropropagation, le seul coût est mémoire.\n"
]
},
{
"cell_type": "code",
"execution_count": 6,
Expand Down Expand Up @@ -777,6 +807,16 @@
"print(f'Dense final test acc = {dense_test_acc:.4f}')"
]
},
{
"cell_type": "markdown",
"id": "fa7576c5",
"metadata": {},
"source": [
"### Lecture du résultat\n",
"\n",
"La baseline dense converge en 5 epochs : la perte passe de 0.4529 à 0.0671, l'accuracy de test de 0.9298 à 0.9675 — mais le gain de la dernière epoch n'est que de +0.34 point (0.9641 → 0.9675) : la courbe s'aplatit. L'écart final train/test (0.9800 contre 0.9675, soit 1.25 point) signe un léger surapprentissage, attendu pour un MLP de ~235K paramètres nourri de 20K exemples. Ces deux chiffres — **0.9675 en 47.4 s** — sont l'étalon auquel les trois variantes pruning vont se mesurer : l'enjeu de la section 5 est de voir ce qu'il en reste avec 20 % des poids.\n"
]
},
{
"cell_type": "code",
"execution_count": 9,
Expand Down Expand Up @@ -859,6 +899,16 @@
"print(f'LTH final test acc = {lth_test_acc:.4f}')\n"
]
},
{
"cell_type": "markdown",
"id": "9dfcfbd4",
"metadata": {},
"source": [
"### Lecture du résultat\n",
"\n",
"La signature du **reset à l'init** est visible dès la première epoch : la loss repart à 0.5314, au même niveau que celle du dense à son premier passage (0.4529) — le réseau a tout oublié de l'entraînement dense, seul le masque a survécu. Pourtant cinq epochs suffisent à rattraper presque tout : 0.9678 contre 0.9675 au dense, avec 20 % des poids. C'est le comportement qualitatif annoncé par la LTH. Le temps (41.8 s contre 47.4 s au dense) n'est pas une accélération : le masque multiplie les poids par zéro mais les tenseurs restent denses en mémoire — sans noyau sparse dédié, la sparsité ne s'échange pas contre du calcul.\n"
]
},
{
"cell_type": "code",
"execution_count": 10,
Expand Down Expand Up @@ -955,6 +1005,16 @@
"print(f'Pruned final test acc = {pruned_test_acc:.4f}')\n"
]
},
{
"cell_type": "markdown",
"id": "e9e4817a",
"metadata": {},
"source": [
"### Lecture du résultat\n",
"\n",
"Le contraste avec la cellule précédente est immédiat : sans reset, la loss de la première epoch démarre à 0.1133 — environ 4.7× plus bas que le 0.5314 du LTH. Le modèle garde ses poids entraînés, l'entraînement **continue** au lieu de repartir. Conséquence mesurée : 0.9704 en finale, mieux que le LTH (0.9678) **et** que le dense (0.9675). Sur ce terrain léger, conserver les poids entraînés bat le retour à l'init — l'inversion par rapport à la prédiction de la section 5, analysée en synthèse (§6).\n"
]
},
{
"cell_type": "code",
"execution_count": 11,
Expand Down Expand Up @@ -1053,6 +1113,16 @@
"print(f'torch.prune final test acc = {torchprune_test_acc:.4f}')"
]
},
{
"cell_type": "markdown",
"id": "17208331",
"metadata": {},
"source": [
"### Lecture du résultat\n",
"\n",
"Les modules éligibles sont les trois couches `Linear` du MLP (784→256, 256→128, 128→10). Deux choses distinguent cette variante du from-scratch. D'abord le mécanisme : `global_unstructured` traite les poids des trois couches comme **un seul pool** pour fixer le seuil — la sparsité se répartit là où elle coûte le moins, là où le from-scratch l'appliquait couche par couche. Ensuite le résultat : 0.9719, le meilleur des quatre protocoles, avec une loss de départ à 0.0516 (comme le pruning simple, cette variante conserve les poids entraînés). L'écart reste mince — 0.15 point sur le pruning simple (0.9704) — mais il va dans le sens du pool global.\n"
]
},
{
"cell_type": "code",
"execution_count": 12,
Expand Down
Loading