An MLP (for Multi-Layer Perceptron) or multi-layer neural network defines
a family of functions. Let us first consider the most classical case
of a single hidden layer neural network, mapping a
-vector to an
-vector (e.g. for regression):
where is a
-vector (the input),
is an
matrix (called input-to-hidden weights),
is a
-vector (called hidden units offsets or hidden unit biases),
is an
-vector (called output units offset or output units biases),
and
is an
matrix (called hidden-to-output weights).
The vector-valued function is called
the output of the hidden layer. Note how the output is an affine
transformation of the hidden layer, in the above network. A non-linearity
may be tacked on to it in some network architectures.
The elements of the hidden layer are called hidden units.
The kind of operation computed by the above can be
applied on
itself, but with different parameters
(different biases and weights). This would give rise to a
feedforward multi-layer network with two hidden layers. More generally,
one can build a deep neural network by stacking more such layers.
Each of these layers may have a different dimension (
above).
A common variant is to have skip connections, i.e., a layer can take as
input not only the layer at the previous level but also some of the lower layers.
Let with
representing the output non-linearity function.
In supervised learning, the output
can be compared with
a target value
through a loss functional
.
Here are common loss functionals, with the associated output non-linearity:
We just apply the recursive gradient computation algorithm seen previously to the graph formed naturally by the MLP, with one node for each input unit, hidden unit and output unit. Note that each parameter (weight or bias) also corresponds to a node, and the final
Let us formalize a notation for MLPs with more than one hidden layer.
Let us denote with the output vector of the i-th layer,
starting with
(the input), and finishing with
a special output layer
which produces the
prediction or output of the network.
With tanh units in the hidden layers, we have (in matrix-vector notation):
where
is a vector of biases and
is a matrix of weights connecting layer
to layer
. The scalar computation associated with a single unit
of layer
is
In the case of a probabilistic classifier, we would then have a softmax output layer, e.g.,
where we used to denote the output because it is a vector indicating
a probability distribution over classes. And the loss is
where is the target class, i.e., we want to maximize
, an
estimator of the conditional probability of class
given input
.
Let us now see how the recursive application of the chain rule in flow graphs is instantiated in this structure. First of all, let us denote
(for the argument of the non-linearity at each level) and note (from a small derivation) that
and that
.
Now let us apply the back-propagation recipe in the corresponding flow graph. Each parameter (each weight and
each bias) is a node, each neuron potential and each neuron output
is also a node.
starting at the output node:
then compute the gradient with respect to each pre-softmax sum :
We can now repeat the same recipe for each layer. For down to 1
obtain trivially the gradient wrt biases:
compute the gradient wrt weights:
back-propagate the gradient into lower layer, if :
Logistic regression is a special case of the MLP with no hidden layer (the input is directly connected to the output) and the cross-entropy (sigmoid output) or negative log-likelihood (softmax output) loss. It corresponds to a probabilistic linear classifier and the training criterion is convex in terms of the parameters (which garantees that there is only one minimum, which is global).
Many algorithms have been proposed to train multi-layer neural networks but the most commonly used ones are gradient-based.
Two fundamental issues guide the various strategies employed in training MLPs:
- training as efficiently as possible, i.e., getting training error down as quickly as possible, avoiding to get stuck in narrow valleys or even local minima of the cost function,
- controlling capacity so as to achieve the largest capacity avoids overfitting, i.e., to minimize generalization error.
L’optimisation du critère d’apprentissage dans les réseaux de neurones multi-couches est difficile car il y a de nombreux minima locaux. On peut même démontrer que de trouver les poids optimaux est NP-dur. Cependant on se contente de trouver un bon minimum local, ou même simplement une valeur suffisamment basse du critère. Comme ce qui nous intéresse est la généralisation et non pas l’erreur d’apprentissage (ce qu’on minimise n’est pas ce qu’on voudrait vraiment minimiser), la différence entre “près d’un minimum” et “au minimum” est souvent sans importance. Par ailleurs, comme il n’y a pas de solution analytique au problème de minimisation, on est forcé de faire cette optimisation de manière itérative.
En principe, une manière d’accélérer la descente de gradient
est de faire des choix qui rendent la matrice
Hessienne
mieux conditionnée. La dérivée second dans une certaine
direction indique la courbure de la fonction de coût dans
cette direction. Plus la courbure est grande (vallée étroite)
et plus petites doivent être les mises à jour des paramètres
si on éviter que l’erreur augmente. Plus précisement,
le pas de gradient optimal est 1 sur la courbure. On
peut voir cela par une simple expansion de Taylor du
coût et est derrière le fameux algorithme de Newton
pour l’optimisation. Mettons que l’on soit à
et que l’on veuille choisir
pour qu’il
soit un minimum:
Donc on veut un pas de gradient égal à l’inverse de la dérivée seconde. On peut montrer que le nombre d’itération d’un algorithme de descente de gradient sera proportionnel au ratio de la plus grande à la plus petite valeur propre de la matrice Hessienne (avec une approximation quadratique de la fonction de coût). La raison de base en est que la plus grande valeur propre limite le pas de gradient maximum (on ne peut aller plus vite que la courbure la plus forte parmi toutes les directions possibles, sinon l’erreur remonte), mais qu’en utilisant le même pas de gradient dans toutes les directions, la convergence sera la plus longue dans la direction la plus “plate” (valeur propre la plus petite).
- En théorie une couche cachée suffit, mais cette théorie ne dit pas que cette représentation de la fonction sera efficace. En pratique cela a été le choix le plus commun avant 2006, sauf pour les réseaux de neurones à convolution (qui peuvent avoir 5 ou 6 couches par exemple). Parfois on obtient de bien meilleurs résultats avec 2 couches cachées. En fait on peut obtenir une bien meilleure généralisation avec encore plus de couches, mais une initialisation aléatoire ne fonctionne pas bien avec plus de deux couches (mais voir les travaux depuis 2006 sur l’initialisation non-supervisée vorace pour les architectures profondes).
- Pour la régression ou avec des cibles réelles et non-bornées en général, il vaut généralement mieux utiliser des neurones linéaires à la couche de sortie. Pour la classification, il vaut généralement mieux utiliser des neurones avec non-linéralité (sigmoide ou softmax) à la couche de sortie.
- Dans certains cas une connexion directe entre l’entrée et la sortie peut être utile. Dans le cas de la régression, elle peut aussi être initialisée directement par le résultat d’une régression linéaire des sorties sur les entrées. Les neurones cachées servent alors seulement à apprendre la partie non-linéaire manquante.
- Une architecture avec poids partagés, ou bien le partage de certains éléments de l’architecture (e.g., la première couche) entre les réseaux associés à plusieurs tâches connexes, peuvent significativement améliorer la généralisation. Voir aussi la discussion à venir sur les réseaux à convolution.
- Il vaut mieux utiliser utiliser une non-linéarité symétrique dans les couches cachées (comme la tanh, et non pas la sigmoide), afin d’améliorer le conditionnement du Hessien et éviter la saturation des couches cachées.
Il est impératif que les entrées soient de moyenne pas trop loin
de zéro et de variance pas trop loin de 1. Les valeurs en entrées
devraient aussi ne pas avoir une magnitude trop grande. On peut faire
certaines transformations monotones non-linéaires qui réduisent les
grandes valeurs. Si on a une entrée
très grande, elle fait saturer plusieurs neurones et bloque
l’apprentissage pour cet exemple. Les magnitudes (variances) des
entrées de chaque couche devraient aussi être du même ordre
quand on utilise un pas de gradient commun pour toute les couches,
pour éviter que l’une des couches devienne le goulot d’étranglement
(plus lent à entraîner).
En fait, dans le cas linéaire,
le conditionnement du Hessien est optimal quand les entrées
sont normalisées (donc avec matrice de covariance = identité),
ce qui peut se faire en les projetant dans l’espace des
vecteurs propres de la matrice , où
est la matrice
de dimension nombre d’exemples par nombre d’entrées.
Dans le cas d’apprentissage par minimisation d’un coût quadratique, on doit s’assurer que les sorties désirées
sont toujours dans l’intervalle des valeurs que la non-linéarité de la couche de sortie peut produire (et sont à peu près normales N(0,1) dans le cas linéaire),
ne sont pas trop proches des valeurs limites de la non-linéarité de la couche de sortie: pour la classification, une valeur optimale est près d’un des deux points d’inflexion (i.e., les points de courbure (dérivée seconde) maximale, environ -0.6 et 0.6 pour tanh, 0.2 et 0.8 pour la sigmoide).
Il vaut mieux utiliser le critère d’entropie croisée (ou la vraisemblance conditionnelle) pour la classification probabiliste, ou bien le critère de marge “hinge” (comme pour le perceptron et les SVMs, mais en pénalisant les écarts à la surface de décision au-delà d’une marge). Dans le cas multiclasse, ça donne
où
est la partie positive et
est la sortie (sans non-linéarité) pour la classe
.
En entrée comme en sortie, on va généralement représenter les variables discrètes par des groupes d’unités (un groupe de k unités par variable discrète pouvant prendre k valeurs). L’exception pratique est le cas d’une variable binaire, qu’on encode généralement avec une seule unité. Dans le cas des sorties on va associer à chaque groupe une distribution discrète (binomiale pour un seul bit, multinomiale pour une variable discrète générale).
Quand le nombre d’exemples est grand (plusieurs milliers) la descente de gradient stochastique est souvent le meilleur choix (surtout pour la classification), en terme de vitesse et en terme de contrôle de la capacité (il est plus difficile d’avoir de l’overfitting avec la descente de gradient stochastique. En effet, la descente de gradient stochastique ne tombe pas facilement dans les minima très pointus (qui ne généralisent pas bien, car une légére perturbation des données déplaçant la surface d’erreur donnerait une très mauvaise performance), à cause du bruit induit par le pas de gradient et le gradient “bruité”. Ce gradient bruité aide aussi à sortir de certains minima locaux, pour la même raison.
Quand la descente de gradient stochastique est utilisée, il est IMPÉRATIF que les exemples soient bien mélangés: par exemple si on a beaucoup d’exemples consécutifs de la même classe, la convergence sera très lente. Il suffit de permuter aléatoirement les exemples une fois pour toute, pour éliminer toute dépendence entre les exemples successifs. Avec certaines architectures qui captent des dépendences temporelles (signaux, musique, parole, séries chrono, vidéo) on a pas le choix de présenter des séquences dont les éléments sont fortement dépendents, mais on peut mélanger les séquences (l’ensemble d’apprentissage est une suite de séquences).
En principe le pas de gradient devrait être
graduellement réduit pendant l’apprentissage pour
garantir la convergence asymptotique. Pour certains
problèmes (surtout de classification) cela ne semble pas
nécessaire, et peut même nuire. Une cédule de descente raisonnable est par
exemple
comme discuté ici.
Si on pouvait le calculer, le pas de gradient optimal
serait
, i.e., l’inverse
de la valeur propre la plus grande de la matrice Hessienne,
et le pas de gradient maximal (avant divergence) est
deux fois plus grand. Le Cun propose une méthode pour
estimer efficacemenet
(voir son
tutorial sur le sujet), mais cette technique ne semble
pas courramment utilisée.
Quand le nombre d’exemples (et donc de paramètres) est plus petit, et surtout pour la régression, les techniques du second degré (surtout la technique des gradients conjugués) permettent une convergence beaucoup plus rapide. Ces techniques sont batch (modification des paramètres après calcul de l’erreur et gradient sur tous les exemples). Ces techniques sont généralement plus facile à ajuster que la descente de gradient stochastique (moins d’hyper-paramètres ou moins nécessaire de les ajuster par rapport à une valeur par défaut), mais la généralisation est parfois moins bonne à cause de la facilité de tomber dans des minima pointus.
Jusqu’à quelques dizaines de milliers d’exemples, la descente de gradient conjugués reste une des meilleures techniques pour l’optimisation des réseaux de neurones. Au-delà il vaut généralement mieux s’en tenir au gradient stochastique ou à sa version minibatch.
On ne peut initialiser tous les poids à zéro sans quoi
tous les neurones cachés sont condamnés à toujours faire
la même chose (qu’on peut voir par un simple argument de symétrie).
On veut aussi éviter la saturation des neurones (sortie près des
limites de la non-linéarité, donc gradient presque 0),
mais ne pas être trop près initialement d’une fonction
linéaire. Quand les paramètres sont tous près de 0,
le réseau multicouche calcule une transformation
affine (linéaire), donc sa capacité effective
par sortie est égale au nombre d’entrées plus 1.
En se basant sur ces considérations, le point idéal
d’opération du neurone devrait être proche du point d’inflexion
de la non-linéarité (entre la partie linéaire près
de l’origine et la partie saturation).
Par ailleurs, on aimerait que la variance moyenne des valeurs
des unités cachées soit préservée quand on propage
les “activations” de l’entrée vers la sortie, et
de la même manière on aimerait que la variance des
gradients le soit aussi quand on les propage de la sortie
vers l’entrée.
Pour atteindre cet objectif,
on peut argumenter que les poids initiaux
devraient être initialisés de manière uniforme
dans un intervalle , où
est le fan-in, i.e., le nombre d’entrées du neurone, le nombre
de neurones de la couche précédente, et
est le fan-out,
i.e., le nombre de neurones de la couche visée. Cela suppose
que les entrées sont approximativement uniformes dans l’intervalle (-1,1)
(et remarquez comme les sorties des unités cachées tanh sont aussi
dans le même intervalle).
Un des problèmes fréquents pendant l’apprentissage est la saturation des neurones, souvent dûe à une mauvaise normalisation des entrées ou des sorties désirées ou une mauvaise initialisation des poids, ou bien à l’utilisation de la sigmoide plutôt qu’une fonction de non-linéarité symétrique comme la tanh. On peut contrôler cela on observant la distribution des sorties des neurones (en particulier, la moyenne des valeurs absolues de la somme pondérée est un bon indice). Quand les neurones saturent fréquemment, l’apprentissage est bloqué sur un plateau de la fonction de coût dû à de très petits gradients sur certains paramètres (donc un très mauvais conditionnement du Hessien).
La théorie du structural risk minimization de Vapnik nous dit qu’il existe une capacité optimale autour de laquelle l’erreur de généralisation augmente (c’est un minimum global et unique). Les techniques de contrôle de la capacité effective visent donc à chercher ce minimum (evidemment de façon approximative).
early stopping: il s’agit d’une des techniques les plus populaires et les plus efficaces, mais elle ne marche pas bien quand le nombre d’exemples disponibles est très petit. L’idée est très simple: on utilise un ensemble d’exemples de validation non-utilisés pour l’apprentissage par descente de gradient pour estimer l’erreur de généralisation au fur et à mesure que l’apprentissage itératif progresse (normalement, après chaque époque on mesure l’erreur sur l’ensemble de validation). On garde les paramètres correspondant au minimum de cette courbe d’erreur de généralisation estimée (et on peut s’arrêter quand cette erreur commence à remonter sérieusement ou qu’un minimum a été atteint depuis un certain nombre d’époques). Cela a l’avantage de répondre à une des questions difficile de l’optimisation, qui est: quand arrêter? De plus on remarque qu’on a ainsi choisi pour pas cher (en temps de calcul) un hyper-paramètre important (le nombre d’itérations d’entraînement) qui touche à la fois l’optimisation et la généralisation.
contrôle du nombre d’unités cachées: ce nombre influence directement la capacité. Dans ce cas il faut malheureusement faire plusieurs d’expériences d’apprentissage, à moins d’utiliser un algorithme d’apprentissage constructif (qui rajoute des ressources au fur et à mesure), voir l’algorithme de cascade-correlation (Fahlman, 1990). On peut utiliser un ensemble de validation ou la validation croisée pour estimer l’erreur de généralisation. Il faut faire attention au fait que cet estimé est bruité (d’autant plus qu’il y a peu d’exemples de validation). Quand on a plusieurs couches cachées, choisir le même nombre d’unités par couche semble bien fonctionner. Le prix à payer pour un nombre d’unités trop grand est surtout que les calculs sont plus longs, car le nombre accru de paramètre est généralement compensé par le early stopping. Par contre quand le nombre d’unités cachées est trop petit, l’effet sur l’erreur de généralisation et sur l’erreur d’apprentissage peut être beaucoup plus grand. On va généralement choisir la taille des réseau de façon empirique, en gardant ces considérations à l’esprit pour éviter d’avoir à essayer trop de valeurs de la taille.
weight decay: c’est une méthode de régularisation (pour contrôler la capacité, empêcher l’overfitting) dont le but est de pénaliser les poids forts. En effet, on peut montrer que la capacité est bornée par la magnitude des poids du réseau de neurones. On rajoute la pénalité
![]()
à la fonction de coût. On l’appelle régularisation L2 car on minimise la norme 2 des paramètres. Certains l’appliquent uniquement aux poids et non pas au biais.
Comme dans le cas précédent, il faut faire plusieurs expériences d’apprentissage et choisir le facteur de pénalité
(un hyper-paramètre) qui minimise l’erreur de généralisation estimée. On l’estime avec un ensemble de validation ou bien par validation croisée.
Une forme de régularisation de plus en plus utilisée comme alternative à la régularisation L2 est la régularisation L1, qui a comme avantage que les petits paramètres seront carrément amenés à 0, donnant lieu à un vecteur de paramètres qui est sparse. On va donc minimiser la somme des valeurs absolues des paramètres.