Hiper-parâmetros em Ação! Parte I — Funções de Ativação

Daniel Godoy
Ensina.AI
Published in
11 min readMay 22, 2018
Função de ativação sigmóide em ação!

Introdução

Esse é o primeiro de uma série de artigos que pretende apresentar, de uma maneira clara, concisa e, principalmente, visual, uma das peças fundamentais no treino de redes neurais: os hiper-parâmetros.

Motivação

Os hiper-parâmetros são a coisa mais importante em Deep Learning! Ter uma boa compreensão dos efeitos que cada um dos diferentes hiper-parâmetros têm sobre o treino de uma rede neural profunda facilita bastante a vida do cientista de dados.

Com certeza, durante seu estudo de Deep Learning, você já encontrou toneladas de informação a respeito da importância de configurar adequadamente os hiper-parâmetros de uma rede neural: função de ativação, inicialização dos pesos, otimizadores, taxa de aprendizado, tamanho do mini-lote e até a própria arquitetura da rede, como o número de camadas ocultas e o número de unidades em cada camada.

Você estudou as melhores práticas, configurou sua rede, definiu os hiper-parâmetros (ou usou seus valores default), começou a treinar sua rede neural e monitorou o progresso dos custos e das métricas do seu modelo.

Talvez o resultado de seu experimento não tenha sido tão bom quanto o esperado, e então você repetiu o processo, fazendo ajustes, até que encontrou os parâmetros que resolveram o seu problema.

Buscando um entendimento mais profundo

Você já parou pra pensar no que realmente está acontecendo nos bastidores? Eu já, e posso dizer que alguns experimentos simples podem ajudar bastante a entender o que está acontecendo.

Por exemplo, considere as funções de ativação, o tópico desse artigo. Você e eu sabemos que o papel das funções de ativação é introduzir uma não-linearidade. Sem elas, uma rede neural, mesmo profunda, poderia ser completamente subtituída por uma transformação afim (ou seja, uma transformação linear, tal qual uma rotação, escala ou inclinação, seguida de uma translação).

Uma rede neural apenas com ativações lineares (ou seja, sem ativações!) teria dificuldade em modelar até mesmo um problema de classificação simples (cada linha tem 1.000 pontos, para valores de x em intervalos regulares entre -1,0 e 1,0):

Figura 1: nesse espaço de atributos bidimensional, a linha azul representa os exemplos negativos (y = 0) e a verde, os exemplos positivos (y = 1).

Se uma rede é capaz de realizar apenas transformações afins, a solução provável encontrada por ela seria algo como:

Figura 2: fronteira de decisão linear — não ajuda muito, não é?

Claramente, a rede não chegou nem perto da solução! Abaixo, algumas alternativas bem melhores:

Figura 3: não-linearidades em ação!

As alternativas acima são ótimos exemplos do que funções de ativação não-lineares são capazes de fazer! Adivinhe qual delas corresponde a uma ReLU?

Fronteiras de decisão não-linares (mesmo?)

Como podemos obter essas fronteiras não-lineares? A principal função de uma não-linearidade é retorcer o espaço de atributos de tal forma que a fronteira acabe sendo… LINEAR!

OK, isso está ficando interessante (pelo menos, foi o que eu pensei na primeira vez que vi o excelente artigo do Chris Olah — em inglês —, que foi a minha inspiração para escrever esse artigo). Vamos seguir adiante!

O próximo passo é construir a rede neural mais simples possível e que ainda seja capaz de resolver nosso problema de classificação. Nosso espaço de atributos tem duas dimensões (x1 e x2), e vamos usar uma rede que tem apenas uma camada oculta com duas unidades. Dessa forma, preservamos o número de dimensões, considerando os valores de saída da camada oculta (z1 e z2).

Figura 4: diagrama de uma rede neural simples com apenas uma camada oculta de 2 unidades

Até agora, o resultado ainda é equivalente a uma transformação afim… vamos, então, acrescentar uma função de ativação não-linear, representada pela letra grega sigma, obtendo os valores de ativação (a1 e a2) da camada oculta.

