Combinando os neurônios artificias em uma ou mais camadas, que podem conter um ou mais neurônios e interligando estes neurônios através das sinapses, pode-se formar uma RNA (Rede Neural Artificial). Dentre as vantagens das redes neurais, estão sua adaptação por experiência, tolerância a falhas, aplicações em tempo real, capacidade de aprendizado e de resolver problemas práticos sem a necessidade da definição de listas de regras ou de modelos precisos.
O primeiro trabalho sobre Redes Neurais Artificiais foi realizado por McCullock e Pitts em 1943, com o objetivo de modelar matematicamente o comportamento de um neurônio biológico. Dentre as conclusões desse estudo, está que o neurônio estará no estado ativado (transmitindo informações a outros neurônios) se a sua saída ultrapassar um valor limite; caso contrário, ficará no estado de repouso (este princípio originou a função limiar). Outra conclusão é que cada entrada do neurônio terá um valor associado (daí veio o conceito de pesos para cada sinal de entrada); caso este seja positivo, tenderá a excitar a célula; e caso ele seja negativo, tenderá a inibir.
Em 1949, veio o primeiro método de treinamento para rede, proposto por Donald Hebb. O primeiro modelo de rede neural implementado foi o perceptron, por Frank Rosenblatt em 1958. Ele é formado de uma camada de entrada e uma camada de saída. A cada entrada existe um peso relacionado, sendo que o valor de saída será a soma dos produtos de cada entrada pelo seu respectivo peso. Veja mais sobre a estrutura do perceptron clicando no link.
Em 1972, Teuvo Kohonen definiu o “mapa auto-organizável de características”: os valores das entradas, dos pesos e das saídas poderiam ser contínuos, não existe apenas um neurônio responsável pela representação do padrão de entrada, e sim um conjunto de neurônios que interagem entre si, além do o aprendizado não-supervisionado, segundo o qual a rede não precisa ficar sendo comparada constantemente a um valor de saída durante a fase de aprendizado.
Arquitetura das redes neurais
Em 1982, John Hopfield cria um modelo do tipo feedback, isto é, há uma conexão das entradas com as saídas. Isso pode se comparar a um modelo físico, no qual a energia da rede diminui a cada troca de estado, de modo que a fase de aprendizado chega ao fim quando a rede tiver a sua energia minimizada. Em 1986, Rumelhart, Hinton e Willams apresentaram um algoritmo que permitia ajustar os pesos em uma rede com mais de uma camada, denominado backpropagation. Foi criado a partir da generalização da regra de aprendizado “Widrow-Hoff” (também conhecida como “regra Delta”), que fora introduzida por Bernard Widrow e Marcian Hoff em 1960-1962 para redes do tipo feedfoward perceptron.
As redes de múltiplas camadas são caracterizadas pela presença de pelo menos uma camada intermediaria (oculta) de neurônios, situada entre a camada de entrada e a respectiva camada neural de saída. Por exemplo, o perceptron de múltiplas camadas diferencia-se do perceptron simples por conter as camadas escondidas, sua camada de saída pode ser composta por diversos neurônios e o conhecimento relacionado ao comportamento entrada/saída do sistema é distribuído por todos os neurônios – no perceptron simples, um único neurônio era responsável pelo mapeamento integral de todo o processo. Redes de apenas uma camada só representam funções linearmente separáveis enquanto redes de múltiplas camadas solucionam essa restrição.
Na estrutura unidirecional (feedforward), todas as saídas dos neurônios de uma camada são conectadas com todos os neurônios da camada posterior obedecendo à direção entrada => saída, sem conexões entre neurônios de uma mesma camada.
Já na estrutura realimentada, cada camada pode conter conexões entre os elementos de processamento da mesma camada (estímulos laterais), das camadas anteriores e das camadas posteriores – um neurônio pode ser retroalimentado pela sua saída direta ou indiretamente.
Operação de uma rede neural
A 1ª etapa é o treinamento, na qual ocorre o ajuste dos parâmetros do modelo (geralmente ajuste dos pesos). Ele pode ocorrer das seguintes formas:
- Treinamento supervisionado: um conjunto de pares “entrada-saída” é utilizado de modo que, se os cálculos efetuados com o padrão de entrada e os respectivos pesos resultarem no padrão de saída informado dentro de uma faixa considerada satisfatória, o aprendizado está completo (caso contrário, os pesos são reajustados para reduzir o erro e é reiniciado o treinamento).
- Treinamento não-supervisionado (ou auto-supervisionado): os neurônios usam somente valores de entrada, tentando classificá-los mediante algum critério de semelhança.
A aprendizagem em si (ajustes nos vetores de pesos das redes e em seus limiares) pode ser realizada de duas formas:
- Aprendizagem usando lote de padrões (off-line): ajustes são efetivados somente após a apresentação de todo o conjunto de treinamento, pois cada passo de ajuste leva em consideração o total de desvios observados nas amostras de treinamento frente aos respectivos valores desejados para as suas saídas.
- Aprendizagem usando lote de padrão-por-padrão (on-line): ajustes são feitos após a apresentação de cada amostra de treinamento (depois, a respectiva amostra pode ser descartada).
No processo de treinamento de redes perceptron de múltiplas camadas, é aplicado o algoritmo de aprendizado de retropropagação do erro (ou “backpropagation”), conhecido também como regra Delta generalizada. A regra Delta ajusta iterativamente dos pesos da rede para minimizar as diferenças entre a saída atual e a saída desejada.
Esse ajuste é calculado através da minimização do erro quadrático pelo método do gradiente descendente: cada peso sináptico i do neurônio j é atualizado proporcionalmente ao negativo da derivada parcial do erro deste neurônio com relação ao peso, multiplicado pela taxa de aprendizagem. Assim, temos que o ajuste do peso (Δwij) é o produto entre a taxa de aprendizagem (η), o valor de entrada recebido pela conexão (xi) e o valor calculado do erro do neurônio (ej). No aprendizado supervisionado, só se conhece o erro na camada de saída, então o neurônio j pertencente à camada de saída, e o erro é dado pela diferença entre o valor desejável e a saída do modelo.
Na sequência, o vetor de saída produzido pela rede é comparado com o vetor desejado resultando num sinal de erro que é retropropagado através da rede para permitir o ajuste dos pesos.
A 2ª etapa é o teste, através da validação dos parâmetros do modelo. Por fim, segue a produção, com a utilização do modelo.
Exemplo – XOR
É comum a utilização da conjunção “OU” para indicar que uma condição será verdadeira (igual a 1) se a condição A ou a condição B for verdadeira. Portanto, as condições {A=1,B=1}, {A=0,B=1} e {A=1,B=0} satisfazem a proposição (A+B=1). Isso é chamado de Disjunção Inclusiva.
Já a Disjunção Exclusiva (ou XOR) é caracterizada pelo termo “OU…OU”, sendo verdadeira quando ambas são diferentes. Portanto, as condições {A=1,B=1} e {A=0,B=0} satisfazem a proposição (A#B=1) e as condições {A=1,B=0} e {A=0,B=1} não. Veja como fica a tabela-verdade:
A | B | A#B |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
Implementação em Python
O PyBrain (acrônimo para Python-Based Reinforcement Learning, Artificial Intelligence and Neural Networks) é um biblioteca do Python com vários módulos úteis para programação de redes neurais. Para instalá-lo, basta usar o comando “sudo pip install pybrain” (python versão menor que a 3).
A função “buildNetwork()” recebe como argumentos o tamanho da camada de entrada (dataset.indim, de input dimensions), a quantidade de camadas intermediárias (4 no caso), o tamanho da camada de saída (dataset.outdim) e a utilização ou não de bias.
A função “BackpropTrainer()” é o algoritmo de backpropagation. Recebe como argumentos a rede construída no passo anterior, o conjunto de dados, a taxa de aprendizado (learningrate) e o momentum. A taxa de aprendizado controla a intensidade da variação dos pesos e o momentum tem como objetivo aumentar a velocidade de treinamento da rede neural e diminuir o perigo da instabilidade (por exemplo, o algoritmo começa a convergir para um ponto que pensa ser um mínimo global, mas na verdade está em um mńimo local).
Com relação ao treino, o loop pode ser substituído por “trainer.trainUntilConvergence()” para realizar o treinamento até obter uma convergência.
#!/usr/bin/python # -*- coding: utf-8 -*- from pybrain.datasets import SupervisedDataSet from pybrain.tools.shortcuts import buildNetwork from pybrain.supervised import BackpropTrainer # Passar as dimensões dos vetores de entrada e do objetivo dataset = SupervisedDataSet(2, 1) # Inserir amostras de entrada e do objetivo (tabela-verdade) dataset.addSample([1,1], [0]) dataset.addSample([1,0], [1]) dataset.addSample([0,1], [1]) dataset.addSample([0,0], [0]) # Construir rede neural network = buildNetwork(dataset.indim, 4, dataset.outdim, bias=True) # Definir aprendizado trainer = BackpropTrainer(network, dataset, learningrate=0.01, momentum=0.99) # Treinar por 1000 épocas for epoch in range(1000): trainer.train() # Testar a rede com um conjunto de dados (igual ao original) test_data = SupervisedDataSet(2, 1) test_data.addSample([1,1], [0]) test_data.addSample([1,0], [1]) test_data.addSample([0,1], [1]) test_data.addSample([0,0], [0]) trainer.testOnData(test_data, verbose=True)
Para testar, foi inserida um novo conjunto de dados (no caso, foi utilizada a tabela-verdade XOR novamente). Ao executar o script (python script.py), após alguns segundos deve aparecer a saída calculada (out) e a esperada (correct), assim como o cálculo do erro, para cada saída inserida; no final, uma estatística dos erros será calculada e impressa também.
Fontes
- Curso Machine Learning e Data Science com Python – Marcos Castro & Gileno Alves Santa Cruz Filho
- Introdução Às Redes Neurais Artificiais – André Cardon & Daniel Nehme Müller (UFRGS, 1994)
- Soluções de Equações Diferenciais Usando Redes Neurais de Múltiplas camadas com os métodos da Descida mais íngreme e Levenberg-Marquardt – Brigida Cristina Fernandes Batista (UFPA, 2012)
- Ferramentas de Python para aprendizado de máquina – Alexandre Volpi
4 comments