{"notes":[{"id":"lightweight/fasternet","category":"lightweight","legacyPath":"","legacySlug":"","legacyPaths":[],"title":"FasterNet","subtitle":"Les FLOPs mentent","author":"Z. Yuan","paperDate":"2023-03-07","publishedOn":"2025-10-23","world":"external/fasternet","paperTitle":"Run, Don't Walk: Chasing Higher FLOPS for Faster Neural Networks","paperUrl":"https://arxiv.org/abs/2303.03667","bibliography":{"title":"Run, Don't Walk: Chasing Higher FLOPS for Faster Neural Networks","authors":["Jierun Chen","Shiu-hong Kao","Hao He","Weipeng Zhuo","Song Wen","Chul-Ho Lee","S.-H. Gary Chan"],"url":"https://arxiv.org/abs/2303.03667","pdfUrl":"https://arxiv.org/pdf/2303.03667v3","codeUrl":null,"preprint":{"id":"2303.03667","submittedOn":"2023-03-07","url":"https://arxiv.org/abs/2303.03667"},"publication":{"venue":"CVPR","year":2023,"kind":"conference","url":"https://openaccess.thecvf.com/content/CVPR2023/html/Chen_Run_Dont_Walk_Chasing_Higher_FLOPS_for_Faster_Neural_Networks_CVPR_2023_paper.html"},"citation":"@misc{lightweightfasternet2023,\n  title = {{Run, Don't Walk: Chasing Higher FLOPS for Faster Neural Networks}},\n  author = {Jierun Chen and Shiu-hong Kao and Hao He and Weipeng Zhuo and Song Wen and Chul-Ho Lee and S.-H. Gary Chan},\n  year = {2023},\n  eprint = {2303.03667},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/2303.03667}\n}\n","citationPath":"/content/papers/citations/lightweight/fasternet.7a313d25fdbe.bib"},"thumbnail":{"src":"/content/papers/assets/f7b24b9388f5bb090f5420a96d640e9f851fd40becb24e6bb9b31ba1ebee4b71.png","width":1012,"height":500},"locale":"fr","path":"/content/papers/fr/lightweight/fasternet.9f680bcb7ad1.md","headings":[{"id":"définir-le-problème","text":"Définir le problème","depth":2},{"id":"latence--flops-divisés-par-flops","text":"Latence = FLOPs divisés par FLOPS","depth":3},{"id":"ce-qui-ralentit-la-convolution-depthwise","text":"Ce qui ralentit la convolution depthwise","depth":3},{"id":"résoudre-le-problème","text":"Résoudre le problème","depth":2},{"id":"la-convolution-partielle-pconv","text":"La convolution partielle PConv","depth":3},{"id":"ajouter-une-convolution-11","text":"Ajouter une convolution 1×1","depth":3},{"id":"fasternet","text":"FasterNet","depth":3},{"id":"discussion","text":"Discussion","depth":2},{"id":"imagenet","text":"ImageNet","depth":3},{"id":"détection-et-segmentation","text":"Détection et segmentation","depth":3},{"id":"ablations","text":"Ablations","depth":3},{"id":"conclusion","text":"Conclusion","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"lightweight/mobilenet-v2","relation":"referenced","topic":""},{"id":"lightweight/shufflenet","relation":"referenced","topic":""},{"id":"lightweight/ghostnet","relation":"referenced","topic":""}]},{"id":"lightweight/mobilenet-v2","category":"lightweight","legacyPath":"lightweight/1801-mobilenet-v2","legacySlug":"1801-mobilenet-v2","legacyPaths":[],"title":"MobileNet-V2","subtitle":"Ce qui se joue dans le goulot","author":"Z. Yuan","paperDate":"2018-01-13","publishedOn":"2024-06-27","paperTitle":"MobileNetV2: Inverted Residuals and Linear Bottlenecks","paperUrl":"https://arxiv.org/abs/1801.04381","bibliography":{"title":"MobileNetV2: Inverted Residuals and Linear Bottlenecks","authors":["Mark Sandler","Andrew Howard","Menglong Zhu","Andrey Zhmoginov","Liang-Chieh Chen"],"url":"https://arxiv.org/abs/1801.04381","pdfUrl":"https://arxiv.org/pdf/1801.04381","codeUrl":null,"preprint":{"id":"1801.04381","submittedOn":"2018-01-13","url":"https://arxiv.org/abs/1801.04381"},"publication":{"venue":"CVPR","year":2018,"kind":"conference","url":"https://arxiv.org/abs/1801.04381"},"citation":"@misc{lightweightmobilenetv22018,\n  title = {{MobileNetV2: Inverted Residuals and Linear Bottlenecks}},\n  author = {Mark Sandler and Andrew Howard and Menglong Zhu and Andrey Zhmoginov and Liang-Chieh Chen},\n  year = {2018},\n  eprint = {1801.04381},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/1801.04381}\n}\n","citationPath":"/content/papers/citations/lightweight/mobilenet-v2.a882707cbaa2.bib"},"thumbnail":{"src":"/content/papers/assets/e6bbfb346bb449f83897d76b69c3711d2e9937d40320a7aab0f3843653a688c0.jpg","width":2332,"height":1324},"locale":"fr","path":"/content/papers/fr/lightweight/mobilenet-v2.19bf0284e711.md","headings":[{"id":"définir-le-problème","text":"Définir le problème","depth":2},{"id":"goulot-linéaire","text":"Goulot linéaire","depth":3},{"id":"réseau-résiduel","text":"Réseau résiduel","depth":3},{"id":"résoudre-le-problème","text":"Résoudre le problème","depth":2},{"id":"résidu-inversé","text":"Résidu inversé","depth":3},{"id":"goulot-élargi-annexe-a-de-larticle","text":"Goulot élargi (annexe A de l'article)","depth":3},{"id":"architecture-du-modèle","text":"Architecture du modèle","depth":3},{"id":"discussion","text":"Discussion","depth":2},{"id":"résultats-de-classification-dimages","text":"Résultats de classification d'images","depth":3},{"id":"conclusion","text":"Conclusion","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"lightweight/mobilenet-v1","relation":"background","topic":"Convolutions efficaces sur mobile"},{"id":"lightweight/mobilenet-v3","relation":"next","topic":"Convolutions efficaces sur mobile"}]},{"id":"lightweight/shufflenet","category":"lightweight","legacyPath":"lightweight/1707-shufflenet","legacySlug":"1707-shufflenet","legacyPaths":[],"title":"ShuffleNet","subtitle":"Un réseau qui mélange les canaux","author":"Z. Yuan","paperDate":"2017-07-04","publishedOn":"2024-06-26","paperTitle":"ShuffleNet: An Extremely Efficient Convolutional Neural Network for Mobile Devices","paperUrl":"https://arxiv.org/abs/1707.01083","bibliography":{"title":"ShuffleNet: An Extremely Efficient Convolutional Neural Network for Mobile Devices","authors":["Xiangyu Zhang","Xinyu Zhou","Mengxiao Lin","Jian Sun"],"url":"https://arxiv.org/abs/1707.01083","pdfUrl":"https://arxiv.org/pdf/1707.01083","codeUrl":null,"preprint":{"id":"1707.01083","submittedOn":"2017-07-04","url":"https://arxiv.org/abs/1707.01083"},"publication":{"venue":"CVPR","year":2018,"kind":"conference","url":"https://doi.org/10.1109/cvpr.2018.00716"},"citation":"@misc{lightweightshufflenet2017,\n  title = {{ShuffleNet: An Extremely Efficient Convolutional Neural Network for Mobile Devices}},\n  author = {Xiangyu Zhang and Xinyu Zhou and Mengxiao Lin and Jian Sun},\n  year = {2017},\n  eprint = {1707.01083},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/1707.01083}\n}\n","citationPath":"/content/papers/citations/lightweight/shufflenet.1e5a6869f5a9.bib"},"thumbnail":{"src":"/content/papers/assets/6d0c746d403d2823809ffbd52c9b3614cc2063afee07608d6d0cb26b11fc3ac8.jpg","width":1746,"height":678},"locale":"fr","path":"/content/papers/fr/lightweight/shufflenet.a26af47a88af.md","headings":[{"id":"définir-le-problème","text":"Définir le problème","depth":2},{"id":"calcul-et-vitesse-ne-vont-pas-toujours-de-pair","text":"Calcul et vitesse ne vont pas toujours de pair","depth":3},{"id":"le-poids-des-convolutions-1--1","text":"Le poids des convolutions 1 × 1","depth":3},{"id":"résoudre-le-problème","text":"Résoudre le problème","depth":2},{"id":"convolutions-groupées","text":"Convolutions groupées","depth":3},{"id":"mélange-des-canaux","text":"Mélange des canaux","depth":3},{"id":"où-placer-le-mélange-","text":"Où placer le mélange ?","depth":3},{"id":"architecture-du-modèle","text":"Architecture du modèle","depth":3},{"id":"discussion","text":"Discussion","depth":2},{"id":"effet-des-convolutions-groupées","text":"Effet des convolutions groupées","depth":3},{"id":"effet-du-mélange-des-canaux","text":"Effet du mélange des canaux","depth":3},{"id":"comparaison-avec-dautres-modèles","text":"Comparaison avec d'autres modèles","depth":3},{"id":"mesure-réelle-de-la-vitesse-dinférence","text":"Mesure réelle de la vitesse d'inférence","depth":3},{"id":"conclusion","text":"Conclusion","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"lightweight/ghostnet","relation":"comparison","topic":"Réduire le coût des convolutions et des canaux"},{"id":"lightweight/pp-lcnet","relation":"comparison","topic":"Réduire le coût des convolutions et des canaux"}]},{"id":"lightweight/ghostnet","category":"lightweight","legacyPath":"lightweight/1911-ghostnet","legacySlug":"1911-ghostnet","legacyPaths":[],"title":"GhostNet","subtitle":"Les fantômes des cartes de caractéristiques","author":"Z. Yuan","paperDate":"2019-11-27","publishedOn":"2024-07-23","paperTitle":"GhostNet: More Features from Cheap Operations","paperUrl":"https://arxiv.org/abs/1911.11907","bibliography":{"title":"GhostNet: More Features from Cheap Operations","authors":["Kai Han","Yunhe Wang","Qi Tian","Jianyuan Guo","Chunjing Xu","Chang Xu"],"url":"https://arxiv.org/abs/1911.11907","pdfUrl":"https://arxiv.org/pdf/1911.11907","codeUrl":"https://github.com/huawei-noah/ghostnet","preprint":{"id":"1911.11907","submittedOn":"2019-11-27","url":"https://arxiv.org/abs/1911.11907"},"publication":{"venue":"CVPR","year":2020,"kind":"conference","url":"https://arxiv.org/abs/1911.11907"},"citation":"@misc{lightweightghostnet2019,\n  title = {{GhostNet: More Features from Cheap Operations}},\n  author = {Kai Han and Yunhe Wang and Qi Tian and Jianyuan Guo and Chunjing Xu and Chang Xu},\n  year = {2019},\n  eprint = {1911.11907},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/1911.11907}\n}\n","citationPath":"/content/papers/citations/lightweight/ghostnet.4dd65d9540bb.bib"},"thumbnail":{"src":"/content/papers/assets/22fa9d36b042deb7995e9695a803de3a973542f58cd9cd48e37ef13167df2222.jpg","width":972,"height":904},"locale":"fr","path":"/content/papers/fr/lightweight/ghostnet.b2f54451ed88.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":"architecture-du-modèle","text":"Architecture du modèle","depth":3},{"id":"configuration-des-modules","text":"Configuration des modules","depth":3},{"id":"discussion","text":"Discussion","depth":2},{"id":"performances-sur-imagenet","text":"Performances sur ImageNet","depth":3},{"id":"conclusion","text":"Conclusion","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"lightweight/shufflenet","relation":"comparison","topic":"Réduire le coût des convolutions et des canaux"},{"id":"lightweight/pp-lcnet","relation":"comparison","topic":"Réduire le coût des convolutions et des canaux"}]}],"text":"Quand on conçoit un réseau léger, le chiffre qu'on regarde le plus, ce sont les FLOPs. De MobileNet à ShuffleNet puis GhostNet, chacun s'est ingénié à réduire le nombre d'opérations en virgule flottante, avec pour outils favoris la convolution depthwise et la convolution groupée.\n\n\n> [!TIP]\n> \n> Pour ces travaux, vous pouvez commencer par nos notes :\n> \n> - **[[18.01] MobileNet-V2 : Ce qui se joue dans le goulot](/blog/papers/lightweight/mobilenet-v2)**\n> - **[[17.07] ShuffleNet : Un réseau qui mélange les canaux](/blog/papers/lightweight/shufflenet)**\n> - **[[19.11] GhostNet : Les fantômes des cartes de caractéristiques](/blog/papers/lightweight/ghostnet)**\n\n\nMais moins de FLOPs, est-ce forcément un réseau plus rapide ? Jierun Chen et ses collègues de l'université des sciences et technologies de Hong Kong ont fait le tour des mesures, et la réponse est souvent non. CycleMLP-B1, par exemple, n'a que la moitié des FLOPs de ResNet-50, mais tourne plus lentement sur CPU, 116,1 ms contre 73,0 ms. L'article s'intitule « Run, Don't Walk » ; autrement dit, plutôt que d'économiser les pas, mieux vaut courir plus vite.\n\n## Définir le problème\n\n### Latence = FLOPs divisés par FLOPS\n\nCes deux termes ne diffèrent que par une majuscule. Les FLOPs sont un nombre d'opérations en virgule flottante ; les FLOPS, le nombre d'opérations en virgule flottante effectuées par seconde, c'est-à-dire la vitesse réellement atteinte par le matériel. La latence est le quotient des deux :\n\n$$\n\\text{Latency}=\\frac{\\text{FLOPs}}{\\text{FLOPS}} .\n$$\n\nSi l'on ne fait que réduire les FLOPs et que les FLOPS chutent davantage, la latence s'allonge au contraire. Les auteurs ont mesuré une série de réseaux courants sur un CPU Intel :\n\n[![Deux graphiques. (a) En abscisse, les FLOPs (G) ; en ordonnée, les FLOPS réellement atteints sur CPU (G/s). FasterNet, en étoiles orange, est tout en haut, et monte d'environ 37 à 64 ; ResNet50 est un point isolé vers 56 ; PVT, PoolFormer, MobileViT et EdgeNeXt se situent à peu près entre 13 et 43 ; MobileNetV2, GhostNet, ShuffleNetV2, MobileFormer et CycleMLP sont pour la plupart sous 30, MobileFormer et GhostNet étant les plus bas, entre quelques unités et un peu plus de dix. (b) En abscisse, les FLOPs ; en ordonnée, la latence sur CPU (ms) ; à droite la plage complète, à gauche un agrandissement de la partie sous 1,8 GFLOPs ; à FLOPs égaux, la courbe orange de FasterNet est toujours la plus basse, et les deux points de CycleMLP sont tout en haut, vers 116 et 186 ms](/content/papers/assets/20f1c9a908d887f3d0a9df04a50fcc019d38cf455e2b89451d3b2c8469b91f94.png)](/content/papers/assets/20f1c9a908d887f3d0a9df04a50fcc019d38cf455e2b89451d3b2c8469b91f94.png)\n\n*Figure 2 de l'article, extraite de la [**page 2 du PDF v3**](https://arxiv.org/pdf/2303.03667v3#page=2), CC BY 4.0. (a) FLOPS sur CPU en fonction des FLOPs ; (b) latence sur CPU en fonction des FLOPs.*\n\nL'ordonnée de la figure de gauche indique combien d'opérations sont réellement effectuées par seconde. Bien des réseaux réputés rapides ont des FLOPS inférieurs à ceux de ResNet-50, et laissent inexploitée la puissance de calcul du matériel.\n\nShuffleNet V2 avait déjà signalé ce phénomène en 2018, en notant lui aussi que FLOPs et vitesse ne concordent pas. Les réseaux légers suivants ont pourtant continué à utiliser la convolution depthwise, faute de meilleur remplaçant.\n\n### Ce qui ralentit la convolution depthwise\n\nL'entrée est une carte de caractéristiques $c\\times h\\times w$, et le noyau 3×3 a un côté $k=3$. Une convolution ordinaire coûte $h\\times w\\times k^2\\times c^2$ FLOPs ; la convolution depthwise, où chaque canal n'utilise que son propre noyau, descend à $h\\times w\\times k^2\\times c$, soit $c$ fois moins.\n\nLe problème est que la convolution depthwise n'opère que dans la dimension spatiale ; utilisée seule, elle fait beaucoup perdre en précision, et l'on augmente donc en pratique le nombre de canaux, d'un facteur 6 dans le bloc résiduel inversé de MobileNet-V2. Une fois les canaux passés de $c$ à $c'$, l'accès mémoire vaut\n\n$$\nh\\times w\\times 2c' + k^2\\times c' \\approx h\\times w\\times 2c' ,\n$$\n\nsoit une lecture de l'entrée et une écriture de la sortie ; ce n'est presque que du transfert de cartes de caractéristiques. Une convolution ordinaire accède à environ $h\\times w\\times 2c$ éléments, donc moins.\n\nPeu de calcul, beaucoup de transferts ; avec seulement quelques opérations par nombre transféré, le matériel passe son temps à attendre la mémoire.\n\n## Résoudre le problème\n\n### La convolution partielle PConv\n\nLes auteurs observent que les différents canaux d'une carte de caractéristiques se ressemblent souvent. En affichant les cartes de caractéristiques d'une couche intermédiaire d'un ResNet-50 préentraîné, ils constatent que de nombreux canaux sont très semblables. Avec autant de redondance, inutile d'appliquer la convolution spatiale à chaque canal.\n\n[![Schéma de trois convolutions. (a) Convolution ordinaire : une entrée en parallélépipède est convoluée avec toute une rangée de noyaux, pour une sortie de même taille. (b) Convolution depthwise ou groupée : l'entrée est découpée en pointillés en nombreuses tranches le long des canaux, chacune avec son propre petit noyau. (c) Convolution partielle : seule une petite portion des canaux en tête de l'entrée est encadrée en pointillés et convoluée avec quelques noyaux, les autres canaux rejoignant la sortie intacts, le long d'une flèche](/content/papers/assets/f7b24b9388f5bb090f5420a96d640e9f851fd40becb24e6bb9b31ba1ebee4b71.png)](/content/papers/assets/f7b24b9388f5bb090f5420a96d640e9f851fd40becb24e6bb9b31ba1ebee4b71.png)\n\n*Figure 1 de l'article, extraite de la [**page 1 du PDF v3**](https://arxiv.org/pdf/2303.03667v3#page=1), CC BY 4.0.*\n\nLa convolution partielle (Partial Convolution, PConv) n'applique une convolution 3×3 ordinaire qu'aux $c_p$ premiers canaux, et recopie directement les autres vers la sortie. Prendre une tranche contiguë en tête permet de garder des accès mémoire contigus. Par défaut, $c_p = c/4$, et les FLOPs valent\n\n$$\nh\\times w\\times k^2\\times c_p^2 ,\n$$\n\nsoit 1/16 d'une convolution ordinaire ; l'accès mémoire vaut environ $h\\times w\\times 2c_p$, soit 1/4 d'une convolution ordinaire.\n\nMesurons-le sur notre propre CPU. Nous empilons 10 couches de chacun des trois opérateurs, sur une entrée de 192×28×28, et ajoutons un groupe de convolutions depthwise aux canaux multipliés par 6, pour imiter l'usage qu'en fait MobileNet-V2 :\n\n```python\nimport time\nimport torch\nimport torch.nn as nn\n\ntorch.set_num_threads(1)                                   # comme dans l'article, un seul thread sur CPU\nc, h, w = 192, 28, 28                                      # taille de carte de caractéristiques courante au deuxième étage\ncp = c // 4                                                # PConv ne convolue qu'1/4 des canaux\n\nclass PConv(nn.Module):\n    def __init__(self, c, cp):\n        super().__init__()\n        self.cp = cp\n        self.conv = nn.Conv2d(cp, cp, 3, padding=1, bias=False)\n\n    def forward(self, x):\n        x1, x2 = torch.split(x, [self.cp, x.shape[1] - self.cp], dim=1)\n        return torch.cat((self.conv(x1), x2), 1)           # les 3/4 restants des canaux passent intacts\n\n# (opérateur, canaux d'entrée, FLOPs, accès mémoire) ; FLOPs en multiplications-additions, accès mémoire en éléments (cartes lues et écrites, plus poids lus)\nops = {\n    \"Conv 3×3\": (nn.Conv2d(c, c, 3, padding=1, bias=False), c, h * w * 9 * c * c, h * w * 2 * c + 9 * c * c),\n    \"DWConv 3×3\": (nn.Conv2d(c, c, 3, padding=1, groups=c, bias=False), c, h * w * 9 * c, h * w * 2 * c + 9 * c),\n    \"PConv 3×3\": (PConv(c, cp), c, h * w * 9 * cp * cp, h * w * 2 * cp + 9 * cp * cp),\n    \"DWConv ×6\": (nn.Conv2d(6 * c, 6 * c, 3, padding=1, groups=6 * c, bias=False), 6 * c,\n                  h * w * 9 * 6 * c, h * w * 2 * 6 * c + 9 * 6 * c),\n}\nwith torch.no_grad():\n    for name, (op, cin, flops, mem) in ops.items():\n        x = torch.randn(1, cin, h, w)\n        net = nn.Sequential(*[op] * 10)                    # la même couche empilée 10 fois\n        for _ in range(20):\n            net(x)                                         # échauffement\n        t = time.perf_counter()\n        for _ in range(200):\n            net(x)\n        ms = (time.perf_counter() - t) / 200 * 1000\n        total = flops * 10\n        print(f\"{name:<10}  FLOPs {total / 1e6:6.1f}M  mult.-add. par élément accédé {flops / mem:5.1f}  \"\n              f\"latence {ms:5.2f} ms  FLOPS {total / ms / 1e6:4.1f} G/s\")\n```\n\n```\nConv 3×3    FLOPs 2601.1M  mult.-add. par élément accédé 411.0  latence 32.83 ms  FLOPS 79.2 G/s\nDWConv 3×3  FLOPs   13.5M  mult.-add. par élément accédé   4.5  latence  0.83 ms  FLOPS 16.4 G/s\nPConv 3×3   FLOPs  162.6M  mult.-add. par élément accédé 169.3  latence  2.72 ms  FLOPS 59.8 G/s\nDWConv ×6   FLOPs   81.3M  mult.-add. par élément accédé   4.5  latence 10.29 ms  FLOPS  7.9 G/s\n```\n\nCes résultats ont été obtenus sur un Intel i9-13900K ; sur une autre machine, les chiffres seront différents, mais la tendance devrait être à peu près la même.\n\nRegardons d'abord la colonne FLOPS. La convolution ordinaire effectue 411 multiplications-additions par élément accédé et exploite le mieux le matériel ; la convolution depthwise n'en fait que 4,5, et ses FLOPS tombent à environ un cinquième. PConv en fait 169 par élément, pour des FLOPS d'environ les trois quarts de ceux de la convolution ordinaire.\n\nPour être juste, avec les mêmes 192 canaux et les mêmes 10 couches empilées, la convolution depthwise non élargie est en fait la plus rapide, avec seulement 0,83 ms, tant ses FLOPs sont faibles. Mais elle ne s'emploie pas seule de cette façon. Avec 6 fois plus de canaux, elle n'a que la moitié des FLOPs de PConv, mais près de 4 fois sa latence.\n\nL'article mène la même expérience sur 2080Ti, i9-9900X et Cortex-A72 ; en moyenne sur quatre tailles de carte de caractéristiques, PConv a 1/16 des FLOPs d'une convolution ordinaire, et des FLOPS 10,5 fois (GPU), 6,2 fois (CPU) et 22,8 fois (ARM) plus élevés que ceux de la convolution depthwise.\n\n### Ajouter une convolution 1×1\n\nPConv ne regarde qu'un quart des canaux, et le reste de l'information doit venir de la convolution 1×1 qui la suit. Ensemble, leur champ réceptif a la forme d'un T ; la position centrale voit tous les canaux, les huit positions qui l'entourent seulement $c_p$ canaux.\n\nLes auteurs vérifient sur un ResNet-18 préentraîné que cette forme est justifiée. Pour chaque noyau 3×3, ils calculent la magnitude des poids à chacune des neuf positions et regardent laquelle est la plus grande ; dans les quatre étages, c'est le plus souvent la position centrale. Le centre compte naturellement plus que son pourtour, et il est logique d'y consacrer un peu plus de calcul.\n\nPourquoi alors ne pas utiliser directement une convolution en forme de T ? Parce que la décomposer coûte moins. Une convolution en T coûte $h\\times w\\times(k^2 c_p c + c(c-c_p))$ FLOPs, contre $h\\times w\\times(k^2 c_p^2 + c^2)$ pour une PConv suivie d'une convolution 1×1. Avec $c_p = c/4$, la première vaut $3c^2$, la seconde seulement $1.5625c^2$.\n\nLes auteurs vérifient aussi si cette combinaison peut remplacer une convolution ordinaire. Ils extraient les entrées et sorties de la première convolution 3×3 de chaque étage d'un ResNet-50 préentraîné, et entraînent de petits réseaux à l'imiter. En moyenne sur les quatre étages, la perte de test vaut 0,0148 pour depthwise + 1×1, 0,0133 pour convolution groupée + 1×1, et 0,0123 pour PConv + 1×1, la plus proche de la convolution ordinaire d'origine.\n\n### FasterNet\n\n[![En haut, l'architecture d'ensemble de FasterNet ; l'entrée passe par une couche Embedding, puis par quatre étages composés chacun de plusieurs FasterNet Blocks, reliés par des couches Merging, la carte de caractéristiques passant de h/4×w/4 à h/32×w/32, avant un pooling global, une convolution 1×1 et une couche entièrement connectée en sortie. En bas à gauche, un agrandissement de la convolution partielle, où seuls les c_p premiers canaux de l'entrée sont multipliés par c_p noyaux k×k, les autres canaux rejoignant directement la sortie par une flèche Identity ; à droite, le FasterNet Block, avec dans l'ordre PConv 3×3, convolution 1×1, BN et ReLU, une autre convolution 1×1, puis l'addition avec l'entrée](/content/papers/assets/25dba5e2fc3ece26c7c5fd70741eb94aaf914907a40406aabfb39756ab3f1144.png)](/content/papers/assets/25dba5e2fc3ece26c7c5fd70741eb94aaf914907a40406aabfb39756ab3f1144.png)\n\n*Figure 4 de l'article, extraite de la [**page 5 du PDF v3**](https://arxiv.org/pdf/2303.03667v3#page=5), CC BY 4.0.*\n\nLe squelette de FasterNet est sobre. Le stem est une convolution 4×4 de pas 4, et entre les étages, des convolutions 2×2 de pas 2 assurent le sous-échantillonnage. Chaque bloc se compose d'une PConv suivie de deux convolutions 1×1, avec des canaux doublés entre les deux, et d'une connexion résiduelle à la fin.\n\nDeux détails méritent d'être signalés. D'abord, la normalisation et l'activation ne figurent qu'après la couche du milieu, une seule fois par bloc ; selon les auteurs, en mettre davantage réduirait la diversité des caractéristiques et ralentirait le réseau. Ensuite, la normalisation est une BatchNorm, que l'on peut fusionner dans la convolution voisine à l'inférence.\n\nLes deux derniers étages ont moins d'accès mémoire et des FLOPS plus élevés ; les auteurs y placent donc davantage de blocs et de calcul, T0 comptant par exemple 1, 2, 8 et 2 blocs sur ses quatre étages. Du plus petit au plus grand, la famille comprend T0, T1, T2, S, M et L ; les petits modèles utilisent GELU, les grands ReLU.\n\n## Discussion\n\n### ImageNet\n\nLes auteurs mesurent la vitesse sur trois appareils. Sur GPU, une 2080Ti, ils mesurent le débit avec des lots de 32 ; sur CPU, un i9-9900X, et sur ARM, un Cortex-A72, la latence en un seul thread avec des lots de 1. Voici quelques groupes de modèles de précision comparable :\n\n| Modèle | FLOPs | GPU (images/s) | CPU (ms) | ARM (ms) | Top-1 |\n| --- | ---: | ---: | ---: | ---: | ---: |\n| MobileViT-XXS | 0,42 G | 2 393 | 30,8 | 348 | 69,0 % |\n| MobileNetV2 | 0,31 G | 4 198 | 12,2 | 442 | 72,0 % |\n| ShuffleNetV2 ×1,5 | 0,30 G | 4 878 | 12,1 | 266 | **72,6 %** |\n| **FasterNet-T0** | 0,34 G | **6 807** | **9,2** | **143** | 71,9 % |\n| ResNet-50 | 4,11 G | 959 | 73,0 | 1 131 | 78,8 % |\n| **FasterNet-T2** | 1,91 G | **1 991** | **33,5** | **497** | **78,9 %** |\n| Swin-T | 4,51 G | 609 | 122,2 | 1 424 | 81,3 % |\n| ConvNeXt-T | 4,47 G | 657 | 86,3 | 1 889 | **82,1 %** |\n| **FasterNet-S** | 4,56 G | **1 029** | **71,2** | **1 103** | 81,3 % |\n| Swin-B | 15,47 G | 237 | 349,2 | OOM | 83,5 % |\n| ConvNeXt-B | 15,38 G | 253 | 257,1 | OOM | **83,8 %** |\n| **FasterNet-L** | 15,52 G | **323** | **219,5** | OOM | 83,5 % |\n\n*Tableau : extrait de la Table 3 de l'article. Entrée de 256×256 pour MobileViT, de 224×224 pour les autres ; OOM signale une mémoire insuffisante.*\n\nDans chaque groupe, FasterNet est le plus rapide sur les trois appareils. Le groupe le plus parlant est le dernier, où FasterNet-L, ConvNeXt-B et Swin-B ont des FLOPs presque identiques, autour de 15,4 G à 15,5 G, alors que FasterNet-L a un débit GPU supérieur de 28 % à 36 %, et un temps CPU inférieur de 15 % à 37 %. Mêmes FLOPs, vitesses différentes ; c'est tout le propos de l'article.\n\nLa précision, elle, demande une lecture attentive. Le résumé annonce que T0 est plus précis que MobileViT-XXS de 2,9 points de pourcentage, ce qui est exact, mais MobileNetV2 et ShuffleNetV2, dans le même groupe, sont tous deux plus précis que T0. FasterNet-S atteint 81,3 %, comme Swin-T, soit 0,8 de moins que ConvNeXt-T ; l'article dit FasterNet-L « comparable » à ConvNeXt-B, alors qu'il lui est inférieur de 0,3. Ce que FasterNet gagne, c'est la vitesse ; la précision reste à peu près au même niveau, et parfois un peu en dessous.\n\n### Détection et segmentation\n\nSur COCO, Mask R-CNN est entraîné 12 époques. FasterNet-S obtient une box AP de 39,9, contre 38,0 pour ResNet-50, avec une latence GPU presque identique (54,3 ms contre 54,9 ms). FasterNet-L atteint 44,0, contre 42,9 pour PVT-Large, et la latence descend de 152,2 ms à 93,8 ms.\n\n### Ablations\n\n| Configuration | GPU (images/s) | CPU (ms) | ARM (ms) | Top-1 |\n| --- | ---: | ---: | ---: | ---: |\n| T0, $c_p = c/4$ (par défaut) | 6 807 | 9,2 | 143 | 71,9 % |\n| T0\\*, $c_p = c/2$ | 6 626 | 9,6 | 145 | 71,7 % |\n| T0\\*, $c_p = c/8$ | 6 204 | 8,9 | 140 | 71,3 % |\n| T0, LayerNorm au lieu de BatchNorm | 5 515 | 10,7 | 159 | 71,9 % |\n| T0, ReLU au lieu de GELU | 6 929 | 8,2 | 114 | 71,3 % |\n| T2, GELU au lieu de ReLU | 1 985 | 35,4 | 557 | 78,7 % |\n\n*Tableau : extrait de la Table 5 de l'article. T0\\* est une version dont la largeur et la profondeur ont été ajustées pour une complexité comparable ; T2 utilise ReLU par défaut, d'où la comparaison avec GELU.*\n\nPrendre $c_p$ égal à 1/4 offre le meilleur équilibre ; trop grand, PConv dégénère en convolution ordinaire, trop petit, elle ne capte plus les caractéristiques spatiales. LayerNorm et BatchNorm donnent la même précision, mais LayerNorm ne peut pas être fusionnée dans la convolution, et le débit GPU baisse de 20 %. Côté activation, GELU est plus précis pour les petits modèles, et ReLU meilleur pour les grands ; les auteurs supposent que les petits modèles ont davantage besoin de la non-linéarité de GELU.\n\nEn annexe, les auteurs mentionnent aussi deux limites. Le pas de PConv doit être de 1, sinon les canaux convolués et les canaux inchangés ne s'alignent plus, et le sous-échantillonnage doit être confié à d'autres couches. FasterNet n'est fait que de petites convolutions, avec un champ réceptif limité ; les auteurs laissent son élargissement à des travaux futurs.\n\n## Conclusion\n\nLa latence, ce sont les FLOPs divisés par les FLOPS ; c'est la formule à retenir de cet article. À ne chercher qu'à réduire le numérateur, on fait chuter plus vite le dénominateur, et le réseau ralentit. C'est le cas de la convolution depthwise, qui économise des opérations mais passe tout son temps à transférer des données en mémoire.\n\nPConv est d'une simplicité presque gênante ; on convolue un quart des canaux, on raccroche le reste, et c'est tout. Quelques lignes suffisent pour l'intégrer à votre propre réseau.\n\nEnfin, mesurez toujours la vitesse sur vos propres appareils. L'article utilise une 2080Ti, un i9-9900X et un Cortex-A72 ; sur notre i9-13900K, la tendance est la même, mais les chiffres diffèrent sensiblement. Sur le NPU d'un téléphone ou avec un autre framework d'inférence, le classement peut s'inverser ; ne tirez pas vos conclusions directement des tableaux de l'article.\n","imageSizes":{"/content/papers/assets/20f1c9a908d887f3d0a9df04a50fcc019d38cf455e2b89451d3b2c8469b91f94.png":{"width":2083,"height":650},"/content/papers/assets/f7b24b9388f5bb090f5420a96d640e9f851fd40becb24e6bb9b31ba1ebee4b71.png":{"width":1012,"height":500},"/content/papers/assets/25dba5e2fc3ece26c7c5fd70741eb94aaf914907a40406aabfb39756ab3f1144.png":{"width":1767,"height":742}}}
