A desvantagem da função ReLU.

Como o problema dos neurônios mortos pode impactar o aprendizado de uma rede neural.

Toni Esteves
7 min readJan 25, 2022

Recentemente retomei meus estudos sobre redes neurais e comecei a identificar situações curiosas nas minúcias de cada algoritmo comumente utilizado na construção dessas estruturas. Em verdade saber qual a melhor forma de construir uma rede neural com seus parâmetros, camadas, entradas e saídas está longe de ser uma tarefa simples.

Escolher uma função de ativação para as camadas ocultas de uma rede neural, também não é uma tarefa tão trivial quanto parece. A configuração das camadas ocultas é um tópico de pesquisa extremamente ativo, e simplesmente não tem nenhuma teoria sobre quantos neurônios, quantas camadas e qual função de ativação usar em um conjunto de dados.

Há tempos atrás, a função sigmoide era a função de ativação mais popular devido à sua não linearidade. Com o passar do tempo, as redes neurais avançaram para arquiteturas de rede mais profundas, o que levantou a nos depararmos com outro problema: Vanishing gradientou em tradução literal o problema da Dissipação do Gradiente.

A unidade linear retificada (ReLU Rectified Linear Unit) acaba sendo a opção padrão para a função de ativação das camadas ocultas, pois inibe o problema de dissipação do gradiente já que possui um gradiente maior que o da função sigmoide.

Dissipação do Gradiente

A dissipação do gradiente é um dos maiores desafios ao treinar uma rede neural profunda. É uma situação em que uma rede neural profunda é incapaz de realizar a retropropagação do gradiente da camada de saída de volta para as primeiras camadas ocultas. Isso geralmente acontece quando você tenta construir uma rede neural profunda utilizando a função sigmoide como função de ativação em suas camadas ocultas.

O termo dissipação do gradiente refere-se ao fato de que em uma rede feedforward (FFN) o sinal de erro retropropagado normalmente diminui (ou aumenta) exponencialmente em função da distância da camada final. — Random Walk Initialization for Training Very Deep Feedforward Networks, 2014.

A fórmula para sigmoide é a seguinte:

e sua derivada resultante é a seguinte:

O problema é que a derivada resultante da sigmoide é sempre menor que 1.

Dada a fórmula acima, podemos dizer que a maior derivada é obtida quando f(x) = 0.5 de modo que f’(x) = 0,5 * (1–0.5), que é 0.25.

Agora imagine que ao construir uma rede neural de 7 camadas com uma função de ativação sigmoide em cada camada, independentemente do gradiente resultante fornecido pela função de perda, se multiplicarmos o gradiente por 0.25, esse gradiente ficará cada vez menor à medida que o retropropagamos pela rede. Logo, como existem 7 camadas, significa que o gradiente será multiplicado 7 vezes por um valor menor que 0.

Em um exemplo real, a derivada da função sigmoide nem sempre será 0.25. Pode ser 0.1, 0.06, 0.04 ou talvez 0.001. Logo o gradiente na primeira camada oculta seria extremamente pequeno,

A solução mais fácil é substituir a função de ativação nas camadas ocultas pela função ReLU ou Rectified Linear Unit.

Rectified Linear Unit (ReLU)

A função ReLU é considerado um dos maiores avanços em aprendizado profundo porque possibilita treinar uma rede neural muito profunda sem que exista a dissipação do gradiente. A função ReLU é fácil de otimizar porque é simples, computacionalmente barata e semelhante à função de ativação linear, no entanto, ReLU é uma função de ativação não linear que permite que padrões complexos nos dados sejam aprendidos. Ou seja, a única diferença entre uma função de ativação linear e uma ReLU é que ReLU empurra o valor negativo para 0.

A fórmula para ReLU é a seguinte:

e sua derivada resultante é a seguinte:

Neurônio Morto

