Algorithme de rétropropagation


19

J'ai eu une légère confusion sur le algorithme de rétropropagation utilisé dans le perceptron multicouche (MLP).

L'erreur est ajustée par la fonction de coût. En rétropropagation, nous essayons d'ajuster le poids des couches cachées. L'erreur de sortie que je peux comprendre, c'est-à-dire e = d - y[sans les indices].

Les questions sont:

  1. Comment obtient-on l'erreur de couche cachée? Comment le calcule-t-on?
  2. Si je la rétropropagie, dois-je l'utiliser comme fonction de coût d'un filtre adaptatif ou dois-je utiliser un pointeur (en C / C ++) au sens de la programmation, pour mettre à jour le poids?

NN est plutôt une technologie obsolète, donc je crains que vous n'obtiendrez pas de réponse car personne ici ne les utilise ...

@mbq: Je ne doute pas de vos mots, mais comment en arrivez-vous à la conclusion que les NN sont des "technologies obsolètes"?
steffen

1
@steffen Par observation; Je veux dire qu'il est évident que personne significatif de la communauté NN ne sortira et dira "Hé les gars, abandonnons notre travail de vie et jouons avec quelque chose de mieux!", Mais nous avons des outils qui atteignent une précision identique ou meilleure sans toute cette ambivalence et jamais formation continue. Et les gens abandonnent NN en leur faveur.

5
Cela avait une certaine vérité quand vous l'avez dit, @mbq, mais plus maintenant.
jerad

1
@jerad Assez facile - je n'ai tout simplement pas encore vu de comparaison équitable avec d'autres méthodes (Kaggle n'est pas une comparaison équitable en raison du manque d'intervalles de confiance pour les précisions - en particulier lorsque les résultats de toutes les équipes à haut score sont si proches comme dans le concours Merck), ni aucune analyse de la robustesse de l'optimisation des paramètres - ce qui est bien pire.

Réponses:


27

Je pensais que je répondrais à un message autonome ici pour toute personne intéressée. Ce sera en utilisant la notation décrite ici .

introduction

L'idée derrière la rétropropagation est d'avoir un ensemble «d'exemples de formation» que nous utilisons pour former notre réseau. Chacun d'eux a une réponse connue, nous pouvons donc les brancher sur le réseau de neurones et trouver à quel point c'était faux.

Par exemple, avec la reconnaissance de l'écriture manuscrite, vous auriez beaucoup de caractères manuscrits à côté de ce qu'ils étaient réellement. Ensuite, le réseau de neurones peut être formé par rétropropagation pour «apprendre» à reconnaître chaque symbole, de sorte que lorsqu'il est ensuite présenté avec un caractère manuscrit inconnu, il peut identifier ce qu'il est correctement.

Plus précisément, nous introduisons un échantillon d'apprentissage dans le réseau neuronal, voyons à quel point cela a bien fonctionné, puis «ruisselons en arrière» pour trouver dans quelle mesure nous pouvons changer les poids et les biais de chaque nœud pour obtenir un meilleur résultat, puis les ajuster en conséquence. Alors que nous continuons à le faire, le réseau "apprend".

Il existe également d'autres étapes qui peuvent être incluses dans le processus de formation (par exemple, l'abandon), mais je me concentrerai principalement sur la rétropropagation, car c'est de cela qu'il s'agissait.

Dérivés partiels

Une dérivée partielle est une dérivée defpar rapport à une variablex.fxfx

Par exemple, si , ff(x,y)=x2+y2, cary2est simplement une constante par rapport àx. De même,ffx=2xy2x, carx2est simplement une constante par rapport ày.fy=2yx2y

Un gradient d'une fonction, désigné , est une fonction contenant la dérivée partielle pour chaque variable de f. Plus précisément:F

,

F(v1,v2,...,vn)=Fv1e1++Fvnen

est un vecteur unitaire pointant dans la direction de la variable v 1 .ejev1