Esses valores de ativação representam o espaço de atributos retorcido mencionado no primeiro parágrafo dessa seção. Se utilizarmos uma função de ativação sigmóide, por exemplo, o espaço de atributos vai se parecer com este:

Figura 5: espaço de atributos bidimensional: versão retorcida!

Conforme o prometido, a fronteira de decisão é LINEAR! A propósito, a figura acima corresponde à fronteira de decisão não-linear mais à esquerda na Figura 3, que mostrava o espaço de atributos na versão original.

Relembrando a matemática básica de redes neurais

Só pra ter certeza de que estamos sincronizados, seguem abaixo quatro formas distintas de representar as operações realizadas pela rede neural até retornar os valores de saída da camada oculta, mas ANTES de aplicar a função de ativação (ou seja, o equivalente a uma transformação afim tal qual xW + b)

Aritmética básica de matrizes: 4 maneiras de representar a mesma operação na rede neural

Então, aplicamos a função de ativação, representada pela letra sigma no diagrama da rede neural.

Função de ativação: aplicada sobre os resultados das transformações afins

Feito! Percorremos todo o caminho, desde os valores de entrada até os valores de ativação da camada oculta!

Implementando a rede neural no Keras

Eu usei a API sequencial do Keras para implementar uma rede neural básica. Todos os modelos utilizaram exatamente os mesmos hiper-parâmetros, exceto pelas diferentes funções de ativação:

  • inicializadores de pesos: Glorot (He) normal (camada oculta) e normal (camada de saída);
  • otimizador: gradiente descendente estocástico (SGD);
  • taxa de aprendizado: 0,05;
  • tamanho do mini-lote: 16;
  • número de camadas ocultas: 1;
  • número de unidades (na camada oculta): 2.

Já que o nosso problema é uma classificação binária, a camada de saída tem apenas uma unidade com uma função de ativação sigmóide e a função de custo é a entropia cruzada.

Código: rede neural simples com apenas uma camada oculta de 2 unidades

Funções de ativação em ação!

Chegamos ao “prato principal”: a visualização da evolução do espaço de atributos retorcido ao longo do treino da rede neural, usando cada uma das funções de ativação: sigmóide, tangente hiperbólica e ReLU.

Além de mostrar as alterações no espaço de atributos, as animações também contém:

  • histogramas das probabilidades previstas, tanto para os exemplos negativos (linha azul), quanto para os positivos (linha verde), mostrando os exemplos erroneamente classifcados como barras vermelhas (usando ponto de corte = 0.5);
  • gráficos de linha para exatidão e custo médio;
  • histograma dos custos para todos elementos do conjunto de dados.

Sigmóide

Vamos começar pela mais tradicional das funções de ativação, a sigmóide. Atualmente, a sua utilização está praticamente restrita à camada de saída em problemas de classificação.

Figura 6: função de ativação sigmóide e seu gradiente

Como se pode observar na Figura 6, a função de ativação sigmóideespreme” os valores de entrada no intervalo (0, 1) (o que pode ser interpretado como probabilidade, motivo pelo qual ela é usada da camada de saída de problemas de classificação). Além disso, lembre-se também que os valores de ativação de uma dada camada são as os valores de entrada da camada seguinte. E, dado o intervalo dos valores retornados pela sigmóide, os valores de ativação estarão centrados em torno de 0,5, ao invés de zero (como seria esperado no caso de valores de entrada normalizados).

O valor máximo do gradiente, como podemos ver no gráfico, é 0,25 (para z = 0), e o gradiente aproxima-se de zero para valores de |z| iguais a 5 ou mais.

Qual o efeito da função de ativação sigmóide em nossa rede neural? Confira na animação abaixo:

Sigmóide em ação!

