Redes Neurais Artificiais e MLP
UFPE
O cérebro é o mais requintado dos instrumentos, capaz de refletir as complexidades e os emaranhamentos do mundo ao nosso redor.
Centro da inteligência, memória, consciência e linguagem, o cérebro controla, em colaboração com outras partes do encéfalo, as sensações e os órgãos efetores, ele é o ponto mais alto da evolução, o único órgão consciente da sua existência.

O córtex cerebral é a fina camada de substância cinzenta que reveste o centro branco medular de todo encéfalo e possui uma espessura que varia de 1 a 4 mm.
Trata-se de uma das partes mais importantes do sistema nervoso e a maior parte é composta por células nervosas (neurônios) que recebem impulsos dos pontos mais distantes do corpo e os retransmitem ao destino certo.

No córtex cerebral chegam impulsos provenientes de todas as vias da sensibilidade que aí se tornam conscientes e são interpretadas.
Do córtex saem os impulsos nervosos que iniciam e comandam os movimentos voluntários e involutários. Com ele estão relacionados os fenômenos psíquicos como a memória, a inteligência, a linguagem e a consciência.
Sabendo que o Córtex Cerebral é formado em sua maior parte por Neurônios, vamos entender um pouco mais sobre eles!

Em geral os neurônios constituem-se dos mesmos compontes básicos:

Corpo celular: contém o núcleo e a maioria dos organelos celulares.
Dendritos: prolongamentos que recebem sinais de outros neurônios e levam o impulso nervoso até o corpo celular, sendo, na maioria das vezes, responsáveis pela comunicação entre os neurônios através das sinapses.
Axônio: prolongamento que transmite sinais para outros neurônios. É responsável pela condução do impulso nervoso para o próximo neurônio
Bainha de Mielina: protege o axônio e acelera a transmissão de sinais.
A região de contato entre o fim do axônio de um neurônio e os dendritos de outro neurônio é chamado de Sinapse;
A sinapse é composta por:
Botão sináptico: extremidade do axônio que libera neurotransmissores;
Fenda sináptica: espaço entre o botão sináptico e os dendritos;
Receptor: proteína localizada na membrana do dendrito que recebe os neurotransmissores.
O axônio leva os impulsos para fora do corpo celular, as extremidades de cada axônio chegam até bem próximo dos dendritos do próximo neurônio, mas não chega a tocá-lo, ou seja, os neurônios não tem uma ligação física entre eles, mas os mediadores químicos são passados de um neurônio a outro.
Redes Neurais Artificiais são estruturas computacionais inspiradas no sistema nervoso de seres vivos, mais especificamente neurônios. Porém aqui devem ser guardadas as proporções:
enquanto as redes neurais biológicas estão entre as estruturas mais complexas já conhecidas e seu funcionamento ainda não é totalmente compreendido,
as Redes Neurais Artificiais buscam simular o comportamento dos neurônios para executar apenas tarefas bem específicas, como as de classificar um objeto.
As redes neurais são semelhantes ao funcionamento do cérebro humano em dois aspectos fundamentais:
o conhecimento é adquirido pela rede neural por meio de um processo de aprendizado
e os pesos das conexões entre neurônios, conhecidas como sinapses, são utilizados para armazenar o conhecimento.
O procedimento utilizado para representar o processo de aprendizado, normalmente conhecido como algoritmo de aprendizado, é uma função para modificar os pesos das conexões da rede com o objetivo de alcançar um valor previamente estabelecido.
Conceitualmente, uma rede neural artificial consiste de um conjunto de componentes de processamento interconectados entre si, formando uma rede.

Conceitualmente, uma rede neural artificial consiste de um conjunto de componentes de processamento interconectados entre si, formando uma rede.

Uma unidade da rede é chamada de neurônio, assim como no sistema nervoso humano, e as conexões entre essas unidades são chamadas de sinapses, seguindo a mesma analogia.


