Algoritmo de retropropagação


19

Fiquei um pouco confuso sobre o algoritmo de retropropagação usado no perceptron multicamada (MLP).

O erro é ajustado pela função de custo. Na retropropagação, estamos tentando ajustar o peso das camadas ocultas. O erro de saída que posso entender, isto é, e = d - y[Sem os subscritos].

As perguntas são:

  1. Como se obtém o erro da camada oculta? Como alguém calcula isso?
  2. Se eu retropropagá-lo, devo usá-lo como uma função de custo de um filtro adaptável ou devo usar um sentido de programação de ponteiro (em C / C ++) para atualizar o peso?

NN é sim uma tecnologia obsoleta, então eu tenho medo que você não vai obter uma resposta, porque aqui ninguém é usá-los ...

@mbq: Não duvido de suas palavras, mas como você chega à conclusão de que NN é "tecnologia obsoleta"?
steffen

1
@steffen Por observação; Quero dizer, é óbvio que ninguém significativo da comunidade NN aparecerá e dirá: "Ei, pessoal, vamos abandonar nossa vida profissional e brincar com algo melhor!", Mas temos ferramentas que atingem uma precisão igual ou melhor sem toda essa ambivalência e nunca treinamento contínuo. E as pessoas largam o NN em favor deles.

5
Isso teve alguma verdade quando você disse, @mbq, mas não mais.
Jerad

1
@jerad Muito fácil - eu simplesmente ainda não vi uma comparação justa com outros métodos (o Kaggle não é uma comparação justa por causa da falta de intervalos de confiança para a precisão - especialmente quando os resultados de todas as equipes com pontuação alta estão tão próximos como no concurso Merck), nem qualquer análise de robustez da otimização de parâmetros - o que é muito pior.

Respostas:


27

Imaginei que responderia a um post independente aqui para qualquer pessoa interessada. Isso usará a notação descrita aqui .

Introdução

A idéia por trás da retropropagação é ter um conjunto de "exemplos de treinamento" que usamos para treinar nossa rede. Cada um deles tem uma resposta conhecida, para que possamos conectá-los à rede neural e descobrir o quanto estava errado.

Por exemplo, com o reconhecimento de manuscrito, você teria muitos caracteres manuscritos ao lado do que eles realmente eram. Em seguida, a rede neural pode ser treinada via retropropagação para "aprender" como reconhecer cada símbolo; portanto, quando mais tarde for apresentada com um caracter manuscrito desconhecido, ela poderá identificar o que é corretamente.

Especificamente, inserimos algumas amostras de treinamento na rede neural, vemos o quão bom foi e, em seguida, "retrocedemos" para descobrir o quanto podemos alterar os pesos e a polarização de cada nó para obter um resultado melhor e, em seguida, ajustá-los de acordo. Enquanto continuamos a fazer isso, a rede "aprende".

Também existem outras etapas que podem ser incluídas no processo de treinamento (por exemplo, desistência), mas vou me concentrar principalmente na retropropagação, já que essa é a questão.

Derivados parciais

Uma derivada parcial é um derivado defcom respeito a algumas variáveisxfxfx .

Por exemplo, se , ff(x,y)=x2+y2, porquey2é simplesmente uma constante no que diz respeito aX. Da mesma forma,ffx=2xy2x, porquex2é simplesmente uma constante em relação ayfy=2yx2y .

Um gradiente de uma função, designado , é uma função que contém a derivada parcial para cada variável em f. Especificamente:f

,

f(v1,v2,...,vn)=fv1e1++fvnen

onde é um apontador vector unitário na direcção da variável v 1 .eEuv1

Agora, uma vez que temos calculado o para alguma função f , se estamos na posição ( v 1 , v 2 , . . . , V n ) , nós podemos "deslizar" f indo na direção - f ( v 1 , v 2 , . . . , v n ) .ff(v1,v2,...,vn)f-f(v1,v2,...,vn)

No nosso exemplo de , os vetores unitários são e 1 = ( 1 , 0 ) e e 2 = ( 0 , 1 ) , porque v 1 = x e v 2 = y , e esses vetores apontam na direção dos eixos x e y . Assim, f ( xf(x,y)=x2+y2e1=(1,0)e2=(0,1)v1=xv2=yxy .f(x,y)=2x(1,0)+2y(0,1)

Agora, para "deslizar" nossa função , digamos que estamos em um ponto ( - 2 , 4 ) . Então precisamos mover na direção - f ( - 2 , - 4 ) = - ( 2 - 2 ( 1 , 0 ) + 2 4 ( 0 , 1 ) ) = - ( ( - 4 , 0f(2,4).f(2,4)=(22(1,0)+24(0,1))=((4,0)+(0,8))=(4,8)

A magnitude desse vetor nos dará a inclinação da colina (valores mais altos significam que a colina é mais íngreme). Nesse caso, temos .42+(8)28.944

Gradient Descent

Produto Hadamard

O Produto Hadamard de duas matrizes A,BRn×m , é como adição de matriz, exceto que, em vez de adicionar as matrizes elemento a elemento, nós as multiplicamos elemento a elemento.

Formalmente, enquanto a adição da matriz é , onde C R n × m tal queA+B=CCRn×m

,

Cji=Aji+Bji

O Produto Hadamard , onde C R n × m tal queAB=CCRn×m

Cji=AjiBji

Computando os gradientes

(a maior parte desta seção é do livro de Neilsen ).

Temos um conjunto de amostras de treino, , onde S r é um exemplo de formação de entrada única, e E r é o valor de saída esperado do que amostras de treino. Nós também temos nossa rede neural, composto por preconceitos W , e pesos B . r é usado para evitar confusão dos i , j e k usados ​​na definição de uma rede de feedforward.(S,E)SrErWBrijk

Em seguida, definimos uma função de custo, que leva em nossa rede neural e um único exemplo de treinamento e mostra como ela foi boa.C(W,B,Sr,Er)

Normalmente, o que é usado é o custo quadrático, definido por

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

em que é a saída para a rede neural, dada entrada da amostra S raLSr

Então queremos encontrar eCCwji para cada nó na nossa alimentação de entrada da rede neural.Cbji

Podemos chamar isso de gradiente de em cada neurônio porque consideramos S r e E r como constantes, pois não podemos alterá-las quando estamos tentando aprender. E isso faz sentido - queremos avançar em uma direção em relação a W e B que minimize o custo, e mover na direção negativa do gradiente em relação a W e B fará isso.CSrErWBWB

Para fazer isso, definimos como o erro de neuróniojem camadai.δji=Czjiji

Começamos com o cálculo de conectando S r à nossa rede neural.aLSr

Em seguida, calculamos o erro de nossa camada de saída, , viaδL

.

δjL=CajLσ(zjL)

Que também pode ser escrito como

δL=aCσ(zL)
.

Em seguida, encontramos o erro em termos do erro na próxima camada δ i + 1 , viaδiδi+1

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

Agora que temos o erro de cada nó em nossa rede neural, é fácil calcular o gradiente com relação aos nossos pesos e desvios:

Cwjki=δjiaki1=δi(ai1)T

Cbji=δji

Observe que a equação para o erro da camada de saída é a única equação dependente da função de custo; portanto, independentemente da função de custo, as três últimas equações são iguais.

Como exemplo, com custo quadrático, obtemos

δL=(aLEr)σ(zL)

L1th

δ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.


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.