Como a retropropagação funciona através da camada Max Pooling ao fazer um lote?

10

Vamos supor que estamos usando um tamanho de lote de 100 amostras para aprender.

Assim, em cada lote, o peso de cada neurônio (e viés, etc.) está sendo atualizado adicionando menos a taxa de aprendizado * o valor médio de erro que encontramos usando as 100 amostras * a derivada da função de erro com relação a o peso atual do neurônio que está sendo atualizado.

Agora, quando usamos uma camada Max Pool, como podemos calcular a derivada nessa camada? Em cada amostra que alimentamos para a frente, um pixel diferente (digamos) é escolhido como o máximo, portanto, quando retropropagamos mais de 100 amostras nas quais cada vez que um caminho diferente era escolhido, como podemos fazê-lo? Uma solução que tenho em mente é lembrar todos os pixels escolhidos como o máximo e, talvez, dividir a derivada por todos os pixels máximos. É isso que está sendo feito?

Nadav B
fonte
Eu tenho a mesma pergunta. quando a BP com apenas uma amostra, fica claro que apenas a derivada do maior elemento não é zero, mas quando a BP com amostras em lote, uma amostra diferente pode causar uma posição diferente do maior elemento, podemos apenas calcular a derivada média de cada parâmetro como de costume (apenas adicione ∂L / ∂wi de cada amostra e dividido pelo tamanho do lote)?
Shaotao Li 31/08/19

Respostas:

8

Quando uma rede neural processa um lote, todos os valores de ativação para cada camada são calculados para cada exemplo (talvez em paralelo, por exemplo, se a biblioteca e o hardware suportarem). Esses valores são armazenados para possível uso posterior - ou seja, um valor por ativação por exemplo no lote, eles não são agregados de forma alguma

Durante a propagação de retorno, esses valores de ativação são usados ​​como uma das fontes numéricas para calcular os gradientes, juntamente com os gradientes calculados até agora trabalhando para trás e os pesos de conexão. Como a propagação direta, a propagação reversa é aplicada por exemplo, não funciona com valores médios ou somados. Somente quando todos os exemplos foram processados, você trabalha com os gradientes somados ou médios do lote.

Isso se aplica igualmente às camadas máximas do pool. Você não apenas sabe qual foi a saída da camada de pool para cada exemplo no lote, mas também pode olhar para a camada anterior e determinar qual entrada no pool foi a máxima.

Matematicamente, e evitando a necessidade de definir índices para camadas e neurônios NN, a regra pode ser expressa assim

  • A função de avanço é m=max(a,b)

  • Nós sabemos Jm para alguma função de destino J (na rede neural que será a função de perda que queremos minimizar e estamos assumindo que já retropropagamos para esse ponto)

  • Nós queremos saber Ja e Jb

  • E se a>b

    • Localmente , *m=a. assimJa=Jm

    • Localmente , *m não depende de b. assimJb=0

  • Portanto Ja=Jm E se a>b, outro Ja=0

  • e Jb=Jm E se b>a, outro Jb=0

Quando a propagação de retorno passa por uma camada de pool máximo, o gradiente é processado por exemplo e atribuído apenas à entrada da camada anterior que era o máximo. Outras entradas obtêm gradiente zero. Quando isso é feito em lote, não é diferente, é apenas processado por exemplo, talvez em paralelo. Em todo um lote, isso pode significar que mais de uma, talvez todas, as ativações de entrada no pool máximo recebem uma parte do gradiente - cada uma de um subconjunto diferente de exemplos no lote.


* Localmente -> ao fazer apenas alterações infinitesimais em m.

** Tecnicamente, se a=b exatamente então temos uma descontinuidade, mas na prática podemos ignorá-la sem problemas ao treinar uma rede neural.

Neil Slater
fonte
3
Não tenho certeza se entendi. O que você está dizendo funciona quando você faz backprop após um único adiante. Porém, quando você tem um lote, fornece 100 amostras para calcular uma função de erro média. O ponto inteiro de um lote é poder produzir gradientes mais precisos e, em seguida, você só executa uma vez o backprop com base na derivada da função de erro em relação a W, no valor médio do erro encontrado multiplicado pela taxa de aprendizado. Portanto, ainda não está claro como você calcula a derivada da função max, quando cada nó diferente é selecionado como máximo. o que estou perdendo?
Nadav B
4
@NadavB: Está faltando a sequência de eventos. 1) O lote é calculado para a frente, item por item. 2) O lote é retropropagado, item por item. 3) Faça as médias dos gradientes. 4) Aplique uma etapa de descida de gradiente (talvez modificada por algo como Adagrad ou RMSProp). Então, você está colocando a etapa 3 fora de sequência e se perguntando como desmarcar os gradientes médios sobre a camada máxima do pool - mas você nunca precisa fazer isso porque adota cada exemplo individualmente - você só agrega resultados para o lote depois disso
Neil Slater
1
Perfeito. Você deixou claro agora.
Nadav B
@NeilSlater A retropropagação é feita apenas item por item, porque é necessária para a camada máxima do pool? Em uma MLP, a média da média do erro de todo o lote e o cálculo do gradiente nesse erro médio são idênticos ao cálculo do gradiente por item e do ajuste dos parâmetros pela taxa média de aprendizado do gradiente *, certo? No entanto, a propagação retroativa do erro médio é muito mais rápida do que a retropropagação de todos os erros individuais e a aplicação das atualizações. Então, quando possível, você gostaria de fazê-lo assim e somente por item, se necessário ... como para o pool máximo. Isso está certo?
lo tolmencre 25/07/19
@lotolmencre Você está errado ao calcular o erro médio em um lote. Você deve voltar a propagar-se individualmente e somar gradientes no final. Os cálculos de gradiente não funcionarão corretamente, caso contrário, por quaisquer não linearidades. Se você quiser saber mais sobre isso, faça uma nova pergunta
Neil Slater
2

Eu tenho a mesma pergunta, mas provavelmente descobri analisando o código fonte do Caffe.

Por favor, veja o código fonte do Caffe:

linha 620 e 631 deste código.

Ele calcula a derivada de cada parâmetro adicionando a derivada (deste parâmetro) de cada entrada e depois dividindo-a pelo tamanho do lote.

Veja também a linha 137 deste código, ele simplesmente escala a derivada para 1 / iter_size, exatamente igual à média.

Podemos ver que NÃO há tratamento especial para a camada Max Pooling quando a BP.

Quanto à derivada do Max Pooling, vamos ver o código-fonte do Caffe novamente:

linha 272 deste código. Obviamente, apenas a derivada do maior elemento é a derivada dos 1*top_diffoutros 0*top_diff.

Shaotao Li
fonte