{"notes":[{"id":"classic-cnns/stochastic-depth","category":"classic-cnns","legacyPath":"","legacySlug":"","legacyPaths":[],"title":"Stochastic Depth","subtitle":"Cette couche a pris sa journée","author":"Z. Yuan","paperDate":"2016-03-30","publishedOn":"2026-03-04","world":"external/stochastic-depth","paperTitle":"Deep Networks with Stochastic Depth","paperUrl":"https://arxiv.org/abs/1603.09382","bibliography":{"title":"Deep Networks with Stochastic Depth","authors":["Gao Huang","Yu Sun","Zhuang Liu","Daniel Sedra","Kilian Weinberger"],"url":"https://arxiv.org/abs/1603.09382","pdfUrl":"https://arxiv.org/pdf/1603.09382v3","codeUrl":null,"preprint":{"id":"1603.09382","submittedOn":"2016-03-30","url":"https://arxiv.org/abs/1603.09382"},"publication":null,"citation":"@misc{classiccnnsstochasticdepth2016,\n  title = {{Deep Networks with Stochastic Depth}},\n  author = {Gao Huang and Yu Sun and Zhuang Liu and Daniel Sedra and Kilian Weinberger},\n  year = {2016},\n  eprint = {1603.09382},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/1603.09382}\n}\n","citationPath":"/content/papers/citations/classic-cnns/stochastic-depth.3716109ef477.bib"},"thumbnail":{"src":"/content/papers/assets/620e6ddf909f1f405e38b6055bd732ae4c4b7c208f147e00b870a56642020c02.png","width":963,"height":339},"locale":"fr","path":"/content/papers/fr/classic-cnns/stochastic-depth.7e0025863915.md","headings":[{"id":"définir-le-problème","text":"Définir le problème","depth":2},{"id":"résoudre-le-problème","text":"Résoudre le problème","depth":2},{"id":"des-blocs-absents-au-hasard","text":"Des blocs absents au hasard","depth":3},{"id":"les-premières-couches-sont-plus-souvent-présentes","text":"Les premières couches sont plus souvent présentes","depth":3},{"id":"au-test-multiplier-par-la-probabilité-de-survie","text":"Au test, multiplier par la probabilité de survie","depth":3},{"id":"pourquoi-ça-marche","text":"Pourquoi ça marche ?","depth":3},{"id":"discussion","text":"Discussion","depth":2},{"id":"taux-derreur-et-temps-dentraînement","text":"Taux d'erreur et temps d'entraînement","depth":3},{"id":"mille-deux-cents-couches","text":"Mille deux cents couches","depth":3},{"id":"pas-de-victoire-sur-imagenet","text":"Pas de victoire sur ImageNet","depth":3},{"id":"le-gradient-est-il-vraiment-plus-fort","text":"Le gradient est-il vraiment plus fort ?","depth":3},{"id":"quelle-probabilité-de-survie-choisir","text":"Quelle probabilité de survie choisir ?","depth":3},{"id":"conclusion","text":"Conclusion","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"classic-cnns/resnet","relation":"referenced","topic":""},{"id":"classic-cnns/resnet-v2","relation":"referenced","topic":""},{"id":"classic-cnns/densenet","relation":"referenced","topic":""}]},{"id":"classic-cnns/resnet","category":"classic-cnns","legacyPath":"classic-cnns/1512-resnet","legacySlug":"1512-resnet","legacyPaths":[],"title":"ResNet","subtitle":"Un réseau convolutif de 100 couches","author":"Z. Yuan","paperDate":"2015-12-10","publishedOn":"2024-08-08","paperTitle":"Deep Residual Learning for Image Recognition","paperUrl":"https://arxiv.org/abs/1512.03385","bibliography":{"title":"Deep Residual Learning for Image Recognition","authors":["Kaiming He","Xiangyu Zhang","Shaoqing Ren","Jian Sun"],"url":"https://arxiv.org/abs/1512.03385","pdfUrl":"https://arxiv.org/pdf/1512.03385","codeUrl":null,"preprint":{"id":"1512.03385","submittedOn":"2015-12-10","url":"https://arxiv.org/abs/1512.03385"},"publication":{"venue":"CVPR","year":2016,"kind":"conference","url":"https://doi.org/10.1109/cvpr.2016.90"},"citation":"@misc{classiccnnsresnet2015,\n  title = {{Deep Residual Learning for Image Recognition}},\n  author = {Kaiming He and Xiangyu Zhang and Shaoqing Ren and Jian Sun},\n  year = {2015},\n  eprint = {1512.03385},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/1512.03385}\n}\n","citationPath":"/content/papers/citations/classic-cnns/resnet.cf4014e8baae.bib"},"thumbnail":{"src":"/content/papers/assets/b8fe87fe757249ea6d7bb667fef3196754b9f80e28bf842a69b540ca94585d08.jpg","width":1224,"height":408},"locale":"fr","path":"/content/papers/fr/classic-cnns/resnet.2cc70ebed590.md","headings":[{"id":"définition-du-problème","text":"Définition du problème","depth":2},{"id":"résolution-du-problème","text":"Résolution du problème","depth":2},{"id":"quest-ce-quun-résidu-","text":"Qu'est-ce qu'un résidu ?","depth":3},{"id":"apprentissage-résiduel","text":"Apprentissage résiduel","depth":3},{"id":"blocs-résiduels","text":"Blocs résiduels","depth":3},{"id":"architecture-du-réseau","text":"Architecture du réseau","depth":3},{"id":"configuration-des-paramètres","text":"Configuration des paramètres","depth":3},{"id":"discussion","text":"Discussion","depth":2},{"id":"resnet-18-contre-resnet-34","text":"ResNet-18 contre ResNet-34","depth":3},{"id":"blocs-goulots-pour-les-réseaux-plus-profonds","text":"Blocs goulots pour les réseaux plus profonds","depth":3},{"id":"résultats-sur-imagenet","text":"Résultats sur ImageNet","depth":3},{"id":"conclusion","text":"Conclusion","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"classic-cnns/vgg","relation":"background","topic":"Entraîner des réseaux convolutifs plus profonds"},{"id":"classic-cnns/densenet","relation":"next","topic":"Entraîner des réseaux convolutifs plus profonds"}]},{"id":"classic-cnns/resnet-v2","category":"classic-cnns","legacyPath":"","legacySlug":"","legacyPaths":[],"title":"ResNet v2","subtitle":"Le raccourci doit rester propre","author":"Z. Yuan","paperDate":"2016-03-16","publishedOn":"2026-02-14","world":"external/resnet-v2","paperTitle":"Identity Mappings in Deep Residual Networks","paperUrl":"https://arxiv.org/abs/1603.05027","bibliography":{"title":"Identity Mappings in Deep Residual Networks","authors":["Kaiming He","Xiangyu Zhang","Shaoqing Ren","Jian Sun"],"url":"https://arxiv.org/abs/1603.05027","pdfUrl":"https://arxiv.org/pdf/1603.05027v3","codeUrl":null,"preprint":{"id":"1603.05027","submittedOn":"2016-03-16","url":"https://arxiv.org/abs/1603.05027"},"publication":null,"citation":"@misc{classiccnnsresnetv22016,\n  title = {{Identity Mappings in Deep Residual Networks}},\n  author = {Kaiming He and Xiangyu Zhang and Shaoqing Ren and Jian Sun},\n  year = {2016},\n  eprint = {1603.05027},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/1603.05027}\n}\n","citationPath":"/content/papers/citations/classic-cnns/resnet-v2.3d311a21e308.bib"},"thumbnail":{"src":"/content/papers/assets/7eda4acdde3019e92c5b44f59917b1e493a5b11b5b8a63280d03b15787934ef5.png","width":967,"height":469},"locale":"fr","path":"/content/papers/fr/classic-cnns/resnet-v2.1e2cdeb3e2c3.md","headings":[{"id":"définir-le-problème","text":"Définir le problème","depth":2},{"id":"résoudre-le-problème","text":"Résoudre le problème","depth":2},{"id":"deux-applications-identité","text":"Deux applications identité","depth":3},{"id":"que-se-passe-t-il-si-lon-charge-le-raccourci","text":"Que se passe-t-il si l'on charge le raccourci ?","depth":3},{"id":"où-placer-la-relu-qui-suit-laddition","text":"Où placer la ReLU qui suit l'addition ?","depth":3},{"id":"changer-de-point-de-vue-la-préactivation","text":"Changer de point de vue : la préactivation","depth":3},{"id":"discussion","text":"Discussion","depth":2},{"id":"plus-cest-profond-plus-lécart-se-creuse","text":"Plus c'est profond, plus l'écart se creuse","depth":3},{"id":"comparaison-avec-dautres-méthodes","text":"Comparaison avec d'autres méthodes","depth":3},{"id":"conclusion","text":"Conclusion","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"classic-cnns/resnet","relation":"referenced","topic":""},{"id":"classic-cnns/highway-networks","relation":"referenced","topic":""},{"id":"classic-cnns/inception-v4","relation":"referenced","topic":""}]},{"id":"classic-cnns/densenet","category":"classic-cnns","legacyPath":"classic-cnns/1608-densenet","legacySlug":"1608-densenet","legacyPaths":[],"title":"DenseNet","subtitle":"Tout relier","author":"Z. Yuan","paperDate":"2016-08-25","publishedOn":"2024-07-02","paperTitle":"Densely Connected Convolutional Networks","paperUrl":"https://arxiv.org/abs/1608.06993","bibliography":{"title":"Densely Connected Convolutional Networks","authors":["Gao Huang","Zhuang Liu","Laurens van der Maaten","Kilian Q. Weinberger"],"url":"https://arxiv.org/abs/1608.06993","pdfUrl":"https://arxiv.org/pdf/1608.06993","codeUrl":null,"preprint":{"id":"1608.06993","submittedOn":"2016-08-25","url":"https://arxiv.org/abs/1608.06993"},"publication":{"venue":"CVPR","year":2017,"kind":"conference","url":"https://arxiv.org/abs/1608.06993"},"citation":"@misc{classiccnnsdensenet2016,\n  title = {{Densely Connected Convolutional Networks}},\n  author = {Gao Huang and Zhuang Liu and Laurens van der Maaten and Kilian Q. Weinberger},\n  year = {2016},\n  eprint = {1608.06993},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/1608.06993}\n}\n","citationPath":"/content/papers/citations/classic-cnns/densenet.6f28153b67f7.bib"},"thumbnail":{"src":"/content/papers/assets/4f073a0fd1fc5b7415ca19c48934d180f9043fddc08301819a50ceb1b0ebfc69.jpg","width":1184,"height":828},"locale":"fr","path":"/content/papers/fr/classic-cnns/densenet.85e3233664cd.md","headings":[{"id":"définition-du-problème","text":"Définition du problème","depth":2},{"id":"résolution-du-problème","text":"Résolution du problème","depth":2},{"id":"architecture-du-réseau","text":"Architecture du réseau","depth":3},{"id":"pooling-moyen","text":"Pooling moyen","depth":3},{"id":"taux-de-croissance","text":"Taux de croissance","depth":3},{"id":"couches-bottleneck","text":"Couches bottleneck","depth":3},{"id":"compression","text":"Compression","depth":3},{"id":"détails-de-mise-en-œuvre","text":"Détails de mise en œuvre","depth":3},{"id":"discussion","text":"Discussion","depth":2},{"id":"résultats-expérimentaux","text":"Résultats expérimentaux","depth":3},{"id":"modèles-compacts","text":"Modèles compacts","depth":3},{"id":"réutilisation-des-caractéristiques","text":"Réutilisation des caractéristiques","depth":3},{"id":"conclusion","text":"Conclusion","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"classic-cnns/resnet","relation":"background","topic":"Entraîner des réseaux convolutifs plus profonds"}]}],"text":"Entraîner un réseau très profond pose un dilemme.\n\nDans un réseau peu profond, le signal circule bien dans les deux sens et l'entraînement est rapide, mais l'expressivité est limitée. Un réseau profond est plus expressif, mais le gradient s'évanouit, les caractéristiques calculées au début sont délavées couche après couche par les poids, et le temps d'entraînement augmente avec la profondeur : un ResNet de 152 couches demande plusieurs semaines d'entraînement sur ImageNet, même avec plusieurs GPU.\n\nEt si l'on utilisait un réseau peu profond à l'entraînement, et un réseau profond au test ?\n\nL'idée semble contradictoire. En mars 2016, Gao Huang, Yu Sun, Daniel Sedra et Kilian Q. Weinberger, de l'université Cornell, et Zhuang Liu, de l'université Tsinghua, publient cet article, présenté ensuite à l'ECCV 2016. Leur approche : construire le réseau aussi profond qu'à l'ordinaire, mais, à l'entraînement, retirer au hasard une partie des blocs résiduels à chaque mini-lot, en ne gardant que leurs raccourcis.\n\n## Définir le problème\n\nLes auteurs énumèrent trois problèmes que rencontrent les réseaux très profonds :\n\n1. **La disparition du gradient** : en remontant, le gradient est multiplié encore et encore par de petits poids, et devient minuscule dans les premières couches.\n2. **La perte progressive des caractéristiques en propagation avant** : les caractéristiques d'entrée, ou celles calculées par les premières couches, sont multipliées encore et encore par des poids initialisés au hasard et finissent « délavées » ; les couches suivantes peinent à trouver une direction de gradient pertinente.\n3. **Un temps d'entraînement trop long** : les durées de propagation avant et de rétropropagation sont proportionnelles à la profondeur.\n\nResNet et les Highway Networks traitent les deux premiers problèmes avec des raccourcis, qui permettent aux caractéristiques et au gradient de contourner les couches de poids. Le troisième demeure : autant de couches dans le réseau, autant de couches à calculer à chaque pas.\n\nExiste-t-il un moyen de rendre le réseau « en moyenne » moins profond à l'entraînement, tout en conservant toute sa profondeur au test ?\n\n\n> [!TIP]\n> \n> Pour les blocs résiduels de ResNet, vous pouvez commencer par notre note :\n> \n> - **[[15.12] ResNet : Un réseau convolutif de 100 couches](/blog/papers/classic-cnns/resnet)**\n\n\n## Résoudre le problème\n\n### Des blocs absents au hasard\n\nLes auteurs utilisent tels quels les blocs résiduels du ResNet d'origine. La sortie du $\\ell$-ième bloc s'écrit :\n\n$$\nH_\\ell = \\mathrm{ReLU}\\big(f_\\ell(H_{\\ell-1}) + \\mathrm{id}(H_{\\ell-1})\\big)\n$$\n\n$f_\\ell$ enchaîne « convolution, BN, ReLU, convolution, BN », et $\\mathrm{id}$ est le raccourci identité.\n\nLa profondeur stochastique n'ajoute qu'une variable aléatoire de Bernoulli $b_\\ell \\in \\{0, 1\\}$ :\n\n$$\nH_\\ell = \\mathrm{ReLU}\\big(b_\\ell\\, f_\\ell(H_{\\ell-1}) + \\mathrm{id}(H_{\\ell-1})\\big)\n$$\n\nPour $b_\\ell = 1$, on retrouve le bloc résiduel d'origine. Pour $b_\\ell = 0$, la branche résiduelle disparaît entièrement, et il reste $\\mathrm{ReLU}(H_{\\ell-1})$.\n\nPetit détail au passage : $H_{\\ell-1}$ est la sortie de la dernière ReLU du bloc précédent, donc jamais négative (l'entrée du premier bloc est elle aussi la sortie d'un groupe « convolution, BN, ReLU ») ; ainsi $\\mathrm{ReLU}(H_{\\ell-1}) = H_{\\ell-1}$. Un bloc absent est donc exactement une application identité, et le signal passe intact au bloc suivant.\n\nLa probabilité que $b_\\ell = 1$ est notée $p_\\ell$ ; les auteurs l'appellent **probabilité de survie**. Le tirage est refait à chaque mini-lot, et un bloc tiré absent n'est pas calculé du tout à cette étape : ni propagation avant, ni rétropropagation, ni mise à jour des poids.\n\n### Les premières couches sont plus souvent présentes\n\nComment fixer la probabilité de survie de chaque bloc ? Le plus simple est de prendre la même pour tous. Les auteurs recommandent une décroissance linéaire : $p_0 = 1$ du côté de l'entrée, $p_L$ pour le dernier bloc, et une décroissance proportionnelle entre les deux :\n\n$$\np_\\ell = 1 - \\frac{\\ell}{L}(1 - p_L)\n$$\n\n[![En haut, une rangée de barres graduées 1,0 ; 0,9 ; 0,8 ; 0,7 ; 0,6 et 0,5, dont la partie bleue représente la probabilité de survie et raccourcit de gauche à droite ; de petites icônes à côté illustrent les deux états d'un bloc, active et inactive. En bas, une photo de fleur sert d'Input, suivie de cinq blocs résiduels f1 à f5 séparés par H1 à H4 ; f3 et f5 sont barrés d'une croix rouge, signe qu'ils sont sautés cette fois-ci](/content/papers/assets/620e6ddf909f1f405e38b6055bd732ae4c4b7c208f147e00b870a56642020c02.png)](/content/papers/assets/620e6ddf909f1f405e38b6055bd732ae4c4b7c208f147e00b870a56642020c02.png)\n\n*Fig. 2 de l'article, extraite de la [**page 5 du PDF v3**](https://arxiv.org/pdf/1603.09382v3#page=5). Décroissance linéaire avec $p_0 = 1$ et $p_L = 0.5$ ; l'entrée du premier bloc est traitée comme un $H_0$ toujours présent.*\n\nL'argument des auteurs : les premières couches extraient des caractéristiques de bas niveau dont toutes les couches suivantes ont besoin ; elles doivent donc être présentes de façon plus fiable. Les expériences montrent aussi que la décroissance linéaire fait mieux qu'une probabilité fixe ; et comme les résultats sont peu sensibles à $p_L$, les auteurs utilisent $p_L = 0.5$ dans tout l'article.\n\nPrenons le ResNet de 110 couches utilisé couramment dans les expériences sur CIFAR, qui compte $L = 54$ blocs résiduels :\n\n```python\nimport torch\n\nL, p_L = 54, 0.5                                  # ResNet-110 : 54 blocs résiduels\np = torch.tensor([1 - l / L * (1 - p_L) for l in range(1, L + 1)])\nprint(\"probabilités de survie des trois premiers blocs :\", [f\"{v:.3f}\" for v in p[:3]], \"; des trois derniers :\", [f\"{v:.3f}\" for v in p[-3:]])\nprint(\"profondeur attendue :\", round(p.sum().item(), 2), \"; formule (3L-1)/4 =\", (3 * L - 1) / 4)\n\ntorch.manual_seed(0)\nactive = torch.bernoulli(p.expand(10000, L)).sum(dim=1)   # tirage de 10000 mini-lots\nprint(\"tirage réel : en moyenne\", round(active.mean().item(), 2), \"blocs, au minimum\", int(active.min()), \", au maximum\", int(active.max()))\nprint(\"nombre de sous-réseaux possibles : 2^54 =\", f\"{2 ** L:.3e}\")\n```\n\n```text\nprobabilités de survie des trois premiers blocs : ['0.991', '0.981', '0.972'] ; des trois derniers : ['0.519', '0.509', '0.500']\nprofondeur attendue : 40.25 ; formule (3L-1)/4 = 40.25\ntirage réel : en moyenne 40.25 blocs, au minimum 28 , au maximum 51\nnombre de sous-réseaux possibles : 2^54 = 1.801e+16\n```\n\nÀ l'entraînement, chaque passage n'utilise en moyenne qu'environ 40 blocs, contre les 54 au complet au test. La profondeur attendue vaut $\\sum_\\ell p_\\ell = (3L-1)/4$, soit environ $3L/4$ ; le quart non calculé correspond au temps d'entraînement économisé. La profondeur du réseau tiré varie aussi beaucoup d'une fois à l'autre, de 28 à 51 blocs ; certaines mises à jour passent par un réseau particulièrement court, où le gradient dispose d'un chemin plus direct jusqu'aux premières couches.\n\n### Au test, multiplier par la probabilité de survie\n\nAu test, tous les blocs doivent être présents pour exploiter toute la capacité du réseau. Mais à l'entraînement, $f_\\ell$ n'apparaît que dans une proportion $p_\\ell$ des mises à jour, et les poids de la couche suivante sont calibrés selon cette proportion. Au test, il faut donc multiplier la sortie de chaque bloc par sa probabilité de survie :\n\n$$\nH_\\ell^{\\text{Test}} = \\mathrm{ReLU}\\big(p_\\ell\\, f_\\ell(H_{\\ell-1}^{\\text{Test}}; W_\\ell) + H_{\\ell-1}^{\\text{Test}}\\big)\n$$\n\nÉcrivons un bloc et comparons ses sorties à l'entraînement et au test. Pour plus de lisibilité, la fonction résiduelle est ici une couche linéaire, et la ReLU finale est omise :\n\n```python\nimport torch\nimport torch.nn as nn\n\nclass StochasticDepthBlock(nn.Module):\n    def __init__(self, f, p):\n        super().__init__()\n        self.f, self.p = f, p                      # p : probabilité de survie de ce bloc\n\n    def forward(self, x):\n        if self.training:\n            if torch.rand(()) < self.p:            # survie : le résidu est calculé normalement\n                return x + self.f(x)\n            return x                               # pas de survie : tout le bloc devient une application identité\n        return x + self.p * self.f(x)              # test : multiplication par la probabilité de survie\n\ntorch.manual_seed(0)\nblock = StochasticDepthBlock(nn.Linear(4, 4), p=0.6)\nx = torch.randn(1, 4)\n\nblock.train()\nwith torch.no_grad():\n    outs = torch.stack([block(x) for _ in range(20000)])\nblock.eval()\nwith torch.no_grad():\n    test = block(x)\n\nprint(\"sorties distinctes à l'entraînement :\", torch.unique(outs.round(decimals=4), dim=0).shape[0], \"au total\")\nprint(\"moyenne des sorties à l'entraînement :\", [f\"{v:.3f}\" for v in outs.mean(0).squeeze()])\nprint(\"sortie au test :                     \", [f\"{v:.3f}\" for v in test.squeeze()])\n```\n\n```text\nsorties distinctes à l'entraînement : 2 au total\nmoyenne des sorties à l'entraînement : ['-0.479', '0.711', '-1.017', '1.223']\nsortie au test :                      ['-0.479', '0.713', '-1.017', '1.223']\n```\n\nÀ l'entraînement, ce bloc ne produit que deux sorties possibles : avec ou sans résidu. La moyenne sur vingt mille passages est presque identique à la sortie de test, où le résidu est multiplié par $p = 0.6$.\n\n\n> [!NOTE]\n> \n> Les bibliothèques actuelles déplacent le plus souvent la correction vers l'entraînement, comme l'inverted dropout : en cas de survie, le résidu est divisé par la probabilité de survie, et rien ne change au test. Par exemple, dans `torchvision.ops.stochastic_depth` de torchvision, le paramètre `p` est la probabilité « d'être abandonné », et l'entrée est divisée par $1-p$ en cas de survie. Les deux approches ont la même espérance ; en lisant du code, vérifiez à quelle probabilité correspond `p`.\n\n\n### Pourquoi ça marche ?\n\nLes auteurs avancent trois raisons.\n\n- **Un entraînement plus rapide** : les blocs sautés ne sont pas calculés, et la durée des propagations avant et arrière suit la profondeur attendue plutôt que la profondeur complète.\n- **Un gradient plus fort** : le réseau d'entraînement étant plus court, le gradient traverse moins de couches, et les premières couches reçoivent un gradient plus grand.\n- **Un ensemble implicite** : avec 54 blocs, chacun présent ou absent, il existe $2^{54}$ combinaisons. Chaque mini-lot tire un sous-réseau aux poids partagés pour la mise à jour, et au test, l'équation ci-dessus les combine en un seul réseau. Les résultats record de l'article de ResNet provenaient justement d'un ensemble de ResNet de profondeurs différentes.\n\nCette lecture en termes d'ensemble rappelle beaucoup le dropout. La différence : le dropout rend le réseau plus **étroit**, la profondeur stochastique le rend moins **profond**. Les auteurs signalent aussi que l'effet du dropout s'émousse souvent quand il est combiné à la batch normalization : sur un ResNet de 110 couches avec BN, ils ont essayé divers taux de dropout, sans presque aucune amélioration ; sur le même réseau, la profondeur stochastique reste efficace.\n\n## Discussion\n\n### Taux d'erreur et temps d'entraînement\n\n| Méthode | CIFAR-10+ | CIFAR-100+ | SVHN | ImageNet |\n| --- | ---: | ---: | ---: | ---: |\n| Highway Network | 7,60 | 32,24 | – | – |\n| Gen. Pool | 6,05 | 28,02 | 1,69 | – |\n| ResNet, profondeur constante | 6,41 | 27,76 | 1,80 | 21,78 |\n| ResNet, profondeur stochastique | **5,25** | **24,98** | 1,75 | 21,98 |\n\n*Tableau : quelques lignes extraites de la Table 1 de l'article, taux d'erreur en test (%) ; « + » indique une augmentation de données standard. « Profondeur constante » désigne la reproduction par les auteurs des expériences de He et al.*\n\nCIFAR-10 utilise un ResNet de 110 couches entraîné pendant 500 époques. À profondeur constante, le taux d'erreur est de 6,41 % ; avec la profondeur stochastique, il tombe à 5,25 %, soit une amélioration relative de 18 % ; l'entraînement et la configuration du réseau sont strictement identiques, à la seule différence des blocs sautés au hasard pendant l'entraînement. Sur CIFAR-100, avec le même réseau, l'erreur passe de 27,76 % à 24,98 %.\n\n[![Deux graphiques de courbes d'entraînement : à gauche, un ResNet de 110 couches sur CIFAR-10 ; à droite, sur CIFAR-100. La ligne rouge est l'erreur de test à profondeur constante, la bleue l'erreur de test avec profondeur stochastique, et deux lignes fines montrent la perte d'entraînement de chacune. Après la baisse du taux d'apprentissage à l'époque 250, la ligne bleue passe nettement sous la rouge ; le graphique de gauche indique 6,41 % et 5,25 %, celui de droite 27,88 % et 24,98 %](/content/papers/assets/757bc4adb848efac2620e3a37c465e58ddc4a4c93e54f3b664bcea91cab64ffe.png)](/content/papers/assets/757bc4adb848efac2620e3a37c465e58ddc4a4c93e54f3b664bcea91cab64ffe.png)\n\n*Fig. 3 de l'article, extraite de la [**page 8 du PDF v3**](https://arxiv.org/pdf/1603.09382v3#page=8). Erreur de test et perte d'entraînement sur CIFAR-10 (à gauche) et CIFAR-100 (à droite) ; les points marquent l'époque où l'erreur de validation est la plus basse.*\n\nAprès la première baisse du taux d'apprentissage, l'erreur de test à profondeur constante se stabilise à peu près, tandis que celle de la profondeur stochastique continue de descendre. Les auteurs notent aussi que l'erreur de test de la profondeur stochastique fluctue davantage, sans doute parce que la profondeur ne cesse de changer pendant l'entraînement.\n\nSans augmentation des données, la profondeur stochastique apporte aussi une amélioration relative d'environ 15 % sur CIFAR-10 et CIFAR-100 : de 13,63 % à 11,66 %, et de 44,74 % à 37,8 %. Sur SVHN, avec un réseau de 152 couches, la profondeur constante commence à surapprendre dès la deuxième phase, avec 1,80 % d'erreur ; la profondeur stochastique obtient 1,75 %.\n\nComparaison des temps d'entraînement :\n\n| | CIFAR-10+ | CIFAR-100+ | SVHN |\n| --- | ---: | ---: | ---: |\n| Profondeur constante | 20 h 42 min | 20 h 51 min | 33 h 43 min |\n| Profondeur stochastique | 15 h 7 min | 15 h 20 min | 25 h 33 min |\n\n*Tableau : extrait de la Table 2 de l'article, décroissance linéaire avec $p_L = 0.5$.*\n\nChaque configuration économise environ un quart du temps, ce qui concorde avec la profondeur attendue calculée plus haut.\n\n### Mille deux cents couches\n\nL'article de ResNet avait essayé un réseau de 1202 couches, qui surapprenait : 7,93 % d'erreur de test, moins bien que le réseau de 110 couches. Les auteurs refont cette expérience avec le même réseau de 1202 couches, entraîné pendant 300 époques, avec un échauffement à un taux d'apprentissage de 0,01 pendant les 10 premières époques.\n\nÀ profondeur constante, le réseau de 1202 couches obtient 6,67 % d'erreur, là encore moins bien que les 6,41 % du réseau de 110 couches. Avec la profondeur stochastique, l'erreur tombe à 4,91 % : une amélioration relative de 27 % par rapport au réseau de 1202 couches à profondeur constante, mieux aussi que le réseau de 110 couches avec profondeur stochastique (5,25 %), et sans signe de surapprentissage. Selon les auteurs, c'est la première fois qu'un réseau de plus de mille couches parvient à réduire encore l'erreur de test par rapport à un réseau moins profond.\n\n\n> [!TIP]\n> \n> Le même mois, les auteurs de ResNet ont pris une autre voie en passant l'unité résiduelle à la préactivation ; leur ResNet de 1001 couches atteint 4,92 % sur CIFAR-10 (4,62 % avec une taille de lot de 64) :\n> \n> - **[[16.03] ResNet v2 : Le raccourci doit rester propre](/blog/papers/classic-cnns/resnet-v2)**\n\n\n### Pas de victoire sur ImageNet\n\nSur ImageNet, les auteurs utilisent un ResNet de 152 couches. À profondeur constante, après 90 époques d'entraînement, l'erreur est de 23,06 % ; avec la profondeur stochastique, elle est de 23,38 % à la 90e époque, un peu moins bonne. Les auteurs observent que l'erreur de validation de la profondeur stochastique baisse encore nettement ; et comme la méthode économise 25 % du calcul, 30 époques de plus prennent au total à peu près le même temps que 90 époques à profondeur constante. Après cet entraînement prolongé, la profondeur stochastique atteint 21,98 % ; mais la profondeur constante, elle aussi entraînée 30 époques de plus, atteint 21,78 %.\n\nDans cette configuration, la profondeur stochastique n'apporte donc aucun gain de précision. Les auteurs citent un relecteur anonyme : les modèles pour ImageNet et ceux pour CIFAR ne sont pas encore dans le même régime ; ImageNet demande peut-être une complexité de modèle bien supérieure à celle d'un ResNet de 152 couches, et la profondeur stochastique ne montrera peut-être son effet qu'avec des modèles plus grands.\n\n### Le gradient est-il vraiment plus fort ?\n\n[![Graphique en courbes : en abscisse, les époques (de 0 à 500) ; en ordonnée, l'amplitude moyenne du gradient de la première couche de convolution (en unités de 10 puissance moins 5). La ligne rouge correspond à la profondeur constante, la bleue à la profondeur stochastique. Deux lignes pointillées marquent les baisses du taux d'apprentissage aux époques 250 et 375, où le gradient chute fortement ; la ligne bleue reste toujours au-dessus de la rouge, et l'écart se creuse après les baisses du taux d'apprentissage](/content/papers/assets/6e62eb722549bcdd22e104076055f0d6e70ad5e66c660f0e827fcfa67318c9a1.png)](/content/papers/assets/6e62eb722549bcdd22e104076055f0d6e70ad5e66c660f0e827fcfa67318c9a1.png)\n\n*Fig. 7 de l'article, extraite de la [**page 12 du PDF v3**](https://arxiv.org/pdf/1603.09382v3#page=12). Sur CIFAR-10, amplitude moyenne du gradient, à chaque époque, de la première couche de convolution du premier bloc résiduel ; les lignes pointillées marquent les moments où le taux d'apprentissage est divisé par 10.*\n\nLes deux fortes baisses viennent du calendrier du taux d'apprentissage. Le gradient de la profondeur stochastique reste toujours plus grand, et l'écart se creuse après les baisses du taux d'apprentissage, ce qui appuie l'affirmation des auteurs selon laquelle leur méthode « atténue la disparition du gradient ».\n\n### Quelle probabilité de survie choisir ?\n\n[![À gauche : erreur de test d'un ResNet de 110 couches sur CIFAR-10 en fonction de la probabilité de survie p_L. Trait plein pour la décroissance linéaire, pointillés pour la probabilité fixe, pointillés rouges pour les 6,41 % de la profondeur constante. La courbe de décroissance linéaire est au plus bas vers p_L = 0,5, autour de 5,25 %, annotée d'une accélération de 1,33x ; à p_L = 0,2, elle reste proche de la profondeur constante, annotée 1,67x ; la courbe à probabilité fixe est le plus souvent plus haute, sauf vers p_L = 0,8 où elle passe sous la décroissance linéaire ; elle est annotée 2x à p_L = 0,5. À droite : une carte de chaleur, avec p_L en ordonnée (de 1,0 à 0,5) et la profondeur du réseau en abscisse (de 20 à 110 couches), chaque case donnant l'erreur de test ; à 20 couches, p_L entre 0,9 et 0,7 fait mieux que la profondeur constante, et au-delà l'erreur augmente ; à 110 couches, p_L = 0,5 est le meilleur, et les valeurs les plus basses se répartissent à peu près le long de la diagonale](/content/papers/assets/1f923643ee1fd74e75ef508bccb935e721a1b51f610ca3dcbac82168dc0573ad.png)](/content/papers/assets/1f923643ee1fd74e75ef508bccb935e721a1b51f610ca3dcbac82168dc0573ad.png)\n\n*Fig. 8 de l'article, extraite de la [**page 13 du PDF v3**](https://arxiv.org/pdf/1603.09382v3#page=13). À gauche : erreur de test sur CIFAR-10 d'un ResNet de 110 couches selon $p_L$ ; à droite : erreur de test selon $p_L$ et la profondeur du réseau, la ligne $p_L = 1$ correspondant à la profondeur constante.*\n\n$p_L$ est le seul hyperparamètre de la méthode. Le graphique de gauche montre que :\n\n1. Avec un $p_L$ raisonnable, les deux règles font mieux que la profondeur constante.\n2. Pour la plupart des valeurs de $p_L$, la décroissance linéaire fait mieux que la probabilité fixe.\n3. La décroissance linéaire est peu sensible à $p_L$ : toute valeur entre 0,4 et 0,8 donne de bons résultats.\n4. Même avec $p_L = 0.2$, la décroissance linéaire égale la profondeur constante, pour un temps d'entraînement réduit de 40 %.\n\nLa carte de chaleur de droite ajoute la profondeur. Pour un réseau de 20 couches, sauter quelques blocs ($p_L$ entre 0,9 et 0,7) fait mieux que la profondeur constante, mais au-delà l'erreur augmente : avec $p_L = 0.5$, l'erreur passe de 8,31 % à 9,39 %. Pour le réseau de 110 couches, au contraire, $p_L = 0.5$ est le meilleur choix. Les meilleures cases se répartissent à peu près le long de la diagonale : plus le réseau est profond, plus il supporte des sauts agressifs. Il faut un réseau assez profond pour que la profondeur stochastique batte nettement la profondeur constante ; sur un réseau moins profond, des sauts plus modérés restent utiles.\n\n## Conclusion\n\nLa profondeur stochastique est une méthode d'entraînement qui ne modifie pas le réseau de test : à l'entraînement, des blocs résiduels sont sautés au hasard et la profondeur attendue tombe à environ trois quarts ; au test, les probabilités de survie servent à réunir tous les blocs. Expérimentalement, les taux d'erreur baissent sur CIFAR et SVHN, le temps d'entraînement diminue d'environ un quart, et le réseau de 1202 couches ne surapprend plus. Sur ImageNet, en revanche, le ResNet de 152 couches n'en tire aucun gain de précision.\n\nDans certaines bibliothèques, la méthode apparaît sous le nom de DropPath. Quelques mois plus tard, Gao Huang, Zhuang Liu et Kilian Q. Weinberger, auteurs de cet article, proposent DenseNet, dont l'article cite d'emblée la profondeur stochastique : puisqu'un réseau s'entraîne même en sautant des couches au hasard, beaucoup de couches d'un réseau résiduel n'apportent en réalité qu'une faible contribution.\n\n\n> [!TIP]\n> \n> Pour DenseNet, vous pouvez consulter notre note :\n> \n> - **[[16.08] DenseNet : Tout relier](/blog/papers/classic-cnns/densenet)**\n\n\nLa profondeur stochastique est très simple à utiliser : à l'entraînement, chaque branche résiduelle est multipliée par un 0 ou un 1 tiré au hasard ; au test, ce facteur est remplacé par la probabilité de survie. Les bibliothèques actuelles divisent plutôt par la probabilité de survie dès l'entraînement, comme `stochastic_depth` dans torchvision, si bien que rien ne change au test.\n\nÀ l'époque, les auteurs supposaient que la profondeur stochastique ne montrerait son intérêt sur ImageNet qu'avec des modèles plus grands. Par la suite, les recettes d'entraînement de grands modèles comme [ConvNeXt](/blog/papers/classic-cnns/convnext) et [DINOv2](/blog/papers/contrastive-learning/dinov2) l'ont effectivement toutes adoptée.\n","imageSizes":{"/content/papers/assets/620e6ddf909f1f405e38b6055bd732ae4c4b7c208f147e00b870a56642020c02.png":{"width":963,"height":339},"/content/papers/assets/757bc4adb848efac2620e3a37c465e58ddc4a4c93e54f3b664bcea91cab64ffe.png":{"width":965,"height":372},"/content/papers/assets/6e62eb722549bcdd22e104076055f0d6e70ad5e66c660f0e827fcfa67318c9a1.png":{"width":756,"height":345},"/content/papers/assets/1f923643ee1fd74e75ef508bccb935e721a1b51f610ca3dcbac82168dc0573ad.png":{"width":973,"height":422}}}