Algumas observações:

  • épocas 15–40: a típica “espremida” da função sigmóide torna-se evidente no eixo horizontal;
  • épocas 40–65: o custo permanece estável, e observamos um “alargamento” do espaço de atributos transformado no eixo vertical;
  • época 65: nesse momento, os exemplos negativos (linha azul) estão todos corretamente classificados, embora as suas probabilidades ainda estejam distribuídas até o ponto de corte, 0,5; os exemplos positivos mais extremos, por outro lado, ainda não estão corretamente classificados;
  • épocas 65–100: o “alargamento” torna-se cada vez mais pronunciado, até o ponto em que todo espaço de atributos é novamente ocupado; ao mesmo tempo, o custo permanece caindo;
  • época 103: em virtude do “alargamento”, agora todos os exemplos positivos estão situados do lado correto da fronteira de decisão; suas probabilidades, contudo, ainda estão distribuídas até o ponto de corte, 0,5;
  • épocas 100–150: o eixo vertical também está sendo “espremido”, e o custo segue caindo mais um pouco, até alcançar um novo patamar; as previsões da rede neural exibem um alto grau de confiança para a grande maioria dos exemplos, a não ser por alguns exemplos positivos situados nas extremidades.

No geral, a função de ativação sigmóide consegue separar as duas linhas com sucesso, mas o custo diminuiu lentamente, permanecendo por longos períodos de tempo em patamares estáveis.

Será que conseguimos melhores resultados se usarmos uma função de ativação diferente?

Tangente Hiperbólica

A função de ativação tangente hiperbólica é a sucessora da sigmóide, uma vez que seus valores de saída tem média zero, diferentemente de sua antecessora.

Figura 7: função de ativação tangente hiperbólica e seu gradiente

Como se pode observar na Figura 7, a função de ativação tangente hiperbólica espreme” os valores de entrada no intervalo (-1, 1). Dessa forma, os valores de ativação já se encontram, de certa forma, normalizados, ao serem passados como valores de entrada para a camada seguinte.

Já o gradiente tem um valor máximo bem mais alto, de 1,0 (novamente, para z = 0), mas aproxima-se de zero ainda mais rapidamente, para valores de |z| iguais a 3 ou mais. Essa rápida redução nos valores dos gradientes é chamada também de problema da dissipação dos gradientes e é uma das causas da progressiva lentidão no treinamento de redes neurais.

Confira agora a nova animação, usando a tangente hiperbólica como função de ativação:

Tangente hiperbólica em ação!

Algumas observações:

  • épocas 10–40: observamos uma “espremida” da tangente hiperbólica no eixo horizontal, ainda que menos pronunciado, enquanto o custo permanece em um patamar estável;
  • épocas 40–55: sem alterações no custo, mas percebemos um “alargamento” no eixo vertical do espaço de atributos transformados;
  • época 55: nesse momento, os exemplos negativos (linha azul) estão todos corretamente classificados, embora as suas probabilidades ainda estejam distribuídas até o ponto de corte, 0,5; os exemplos positivos mais extremos, por outro lado, ainda não estão corretamente classificados;
  • épocas 55–65: o “alargamento” torna-se cada vez mais pronunciado, até o ponto em que todo espaço de atributos é novamente ocupado; ao mesmo tempo, o custo cai abruptamente;
  • época 69: em virtude do “alargamento”, agora todos os exemplos positivos estão situados do lado correto da fronteira de decisão; suas probabilidades, contudo, ainda estão distribuídas até o ponto de corte, 0,5;
  • época 65–90: o eixo vertical também está sendo “espremido”, e o custo segue caindo mais um pouco, até alcançar um novo patamar; as previsões da rede neural exibem um alto grau de confiança para a todos os exemplos;
  • épocas 90–150: nada acontece, além de pequenas melhoras nas probabilidades previstas.

OK, parece um pouco melhor… a função de ativação tangente hiperbólica classificou corretamente todos os exemplos em menos tempo. O custo, por sua vez, caiu mais rapidamente, embora também tenha permanecido uma boa parte do tempo em patamares estáveis.