O componente central de uma rede neural é o neurônio, ou nó. O neurônio recebe um conjunto de informações de entrada \(x_j\) a partir de outros nós, e multiplica cada entrada por um peso \(w_{kj}\), que está associado a cada uma das conexões.
O produto resultante dessa multiplicação é somado dentro do neurônio para gerar uma ativação \(\nu_k = \sum_{j=1}^p x_j w_{kj}\).
A ativação é transformada utilizando-se uma função de transferência \(F(\nu_k)\) para produzir a saída do nó.
Usualmente, uma função de transferência sigmoidal do tipo \(F(\nu_k) = 1 / (1 + e^{-\nu_k})\) é utilizada, onde \(\nu_k\) é a ativação.
Conforme visto anteriormente, a saída do neurônio é calculada a partir das entradas ponderadas por um peso associado a conexão.
\[\varphi_k=F(\nu_k) = F\left(\sum_{j=1}^p x_j w_{kj}\right)\]
\(x_j\) é a entrada do neurônio da \(j\)-ésima variável, ou valor de observação, \(w_{kj}\) é o peso da conexão na \(k\)-ésima camada da \(j\)-esima variável, \(\nu_k\) é o valor da ativação e \(F(\cdot)\) é a função de ativação.
Diversas funções de ativação podem ser utilizadas na implementação de uma rede neural em multicamadas.
As funções de ativação mais básicas são a função linear:
\[\varphi_k=F(\nu_k) = \nu_k = \sum_{j=1}^p x_j w_{kj},\] 
a função lógica, ou de ativação por limiar (também conhecida como função degrau):
\[\begin{align} %\begin{eqnarray} \varphi_k = F(\nu_k) =\left\{ \begin{array}{c l} 0, & \nu_k < \beta\\ 1, & \nu_k > \beta \end{array}\right. %\end{eqnarray} \end{align}\]
\(\beta\) é o ponto de transição do neurônio. Nesse caso, o ponto de transição pode ser incorporado ao neurônio, o que resulta em uma função da seguinte forma:
\[\varphi_k=F(\nu_k) = F \left( \sum_{j=1}^p x_j w_{kj} + \beta \right)\]

Entretanto, a função de ativação degrau possui algumas limitações como mapeia valores de entrada para 0 ou 1, tem uma derivada zero quase em todos os lugares, exceto no ponto de mudança (o limiar). Isso faz com que o gradiente seja zero para quase todas as entradas, resultando no “vanishing gradient problem” (problema do gradiente desaparecendo), onde os pesos não são ajustados adequadamente durante o treinamento.
Uma função contínua, que permite a implementação de algoritmos mais complexos para o treinamento da rede, é a função sigmoide:
\[\varphi_k=F(\nu_k) = \dfrac{1}{1+e^{-\alpha \nu_k}}\] onde \(\alpha\) é um parâmetro de ajuste da função, geralmente é utilizado \(\alpha = 1\). A função de ativação sigmoide possui como saída o intervalo [0, 1].

Temos também a função tangente hiperbólica:
\[\varphi_k =F(\nu_k ) = tanh(\nu_k)\]
A função tangente hiperbólica possui como saída o intervalo [-1,1].
Existem outras funções de ativação que podem ser utilizadas, dependendo do problema a ser resolvido e da arquitetura da rede.
Uma função que está sendo muito utilizada ultimamente é a função de ativação ReLU (Rectified Linear Unit), dada por:
\[\varphi_k =F(\nu_k) = max(0,\nu_k)\]
essa função é muito utilizada em redes neurais profundas, pois acelera o treinamento da rede, devido ao fato da derivada ser constante para valores positivos de \(\nu_k\).

Outra que vem em crescente uso, é a função de ativação Leaky ReLU, dada por:
\[\varphi_k = F(\nu_k) = max(0.01\nu_k,\nu_k)\]
Essa função é uma variação da ReLU, que permite que valores negativos de \(\nu\) sejam passados adiante, o que pode ajudar no treinamento da rede.

Em geral quando temos um problema de multiclasse utilizamos a função de ativação softmax, que é uma generalização da função sigmoide para múltiplas classes, dada por:
\[\varphi_{kc} = F(\nu_{kc}) = \dfrac{e^{\nu_{c}}}{\sum_{g=1}^{C}e^{\nu_g}}\]
onde \(c\) é o número de classes do problema.

Na Figura (a), acima, \(\sigma (z) = F(\nu_{k})\) e na Figura (b) \(\sigma (z)_j = F(\nu_{kc})\), e \(z = \nu_k\) ou \(z = \nu_{kc}\).
O perceptron, invenção de Rosenblatt, é considerado o primeiro modelo de redes neurais.
Dentre os tipos de redes neurais existentes, o perceptron é a arquitetura mais simples, apresentando apenas um neurônio, ou seja, uma única camada.


Este tipo de rede neural, embora simples, apresenta problemas específicos, não podendo ser utilizada em aplicações mais avançada, apenas em estruturas de decisão simples.
O perceptron modela um neurônio pegando uma soma ponderada de suas entradas e enviando o resultado 1 se a soma for maior que algum valor inicial ajustável ( caso contrário, ele envia o resultado 0).
Tabela da Verdade
A tabela de verdade para p XOR q de duas entradas é a seguinte:
| p | q | p \(\oplus\) q |
|---|---|---|
| F | F | F |
| F | V | V |
| V | F | V |
| V | V | F |

mudando-se os valores de \(w_1\) e \(w_2\) e \(\theta\), muda-se a inclinação e a posição da reta;
entretanto é impossível achar uma reta que divide o plano de forma a separar os pontos \(A_1\) e \(A_2\) de um lado e \(A_0\) e \(A_3\) do outro.
redes de uma única camada só representam funções linearmente separáveis.



O perceptron de múltiplas camadas ou multilayer perceptron (MLP) é uma rede com uma camada de entrada, que possui a quantidade de nós de entrada iguais a quantidade de features (variáveis) dos dados, uma ou mais camadas ocultas de neurônios e uma camada de saída com um número igual a quantidade desejada dado o problema.
No MLP, o sinal de entrada se propaga para frente (esquerda para direita) através das camadas até a camada de saída, ou seja, é uma rede alimentada para frente, conhecida como feedfoward.

O MLP é uma generalização do perceptron e é treinada de forma supervisionada.
O mecanismo utilizado para a aprendizagem do MLP, é conhecido como algoritmo de retropropagação de erro (backpropagation).
De maneira similar ao perceptron, o MLP necessita da definição da funçã de erro e da taxa de aprendizagem.
Todo o procedimento do treinamento do MLP é baseado no erro.
No MLP, o erro do neurônio de saída \(1_{saida}\), na iteração \(t\), é definido por:
\[e_{1_{saida}}(t) = y - \hat{y}(t),\]
em que, \(1_{saida}\) representa o neurônio na camada \({saida}\), camada de saída, \(\hat{y}(t)\) é o valor predito e \(y\) é a resposta real.
Considerando uma única observação, o de “erro global” e ou “erro global instantâneo” da rede, é dado por:
\[E(t) = L(\mathbf{y}, \hat{\mathbf{y}}(t)),\]
em que:
Se a camada de saída contém \(K_{saida}\) neurônios na iteração \(t\), então:
\[E(t) =\dfrac{1}{2} \sum\limits_{k_{saida}=1}^{K_{saida}} e_{k_{saida}}^2(t).\]
em que: \[e_{k_{saida}}^2(t) = \left( y_{k_{saida}} - \hat{y}_{k_{saida}}(t) \right)^2.\]
E para classificação multiclasse, temos:
\[E(t) = - \sum\limits_{k_{saida}=1}^{K_{saida}} \left[ y_{k_{saida}} \log(\hat{y}_{k_{saida}}(t)) + (1 - y_{k_{saida}}) \log(1 - \hat{y}_{k_{saida}}(t)) \right]\]
Quando analisado no contexto de uma amostra de tamanho \(n\), temos que o erro global total é dado por:
\[E_{total}(t) = \dfrac{1}{n}\sum\limits_{i=1}^{n} E_i(t).\]
O erro global total, assim como, o erro global instantâneo \(E_i(t)\) são funções de todos os parâmetros livres (pesos sinápticos e viés) da rede.
Dessa forma, a questão passa a ser em como atribuir uma parcela de culpa, pelo erro global instantâneo, a cada um dos parâmetros, com finalidade de possibilitar o ajuste destes parâmetros em direção a um erro global mínimo.
Vamos seguir os próximos passos com apenas uma observação, ou seja, \(n=1\).


\[E(t) = \dfrac{1}{2} \left(y - \varphi \left( \sum\limits_{k_{saida} = 1}^{K_{saida}} w_{k_{saida}k_d}\varphi \left( \ldots \varphi \left( \sum\limits_{k_l = 1}^{K_l} w_{k_l k_g} \varphi \left(\ldots \varphi \left( \sum\limits_{k_1 = 1}^{K_1} w_{k_{1}k_{2}} x_j \right) \right) \right) \right) \right) \right)^2 \]

Esta equação é composta de somatórios de funções sigmoides aninhados, onde \(y\) representa a saída observada, \(x_j\) representa a observação na \(j\)-ésima variável e \(\varphi\) a função de ativação sigmoide. A representação gráfica teria a forma similar a figura apresentada a seguir:
Representação gráfica para o processo de minimização do erro entre \(E \, \times\, w_{k_l k_g}(t)\).
\[\dfrac{\partial E(t)}{\partial w_{k_l k_g}(t)}.\]
Essa derivada parcial traz informações sobre o peso \(w_{k_l k_g}(t)\):
se o valor da derivada parcial for positivo, significa que: se for aplicada uma correção positiva ao peso sináptico \(w_{k_l k_g}(t)\), ter-se-ia um acréscimo no erro global \(E(t)\), devendo, neste caso, deve ser aplicada uma correção negativa e vice-versa.
Se o valor da derivada parcial for pequeno, estamos próximos a um \(E(t)\) mínimo para \(w_{k_l k_g}\), devendo assim ser aplicada uma correção a \(w_{k_l k_g}\) pequena.
se o valor desta derivada for grande, o valor de \(w_{k_l k_g}\) está distante do valor que resultaria em \(E(t)\) mínimo, portanto seria necessário aplicar uma correção maior para \(w_{k_l k_g}(t)\).
Para corrigir o peso sináptico \(w_{kj}(t)\), utilizamos a regra delta, conforme a equação a seguir:
\[\Delta w_{k_l k_g}(t) = -\eta\dfrac{\partial E(t)}{\partial w_{k_l k_g}(t)},\]
em que \(\eta\) é a taxa de aprendizado.
O processo é repetido até caminhar por todos os pesos e vieses da rede. Em que, após a finalização de uma iteração é dito que foi executado 1 época (epoch).
Entretanto, o cálculo da derivada parcial \(\partial E(t)/\partial w_{k_l k_g}(t)\) para cada um dos pesos não é simples, pois, como já foi visto, \(E(t)\) é uma equação composta de somatórios de funções de ativação (\(\varphi\)) aninhados.
\[E(t) = \dfrac{1}{2} \left(y - \varphi \left( \sum\limits_{k_{saida} = 1}^{K_{saida}} w_{k_{saida}k_d}\varphi \left( \ldots \varphi \left( \sum\limits_{k_l = 1}^{K_l} w_{k_l k_g} \varphi \left(\ldots \varphi \left( \sum\limits_{k_1 = 1}^{K_1} w_{k_{1}k_{2}} x_j \right) \right) \right) \right) \right) \right)^2 \]
Para nosso entendimento, vamos utilizar como base a estrutura abaixo:

Legenda:
O processo é iniciado pela pela última camada em direção à primeira
são calculados gradientes locais em uma camada, e estes serão utilizados no cálculo dos gradientes de erro da camada imediatamente anterior.
O objetivo será sempre determinar a derivada parcial \(\partial E(t)/\partial w_{k_l k_g}(t)\), para aplicar a correção \(\Delta w_{k_l k_g}(t)\) ao peso sináptico \(w_{k_l k_g}(t)\) ou \(\Delta b_{k_g}(t)\) ao viés \(b_{k_g}(t)\).
Como mencionado anteriormente, o processo é iniciado da camada de saída para as demais camadas anteriores, então, aqui vamos considerar a camada \(d\) como sendo a última camada oculta antes da camada de saída, ou seja, \(k_d\) é o neurônio \(k\) da camada \(d\).
De acordo com a regra da cadeia, é possível expressar a derivada parcial como sendo a equação a seguir
\[\begin{equation} \dfrac{\partial E(t)}{\partial w_{k_d k_{saida}}(t)} = \dfrac{\partial E(t)}{\partial e(t)} \dfrac{\partial e(t)}{\partial \hat{y}(t)} \dfrac{\partial \hat{y}(t)}{\partial \nu_{k_{saida}}(t)} \dfrac{\partial \nu_{k_{saida}}(t)}{\partial w_{k_d k_{saida}}(t)}, \label{equacao56} \end{equation}\]
Lembrem-se que \(\hat{y}(t) = \varphi_{k_{saida}}(\nu_{k_{saida}})(t)\).
É importante também definir o gradiente local do neurônio \(k_{saida}\), que é definido por \(\delta_{k_{saida}}(t)\), que é dado pela derivada \(\partial E(t) / \partial \nu_{saida}(t)\), que pode ser escrita como
\[\begin{equation} \delta_{k_{saida}}(t) = \dfrac{\partial E(t)}{\partial \nu_{k_{saida}}(t)} = \dfrac{\partial E(t)}{\partial e(t)} \dfrac{\partial e(t)}{\partial \hat{y}(t)} \dfrac{\partial \hat{y}(t)}{\partial \nu_{k_{saida}}(t)}, \label{equacao57} \end{equation}\]
ou seja, o gradiente é formado pela multiplicação dos três primeiros fatores da função \(\partial E(t) / \partial w_{k_d k_{saida}}(t)\).
Vamos desenvolver cada fator da equação:
\[ \dfrac{\partial E(t)}{\partial w_{k_d k_{saida}}(t)} = \color{red}{\dfrac{\partial E(t)}{\partial e(t)}} \dfrac{\partial e(t)}{\partial \hat{y}(t)} \dfrac{\partial \hat{y}(t)}{\partial \nu_{k_{saida}}(t)} \dfrac{\partial \nu_{k_{saida}}(t)}{\partial w_{k_d k_{saida}}(t)}, \]
Temos
\[E(t)=\dfrac{1}{2} e^2(t),\]
logo,
\[ \color{red}{\dfrac{\partial E(t)}{\partial e(t)} = e(t) = y - \hat{y}(t).} \]
Desenvolvendo o segundo fator
\[ \dfrac{\partial E(t)}{\partial w_{k_d k_{saida}}(t)} = \dfrac{\partial E(t)}{\partial e(t)} \color{blue}{\dfrac{\partial e(t)}{\partial \hat{y}(t)}} \dfrac{\partial \hat{y}(t)}{\partial \nu_{k_{saida}}(t)} \dfrac{\partial \nu_{k_{saida}}(t)}{\partial w_{k_d k_{saida}}(t)}, \]
em que \(\color{red}{e(t) = y - \hat{y}(t)}\), tem-se:
\[\color{blue}{\dfrac{\partial e(t)}{\partial \hat{y}(t)} = -1,}\]
Desenvolvendo o terceiro fator
\[ \dfrac{\partial E(t)}{\partial w_{k_d k_{saida}}(t)} = \dfrac{\partial E(t)}{\partial e(t)} \dfrac{\partial e(t)}{\partial \hat{y}(t)} \color{green}{\dfrac{\partial \hat{y}(t)}{\partial \nu_{k_{saida}}(t)}} \dfrac{\partial \nu_{k_{saida}}(t)}{\partial w_{k_d k_{saida}}(t)}, \]
sendo \(y(t) = \varphi_{k_{saida}}(\nu_{k_{saida}})(t),\) encontra-se
\[\color{green}{\dfrac{\partial \hat{y}(t)}{\partial \nu_{k_{saida}}(t)} = \varphi^\prime_{k_{saida}} (\nu_{k_{saida}})(t).}\]
Se por exemplo, a função de ativação \(\varphi\) for sigmoide \(\left( \varphi_{k_{saida}}(\nu_{k_{saida}}) = \dfrac{1}{1+e^{- \nu_{k_{saida}}}} \right)\), a derivada parcial acima tem a seguinte forma:
\[ \varphi^\prime_{k_{saida}} (\nu_{k_{saida}}) = \dfrac{e^{-\nu_{k_{saida}}}}{(1+e^{-\nu_{k_{saida}}})^2} \]
Dado os resultados anteriores, podemos escrever a equação do gradiente local do neurônio \(k_{saida}\), da seguinte forma:
\[\delta_{k_{saida}}(t) = \dfrac{\partial E(t)}{\partial \nu_{k_{saida}}(t)} = \color{red}{\dfrac{\partial E(t)}{\partial e(t)}} \color{blue}{\dfrac{\partial e(t)}{\partial \hat{y}(t)}} \color{green}{\dfrac{\partial \hat{y}(t)}{\partial \nu_{k_{saida}}(t)}} = \color{blue}{-}\color{red}{e(t)}\color{green}{\varphi^\prime_{k_{saida}}(\nu_{k_{saida}})(t)}.\]
E desenvolvendo o quarto fator
\[ \dfrac{\partial E(t)}{\partial w_{k_d k_{saida}}(t)} = \dfrac{\partial E(t)}{\partial e(t)} \dfrac{\partial e(t)}{\partial \hat{y}(t)} \dfrac{\partial \hat{y}(t)}{\partial \nu_{k_{saida}}(t)} \color{orange}{\dfrac{\partial \nu_{k_{saida}}(t)}{\partial w_{k_d k_{saida}}(t)}}, \]
temos que, para o neurônio \(k_{saida}\) com
\[\nu_{k_{saida}}(t) = \sum\limits_{m = 1}^{K_d} w_{m_d k_{saida}} \varphi_{m_d}(\nu_{m_d})(t) \quad \quad \Longrightarrow \quad \quad \color{orange}{\dfrac{\partial \nu_{k_{saida}}(t)}{\partial w_{k_d k_{saida}}} = \varphi_{k_d}(\nu_{k_d})(t).} \]
Substituindo os fatores desenvolvidos, temos
\[\begin{align} \dfrac{\partial E(t)}{\partial w_{k_d k_{saida}}(t)} & = \color{red}{\dfrac{\partial E(t)}{\partial e(t)}} \color{blue}{\dfrac{\partial e(t)}{\partial \hat{y}(t)}} \color{green}{\dfrac{\partial \hat{y}(t)}{\partial \nu_{k_{saida}}(t)}} \color{orange}{\dfrac{\partial \nu_{k_{saida}}(t)}{\partial w_{k_d k_{saida}}(t)}} \\ & = \color{blue}{-}\color{red}{e(t)}\color{green}{\varphi^\prime_{k_{saida}}(\nu_{k_{saida}}(t))}\color{orange}{\varphi_{k_d}(\nu_{k_d})(t)} = \delta_{k_{saida}}(t)\color{orange}{\varphi_{k_d}(\nu_{k_d})(t)}. \end{align}\]
Com os resultados anteriores, é possível aplicar a correção a todos os pesos sinápticos e viés dos neurônios.
A correção se dará pela aplicação da regra delta dada por
\[ \Delta w_{k_d k_{saida}}(t) = -\eta \dfrac{\partial E(t)}{\partial w_{k_d k_{saida}}(t)} = -\eta \delta_{k_{saida}}(t)\varphi_{k_d}(\nu_{k_d})(t) \]
em que \(\eta\) é um hiperparâmetro que define a taxa de aprendizado e geralmente é previamente definido pelo usuário.
Assim, temos que
\[w_{k_d k_{saida}}(t) = w_{k_d k_{saida}}(t-1) + \Delta w_{k_d k_{saida}}(t)\]
A taxa de aprendizagem \(\eta\) é responsável pela velocidade com que se dá a busca no espaço de pesos, em direção aos valores que resultam em um erro global mínimo.
Quanto menor for a taxa de aprendizagem, mais suave e precisa será a trajetória através do espaços de pesos, entretanto o aprendizado será lento.
Vamos agora considerar que temos uma camada \(g\) antecedendo a camada \(d\). Então a derivada parcial para um peso \(w_{k_g k_d}(t)\) pode ser obtido como:
\[\begin{equation} \dfrac{\partial E(t)}{\partial w_{k_g k_d}(t)} = \dfrac{\partial E(t)}{\partial e(t)} \dfrac{\partial e(t)}{\partial \hat{y}(t)} \dfrac{\partial \hat{y}(t)}{\partial \nu_{k_{saida}}(t)} \dfrac{\partial \nu_{k_{saida}}(t)}{\partial \varphi_{k_d}(\nu_{k_d})(t)} \dfrac{\partial \varphi_{k_d}(\nu_{k_d})(t)}{\partial \nu_{k_d}(t)} \dfrac{\partial \nu_{k_d}(t)}{\partial w_{k_g k_d}(t)}, \label{equacao59} \end{equation}\]
entretanto, os três primeiros fatores já foram desenvolvidos anteriormente e correspondem ao gradiente local do neurônio \(k_{saida}\), ou seja, \[\begin{equation} \delta_{k_{saida}}(t) = \dfrac{\partial E(t)}{\partial e(t)} \dfrac{\partial e(t)}{\partial \hat{y}(t)} \dfrac{\partial \hat{y}(t)}{\partial \nu_{k_{saida}}(t)}, \label{equacao60} \end{equation}\]
sendo \(\dfrac{\partial \nu_{k_{saida}}(t)}{\partial \varphi_{k_d}(\nu_{k_d})(t)} = w_{k_d k_{saida}}\), e considerando que a camada de saída pode ser composta por mais de um neurônio, temos que:
\[\begin{equation} \delta_{k_{d}}(t) = \varphi^\prime _{k_d}(\nu_{k_d})(t) \sum\limits_{m=1}^{K_{saida}} \delta_{m_{saida}}(t) w_{k_d m_{saida}}(t). \label{equacao62} \end{equation}\]
em que \(\varphi^\prime _{k_d}(\nu_{k_d})(t) = \dfrac{\partial \varphi_{k_d}(\nu_{k_d})(t)}{\partial \nu_{k_d}(t)}\). Sendo assim, podemos reescrever a equação anterior como:
\[\begin{equation} \dfrac{\partial E(t)}{\partial w_{k_g k_d}(t)} = \delta_{k_{d}}(t) \varphi_{k_g}(\nu_{k_g})(t), \label{equacao61} \end{equation}\]
com \(\varphi_{k_g}(\nu_{k_g})(t) = \dfrac{\partial \nu_{k_d}(t)}{\partial w_{k_g k_d}(t)}\). Novamente, a correção neste caso é dado por
\[ \Delta w_{k_g k_{d}} = -\eta \dfrac{\partial E(t)}{\partial w_{k_g k_{d}}(t)} = -\eta \delta_{k_{d}}(t) \varphi_{k_g}(\nu_{k_g})(t) \]
Em resumo, o processo backpropagation pode ser descrito em cinco etapas, conforme apresentadas a seguir:
Inicialização: valores são inicializados aleatoriamente aos pesos sinápticos e viés*, geralmente com uma distribuição uniforme, cuja média deverá ser zero.
Propagação dos sinais: aplica-se a camada da rede os dados de entrada \(\mathbf{X}_{n \times p}\) e calcula os valores preditos \(\hat{\mathbf{y}}_{n \times 1}(t)\).
Considerando 1 observação de entrada, com \(p\) variáveis.
Em seguida, calcula-se o erro \(e(t)\) pela comparação de \(\hat{y}(t)\) com valor real \(y\).
backpropagation: calculam-se os gradientes locais: \[\delta_{k_{saida}}(t) = -e(t)\varphi'_{k_{saida}}(\nu_{k_{saida}}(t))\]
Em seguida, calculam-se os ajustes para os pesos daquela camada, bem como dos viés, os quais devem ser somados aos valores atuais: \[ \Delta w_{k_d k_{saida}} = \eta e(t)\varphi'_{k_{saida}}(\nu_{k_{saida}}(t))\varphi_{k_d}(\nu_{k_d})(t) = \eta \delta_{k_{saida}}(t)\varphi_{k_d}(\nu_{k_d})(t)\] \[ \Delta b_{k_{saida}} = -\eta e(t)\varphi'_{k_{saida}}(\nu_{k_{saida}}(t)) = -\eta \delta_{k_{saida}}(t)\]
O próximo passo é o cálculo do gradiente local para os neurônios da penúltima camada \(g\) antecedente a \(d\) (camada oculta): \[\delta_{k_d}(t) = \varphi'_{k_d}(\nu_{k_d}(t))\sum\limits_{m=1}^{K_{saida}}(\delta_{m_{saida}}(t)w_{k_d m_{saida}}(t)).\]
Então, calcula-se o ajuste para todos os pesos que chegam nessa camada de uma camada anterior \(g\) desta camada \(d\), bem como dos viés. \[\Delta w_{k_g k_d} = -\eta \varphi'_{k_d}(\nu_{k_d}(t)) \varphi_{k_g}(\nu_{k_g}(t)) \sum\limits_{m=1}^{K_{saida}}(\delta_{m_{saida}}(t)w_{k_d m_{saida}}(t)) = -\eta \delta_{k_d}(t) \varphi_{k_g}(\nu_{k_g}(t))\] \[\Delta b_{k_g} = -\eta \varphi'_{k_d}(\nu_{k_d}(t)) \sum\limits_{m=1}^{K_{saida}}(\delta_{m_{saida}}(t)w_{k_d m_{saida}}(t)) = -\eta \delta_{k_g}(t)\]
O processo prossegue de forma idêntica para as demais camadas ocultas, assim como para a camada de entrada, em que os valores dos ajustes na primeira camada oculta (após a entrada da rede) deve ter o valor \(\varphi_{k_g}(\nu_{k_g}(t))\) substituído pelo valor de \(x_p\).
Tomando como base estes passos, é possível obter uma rede MLP.
Vamos fazer um exemplo.

Vamos usar como função de ativação a função sigmoide: \(\varphi(\nu) = \dfrac{1}{1 + e^{-\nu}}\) e os seguintes valores iniciais.

Valores de \(\mathbf{x} = [1 \quad 1]\), \(y = 0\), \(\eta = 0.8\), os seguintes pesos e vieses iniciais:
Essa primeira iteração é a \(t=0\), vamos ocultar o índice \(t\) para facilitar a notação.
Primeiramente, vamos calcular a primeira iteração da rede, ou seja, o valor predito \(\hat{y}\). As ativações dos neurônios da camada oculta 2:
os resultados das funções de ativação são dadas por:
Assim, para a próxima camada, temos:
Então,
Lembrando que nosso valor real é \(y = 0\), então o erro nessa iteração \(t=0\) é dado por:
\[e = y - \hat{y} = 0 - 0.53 = -0.53\]
Vamos iniciar o processo de backpropagation.
Vamos ajustar o peso \(w_{{1_2}{1_{saida}}}\).
Primeiramente, calculamos o gradiente local do neurônio da camada de saída:
\[\dfrac{\partial E}{\partial w_{{1_2}{1_{saida}}}} = \dfrac{\partial E}{\partial e} \dfrac{\partial e}{\partial \varphi(\nu_{1_{saida}})} \dfrac{\partial \varphi(\nu_{1_{saida}})}{\partial \nu_{1_{saida}}} \dfrac{\partial \nu_{1_{saida}}}{\partial w_{1_2 1_{saida}}},\]
que pode ser escrito como:
\[\dfrac{\partial E}{\partial w_{{1_2}{1_{saida}}}} = \delta_{1_{saida}} \varphi (\nu_{1_2}) = -e\varphi^\prime (\nu_{1_{saida}})\varphi (\nu_{1_{2}}),\]
temos que \(e= 0-0.53 = -0.53\) e \(\varphi (\nu_{1_2}) \approx 0.86\), então
\[\varphi^\prime (\nu_{1_{saida}}) = \dfrac{exp(-\nu_{1_{saida}})}{(1 + exp(-\nu_{1_{saida}}))^2} = \dfrac{exp(-0.14)}{(1+exp(-0.14))^2} \approx 0.25\]
Assim, temos um valor de \(\delta_{1_{saida}}\):
\[\delta_{1_{saida}} = -(-0.53)*0.25 \approx 0.13\]
e, portanto,
\[\dfrac{\partial E}{\partial w_{{1_2}{1_{saida}}}} = 0.13*0.86 \approx 0.11,\]
e assim
\[w_{{1_2}{1_{saida}}}(1) = w_{{1_2}{1_{saida}}}(0) + \Delta w_{{1_2}{1_{saida}}} = 0.7 - 0.8*(0.11) \approx 0.61.\]
Vamos ajustar agora o peso \(w_{{2_2}{1_{saida}}}\). Utilizando o mesmo procedimento, temos:
\[\dfrac{\partial E}{\partial w_{{2_2}{1_{saida}}}} = \delta_{1_{saida}} \varphi (\nu_{2_2})\]
logo, com \(\varphi (\nu_{2_2}) \approx 0.20\) e \(\delta_{1_{saida}} \approx 0.13\), temos:
\[\dfrac{\partial E}{\partial w_{{2_2}{1_{saida}}}} = 0.13*0.20 \approx 0.03,\]
e assim
\[w_{{2_2}{1_{saida}}}(1) = w_{{2_2}{1_{saida}}}(0) + \Delta w_{{2_2}{1_{saida}}} = -0.8 - 0.8*(0.03) \approx -0.82.\]
Ajustando o viés \(b_{1_{saida}}\):
\[\dfrac{\partial E}{\partial b_{1_{saida}}} = \delta_{1_{saida}},\]
pois \(\dfrac{\partial \nu_{1_{saida}}}{\partial b_{1_{saida}}} = 1,\) então
\[\dfrac{\partial E}{\partial b_{1_{saida}}} = 0.13,\]
e
\[b_{1_{saida}}(1) = b_{1_{saida}}(0) + \Delta b_{1_{saida}} = -0.3 - 0.8*(0.13) \approx -0.40.\]
Com os valores dos pesos e vieses que estão atualizados, vamos atualizar os pesos da camada anterior. Primeiramente, vamos atualizar o peso \(w_{{1_1}{1_2}}\), que neste caso é
\[\dfrac{\partial E}{\partial w_{{1_1}{1_2}}} = \delta_{1_2} x_1,\]
temos o valor de \(x_1 = 1\), então precisamos calcular o valor de \(\delta_{1_2}\). Então,
\[\delta_{1_2} = \varphi'(\nu_{1_2}) \sum\limits_{m=1}^{K_{saida}}(\delta_{m_{saida}} w_{1_2 m_{saida}}),\]
como em nosso exercício, \(K_{saida} = 1\), temos:
\[\delta_{1_2} = \varphi'(\nu_{1_2}) (\delta_{1_{saida}} w_{1_2 1_{saida}}).\]
Logo,
\[\varphi'(\nu_{1_2}) = \dfrac{exp(-\nu_{1_2})}{(1 + exp(-\nu_{1_2}))^2} = \dfrac{exp(-1.8)}{(1 + exp(-1.8))^2} \approx 0.12,\]
assim,
\[\delta_{1_2} = 0.12*(0.13*0.61) \approx 0.01,\]
e portanto,
\[\dfrac{\partial E}{\partial w_{{1_1}{1_2}}} = 0.01*1 = 0.01,\]
assim,
\[w_{{1_1}{1_2}}(1) = w_{{1_1}{1_2}}(0) + \Delta w_{{1_1}{1_2}} = 0.8 - 0.8*(0.01) \approx 0.79.\]
Agora, vamos ajustar o peso \(w_{{2_1}{1_2}}\), assim
\[\dfrac{\partial E}{\partial w_{{2_1}{1_2}}} = \delta_{1_2} x_2,\]
dos resultados anteriores, temos que \(x_2 = 1\) e \(\delta_{1_2} \approx 0.01\), logo
\[\dfrac{\partial E}{\partial w_{{2_1}{1_2}}} = 0.01*1 = 0.01,\]
porque o valor de \(x_2 = 1\). Assim,
\[w_{{2_1}{1_2}}(1) = w_{{2_1}{1_2}}(0) + \Delta w_{{2_1}{1_2}} = 0.3 - 0.8*(0.01) \approx 0.29.\]
Agora vamos ajustar o peso \(w_{{1_1}{2_2}}\), que é dado por
\[\dfrac{\partial E}{\partial w_{{1_1}{2_2}}} = \delta_{2_2} x_1,\]
precisamos encontrar o valor de \(\delta_{2_2}\), que é dado por
\[\delta_{2_2} = \varphi'(\nu_{2_2}) (\delta_{1_{saida}} w_{2_2 1_{saida}})\]
então,
\[\delta_{2_2}= \dfrac{exp(-(-1.4))}{(1 + exp(-(-1.4)))^2} \left( 0.13*(-0.82) \right) \approx -0.02,\]
Assim, temos que
\[\dfrac{\partial E}{\partial w_{{1_1}{2_2}}} = -0.02*1 = -0.02,\]
então, o valor do peso atualizado é
\[w_{{1_1}{2_2}}(1) = w_{{1_1}{2_2}}(0) + \Delta w_{{1_1}{2_2}} = -0.6 + 0.8*(0.02) \approx -0.58.\]
Para atualizar o peso \(w_{{2_1}{2_2}}\), temos:
\[\dfrac{\partial E}{\partial w_{{2_1}{2_2}}} = \delta_{2_2} x_2,\]
assim,
\[\dfrac{\partial E}{\partial w_{{2_1}{2_2}}} = -0.02*1 = -0.02,\]
logo,
\[w_{{2_1}{2_2}}(1) = w_{{2_1}{2_2}}(0) + \Delta w_{{2_1}{2_2}} = -0.4 + 0.8*(0.02) \approx -0.38.\]
Vamos agora atualizar os vieses \(b_{1_2}\) e \(b_{2_2}\). Para atualizar o viés \(b_{1_2}\), temos:
\[\dfrac{\partial E}{\partial b_{1_2}} = \delta_{1_2},\]
logo,
\[\dfrac{\partial E}{\partial b_{1_2}} = 0.01,\]
e assim,
\[b_{1_2}(1) = b_{1_2}(0) + \Delta b_{1_2} = 0.7 - 0.8*(0.01) \approx 0.69.\]
Para atualizar o viés \(b_{2_2}\), temos:
\[\dfrac{\partial E}{\partial b_{2_2}} = \delta_{2_2},\]
logo,
\[\dfrac{\partial E}{\partial b_{2_2}} = -0.02,\]
e assim,
\[b_{2_2}(1) = b_{2_2}(0) + \Delta b_{2_2} = -0.4 + 0.8*(0.02) \approx -0.38.\]
Com todos os valores atualizados, podemos fazer uma nova iteração \(t=1\) da rede.
Primeiramente, calculamos as ativações dos neurônios da camada oculta 2:
\(\nu_{1_2} = w_{{1_1}{1_2}}(1) x_1 + w_{{2_1}{1_2}}(1) x_2 + b_{1_2}(1) \approx 0.79*1 + 0.29*1 + 0.69 \approx 1.77\)
\(\nu_{2_2} = w_{{1_1}{2_2}}(1) x_1 + w_{{2_1}{2_2}}(1) x_2 + b_{2_2}(1) \approx -0.58*1 + -0.38*1 - 0.38 \approx -1.34\)
os resultados das funções de ativação são dadas por:
\(\varphi_{1_2}(\nu_{1_2}) = \dfrac{1}{1 + e^{-1.77}} \approx 0.85\)
\(\varphi_{2_2}(\nu_{2_2}) = \dfrac{1}{1 + e^{1.34}} \approx 0.21\)
E assim,
\[\nu_{1_{saida}} = w_{{1_2}{1_{saida}}}(1) \varphi_{1_2}(\nu_{1_2}) + w_{{2_2}{1_{saida}}}(1) \varphi_{2_2}(\nu_{2_2}) + b_{1_{saida}}(1) \\ \quad\quad\, \approx 0.61*0.85 + (-0.82)*0.21 - 0.40 \approx -0.05\]
e
\[\hat{y} = \varphi_{1_{saida}}(\nu_{1_{saida}}) = \dfrac{1}{1 + e^{-(-0.05)}} \approx 0.49\]
Assim, temos que o erro nessa iteração foi \[e = y - \hat{y} = 0 - 0.49 = -0.49\]
Que foi menor que o erro da iteração anterior, que era \(-0.53\).
BRAGA, A. P.; CARVALHO, A.; LUDEMIR, T. Redes Neurais Artificiais: Teoria e Aplicações. .: [s.n.], 2000.
HOPFWELD, J. J. Neural networks and physical systems with emergent collective computational abilities. Proc. NatL Acad. Sci., v. 79, p. 2554–2558, 1982.
LUDWIG, O.; MONTGOMERY, E. Redes Neurais - Fundamentos e Aplicações com Programas em C. .: Ciência Moderna, 2007.
MINSKY, M.; PAPERT, S. Perceptrons: an introduction to computationational geometry. [S.l.]: MIT Press, 1969.
PINHEIRO, C. A. R. Inteligência Analítica: Mineração de Dados e Descoberta de Conhecimento. .: [s.n.], 2008.
RICH, E.; KNIGHT, K. Inteligência Artificial. .: [s.n.], 1993.
ROSENBLATT, F. Principles of Neurodynamics: Perceptrons and Theory of Brain Mechanisms. .: Washigton, DC, 1962.
https://acervolima.com/funcoes-de-ativacao/
OBRIGADO!
Slide produzido com quarto
Tópicos Especiais em Estatística Comp. - Prof. Jodavid Ferreira