.. _chap-tpDeepLearning2: ############################################################################## Travaux pratiques - Perceptron multi-couche ############################################################################## L'objectif de cette seconde séance de travaux pratiques est d'étendre le modèle de régression logistique de la semaine précédente afin de mettre en place des modèles de prédictions plus riches. En particulier, on va s'intéresser aux Perceptron multi-couches (Multi-Layer Percpetron, MLP). Contrairement à la régression logistique qui se limite à des séparateurs linéaires, le Perceptron permet l'apprentissage de frontières de décisions non linéaires, et constituent des approximateurs universels de fonctions. L'objectif de la séance de travaux pratiques est de mettre en place le code pour effectuer des prédiction et entraîner un Perceptron à une couche cachée. Exercice 1 : Prédiction avec un Perceptron (Forward) ***************************************************** L'architecture du perpcetron à une couche cachée est montrée à la figure ci-dessous. .. image:: img/MLP.png :height: 250px :align: center Si on considère les données de la base MNIST, chaque image est représentée par un vecteur de taille :math:`28^2=784`. Le perpcetron va effecteur les différentes étape de transformation pour produire la prédiction finale, *i.e.* la catégorie sémantique de l'image : - Une étape de projection linéaire, qui va projeter chaque image sur un vecteur de taille :math:`(1,L)`, *e.g.* :math:`L=100`. En considérant chaque exemple :math:`\mathbf{x_i}` est un vecteur ligne - taille :math:`(1,784)` - la projection linéaire peut être représentée par la matrice :math:`\mathbf{W^h}` (taille :math:`(784, L)`), et le vecteur de biais :math:`\mathbf{b^h}` (taille :math:`(1, L)`) : :math:`\mathbf{\hat{u_i}} =\mathbf{x_i} \mathbf{W^h} + \mathbf{b^h}`. - Une étape de non linéarité, *e.g.* de type sigmoïde : :math:`\forall j \in \left\lbrace 1; L \right\rbrace ~ h_{i,j} = \frac{1}{1+exp(-u_{i,j})}` - Une seconde étape de projection linéaire, qui va projeter le vecteur latent de taille :math:`(1,L)` sur un vecteur de taille :math:`(1,K)=10` (nombre de classes). Cette opération de projection linéaire sera représentée par la matrice :math:`\mathbf{W^y}` (taille :math:`(L, K)`), et le vecteur de biais :math:`\mathbf{b^y}` (taille :math:`(1, K)`) : :math:`\mathbf{\hat{v_i}} =\mathbf{h_i} \mathbf{W^y} + \mathbf{b^y}`. - Une étape de non linéarité de type soft-max vue la semaine précédente pour la régression logistique : :math:`\forall j \in \left\lbrace 1; K \right\rbrace ~ y_{i,j} = \frac{exp(v_{i,j})}{\sum\limits_{i=1}^K exp(v_{i,k})}` **On demande de mettre en place un script** ``mlp.py`` **qui implémente l'alogorithme du Percpetron sur la base MNIST.** L'algorithme reprendra le squelette du code de la régression logistique. Pour adapter ce code pour le Perceptron pour la partie prédiction, vous devez : - Modifier la fonction de prédiction, afin disposer la fonction ``forward(batch, Wh, bh, Wy, by)`` qui reverra à la fois la prédiction pour le batch ainsi que la matrice des couches latentes. - Si on considère un batch des données de taille :math:`t_b\times 784`, les paramètres :math:`\mathbf{W^h}` (taille :math:`784\times L`), :math:`\mathbf{b^h}` (taille :math:`1\times L`), :math:`\mathbf{W^y}` (taille :math:`L\times K`) et :math:`\mathbf{b^y}` (taille :math:`1\times K`), la fonction ``forward`` renvoie la prédiction :math:`\mathbf{\hat{Y}}` sur le batch (taille :math:`t_b\times K`) et la matrice de variables latentes (taille :math:`t_b\times L`). Exercice 2 : Apprentissage du Perceptron (Backward) ***************************************************** Afin d'entraîner le Perceptron, on va utiliser l'algorithme de rétro-propagation de l'erreur. On rappelle que pour chaque batch d'exemples, l'algorithme va effectuer une passe ``forward`` (Exercice 1), permettant de calculer la prédiction du réseau. Une fonction de coût (ici l'entropie croisée) entre la sortie prédite et la la sortie donnée par la supervision va permettre de calculer le gradient de l'erreur par rapport à tous les paramètres paramètres du modèle, *i.e.* :math:`\mathbf{W^y}` (taille :math:`(L, K)`), :math:`\mathbf{b^y}` (taille :math:`(1, K)`), :math:`\mathbf{W^h}` (taille :math:`(784, L)`), et :math:`\mathbf{b^h}` (taille :math:`(1, L)`). On rappelle les équation des gradients, effectuées depuis le haut vers le bas du réseau : 1. Mise à jour de :math:`\mathbf{W^y}` et :math:`\mathbf{b^y}` : .. math:: \frac{\partial \mathcal{L}}{\partial \mathbf{v_i}} = \mathbf{\delta^y_i} = \mathbf{\hat{y_i}} - \mathbf{y_i^*} .. math:: \frac{\partial \mathcal{L}}{\partial \mathbf{W^y}} = \frac{1}{t_b}(\mathbf{\hat{Y}} - \mathbf{Y^*}) \mathbf{H}^T = \frac{1}{t_b} \mathbf{H}^T \mathbf{\Delta^y} :label: gradientW1 .. math:: \frac{\partial \mathcal{L}}{\partial \mathbf{b^y}} = \frac{1}{t_b}\sum_{i=1}^{t_b}(\mathbf{\hat{y_i}} - \mathbf{y_i^*}) :label: gradientB1 Où :math:`\mathbf{H}` est la matrice des couches cachées sur le batch (taille :math:`t_b\times L`), :math:`\mathbf{\hat{Y}}` est la matrice des labels prédits sur l'ensemble de la base d'apprentissage (taille :math:`t_b\times K`) et :math:`\mathbf{Y^*}` est la matrice des labels donnée issue de la supervision ("ground truth", taille :math:`t_b\times K`), et :math:`\mathbf{\Delta^y}=\mathbf{\hat{Y}}-\mathbf{Y^*}`. 2. Mise à jour de :math:`\mathbf{W^h}` et :math:`\mathbf{b^h}` : .. math:: \frac{\partial \mathcal{L}}{\partial \mathbf{u_i}} = \mathbf{\delta^h_i} = \mathbf{\delta^y_i} \mathbf{W^{y}}^T \odot \sigma^{'}(\mathbf{h_i}) = \mathbf{\delta^y_i} \mathbf{W^{y}}^T \odot (\mathbf{h_i} \odot (1-\mathbf{h_i})) .. math:: \frac{\partial \mathcal{L}}{\partial \mathbf{W^h}} = \frac{1}{t_b} \mathbf{X}^T \mathbf{\Delta^h} .. math:: \frac{\partial \mathcal{L}}{\partial \mathbf{b^h}} = \frac{1}{t_b}\sum_{i=1}^{t_b}(\delta^h_i) Où :math:`\mathbf{X}` est la matrice des données sur le batch (taille :math:`t_b\times 784`), et :math:`\mathbf{\Delta^h}` est la matrice des :math:`\delta^h_i` sur le batch (taille :math:`t_b\times L`). .. admonition:: Adapter la partie backward de l'algorithme pour entraîner le Perceptron : - Question : la fonction de coût de l'Eq. :eq:`CE` est-elle convexe par rapports aux paramètres :math:`\mathbf{W}`, :math:`\mathbf{b}` du modèle ? Avec un pas de gradient bien choisi, peut-on assurer la convergence vers le minimum global de la solution ? - Tester en initialisant les matrices à 0 comme pour la régression logistique. Quelles performances obtenez-vous ? Que peut-on en conclure ? - Vous testerez deux autres initialisations : une qui initialise les poids avec une loi normale de moyenne nulle et d'écart type à fixer, *e.g.* :math:`10^-1`, et une autre connue sous le nom de Xavier, qui divise la valeur de la Gaussienne par :math:`\sqrt{ni}`, où ni est le nombre de neurone dans la couche d'entrée. - Évaluer les performances du modèle. **Vous devez obtenir un score de l'ordre de 98\% sur la base de test pour ce réseau de neurones à une couche cachée.**