O que acontece se nos livrarmos de vez da “espremida”?

ReLU

Unidades retificadoras lineares (Rectified Linear Units, em inglês, ou sua popular abreviação, ReLU) são a escolha mais comum nos dias de hoje como função de ativação. A ReLU não apenas mitiga o problema da dissipação dos gradientes, comum nas funções anteriores, como também é aquela para qual o cálculo dos gradientes é o mais rápido.

Figura 8: função de ativação ReLU e seu gradiente

Como se pode observar na Figura 8, a ReLU é completamente diferente: ela não “espreme” os valores de entrada em um intervalo fixo — ela simplesmente preserva os valores positivos e transforma todos valores negativos em zeros.

Uma vantagem de usar a ReLU é que seu gradiente ou é igual a 1 (para os valores positivos) ou é igual a 0 (para os valores negativos) — adeus dissipação dos gradientes! Essa característica da ReLU também ajuda a rede a convergir mais rápido.

Por outro lado, essa característica também pode acarretar o surgimento de “neurônios mortos”, ou seja, neurônios cujos valores de entrada são sempre negativos, de forma que o valor de ativação é sempre zero.

Chegou a hora da última das animações, que é bem diferente das anteriores, uma vez que a função de ativação ReLU nãoespreme”:

ReLU em ação!

Algumas observações:

  • épocas 0–10: o custo cai constantemente desde o início;
  • época 10: nesse momento, os exemplos negativos (linha azul) estão todos corretamente classificados, embora as suas probabilidades ainda estejam distribuídas até o ponto de corte, 0,5; os exemplos positivos mais extremos, por outro lado, ainda não estão corretamente classificados;
  • épocas 10–60: o custo cai até atingir um patamar estável, todos os exemplos já estão corretamente classificados desde a época 52, e as previsões da rede neural exibem um alto grau de confiança para todos os exemplos;
  • épocas 60–150: nada acontece, além de pequenas melhoras nas probabilidades previstas.

Não é à toa que a ReLU é a função de ativaçãopadrão” atualmente. O custo caiu constantemente desde o início e só estacionou em um patamar estável em um valor próximo de zero, e a rede classificou corretamente todos exemplos em aproximadamente 75% do tempo levado pela tangente hiperbólica.

Confronto

As animações são legais (ok, eu sei, fui eu que fiz!), mas não são muito práticas para comparar o efeito que cada uma das funções de ativação teve sobre o espaço de atributos. Assim, a figura abaixo mostra os respectivos resultados lado a lado, para facilitar a comparação entre eles:

Figura 9: fronteiras de decisão lineares no espaço de atributos transformado (linha superior), fronteiras de decisão não-lineares no espaço de atributos original (linha inferior)

Você pode estar se perguntando: “dá para comparar a exatidão e o custo também?”. Claro!

Figura 10: curvas de exatidão e custo para cada uma das funções de ativação

Considerações Finais

Nesse artigo, eu usei um exemplo extremamente simples para ilustrar o treino de uma rede neural. As animações serviram para dar uma ideia geral do mecanismo de funcionamento de cada uma das funções de ativação.

Talvez eu tenha dado “sorte” com minha inicialização dos pesos (vai que usar 42 como semente aleatória traz boa sorte?!), já que todas as três redes neurais conseguiram classificar corretamente todos os exemplos em menos de 150 épocas. Digo isso porque o treino de uma rede neural é MUITO sensível à inicialização. Mas esse é um tópico para um outro artigo.

De qualquer forma, espero sinceramente que esse artigo e as diversas animações tenham ajudado você a entender um pouco melhor as funções de ativação, uma parte fundamental desse tópico fascinante que é Deep Learning.

Para sugestões, perguntas ou comentários, por favor, escreva abaixo ou me contate no Twitter.

--

--

Daniel Godoy
Ensina.AI

Data Scientist, developer, teacher and writer. Author of "Deep Learning with PyTorch Step-by-Step: A Beginner’s Guide" https://pytorchstepbystep.com