Apache MXNet sur le Cloud AWS en demos

December 14, 2017
Slides : http://chilp.it/848e2e0 Grâce des projets Open Source comme MXNet et Keras, il est désormais beaucoup plus aisé d’intégrer des modèles de Deep Learning dans vos propres applications. Au travers de démos en Python, nous vous montrons comment créer vos modèles, comment les entraîner et comment les invoquer. Au passage, nous aborderons bien sûr l’utilisation des instances EC2 dotées de GPU. ✚ Retrouvez tous nos événements : https://aws.amazon.com/fr/events/ ✚ Rendez-vous sur notre site internet : http://amzn.to/2ktrf5g ✚ Suivez-nous sur Twitter : https://twitter.com/aws_actus

Transcript

Nous revoilà pour le deuxième webinar de l'après-midi. Après cette introduction au deep learning et au fonctionnement de base du deep learning, on va maintenant s'intéresser à une librairie qui s'appelle Apache MXNet. Comme vous allez le voir, celle-ci vous permet, via une API relativement facile, de définir des réseaux et de les entraîner et les utiliser. On va parler d'Apache MXNet évidemment et puis rapidement on va aller sur les démos qu'on va exécuter dans les notebooks. Qu'est-ce que c'est qu'Apache MXNet ? Apache MXNet est une librairie open source spécialisée pour le deep learning. Un projet qui date de 2015, qui est initialement une collaboration universitaire et qui a été rejointe ensuite par les sociétés. MXNet est aujourd'hui le framework de prédilection pour le deep learning chez AWS pour quelques raisons. La première raison, c'est que l'API est de haut niveau, son utilisation est assez simple. Et surtout, elle est possible dans différents langages. La plupart des librairies de deep learning ne fonctionnent que dans un, voire deux langages, ce qui contraint évidemment les utilisateurs dans le choix du langage à utiliser. MXNet est utilisable en Python, C++, R, Scala, et est utilisable en Julia, et je pense que j'en oublie. Donc voilà, un choix de langage à la fois adapté aux environnements exploratoires, data scientist, etc., et des langages plus orientés production, comme peut-être C++ ou Scala, pour plus de performance. Le deuxième point qui nous plaît dans MXNet, c'est son côté logiciel efficace et portable entre les environnements. Vous pouvez entraîner un modèle dans le cloud, le déployer dans une application mobile ou sur un device comme un Raspberry Pi ou des équipements finalement assez peu puissants. Le MXNet va fonctionner de manière tout à fait satisfaisante. Demain, on parlera de ces sujets. Je vais amener mes gadgets et je vous montrerai comment, entre autres, on peut faire du MXNet sur un Pi. Le troisième point qui nous plaît bien, c'est la scalabilité de MXNet en termes de training. Si vous avez des gros datasets, que vous avez envie d'accélérer l'entraînement, vous allez pouvoir ajouter des GPU et profiter d'une scalabilité quasi linéaire. On fait des benchmarks jusqu'à 256 GPU où on montre que sur des modèles complexes, le training scale quasiment linéairement. Cela signifie concrètement que si vous avez un training qui dure 16 jours sur un GPU, si vous utilisez 16 GPU, il est tout à fait probable que le training ne dure plus qu'une journée. Des résultats plus rapides, c'est toujours essentiel, et une bonne utilisation des ressources matérielles. Une autre bonne nouvelle, c'est que ce projet fait maintenant partie de l'incubateur Apache, donc il est soumis à la gouvernance d'Apache. Il n'y a pas d'hégémonie d'un acteur ou d'un autre sur MXNet. Personne ne dirige MXNet. MXNet fait partie d'Apache et est soumis à la gouvernance Apache. Pour les utilisateurs, c'est une garantie d'indépendance et de non-intrusion d'un acteur particulier sur le projet. Et puis enfin, AWS contribue activement au développement de MXNet et fait en sorte que AWS soit le meilleur environnement possible pour faire fonctionner MXNet. Un des points que j'apprécie particulièrement sur MXNet, c'est que, comme j'ai répondu à une question tout à l'heure là-dessus, il est vraiment aisé de basculer d'une utilisation CPU. Voilà un exemple, on le verra concrètement tout à l'heure. Mais ce qu'il faut retenir ici, c'est que pour passer vers un environnement GPU, il suffit de rajouter ce paramètre contexte et d'indiquer le numéro du GPU. Et c'est tout. Vous pourriez tout à fait prototyper sur votre laptop sans GPU et puis faire du training sur un petit dataset et travailler sur CPU. Et puis ensuite passer dans un environnement serveur ou passer en production et dire ok maintenant je veux faire le même modèle sur le vrai dataset et je veux le faire sur des GPU et voilà, la seule chose qui va changer dans votre code c'est le paramètre de contexte que vous indiquez lorsque vous instanciez le réseau que vous allez utiliser. Voilà le fameux benchmark dont je parlais tout à l'heure. On voit ici des modèles de reconnaissance d'image comme Inception V3 ou ResNet et on voit qu'ils vont scaler quasiment linéairement jusqu'à 256 GPU. C'est quand même, voilà, ça c'est une des grandes caractéristiques d'Apache MXNet qu'on ne retrouvera pas dans des librairies concurrentes. La facilité d'emploi des GPU, la facilité de faire du training multi GPU et y compris du training distribué sur plusieurs instances GPU, et à mon avis une caractéristique assez unique d'Apache MXNet aujourd'hui. Dans l'API Apache MXNet, on va voir les notebooks dans une minute, il y a 4 objets, 4 API qui sont particulièrement importantes, et je voulais le souligner. Donc on a bien vu tout à l'heure lorsqu'on a parlé du processus de training, la première étape c'est stocker ces données dans une matrice ou dans un tenseur, donc un tableau à n dimensions. Dans mon exemple trivial, j'étais dans un tableau à deux dimensions, mais en pratique, généralement, on va travailler avec des tableaux multidimensionnels et beaucoup plus grands que ça. Donc on va utiliser cet objet qui s'appelle ND Array, donc N-Dimension Array, qui représente donc les tenseurs dans MXNet. On va s'en servir constamment pour charger nos données. C'est comme ça qu'on va fournir les données pour l'entraînement. Ensuite, il va nous falloir une deuxième API pour construire les modèles, donc construire les couches, les relier entre elles, choisir les fonctions d'activation, etc. Et vous allez voir qu'on le fait de manière assez simple avec Apache MXNet. Ça va être l'API Symbol. La troisième entité importante, c'est l'itérateur qui va nous permettre, sans grande complication, de servir les données au modèle pendant l'entraînement et pendant la validation batch par batch. Vous vous souvenez qu'on va découper le dataset en batch, et donc on va entraîner batch par batch et valider batch par batch. Ça serait assez agaçant d'avoir à faire ce découpage soi-même et à servir les données tranche par tranche au modèle. Avec l'itérateur, vous allez voir, ce problème-là est complètement réglé, c'est lui qui va le faire. Et puis enfin, il nous faut une API pour recoller tous les morceaux, paramétrer le training, lancer le training, sauver les modèles, recharger les modèles. Et ça, ça va être l'API module. Donc on va voir ces 4 API, on va les voir systématiquement dans tous nos notebooks. Avec l'API Apache MXNet, on va pouvoir construire toutes les architectures de réseaux possibles et imaginables. Des réseaux fully connected, comme celui qu'on a vu sur mon exemple tout à l'heure. On va faire des réseaux pour faire de la reconnaissance d'image. On va pouvoir faire des réseaux de type LSTM, Long Short Term Memory, pour prédire des séquences. On va pouvoir construire toutes les architectures de réseaux et on dispose d'un grand nombre de fonctions d'activation. Il est fort probable que vous trouverez dans Apache MXNet les objets et les API qui vous permettent de construire les réseaux dont vous avez besoin. D'ailleurs, je ne le ferai pas aujourd'hui, mais sans doute demain, je vous montrerai un ensemble de projets open source qui ont été réalisés avec Apache MXNet, et vous verrez qu'il y a tout type d'architecture, y compris les plus récentes. On a lancé récemment une API supplémentaire dans N1.0, qui est une collaboration avec Microsoft. Elle est d'ores et déjà disponible dans Apache MXNet et sera prochainement disponible dans le toolkit de Microsoft. L'objectif de Gluon, c'est de simplifier encore plus la construction des modèles, de fournir des API de plus haut niveau pour littéralement en une ligne créer des modèles sur la base d'architecture de référence. Vous allez aussi pouvoir modifier les architectures de réseau pendant le training. Pour des chercheurs ou des gens qui expérimentent, c'est particulièrement intéressant de pouvoir, au fil du training, adapter la structure du réseau. Il y a aussi des cas d'usage sur des architectures de réseau modernes, comme ce qu'on appelle les GAN, les Generative Adversarial Networks. Je vous en montrerai un exemple demain, qui permettent de générer des images, et non pas de les classifier, mais vraiment de les fabriquer. Une technique est de faire grossir le réseau au fur et à mesure qu'on construit l'image. Voilà, technique très avancée, mais on peut faire ça avec Gluon. Donc une API plus simple, plus flexible, mais sans pour autant faire de compromis sur la performance, qui, j'insiste, est vraiment un des grands avantages d'Apache MXNet. J'ai fait des benchmarks entre Apache MXNet et TensorFlow, et Apache MXNet était de loin plus rapide, et en particulier sur du multi GPU. On ne veut pas perdre la simplicité d'usage, on ne veut pas perdre la performance au prix de la simplicité d'usage, on veut les deux. Et puis on a aussi ce qu'on appelle un model zoo, c'est-à-dire une collection de modèles pré-entraînés disponibles sur étagère, qui est particulièrement riche dans Gluon. Voilà la liste, qui est déjà dû même se compléter depuis que j'ai fait ces copies d'écran. Vous voyez qu'on a des grandes familles, des grandes architectures de réseau, VGG, ResNet, AlexNet, etc., qui existent dans différentes tailles, dans différentes configurations. Et donc dans Gluon, tous ces modèles-là sont déjà disponibles. Vous pouvez les créer en une ligne, en un appel d'API. Vous pouvez en charger des versions pré-entraînées en un appel d'API. Donc voilà, tout ça dont l'objectif est évidemment de simplifier la vie des développeurs et de leur permettre d'aller chercher des réseaux soit prêts pour training, soit déjà entraînés en littéralement un appel d'API. Je vous rappelle juste pour ceux qui auraient raté le premier webinar qu'on vous fournit également une AMI pré-configurée qui s'appelle la Deep Learning AMI qui contient toutes les librairies Deep Learning Open Source dont vous pouvez rêver, qui contient les drivers Nvidia, tout l'environnement Nvidia, donc rien à configurer pour utiliser les GPU et puis d'autres outils, Python, Anaconda, etc. Donc si vous voulez vous lancer et découvrir le Deep Learning sur AWS, il faut vraiment utiliser cette AMI, elle vous débarrassera de toute configuration et vous pourrez directement attaquer le développement. Alors voilà, on va attaquer les démos. Je vais faire 4 démos. Vous trouverez les notebooks Jupyter sur GitHub à cette adresse et allons-y. Le premier notebook que je vais vous montrer, c'est un peu le Hello World, j'appelle ça le Hello World des MXNet, vous allez comprendre pourquoi. Ici, je vais générer un dataset synthétique. Je vais prendre des valeurs aléatoires et je vais construire un dataset avec ça. Je vais fabriquer 10 000 échantillons, 8 000 pour l'entraînement et 2 000 pour la validation. Et chacun de ces échantillons va avoir 100 features. Et chacun de ces échantillons appartiendra à une catégorie parmi 10. Pour revenir à ce que j'ai présenté tout à l'heure, je vais construire une matrice qui va avoir 10 000 lignes et 100 colonnes. Chaque ligne sera un échantillon et il sera composé de 100 features. 10 000 lignes, 100 colonnes, ça c'est X. Mes labels Y vont être une matrice de 10 000 lignes et d'une colonne. La colonne, ce sera juste le label en question. Et ce label, ce sera un entier entre 0 et 9, puisque j'ai 10 catégories. Jusque-là, tout va bien. Donc, je vais déclarer tout ça. Et je vais construire mon dataset. Je vais initialiser une matrice X avec des valeurs aléatoires entre 0 et 1, ici d'une distribution uniforme. Donc, cette matrice aura 10 000 lignes et 100 colonnes. Ensuite, je vais créer ma matrice Y, donc 10 000 lignes et 1 colonne, et je vais remplir tout ça avec des entiers compris entre 0 et 9. On est vraiment sur un jeu de données aléatoire. Ensuite, je vais découper mon dataset entre les données de training et les données de validation. OK ? Donc je vais construire Xtrain, Ytrain, Xvalid et Yvalid. Et donc ils auront cette forme-là. Mon Xtrain, c'est 8 000 lignes sans colonne. Et mon Xvalid, forcément, c'est 2 000 lignes et sans colonne. OK ? Donc j'ai gardé quelques échantillons pour la validation. Et le gros de la troupe va servir pour l'entraînement. Ensuite, je vais construire mon réseau. Donc là, je construis un réseau qui ressemble très fortement à celui que je vous ai montré tout à l'heure. Une couche d'entrée qui va recevoir mes données, qui va recevoir un échantillon avec 100 features. Donc il va y avoir 100 neurones sur cette couche d'entrée. Ensuite, une couche cachée avec 1024 neurones qui sont activés par la fonction ReLU. Et puis, une couche de sortie qui va avoir le même nombre de neurones que le nombre de catégories. Souvenez-vous de ce que je vous ai montré tout à l'heure pour la classification. Donc ici, on va avoir 10 neurones sur la couche de sortie. En entrée, 100 neurones parce que j'ai 100 features. 1024 neurones cachés au milieu, et puis 10 neurones sur la couche de sortie. Dans chacun de ces neurones de sortie, je vais trouver la probabilité que l'échantillon appartienne à la classe 0, 1, 2, 3, etc. Voilà en 5 lignes comment je définis mon réseau de neurones. Vous voyez, c'est tout simple, on chaîne les couches les unes après les autres. On les emboîte comme des Legos. Et puis je décide ici que je vais faire ça sur GPU parce que je suis sur une instance GPU donc pourquoi pas. Voilà pour la construction du modèle. Ensuite, on va construire l'itérateur. L'itérateur c'est l'objet qui va servir le jeu de données batch par batch au modèle. Vous voyez que c'est super simple. On passe les données d'entraînement, les labels d'entraînement, la taille de batch, et on récupère l'itérateur. Ça, c'est réglé. On pourrait afficher, tiens, on pourrait utiliser l'itérateur pour afficher les données. Donc là, on voit les échantillons. Évidemment, c'est que des valeurs aléatoires, ça ne me dit pas grand-chose. Mais on voit qu'on a affiché 16 lignes avec 100 colonnes. Bon, ça c'est juste pour vous montrer que l'itérateur va servir les données. Voilà, là évidemment il y en a une montagne. On va passer ça. Ensuite, on va recoller les morceaux. On va associer l'itérateur au modèle qu'on a créé. On va initialiser les paramètres. On va choisir des valeurs initiales pour les poids. On pourrait laisser des valeurs aléatoires, mais en pratique, laisser des valeurs aléatoires, ce n'est pas une bonne idée, parce que ça ne va pas garantir une bonne convergence de l'entraînement. Il y a un certain nombre de techniques pour assigner des valeurs de départ raisonnables au poids. Par exemple, cette méthode de Xavier, du nom de son inventeur, qui va mettre des valeurs raisonnables pour initialiser les poids. Ensuite, je vais choisir ma méthode d'optimisation. On va rester sur des choses simples. Je vais rester sur mon SGD, avec un learning rate de 0,1, qui est une valeur type. Voilà, c'est fait. Et puis maintenant, je peux faire l'entraînement. Donc j'appelle cette API fit en lui passant l'itérateur, en lui disant pendant combien d'époques je veux tourner. Et puis j'ai un petit callback qui va m'afficher des informations pendant le training. Voilà, c'est parti. Donc là, je vois les différentes époques qui défilent. 1, 2, 3, 4, etc. À la fin de chaque époque, je vois la précision de training, elle augmente, ça c'est pas une surprise puisqu'on a dit tout à l'heure qu'elle va arriver à 100. On sait que ce sera suffisamment de données et suffisamment de neurones pour apprendre ce dataset parfaitement, donc allons jusqu'à la fin. 99, 81, 99, 93, voilà et on arrive à 1. Donc une fois de plus, la question n'est pas de savoir est-ce qu'on va arriver à 1, la question c'est quand. Donc là, à la 43ème époque, finalement, on arrive à 1, et puis on ne va pas plus loin, puisqu'on a déjà minimisé la fonction d'erreur, on a appris parfaitement ce dataset. Donc on est capable de prédire exactement la bonne catégorie pour ces 8 000 échantillons, puisqu'on a 8 000 échantillons pour entraîner. Donc, ok, super, on est content, on a appris le training set. Maintenant, qu'en est-il de la validation ? Parce que ce qui nous intéresse, c'est comment ce modèle va se comporter lorsqu'il va avoir de nouveaux échantillons. Donc, on va prendre maintenant le dataset de validation. On va construire un itérateur de validation. Et on va passer ce dataset de validation à travers le modèle et on va mesurer la précision. Voilà. Et là, évidemment, on a un score qu'on pourrait qualifier de lamentable pour la bonne et simple raison qu'on a pris des données aléatoires et que forcément, dans des données aléatoires, il n'y a aucune forme de structure, donc il n'y a aucun feature à apprendre sur des données aléatoires. Donc certes, le réseau a appris, mais il ne généralise pas du tout. Et lorsqu'on lui montre des échantillons, il les prédit de manière lamentable. Il a 10% de précision, ce qui est logique puisqu'il y a 10 classes. Donc si on choisit au pif une classe parmi 10, statistiquement, on va avoir 10% de précision. Donc ça, ça montre deux choses. Ça montre qu'un réseau, ça peut apprendre absolument n'importe quoi. S'il est suffisamment grand, il y a suffisamment de données et qu'on lui laisse suffisamment de temps. Mais que la métrique qui compte, c'est évidemment la précision de validation et qu'il n'y a pas de magie, garbage in, garbage out. Donc si votre jeu de données n'a aucun sens ou est sale ou bref, n'est pas adapté, le réseau de neurones va l'apprendre, mais pour autant, il ne saura rien prédire et il ne saura pas généraliser. Donc une fois de plus, bien faire attention à cette précision de validation. Et dans les exemples suivants, vous verrez qu'on décidera de l'afficher à chaque fois, à la fin de chaque époque, pour s'assurer que cette fois, le training fonctionne correctement. Alors, prenons un vrai dataset maintenant. Donc on va prendre un dataset célèbre, qui est le dataset qui sert à faire pas mal de tests, qui s'appelle MNIST. MNIST, c'est une collection de 70 000 digits manuscrits, donc on en prend traditionnellement 60 000 pour faire l'entraînement et 10 000 pour faire la validation. Donc le but du jeu évidemment, c'est de montrer des images au réseau et de lui demander quel est le chiffre. Le dataset, j'ai déjà téléchargé ici. On va dire on va s'entraîner sur 50 époques. On va construire un itérateur. OK, alors Apache MXNet est vraiment sympa, on a un itérateur spécifique à MNIST, donc voilà, il suffit même de lui dire je veux MNIST et il va aller charger les fichiers localement et on se débrouille. Oups, alors voilà, on construit l'itérateur. Puis ensuite on va construire le réseau. Cette fois, on va rester sur un réseau fully connected. On va avoir deux couches de neurones cachés. Donc on a toujours une couche d'entrée. La couche d'entrée va recevoir des images. Ces images MNIST font 28 pixels par 28 pixels en noir et blanc. Ici, on va faire le choix de l'aplatir cette image. Ça va devenir un vecteur, 28 x 28, c'est-à-dire 784 valeurs. Donc on va avoir un vecteur avec 784 valeurs de pixels. Et c'est ça qu'on va mettre sur la couche d'entrée. On la passe ensuite dans une couche cachée de 512 neurones, activée par ReLU, une couche de 256 neurones, activée par ReLU, et en sortie, une couche de sortie avec, sans surprise, 10 neurones, puisqu'on a 10 classes, et donc on va avoir dans chaque neurone de sortie la probabilité que l'image appartienne à telle ou telle classe. Donc vous voyez, en 6-7 lignes, aisément, on construit son modèle. Ensuite, on va faire comme tout à l'heure, on va instancier ce réseau, on va le placer sur un contexte GPU, parce que pourquoi pas. On va associer ce modèle à l'itérateur, c'est exactement comme tout à l'heure. On va initialiser des paramètres initiaux, on va rester sur Xavier. Et puis on va choisir un optimiseur. Alors ici, on aurait pu choisir SGD, mais histoire de vous montrer autre chose, on va utiliser Adagrad. Adagrad a un avantage par rapport à SGD, c'est qu'Adagrad va faire varier automatiquement le learning rate en fonction de l'apprentissage. Donc il va augmenter le learning rate si l'apprentissage est trop lent et diminuer le learning rate si l'apprentissage doit être affiné. Ça résout un peu le problème, on lui donne juste le learning rate de départ et ensuite il se débrouille. C'est un bon algorithme pour obtenir des résultats affinés dans un temps plus court puisque, contrairement à SGD qui reste sur un learning rate fixe, Adagrad fait progresser ce learning rate. Très bien, en avant, et puis on va faire l'entraînement. Donc ici on a dit 50 époques. On va appeler fit pour 50 époques, c'est parti. Comme tout à l'heure, on voit chaque époque qui se déroule, et puis on voit la précision d'apprentissage. Et on voit la précision de validation. Tout ça va évidemment monter. Donc là on part à 91. Et puis on va avancer, avancer, avancer. Hop, continuons. Voilà, là on est à 99.7 en training. 99. en validation. Et on a dû finir. Et on termine au bout de 50 époques à 99,82 en training et 98,48 en validation. Chaque époque prend à peu près une demi-seconde. Vous voyez, ce n'est pas très long. Donc on va sauver le modèle parce que je vais m'en servir tout à l'heure. Comment est-ce qu'on sauve un modèle comme ça, hop, voilà, save checkpoint, et là j'ai sauvé le modèle avec toutes les valeurs de poids, donc ce fichier et params, et je vais pouvoir m'en resservir plus tard. Alors maintenant, mesurons sa précision, donc on va prendre l'itérateur de validation, on le passe à travers le modèle et on regarde le score, ok ? Bon, et on arrive à 98,48. Alors 98,48 ça paraît bien, ça paraît un score très élevé, 98,48 de succès, on va dire ok c'est super, ça doit être un bon modèle. Alors on va regarder, et on va le tester, on va le confronter à des vrais échantillons. J'ai pris ma belle application Paintbrush, j'ai dessiné des images de digits de 0 à 9, plus ou moins moche, et puis on va voir ce que ça donne. Donc il faut que je sache comment mes images au réseau. Mes images sont des petits fichiers JPEG. Donc il va falloir que je les lise. Je les lis avec OpenCV. Je normalise les valeurs de pixels. Donc mes valeurs de pixels seront entre 0 et 1 puisque c'est comme ça que le dataset a été constitué. Il s'attend à avoir des features qui sont entre 0 et 1. Je vais rajouter une dimension et donc je vais avoir à la fin une NDArray qui va avoir la forme 1, donc une image, x1, donc un seul canal puisqu'elle est noir et blanc. Si c'était une image couleur, j'aurais plusieurs images, rouge, vert, bleu. Donc mon NDArray va être 1 x 1 x 28 x 28. Ok ? Voilà, on verra ça tout à l'heure. Ce qui va être retourné par cette fonction, ça va être une NDArray, 1 x 1 x 28 x 28, donc 4 dimensions. Ensuite, je vais faire ça, et puis ensuite je vais afficher la shape, pourquoi pas, comme ça on la verra. Et puis, je vais, pour prédire, je vais prendre cette array, cette NDArray, puis je vais la pousser à travers mon réseau. Et puis ensuite, je vais récupérer les valeurs qui sont sur la couche de sortie, donc les 10 probabilités qui sont sur la couche de sortie du réseau, puis je vais les retourner. Donc ma prédiction, elle va me retourner un vecteur de 10 probabilités. Et donc pour charger mon modèle, tout à l'heure pour le sauver, j'avais fait « Save Checkpoint », ici je vais faire « Load Checkpoint ». Je récupère mon modèle, je l'instancie, je l'associe à ma donnée. Ici je lui dis non, attention, je ne vais pas faire du training, je vais juste faire de l'inférence. Et la donnée que tu vas avoir en entrée, elle va être, comme je disais tout à l'heure, 1 x 1 x 28 x 28, c'est-à-dire une image qui est en noir et blanc et 28 pixels x 28 pixels. Et puis c'est tout. C'est comme ça qu'on charge un modèle, vous voyez c'est pas très compliqué. Donc je vais charger ici le modèle que j'ai entraîné tout à l'heure, mon perceptron à deux couches là, que j'ai entraîné pendant 50 époques. Je le charge, puis ensuite je vais prendre mes 10 digits. Je les charge un par un, je les transforme en NDArray et puis je les passe à la moulinette du modèle. On voit que la forme c'est bien 1 x 1 x 28 x 28. On voit que le 0 est très bien prédit, aucun doute. Là on voit bien les 10 probabilités. Et donc la probabilité du neurone 0, on va dire, c'est la plus élevée. Donc ça me dit bien que c'est la classe 0. Très bien, bonne nouvelle. Le 1 est à 100% de chance d'être un 1, c'est super. Le 2 aussi. Le 3, tout va bien. Le 4, tout va bien. Le 5, ça va. Le 6 aussi. Le 7, parfait. Le 8, bien. Et le 9 est faux. Parce que vous voyez que la probabilité la plus élevée, elle est pour 0, 1, 2, 3, 4. Donc ils pensent que mon 9 est un 4. Alors c'est que mon 9 est particulièrement laid, mais il n'en est pas moins que c'est un 9. Donc ce réseau-là, c'est décevant, parce qu'on s'attendait à avoir une précision de 98 et quelques, et puis on se rend compte que là, sur 10, on a déjà une erreur, alors que là, à l'œil nu, on dirait non, c'est un œuf, c'est pas un quatre. Donc, manifestement, cette architecture de réseau-là, sur des digits un peu mal fichus comme celui-là, elle n'est pas très pertinente. Alors, on verra pourquoi tout à l'heure. On va tester une autre architecture de modèle. On va tester un modèle de type convolution. Le dataset, je l'ai déjà chargé, ce n'est pas la peine de le faire. On va cette fois s'entraîner pendant 25 époques. On va construire l'itérateur. Et là, cette fois, on va construire un réseau qui est... un réseau célèbre qui s'appelle LeNet, qui est un réseau qui a été inventé par Yann LeCun, qui est un des grands experts de l'intelligence artificielle, qui est français. Et donc ce réseau, il a la particularité d'utiliser une opération qu'on appelle la convolution. Je reviendrai sans doute un peu demain quand on zoomera sur les problématiques de reconnaissance d'image et de classification d'image, mais pour en dire deux mots, la convolution, c'est une opération mathématique qui va travailler sur l'image en deux dimensions, cette fois. Donc ici, on ne va pas aplatir l'image, on va garder l'image en deux dimensions. Et avec cette opération de convolution, on va apprendre à reconnaître des features qui sont marquants. On va, via des filtres, je parlerai de ça demain, via des filtres, on va apprendre à extraire de ces images les features marquants. Et ensuite, avec cette opération qui s'appelle pooling, on va réduire la dimension du problème. Donc on va passer progressivement d'une image de 28 par 28 à une image plus petite, à une image plus petite. Mais grâce à la convolution, on va garder les éléments importants de l'image. On va extraire de l'image les informations qui sont importantes. Et puis finalement, on va éliminer le reste, ce qui va nous permettre de réduire la dimension du problème. Donc on a deux couches de convolution et de pooling, pour finir par une couche connectée qui, elle, va faire la classification en dix catégories. Donc vous voyez, ce n'est pas un réseau très compliqué. Il n'y a pas... Il y a une, deux, trois... 4, 5, voilà, il y a 6 couches, donc c'est pas énorme. Et vous pourriez tout à fait aller regarder la structure du réseau dans l'article de Yann LeCun, et vous verrez, j'ai fait quelques modifications là, parce que, évidemment, entre-temps, ce réseau date de 1998, sauf erreur, donc entre-temps, il y a de nouvelles fonctions, il y a de nouvelles améliorations, donc je me suis permis de... de faire quelques modifs, mais vous pourriez tout à fait lire le papier de Yann LeCun et regarder le dessin du réseau et puis le coder vous-même avec les APIs d'Apache MXNet. Et puis, comme d'habitude, on va instancier le réseau, le placer sur GPU, l'associer aux itérateurs, initialiser ici, alors là j'ai pris une distribution normale, pourquoi pas, et puis j'ai testé un autre optimiseur qui s'appelle Adam qui lui va adapter automatiquement le learning rate et va même aller jusqu'à avoir un learning rate par paramètre. Donc on ne va pas avoir un learning rate pour tous les paramètres, on va pouvoir faire varier le learning rate pour chaque paramètre à optimiser. Ok, et puis en avant pour le training. Donc là on est sur GPU, et on l'a vu tout à l'heure quand on discutait avec Myriam, là on est sur des opérations mathématiques type convolution, etc., pooling, qui sont du calcul matriciel pur et dur, et vous voyez que même avec un petit dataset comme celui-là, et même avec un petit réseau comme celui-là, sur GPU on est à 200%. Là, on est sur un GPU. On est à 2 secondes par époque. Donc, on voit que, effectivement, la charge de calcul, dès qu'on fait des opérations de convolution, dès qu'on travaille avec des architectures plus compliquées, la charge de calcul devient importante. Si vous essayez de le faire sur CPU, vous allez être... Enfin, moi, quand je le fais sur mon Mac, je crois que je suis à 45 ou 50 secondes par époque. Donc, quand on veut faire 30 ou 40 époques, ça fait tout de suite 20 minutes et c'est désagréable. Dès qu'on fait de la convolution, effectivement, le GPU devient assez vite indispensable. Alors, où est-ce qu'on en est ? Je crois qu'on fait 25 époques, voilà. Donc, on arrive à la fin avec 99.77 en training et un petit peu moins de 99 en validation. Bon, alors on va voir ce que ça donne. On va sauver le modèle. On va mesurer sa précision de validation, donc 98, 99. Et puis maintenant, on va tester, on va voir si... Oups ! On va refaire exactement la même prédiction. Cette fois, au lieu de travailler avec mon perceptron, on va travailler avec mon nouveau réseau. Je vais charger l'autre réseau et je vais refaire la prédiction de mes digits en espérant que le 9 cette fois soit reconnu correctement ce qui sera peut-être pas le cas parce que de temps en temps on a des résultats bizarres on verra ce que ça donne alors le 0 est bien le 1 est bien 2 c'est bon 3 c'est bon 4 5 on a des probabilités très très élevées 6 7, 8, et bien voilà. Donc le 9, cette fois, il est bien reconnu comme un 9. On voit la probabilité la plus élevée, c'est bien un 9. Alors, on pourrait se dire pourquoi ? Est-ce que c'est un coup de bol ? Qu'est-ce qui fait qu'on a effectivement une meilleure précision avec... avec ce réseau-là. Alors, on va expliquer un petit peu ça, parce que c'est quand même le cœur du truc. Donc, mon dataset, il a cette tête-là. Donc, je prends des digits, je prends les valeurs de pixels. Donc, chaque pixel a une valeur entre 0 et 255. Et donc ça, c'est ma matrice, c'est donc ma matrice 28 par 28 qui va me servir à faire mon apprentissage. OK ? Alors, dans le cas du premier réseau, souvenez-vous, on aplatissait cette matrice pour faire un vecteur. Donc on prenait les lignes, finalement, on les mettait bout à bout et ça faisait un vecteur de 784 valeurs. Là où LeNet va travailler directement sur l'image et essayer d'extraire des features en 2D de cette image. Donc le perceptron initial, il se débrouille pas mal sur le dataset. Maintenant, sur des échantillons qui sont un peu hors normes, comme mon œuf très moche, ça marche beaucoup moins bien. Et la raison, c'est exactement celle que j'ai donnée, c'est que lorsqu'on aplatit l'image 28-28, pour en faire un vecteur, on perd la relation en 2D entre les pixels. Réfléchissez bien, mais vous verrez, il n'y a aucun autre chiffre qui a un angle comme celui-ci. Donc un angle tourné en haut à gauche. Ça c'est un feature très marquant et quand on détecte, si on arrive à apprendre ce feature géométrique, si on a un détecteur, si on a un filtre dans une couche de convolution qui va être stimulé fortement par cet angle, on sera à peu près sûr qu'il s'agit d'un 5. De même avec le 8, vous voyez que cette intersection, cette espèce de croix qu'on a au milieu du 8, même si elle est moche comme ici, il n'y a aucun autre chiffre qui a ce feature. Donc si un réseau arrive à apprendre dans l'un de ses filtres à reconnaître cette forme géométrique, on aura la quasi-certitude qu'on a un 8. Et c'est ça la force des réseaux à convolution, c'est qu'ils vont travailler sur des images en 2D, et donc ils vont garder la relation en 2D entre les différents pixels, et ils vont apprendre à détecter ces formes géométriques de base, donc les lignes droites, horizontales, verticales, les diagonales, les bordures, les intersections, etc. C'est ça la magie d'un réseau à convolution, c'est que dans les fameux filtres des couches de convolution, on va apprendre à reconnaître ces éléments clés. Et donc, forcément, avec des architectures de ce type-là, on va être beaucoup plus robustes, parce que même si je fais un 5 assez pourri, si je fais une boucle moche sur mon 5, à partir du moment où mon angle ici est quand même relativement visible, le réseau dira « Ok, cette partie de l'image elle me stimule et je sais que c'est un 5. Si je fais un 8 un peu élongué, un peu aplati, à partir du moment où j'ai quand même cette intersection, c'est pareil, ça va stimuler un des filtres dans une des couches de convolution et on pourra conclure avec un bon niveau de confiance que c'est un 8. Alors juste pour conclure, on pourrait refaire un petit test, on va changer des paramètres. Le SGD, tiens, on va repasser sur un optimiseur basique. On va essayer de se souvenir combien on avait, 98, 99, ok, parfait, alors allons-y, on va réentraîner, et on va voir à combien on arrive. Vous voyez, on part déjà, manifestement, on part de beaucoup plus bas. Donc quelque chose me dit qu'on ne va pas arriver à 98-99. Voilà, mais vous voyez le côté sympa des Mixnet et des notebooks, c'est ça. C'est de se dire, bon, on joue avec les paramètres, on optimise son réseau et on ne passe pas trop de temps sur la plomberie. À combien on est ? Ah, on arrive à des choses pas mal finalement. 99,2, on va peut-être arriver à quelque chose de mieux que Adam, ce serait incroyable. 99,9, vous voyez comme quoi ? Le mieux est l'ennemi du bien parfois. Intéressant. Donc avec notre brave optimiseur, peut-être que 25 époques, c'est un peu court pour que Adam fasse vraiment du bon boulot. Vous voyez, c'est un peu plus important. C'est intéressant ici aussi parce qu'on voit, on est à 99, on va remonter un peu, 99,13 en validation, 99,23, 99,12, 99,1. Donc sincèrement, on pourrait se demander si on n'est pas en overfitting. Il aurait fallu ici que je sauve tous les réseaux, tous les modèles intermédiaires parce que manifestement, le modèle qui est issu de l'époque 22 est significativement meilleur que celui d'après. Vous voyez ce que j'ai dit tout à l'heure, l'overfitting, là on le voit, on voit que la validation se met à décroître. Donc ok, on est arrivé à 99.01, mais on a réussi à faire 99.23 un peu plus tôt. On va en refaire encore une fois et puis ensuite on va prendre vos questions. Par exemple, je pourrais partir en SGD avec un learning rate plus petit pour essayer. Et on va voir l'impact. Oulala, on voit qu'effectivement il apprend pas vite. Il apprend pas vite. Donc là manifestement, 0,01, la précision de validation elle augmente pas. Ah, là il s'est mis à prendre un petit coup. Il a eu du mal à démarrer. Là il est à 79, 88, 92, 94. C'est intéressant. On a des comportements. On va voir à combien on arrive. Mais là, vous voyez qu'on a quand même manifestement gaspillé un peu de temps au début. Le temps que la backpropagation nous remette sur des valeurs un peu plus crédibles. 97,6, on va arriver à quelque chose de plus bas. Manifestement, là, on a un learning rate qui est un peu trop bas. Il faudrait sans doute continuer au-delà de 25 époques pour faire quelque chose. Vous pouvez jouer à l'infini avec ces paramètres. On pourrait faire varier la taille de batch, on pourrait faire varier et essayer de trouver des paramètres optimaux. Et donc du coup ça pose la question de comment on les trouve ces paramètres, est-ce qu'on se bat avec son notebook pendant des heures et des heures, ou est-ce qu'on essaie d'automatiser l'entraînement de ces modèles et puis d'essayer plein de combinaisons différentes et de comparer les modèles à la fin. Et bien sûr c'est ça qu'on va avoir envie de faire. Et on en parlera vendredi avec un nouveau service qui s'appelle Amazon SageMaker qui va vous permettre, via un SDK, d'automatiser les trainings, de tester tout un tas de combinaisons et de scaler votre process, entre autres choses, de scaler votre process de training et de trouver plus rapidement quel est le bon modèle. Et ça, on en parlera, on en parlera. Voilà, je crois que c'est ce que je voulais vous dire pour aujourd'hui. Donc, quelques liens, si vous ne les avez pas vu la dernière fois, les pages de haut niveau sur machine learning, le blog AWS, le site d'AmixNet, le GitHub d'AmixNet, Gluon, cette API de haut niveau plus dynamique et plus expérimentale, et puis mon blog sur lequel vous trouverez si vous voulez creuser AmixNet, vous trouverez plein de tutos et plein d'exemples. La plupart des exemples que je prends ici sont issus d'articles sur mon blog, donc ça vous donnera encore davantage d'informations et davantage de pistes pour apprendre. Voilà, j'en ai fini pour cette introduction à MXNet. Je vous remercie de m'avoir écouté. Demain, on va répondre à vos questions bien sûr, mais demain, on continuera sur MXNet. Pour le premier webinaire de l'après-midi, on va se concentrer sur la reconnaissance d'images, donc on va rentrer encore plus profondément dans MXNet, les modèles pré-entraînés, etc. Et puis on va essayer de creuser un peu ces sujets de reconnaissance d'images, et puis de génération d'images. On utilisera un réseau GAN pour générer des échantillons. C'est assez étonnant. Et puis dans le deuxième webinar, c'est le webinar Inspector Gadget, où j'amène mon Raspberry Pi, mon robot avec la caméra, etc. Et j'amène également, au péril de ma vie, j'ai réussi à me procurer une DeepLens. Je ne sais pas si vous êtes au courant de ce magnifique jouet. Donc DeepLens, c'est ça. Ça a été révélé à ReInvent. C'est une caméra qui embarque une infrastructure, une architecture Intel et sur laquelle on peut déployer des modèles de DeepLearning. Si les jeux de la démo sont avec nous, on pourra faire de la détection de visage, de la détection d'objets. On peut voir évidemment les flux de vidéos qui sortent de la caméra. Demain, c'est MXNet avancé sur la reconnaissance d'image. Et puis ensuite, les gadgets, l'IoT, comment faire. Et on va bien s'amuser. Et vendredi, on aura deux sessions. On fera une première session, on fera un récapitulatif des annonces IA et machine learning de reInvent. On a annoncé beaucoup de nouveaux services, on fera un panorama et puis évidemment des démos. Et dans la deuxième session, on parlera justement d'Amazon SageMaker qui est notre nouveau service pour vous aider à accélérer vos workflows de machine learning de deep learning en allant du notebook à l'entraînement au déploiement, etc. Donc un service vraiment intéressant pour tous les gens qui veulent faire du machine learning à l'échelle. Voilà, voilà un peu le programme du reste de la semaine. Le sondage a été affiché. Les questions, alors on est une... Pourquoi est-ce qu'on entraîne le modèle batch par batch et pas avec le training set en un seul coup ? Si on le fait en un seul coup, on va faire la backpropagation qu'une seule fois. Et donc l'objectif, vous l'avez compris, on va le faire une fois par époque. L'objectif c'est de trouver la valeur de batch qui est suffisamment grande pour que le training soit plutôt rapide mais suffisamment petite pour qu'on ait le maximum d'opportunités de faire de la backpropagation. Donc ici mon dataset MNIST de training il fait 60 000 éléments donc si j'ai une taille de batch de 64, bien pour chaque époque j'ai 1000 itérations de backpropagation donc j'ai 1000 opportunités d'ajuster mes poids. Si je fais tout le dataset d'un coup, d'une part, je ne vais faire qu'un ajustement. Et puis, je vais faire l'ajustement sur la base de l'erreur calculée pour 60 000 échantillons. Et honnêtement, ça ne va pas me donner grand-chose. Voilà. Ça ne va pas me donner grand-chose. Il y a une question pour le speech-to-texte. Est-ce qu'il existe des API MXNet ? Le but d'MXNet, ce n'est pas de fournir des API pour résoudre un problème donné. C'est de fournir des API pour construire des modèles de tout type d'architecture. Donc, vous pouvez aller trouver un article de recherche qui a construit un modèle de deep learning pour faire du speech-to-texte et vous pouvez le coder avec AmixNet. Il y a d'ailleurs un modèle basé sur une architecture de Baidu qui m'échappe, je vais essayer de la retrouver, c'est warp.com. Voilà, c'est ça. Donc ça, c'est une architecture dont vous connaissez sans doute Baidu qui est un géant de l'e-commerce en Chine et qui fait énormément de deep learning. Et ils ont conçu une architecture qui s'appelle Warp et qui leur sert à faire du speech-to-text pour le langage chinois. Cette architecture-là a été implémentée sur AmixNet. Je ne sais pas pourquoi cette page-là ne veut pas s'afficher. Est-ce qu'on va essayer celle-là ? Voilà. OK. Voilà, donc c'est ça que vous voulez chercher. Baidu, Warp, CTC, AmixNet. Et là ils utilisent des mixtes pour construire cette architecture de réseaux néo qui est basée sur des LSTM, etc. Bon, c'est sans doute assez expérimental mais bon à essayer. Il y a plusieurs questions sur le site. Ok, mais tout ça, ça a l'air d'être de la cuisine, comment on fait ? C'est de la cuisine et c'est pas de la cuisine. C'est-à-dire que si vous voulez inventer from scratch un modèle, c'est non seulement de la cuisine, mais ça nécessite surtout des compétences techniques en maths et en stats et en deep learning que certainement peu de gens ont et en tout cas que moi j'ai pas. Donc la façon dont moi je travaille c'est que je lis les articles de recherche, je regarde les architectures qui ont été publiées par les chercheurs, je regarde pour quel type de problème est-ce qu'elles ont été utilisées, quels sont les résultats, quel a été le dataset, etc. Après, une fois que j'ai compris que cette architecture de réseau convient bien à tel type de problème, ensuite on peut la tester. Une fois de plus, je vous montrerai demain, mais il y a plein de projets GitHub qui ont implémenté avec AmixNet ces réseaux de référence pour la classification d'images, la traduction, etc. Donc en lisant les papiers, en allant chercher l'implémentation des réseaux dans MXNet, déjà vous économisez énormément de problèmes et de travail. Et si vous avez de la chance, vous trouverez même un réseau qui a été pré-entraîné. Peut-être que certainement l'équipe de recherche ou les développeurs en question vont publier le réseau pré-entraîné sur leur dataset. Donc je vous montrerai demain comment on utilise des réseaux pré-entraînés. Vous verrez que c'est en quelques lignes de code, vous chargez le fichier et puis vous balancez vos data à l'intérieur et vous récupérez des résultats. Donc l'objectif c'est une fois de plus de réutiliser ce qui a été fait et ensuite de comprendre comment il faut éventuellement adapter le réseau, les paramètres du réseau à votre problème à vous. Je vous montrerai demain par exemple comment réentraîner un réseau, pré-entraîner, comment le spécialiser pour une catégorie d'image particulière. Voilà. Et puis après, il y a, comme dans tous les domaines, il y a l'expérience, il y a l'intuition, et il ne faut pas hésiter à bricoler, il ne faut pas hésiter à dire « tiens, je vais prendre ces réseaux là et puis je vais rajouter une couche et puis où je vais mettre moins de neurones, où je vais changer la fonction d'activation, où je vais changer l'optimiseur et puis je vois ce que ça donne. Et puis progressivement comme ça on bâtit des compétences. Enfin j'ai envie de dire c'est comme le software engineering en général. Sur le papier toutes les architectures sont belles. Et puis après, quand il faut les coder, c'est là que l'expérience et que l'intuition ont un rôle important. Ça reste évidemment vrai en deep learning. Une question de Gilles. Quels sont les GPU supportés par MXNet ? Ce sont les GPU NVIDIA. Donc vous pouvez télécharger MXNet et l'installer. Si vous avez un PC à la maison avec un GPU NVIDIA, vous pouvez télécharger MXNet. Vous installez les drivers Nvidia et ça va marcher. Pour ce qui est des instances AWS, on a deux familles d'instances pour le Deep Learning aujourd'hui. Ce sont les P2 qui s'appuient sur des Nvidia K80, qui sont l'ancienne génération. Et puis comme on l'a vu avec Myriam tout à l'heure, on a les instances P3 qui s'appuient sur le Volta et donc qui sont parfaitement reconnues par MXNet. Je ne peux que vous encourager à utiliser la Deep Learning EMI comme j'ai déjà dit tout à l'heure parce qu'elle va venir avec tout préinstallé donc les fameux drivers CUDA etc etc. Et donc vous la démarrez, vous lancez vos scripts MXNet, TensorFlow etc. Une question de Florent, comment est-ce qu'on peut gérer un dataset avec des images de taille variable ? Ça c'est une bonne question et bien on va les mettre en taille fixe. Et ça n'a aucune importance en fait. Enfin la question est intéressante, mais le fait de redimensionner les images, non je ne vais pas me moquer de Florent, non la question est importante. Si vous avez des images de taille variable, il va falloir que vous les redimensionnez. Donc on le verra demain, avec les réseaux pré-entraînés, et bien on peut prendre n'importe quelle image JPEG, résolution quelconque. On la redimensionnera dans la taille qui correspond à la taille des images sur lesquelles le réseau a été entraîné, qui est souvent 224 par 224. On verra demain tout ça. Et c'est ça qu'on va passer à l'intérieur du réseau. Donc il faut... La question est importante parce qu'il faut évidemment que la forme du MD array que vous allez passer au réseau, il faut que ça soit la forme sur laquelle ce réseau a été entraîné. Donc ici, quand j'ai entraîné mon réseau sur MNIST, automatiquement MXNet a créé une couche d'entrée qui faisait 784 neurones, parce que c'est ça que je lui ai passé en entrée, et une fois que j'ai sauvé le réseau, ce réseau-là, il s'attend à trouver une couche d'entrée de 784. Donc si je lui passe des images qui ont une autre taille, il va dire « Dada ça va pas, c'est pas la bonne taille, il va pas être content ». Donc voilà, version courte, il faut comprendre, si vous utilisez un réseau pré-entraîné, à quelle taille faisaient les images, quelle est la forme d'entrée qui est entendue par le réseau, et il faut que ce soit ça que vous présentiez. Une question de Laurent Philippe, est-ce que les reconnaissances d'images sont invariantes par translation, rotation ? Ça c'est une bonne question aussi, on en parlera un peu demain. Le modèle est aussi bon ou aussi mauvais que le dataset. Donc, si dans votre modèle, vous avez entraîné, prenons un exemple avec des chats et des chiens, si tous les chats que vous avez montrés à votre réseau, ils étaient disons, de face, vous avez montré une tête de chat de face, et que soudainement vous montrez à votre réseau des chats de profil, il est probable qu'il n'ait pas forcément de très bonne performance. Donc c'est important dans le dataset d'avoir une grande variété dans les échantillons. Donc il faut que les chats soient de face, de profil, de trois quarts, etc. Vues en gros plan, vues en plan large, etc. Et vous pouvez même aller jusqu'à demander à MXNet de générer automatiquement des nouveaux échantillons. Donc vous pouvez lui demander de les flipper, de les redimensionner, etc. Ce qu'on appelle la data augmentation. Et il y a des API pour faire ça automatiquement, pour générer des nouveaux échantillons encore plus diversifiés à partir de votre dataset. Ça, ça va aider votre réseau à généraliser. Est-ce que j'ai des infos sur MXNet et OpenCL ? MXNet utilise les librairies. Donc quand vous développez sur MXNet, vous utilisez l'API, ici Python, mais je l'ai dit, il y avait d'autres langages, vous utilisez l'API de MXNet et vous n'avez pas à vous soucier du tout des couches Cuda, OpenCL, ça c'est dans la plomberie de MXNet, et justement on ne veut absolument pas les voir, on veut travailler avec des API de haut niveau et de l'application. Et on ne veut pas s'occuper du tout de programmation CUDA ou de programmation OpenCL, qui est intéressante, mais qui est un autre domaine. Si vous avez envie vous-même de coder vos API de Deep Learning, alors faites-le en OpenCL si ça vous amuse, mais voilà, c'est autre chose. Une fois de plus, quand on utilise MXNet ou TensorFlow ou un autre, on bosse avec ces API-là, et c'est dans la librairie qu'on fait les appels au GPU. Qu'est-ce qu'on a encore un peu de temps ? Allez, encore une ou deux ? Est-ce que MXNet permet d'apprendre au fur et à mesure ? Question de Stanislas, donc on peut faire, là on a vu qu'on faisait de l'apprentissage supervisé, donc on fournit tout le dataset et on, en plus il était étiqueté, et puis on fait un. Donc ça c'est une façon de faire. On pourrait faire de l'apprentissage non supervisé aussi. Et on peut aussi faire ce qu'on appelle du online learning. C'est-à-dire on peut avoir des échantillons qui arrivent au fur et à mesure en streaming et qui sont appris progressivement par le réseau. Donc on peut faire ça, pas comme je vous l'ai montré, là ce que je vous ai montré, vous voyez que les phases sont très identifiées, on charge les données, on construit l'itérateur, on construit le réseau, on associe tout et on entraîne. On peut faire ce qu'on appelle une custom training loop, où on ne va pas utiliser ces API fit, etc., qui sont des API de haut niveau avec un système de réseau, qui prennent pas mal de raccourcis, on peut gérer un apprentissage de manière plus fine. On peut le faire avec MXNet, on peut le faire avec Gluon et dire voilà j'apprends au fur et à mesure de l'arrivée de mes échantillons. Il y a des exemples là-dessus. Et puis peut-être une dernière question. Est-ce qu'il est pertinent d'utiliser un GPU pour la partie prédictive ? Alors oui, c'est... Ça peut avoir du sens, ça dépend des contraintes de votre application. Si vous avez une application où vous prédisez image par image sans avoir une contrainte forte de temps réel, on le verra demain, sur un CPU, sur une instance C4, C5, etc., vous prédisez dans des temps parfaitement raisonnables, on prédit en microsecondes, donc il n'y a pas de soucis. Si vous avez besoin de prédire des très très grosses quantités, c'est-à-dire, je ne sais pas, vous êtes sur un back-end d'applications mobiles et puis vous devez prédire 1000 images par seconde, un truc comme ça, là, un GPU va effectivement être plus rapide. Mais là où le GPU va vraiment faire la différence, c'est quand vous allez prédire batch par batch. C'est-à-dire que imaginez que vous vouliez faire de la prédiction sur un flux vidéo, vous allez prendre, disons, 32 images à la fois, ou 30 images par seconde, donc vous faites des batchs de 30, etc. Et puis vous les passez à travers un modèle. Là, pour avoir un débit comme ça soutenu et tenir des contraintes temps réelles, il va falloir aller vers le GPU. Mais le CPU, en particulier les instances C5, qui sont basées sur la dernière archi Intel, elles ont des super performances pour l'inférence. Donc si vous n'avez pas ce besoin de débit ultra brutal, la prédiction sur CPU est tout à fait raisonnable et évidemment beaucoup moins cher que sur des instances GPU. Voilà, je pense qu'on... Hugo me dit que c'est l'heure. Donc merci beaucoup de votre participation, vous étiez encore bien nombreux cet après-midi, ça fait plaisir. Les slides sont téléchargeables, etc. Je te les... Non ? Pas encore ? On va régler ça après ? Ok, pas de soucis. Et donc je vous donne rendez-vous demain pour une plongée plus profonde sur MXNet en classification d'images, en utilisation de modèles pré-entraînés, en affinage de modèles pré-entraînés et en génération d'images. On fera un peu de GAN, et puis aussi pour la session Inspector Gadget avec le robot Raspberry Pi et la DeepLens, voilà, et puis on trouvera plein d'âneries à faire avec tout ça. Merci beaucoup, je vous souhaite une très bonne soirée, et je vous donne rendez-vous demain. Ciao !

Tags

Apache MXNetDeep LearningGPU Optimization