Or, une fois que nous avons calculé la pour une certaine fonction f , si nous sommes en position ( v 1 , v 2 , . . . , V n ) , on peut "glisser vers le bas" f en allant dans la direction - f ( v 1 , v 2 , . . . , v n ) .FF(v1,v2,...,vn)F-F(v1,v2,...,vn)

Avec notre exemple de , les vecteurs unitaires sont e 1 = ( 1 , 0 ) et e 2 = ( 0 , 1 ) , car v 1 = x et v 2 = y , et ces vecteurs pointent dans la direction des axes x et y . Ainsi, = 2 x ( 1f(x,y)=x2+y2e1=(1,0)e2=(0,1)v1=Xv2=yXyf(x,y)=2x(1,0)+2y(0,1) .

Maintenant, pour "faire glisser" notre fonction , disons que nous sommes à un point ( - 2 , 4 ) . Ensuite, nous devons nous déplacer dans la direction - f ( - 2 , - 4 ) = - ( 2 - 2 ( 1 , 0 ) + 2 4 ( 0 , 1 ) ) = - ( ( - - 4 , 0 ) +f(2,4) .f(2,4)=(22(1,0)+24(0,1))=((4,0)+(0,8))=(4,8)

L'amplitude de ce vecteur nous donnera à quel point la colline est raide (des valeurs plus élevées signifient que la colline est plus raide). Dans ce cas, nous avons .42+(8)28.944

Gradient Descent

Produit Hadamard

Le produit de Hadamard de deux matrices , est exactement comme l'addition de matrice, sauf qu'au lieu d'ajouter les matrices élément par élément, nous les multiplions par élément.A,BRn×m

Formellement, alors que l'addition matricielle est , où C R n × m telle queA+B=CCRn×m

,

Cji=Aji+Bji

Le produit Hadamard , où C R n × mAB=CCRn×m tel que

Cji=AjiBji

Calcul des gradients

(la majeure partie de cette section provient du livre de Neilsen ).

Nous avons un ensemble d'échantillons d'apprentissage , où S r est un échantillon d'apprentissage à entrée unique et E r est la valeur de sortie attendue de cet échantillon d'apprentissage. Nous avons également notre réseau de neurones, composé de biais W et poids B . r est utilisé pour éviter la confusion des i , j et k utilisés dans la définition d'un réseau à action directe.(S,E)SrErWBrijk

Ensuite, nous définissons une fonction de coût, C(W,B,Sr,Er) qui prend notre réseau de neurones et un seul exemple de formation, et affiche à quel point il a bien fonctionné.

Normalement, ce qui est utilisé est le coût quadratique, qui est défini par

C(W,B,Sr,Er)=0.5j(ajLEjr)2

est la sortie de notre réseau de neurones, étant donné l'échantillon d'entrée S raLSr

Ensuite, nous voulons trouver etCCwjiCbji pour chaque nœud de notre réseau neuronal à action directe.

Nous pouvons appeler cela le gradient de à chaque neurone parce que nous considérons S r et E r comme des constantes, car nous ne pouvons pas les changer lorsque nous essayons d'apprendre. Et cela a du sens - nous voulons nous déplacer dans une direction par rapport à W et B qui minimise les coûts, et se déplacer dans la direction négative du gradient par rapport à W et B le fera.CSrErWBWB

δji=Czjij in layer i.

We start with computing aL by plugging Sr into our neural network.

Then we compute the error of our output layer, δL, via

δjL=CajLσ(zjL)
.

Which can also be written as

δL=aCσ(zL)
.

Next, we find the error δi in terms of the error in the next layer δi+1, via

δi=((Wi+1)Tδi+1)σ(zi)

Now that we have the error of each node in our neural network, computing the gradient with respect to our weights and biases is easy:

Cwjki=δjiaki1=δi(ai1)T

Cbji=δji

Note that the equation for the error of the output layer is the only equation that's dependent on the cost function, so, regardless of the cost function, the last three equations are the same.

As an example, with quadratic cost, we get

δL=(aLEr)σ(zL)

for the error of the output layer. and then this equation can be plugged into the second equation to get the error of the L1th layer:

δL1=((WL)TδL)σ(zL1)
=((WL)T((aLEr)σ(zL)))σ(zL1)

which we can repeat this process to find the error of any layer with respect to C, which then allows us to compute the gradient of any node's weights and bias with respect to C.

I could write up an explanation and proof of these equations if desired, though one can also find proofs of them here. I'd encourage anyone that is reading this to prove these themselves though, beginning with the definition δji=Czji and applying the chain rule liberally.

For some more examples, I made a list of some cost functions alongside their gradients here.

Gradient Descent

Now that we have these gradients, we need to use them learn. In the previous section, we found how to move to "slide down" the curve with respect to some point. In this case, because it's a gradient of some node with respect to weights and a bias of that node, our "coordinate" is the current weights and bias of that node. Since we've already found the gradients with respect to those coordinates, those values are already how much we need to change.

We don't want to slide down the slope at a very fast speed, otherwise we risk sliding past the minimum. To prevent this, we want some "step size" η.

Then, find the how much we should modify each weight and bias by, because we have already computed the gradient with respect to the current we have

Δwjki=ηCwjki

Δbji=ηCbji

Thus, our new weights and biases are

wjki=wjki+Δwjki
bji=bji+Δbji

Using this process on a neural network with only an input layer and an output layer is called the Delta Rule.

Stochastic Gradient Descent

Now that we know how to perform backpropagation for a single sample, we need some way of using this process to "learn" our entire training set.

One option is simply performing backpropagation for each sample in our training data, one at a time. This is pretty inefficient though.

A better approach is Stochastic Gradient Descent. Instead of performing backpropagation for each sample, we pick a small random sample (called a batch) of our training set, then perform backpropagation for each sample in that batch. The hope is that by doing this, we capture the "intent" of the data set, without having to compute the gradient of every sample.

For example, if we had 1000 samples, we could pick a batch of size 50, then run backpropagation for each sample in this batch. The hope is that we were given a large enough training set that it represents the distribution of the actual data we are trying to learn well enough that picking a small random sample is sufficient to capture this information.

However, doing backpropagation for each training example in our mini-batch isn't ideal, because we can end up "wiggling around" where training samples modify weights and biases in such a way that they cancel each other out and prevent them from getting to the minimum we are trying to get to.

To prevent this, we want to go to the "average minimum," because the hope is that, on average, the samples' gradients are pointing down the slope. So, after choosing our batch randomly, we create a mini-batch which is a small random sample of our batch. Then, given a mini-batch with n training samples, and only update the weights and biases after averaging the gradients of each sample in the mini-batch.

Formally, we do

Δwjki=1nrΔwjkri

and

Δbji=1nrΔbjri

where Δwjkri is the computed change in weight for sample r, and Δbjri is the computed change in bias for sample r.

Then, like before, we can update the weights and biases via:

wjki=wjki+Δwjki
bji=bji+Δbji

This gives us some flexibility in how we want to perform gradient descent. If we have a function we are trying to learn with lots of local minima, this "wiggling around" behavior is actually desirable, because it means that we're much less likely to get "stuck" in one local minima, and more likely to "jump out" of one local minima and hopefully fall in another that is closer to the global minima. Thus we want small mini-batches.

On the other hand, if we know that there are very few local minima, and generally gradient descent goes towards the global minima, we want larger mini-batches, because this "wiggling around" behavior will prevent us from going down the slope as fast as we would like. See here.

One option is to pick the largest mini-batch possible, considering the entire batch as one mini-batch. This is called Batch Gradient Descent, since we are simply averaging the gradients of the batch. This is almost never used in practice, however, because it is very inefficient.


En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.