A principal desvantagem da função ReLU é que eles não podem aprender em exemplos para os quais sua ativação é zero. Isso geralmente acontece se você inicializar toda a rede neural com zero e colocar ReLU nas camadas ocultas. Outra causa é que quando um grande gradiente trafega pela rede, um neurônio com a função ReLU atualizará seu peso e pode acabar com um peso de alto valor negativo além de um alto viés. Caso isso ocorra, esse neurônio sempre produzirá 0 durante a etapa de Foward Propagation e, então, o gradiente que trafega através desse neurônio será para sempre zero, independentemente da entrada.

Em outras palavras, os pesos desse neurônio não serão mais atualizados. Esse neurônio pode então ser chamado Neurônio morto, que é considerado uma espécie de “dano cerebral” permanente em termos biológicos. Um neurônio morto pode ser pensado como um Dropout natural. Mas o problema é que, se cada neurônio em uma camada oculta específica estiver morto, ele corta o gradiente para a camada anterior, resultando em gradientes zero para as camadas atrás dela. Esse neurônio pode ser corrigido usando taxas de aprendizado menores para que o valor do gradiente não defina um grande peso negativo nem tampouco tenha um viés agregado a esse neurônio ReLU. Outra solução é usar o Leaky ReLU, que permite que os neurônios fora do intervalo ativo vazem algum gradiente para trás.

Leaky ReLU

Em vez de empurrar o valor negativo para 0, a função Leaky ReLU permite um “vazamento” na região negativa multiplicando x por uma constante de 0.01.

Ao fazer isso, mesmo que o neurônio tenha um grande peso negativo e um viés, ainda é possível retropropagar o gradiente através da camada. A fórmula para Leaky ReLU é a seguinte:

e sua derivada resultante é a seguinte:

Leaky ReLU é linear com uma derivada de 1 quando x > 0, em contrapartida, sua derivada é 0.01, com 0.01 * x, quando x ≤ 0. A constante na região negativa também pode ser transformada em um hiperparâmetro, como visto em PReLU ou Parametric ReLU, introduzida em Delving Deep into Rectifiers.

Kaiming He initialization

Outra forma de combater o Neurônio Morto é antes de treinar uma rede neural, inicializar os pesos com pequenos valores aleatórios. Existem muitos métodos heurísticos para inicializar os pesos para uma rede neural, mas não há um melhor esquema de inicialização de peso e pouca relação além das diretrizes gerais para mapeamento de esquemas de inicialização de peso para a escolha da função de ativação.

Antes da ampla adoção do ReLU, Xavier Glorot e Yoshua Bengio propuseram um esquema de inicialização em seu artigo de 2010 intitulado Understanding the difficulty of training deep feedforward neural networks que rapidamente se tornou o padrão ao usar funções de ativação sigmoid e tanh, geralmente chamadas de Xavier initialization. Os pesos são definidos em valores aleatórios amostrados uniformemente de um intervalo proporcional ao tamanho do número de nós na camada anterior.

Kaiming He, et al. em seu artigo de 2015 intitulado Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification sugeriram que a inicialização do Xavier e outros esquemas não eram apropriados para ReLU e extensões.

Eles propuseram uma pequena modificação da inicialização Xavier para torná-lo adequado para uso com ReLU, agora comumente referido como He Initialization.

Conclusão

Se você leu esse post até aqui, muito obrigado, espero que esse material tenha sido útil e faça sentido para você. É valido mencionar que ao longo do artigo muitos links foram disponibilizados e possuem um conteúdo extremante rico, além disso, na seção de referências é possível encontrar mais alguns links uteis que foram utilizados para elaboração desse artigo que pode te ajudar a ampliar seus conhecimentos no tema assim como me ajudaram.

Finalmente caso algum outro assunto relacionado ou não com o conteúdo desse post te interesse, ou tenha te deixado em dúvida, coloca aí nos comentários que ficarei muito feliz de trazer o conteúdo de forma mais clara em um novo post.

Lembrando que qualquer feedback, seja positivo ou negativo é basta entrar em contato através do meu twiter, linkedin, Github ou nos comentários aqui em baixo. Obrigado :)

Referências

--

--

Toni Esteves

I’m a Computer Scientist and Quantitative researcher. This is my notepad for applied ML / DS / Deep Learning topics. Follow me on Twitter for more!