This is a 8 hours course that I (Guillaume Chevalier) created, on machine learning design patterns using Neuraxle, adapted to parallel data processing with data streaming architectures and PyTorch. Here is the full course content description: Intro to AI/ML/DL. Supervised Learning Process. Learning by Minimizing loss. Typical R&D ML Workflow v.s. desired R&D ML Workflow. Base Abstract Class for ML Pipeline steps: BaseStep. Hyperparameter (HP) samples, hyperparameter distributions, and hyperparameter spaces. HP in pipelines and base step. OOP Diamond Problem (a.k.a. Deadly Diamond of Death). Machine Learning's Mixins: MetaStepMixin (ForEachDataInput, TrainOnlyWrapper, TestOnlyWrapper, OutputTransformerWrapper, EpochRepeater) and NonFittableMixin (NumpyFlattenDatum, DataShuffler, MultipyByN, Mean) and NonTransformableMixin (Identity, NonFittableMixin). Machine Learning Object Lifecycle with chart. Execution Context. Data Container. Handler methods. SOLID principles and TDA (Tell Don't Ask). Epoch Objects, For Each objects, Machine Learning Pipelines as a Language, Deep learning pipelines examples. Notebooks (Colab). Human Activity Recognition. Clean Machine Learning Kata 1 and Kata 2. Kata: Clean Machine Learning From Dirty Code. Kata 1: Refactor Dirty ML Code into Pipeline. Let's convert dirty machine learning code into clean code using a Pipeline - which is the Pipe and Filter Design Pattern for Machine Learning. We're using a Human Activity Recognition (HAR) dataset captured using smartphones. The dataset can be found on the UCI Machine Learning Repository. Kata 2: AutoML Loop & HyperparameterSpace. Your goal is then to add more choices to try in the pipeline (and with more hyperparameters per choice) to make it really good. Let's reuse our pipeline steps as we should have created them in Kata 1. Define some classifiers here and their hyperparam space. Add your classifiers to the pipeline. Finally do AutoML! Launch the main AutoML optimization loop. Back to the course: Hyperparameter tuning. Validation Techniques. Algorithms of Hyperparameter Selection. Choosing parameters. Grid Search v.s. Random Search v.s. TPE. Hyperband. Test-Driven Development (TDD). TDD in notebooks. Design patterns. Coupling of objects. Layered Software Architecture. Saving Steps according to their lifecycle: Step Savers. Producer-Consumer patterns for parallel processing: using queues. Doing it in parallel with multiple consumers and multiple producers. Pipelining in parallel using this pattern between each step. Putting it all together. PyTorch in Neuraxle and how to integrate it in Neuraxle. Tensorflow in Neuraxle and how it is integrated as well. PyTorch Integration in Neuraxle. Public with open-source license CC-BY:
https://drive.google.com/drive/folders/1F98s_sfhkvob0V-TaHQ0B22tAiDyyd7L?usp=share_link
3. Résultat d’un sondage de mes précédentes formations
Ce que vous voulez savoir:
● Comment bien déployer en production
● Comment faire du Clean Machine Learning
● Les bases du Machine Learning
● Comment faire du Automated Machine Learning
3
10. Apprendre en minimisant l’erreur
réduire la perte (loss, ou erreur) à chaque itération
d’entraînement
Ajuster les poids à chaque itération
10
11. Le Machine Learning implique
1. De charger des données
2. De les prétraiter
3. De créer un modèle
4. D’optimiser le modèle
5. D’optimiser à nouveau avec différents hyperparamètres
6. Le sauvegarder une fois appris
7. Servir le modèle en production
8. Suivre et continuer à évaluer la qualité des prédictions dans le temps
11
12. Workflow de R&D en ML typique
1. Charger les données
2. Les transformer
3. Les dumper sur disque
4. Loader les résultats sur disques
5. Entraîner des modèles sur les données
6. Ré-entraîner manuellement des modèles sur les données (Graduate student descent)
7. Dumper les résultats sur disques
8. Loader les résultats sur disques
9. Stacker des modèles ou faire des ensembles
10. Score final
11. Le code n’est pas réutilisable en prod à cause des interactions de disques.
12
13. Workflow de R&D en ML désirable
1. Charger les données
2. Les transformer
(automatic disks checkpoints
that can be deactivated)
1. Entraîner des modèles sur les données
2. Ré-entraîner automatiquement des modèles sur les données (AutoML)
(automatic disks checkpoints
that can be deactivated)
1. Stacker des modèles ou faire des ensembles
2. Score final
3. Le code est réutilisable en prod avec une REST API ! :D
13
14. Ce qu’il faut:
A-Z :
● Checkpoints automatiques (caching) entre les steps d’un pipeline
● Gestion facile des espaces d’hyperparamètres
● Algorithmes d’AutoML
● Compatibilité avec les autres librairies
● REST API : model serving
14
16. Qu’est-ce qu’un pipeline?
Une série d’étapes dans lesquelles les données
sont transformées.
Un graphique acyclique dirigé (DAG) dans lequel
les données circulent.
Une mise en œuvre du modèle de conception du
tuyau et du filtre.
Est un composite.
Voir un exemple:
https://www.neuraxle.org/stable/ex
amples/sklearn/plot_boston_housi
ng_regression_with_model_stacki
ng.html#sphx-glr-examples-
sklearn-plot-boston-housing-
regression-with-model-stacking-py
16
19. Composite : Pipelines emboîtés
Un pipeline peut lui-même se trouver dans un autre
pipeline.
Voir un exemple:
https://www.neuraxle.org/stable/ex
amples/getting_started/plot_nested
_pipelines.html
19
20. Les étapes et le lien avec les pipelines
1. De loader des données
2. De les pré-traiter
3. De créer un modèle
4. D’optimiser le modèle
5. D’optimiser à nouveau avec différents hyperparamètres
6. Le sauvegarder une fois appris
7. Le loader pour enfin le servir en production
20
32. Comment définir des Hyperparamètres?
Varie selon une distribution statistique.
Voir un exemple :
https://www.neuraxle.org/stable/r
andom_distributions.html
32
33. Hyperparameters & Espaces d’Hyperparametres dans les
Pipelines
Un pipeline devrait pouvoir gérer les
hyperparamètres de ses steps et des autres steps
sous-jacents.
Voir exemple :
https://www.neuraxle.org/stable/ex
amples/hyperparams/plot_hyperpa
rams.html
33
34. Ajout d’espaces d’hyperparamètres aux étapes d’un
pipeline
Les espaces des hyperparamètres doivent être
définis à l’intérieur de chaque étape plutôt qu’à
l’extérieur du pipeline.
Cela ne devrait pas s’appliquer uniquement aux
hyperparamètres.
Voir un exemple:
https://www.neuraxle.org/stable/
examples/sklearn/plot_boston_h
ousing_meta_optimization.html
34
36. OOP Diamond Problem (a.k.a. Deadly Diamond of Death)
● Commun en développement de GUI:
○ Bouton hérite de Rectangle et Clickable
○ Rectangle hérite de UIObject
○ Clickable hérite de UIObject
● Maintenant, si la méthode “equals” est appelée
sur Bouton, mais qu’elle est définie sur
Rectangle et Clickable, quelle(s) méthode(s)
appeler ?
36
37. Une solution: les Mixins
● Faire en sorte que certaines classes “add-on”
n’héritent pas directement de la classe de base.
Ça permet:
○ De fournir plusieurs features optionnelles
à nos classes
○ De permettre d’utiliser plusieurs features
optionnelles pour nos classes
⇒ Bref, beaucoup de petites classes comme C !
37
38. Quelques Mixins Intéressant en ML
- MetaStepMixin
- NonFittableMixin
- NonTransformable Mixin
- ResumableStepMixin
- HandleOnlyMixin
- ForceHandleMixin
- TransformHandlerOnlyMixin
- ForceHandleOnlyMixin
- EvaluableStepMixin
Voir exemples:
https://www.neuraxle.org/stable/exa
mples/getting_started/plot_non_fitta
ble_mixin.html
Et
https://www.neuraxle.org/stable/exa
mples/getting_started/plot_force_ha
ndle_mixin.html
38
39. Exemples de classes qui utilisent des mixins
- MetaStepMixin:
- ForEachDataInput
- TrainOnlyWrapper
- TestOnlyWrapper
- OutputTransformerWrapper
- EpochRepeater
- NonFittableMixin:
- NumpyFlattenDatum
- DataShuffler
- MultipyByN
- Toutes classes de transformation de données qui n’a pas de state (e.x.: Mean)
- NonTransformableMixin:
- Identity (+NonFittableMixin)
- ….
...
39
40. Cycle de vie des Objets
(Object Lifecycle)
Un jour dans la vie d’un objet
40
53. SOLID
Single responsibility principle : 1 responsabilité par classe
Open-closed principle : classes fermées à la modification, ouvertes à l’extension
Liskov substitution principle : Sous-type interchangeables (contrats)
Interface segregation principle : Plusieurs interfaces sont mieux qu’une seule
Dependency inversion principle : Dépendre d’abstractions plutôt que de concrétions
(+ Tell Don’t Ask : Pas de “Leaky Abstractions”)
53
54. Single Responsibility Principle (SRP)
- On cherche à avoir 1 responsabilité par classe
⇒ Cela va faciliter les choses quand vient le temps de faire des changements et de réutiliser du code
Clairement, les steps d’un pipeline représentent chacunes 1 seule étape. Yay!
Plus de longues routines dégeu…
Symptôme: voir souvent le mot clé “and” dans des noms de classe.
Voir exemple: https://www.neuraxle.org/stable/api/steps/neuraxle.steps.numpy.html
54
56. Open-Closed Principle (OCP)
- Classes fermées à la modification, ouvertes à l’extension
- Fortement relié au SRP
⇒ Implique de créer plus de classes abstraites et de mettre en commun les fonctionnalités. Ça simplifie
le code et le rends plus réutilisable.
Clairement, dans les pipelines, une hiérarchie de classe est bien faite, tout est un step.
Symptôme: voir souvent des “if elif elif elif else” (a.k.a. “Poor Man’s Polymorphism”)
Exemples: TruncableSteps et MetaStep: (voir diapos suivantes)
https://www.neuraxle.org/stable/api/neuraxle.base.html
56
59. Liskov Substitution Principle (LSP)
- On veut qu’un objet soit changeable avec les sous-types de ce même objet sans briser
l’application
- Un canard en plastique n’est pas un animal
⇒ Implique une cohérence dans les possibilités de substituer des objets pour d’autres dans certains
contextes pour rendre le code plus générique.
Clairement, dans un pipeline, un step est un step. Les steps sont très remplaçables et flexibles.
Symptôme : faire des “if isinsitance(obj, SomeClass)” avant de faire des traitements est un symptôme
que les sous-types briseraient l’application lorsqu’utilisés dans certains contextes.
59
61. Interface Segregation Principle (ISP)
- On veut plusieurs interfaces (classes abstraites) plutôt qu’une seule
- Ne pas forcer les utilisateurs d’une interface d’utiliser trop de méthodes
⇒ Code léger et sans obligations d’implémenter toutes les fonctionnalités dans tous les objets. Vaut
mieux avoir un objet qui implémente plusieurs interfaces.
Clairement, les nombreux mixins des steps dans les pipelines permettent ça et ça évite de forcer à
chaque objet d’implémenter du comportement inutile.
Symptôme: “god class” trop longue dont on hérite pourrait être divisée en plusieurs classes de base avec
Mixins.
Voir exemple BaseService v.s. BaseTransformer:
https://www.neuraxle.org/stable/api/neuraxle.base.html#neuraxle-base
61
63. Dependency Inversion Principle (DIP)
- On veut utiliser des abstractions et non des implémentations
- On ne veut pas gérer toutes les choses concrètement et on veut déléguer
⇒ De la sorte, notre code se découplerait du loading des données et de toute gestion d’état sur les
disques.
Clairement, dans les pipelines, les données sont “reçues, traitées, et retournées” plutôt que “loadées,
traitées et sauvegardées”. Trop de code de machine learning ne respecte pas ce principe (e.x.: BERT,
Fasttext).
Voir exemple de contexte : https://stackoverflow.com/questions/64477316/how-to-implement-a-
repository-for-lazy-data-loading-with-neuraxle/64850395#64850395
63
66. Tell Don’t Ask (TDA)
- On ne veut pas “micro-manager” nos objets ni devoir aller jouer dedans
- On veut plutôt leur dire quoi faire et qu’ils soient autonomes
⇒ Ainsi, on évite la duplication de code, le code est plus scalable, réutilisable et la logique est gérée aux
bons niveaux d’abstractions.
Clairement, chaque step d’un pipeline s’auto-gère. Chose importante : chaque step est indépendant des
autres steps qui l’entoure, sans quoi le code deviendrait lourd et en spaghetti (e.x.: Loi de Déméter).
Voir exemple d’objets défaits : https://www.neuraxle.org/stable/intro.html
66
68. Mini Batching
Mini-batch gradient descend est une variation de
l’algorithme de descente de gradient qui divise
l’ensemble de données de formation en petits lots
qui sont utilisés pour calculer l’erreur du modèle et
mettre à jour les coefficients du modèle.
Mini Batch Sequential Pipeline(
Pipeline([...]),
batch_size=100
)
68
70. Époques (Epochs)
Une époque représente une itération complète sur
le dataset. 50 époques représentent un ré-
entraînement sur 50 boucles du dataset.
EpochRepeater(
MiniBatchSequentialPipeline(
Pipeline([...]),
batch_size=100
),
), epochs=50)
70
72. Boucle For (For Each)
Lorsqu’une dimension du jeu de données doit être
bouclée dessus
EpochRepeater(
ForEach(
MiniBatchSequentialPipeline(
Pipeline([...]),
batch_size=100
),
),
), epochs=50)
72
73. Et plus… pipelining as a language.
ForEach(...)
While(...)
BreakIf(...)
ContinueIf(...)
ForEach(...)
Try(...)
Catch(...)
Raise(...)
If(...) & ElseIf(...) & Else(...)
Switch(...)
…
73
84. Bonnes utilisations des notebooks :
- Code à jeter
- Le “DE” dans RS&DE
- Visualisations et graphiques
- Démos
- Tutoriels
- EDA et création de features
- Analyze des résultats
- Intéressant pour prototyper les modèles
84
88. La tâche:
Classifier le type de mouvement selon les lectures
spatiales du téléphone cellulaire.
Entrées (X), forme (shape) du tenseur:
[batch_size, time_steps, features] ⇒ [ _ , 128, 9]
● Prédictions (Y), catégories:
● WALKING
● WALKING_UPSTAIRS
● WALKING_DOWNSTAIRS
● SITTING
● STANDING
● LAYING
Prédictions (Y), forme (shape) du tenseur:
[batch size, n_classes] ⇒ [ _, 6]
Features:
- Acc x
- Acc y
- Acc z
- Gyro x
- Gyro y
- Gyro z
- Acc x gravity
- Acc y gravity
- Acc z gravity
*Note: x, y et z ici sont des coordonnées dans l’espace et diffèrent des coordonnées à gauche
dans cette diapositive.
88
89. Quels autres types de traitements peuvent être faits?
E.x.: Seq2seq, LSTM RNN, GRU RNN, U-Nets pour signaux, et pipelines de machine
learning classiques (tels que présentés ici), en mixant des sources de données variées
tels que du texte et des images...
89
100. Algorithmes de sélection des hyperparamètres
● Objectif : prédiction des meilleurs prochains hyperparamètres
● Exploration v.s. Exploitation
○ Au début, essayer des trucs variés
○ Ensuite, tenter vraiment plutôt d’optimiser les choix en fonction de ce qu’on sait
⇒ Certains algorithmes ont avantages à même observer les loss au cours de l’apprentissage et entre les
modèles
⇒ Certains algorithmes pourraient même observer des statistiques sur les poids des réseaux de neurones
pendant et suite à l’entraînement pour mieux les optimiser
100
101. Effet de la quantité des données sur l’erreur
101
102. Effet de la complexité du modèle sur l’erreur
102
103. Effet du taux d’apprentissage sur la perte (loss)
103
107. Sauvegarde des résultats et inspection
Quelques trucs sont cruciaux:
● Sauvegarder les résultats pour chaque hyperparamètres essayés
○ Meilleur score tout au long de l’apprentissage
○ Loss et scores le long de l’apprentissage
○ Parfois visualiser les poids, etc.
● Pouvoir visualiser les résultats
● Parfois, on voudra même sauvegarder chaque modèles entraîné
107
108. Automated Machine Learning (AutoML)
Une classe pour les combiner toutes:
- Spécifier un pipeline
- Spécifier un algorithme de sélection des prochains hyperparamètres
- Spécifier une technique de validation
- Spécifier une métrique
- Spécifier une façon de sauvegarder les résultats sur disques
108
114. Tree-structured Parzen Estimator (TPE)
⇒ Mieux que du random
Exemple:
https://www.neuraxle.org/stable/examples/sklearn/plot_boston_housing_meta_optimization.html 114
115. Hyperband
- Ne pas entraîner chaque modèle jusqu’à la fin
- On entraîne jusqu’au bout seulement les
meilleurs modèles aux premières époques
- Basé sur l’estimation qu’un apprentissage rapide
au début mène à de meilleurs résultats à la fin.
115
119. Développement par tests unitaires
(Test-Driven Development - TDD)
1. Écrire un test
2. Écrire du code pour faire passer le test
3. Peaufiner le code pour que tout soit propre
⇒ Aussi appelé les étapes “Red, Green, Blue”
119
120. Comment écrire un test ?
1. Arrange
2. Act
3. Assert
⇒ La méthode des triples A (AAA)
120
123. TDD & Notebooks
Vous avez souvent déjà vos AAA !
1. Arrange : des données en entrées
2. Act : un algorithme (e.x. : modèle, réseau de neurones)
3. Assert : un print pour voir les résultats
123
124. Ce qu’il faut penser à faire
1. Extraire votre algorithme en une abstraction appropriée, et vers un fichier externe dans votre
architecture
2. Extraire votre test vers vos dossiers de tests
3. Réorganiser vos modules et votre base de code
124
125. Tout le monde passe par là…
- Mauvais versionnage des notebooks
- Je l’ai fait moi-même
- Erreurs typiques en entreprise et en recherche académique.
125
127. Quelques Patrons de Conception (Design Patterns)
Source: https://blog.startifact.com/posts/framework-patterns.html
ML Design Patterns:
- Pipe and Filter;
- State;
- Service Locator;
- Composite;
- Decorator;
Framework Design Patterns:
- Callback functions;
- Subclassing;
- Interfaces;
- Imperative registration (saving) API;
- And more.
127
128. Gestion des modules : cohésion
Devraient faire partie du même modules les classes qui:
- Sont utilisées seulement par les autres classes de ce module
- Changent ensemble
- Sont souvent utilisées ensemble
Source: https://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod
128
129. Gestion des modules : couplage
Entre les modules, on devrait :
- Ne pas avoir de dépendances circulaires dans les imports
- Dépendre vers la direction de la stabilité
- Avoir plus d’abstractions lorsqu’il y a plus de stabilité
Source: https://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod
129
130. Architecture par couches
- API (REST)
- Application Service
- Domain
- Infrastructure & Persistence
130
140. Les Savers
- Les savers permettent de traiter l’usage de steps normalement non-sérialisable
- Appliqués récursivement comme un apply lorsque demandé
- Une liste de savers permettent de retirer peu à peu des parties de l’objet
E.x. : https://www.neuraxle.org/stable/step_saving_and_lifecycle.html
154. PyTorch dans Neuraxle
- Adapter design pattern:
- Doit avoir un step qui adapte le nn.Module utilisé
- Rappel: ce nn.Module utilisé peut lui-même contenir d’autres nn.Module
- Fournit un saver (idéalement)