Tradução de como criar uma rede neural simplesO que vamos fazer? Vamos tentar criar uma rede neural simples e muito pequena, que
explicaremos e
ensinaremos a distinguir algo. Ao mesmo tempo, não entraremos na história e na selva matemática (é muito fácil encontrar essa informação) - em vez disso, tentaremos explicar o problema (não o fato de que será possível) para você e para nós mesmos com desenhos e código.
Muitos dos termos em redes neurais estão relacionados à biologia, então vamos começar do começo:

O cérebro é uma coisa complicada, mas também pode ser dividido em várias partes e operações principais:

O agente causador também pode ser
interno (por exemplo, uma imagem ou uma idéia):

Agora, vamos dar uma olhada nas
partes básicas e simplificadas
do cérebro:
O cérebro geralmente se parece com uma rede a cabo.Um neurônio é a principal unidade de cálculo no cérebro, recebe e processa os sinais químicos de outros neurônios e, dependendo de vários fatores, não faz nada ou gera um impulso elétrico, ou Potencial de Ação, que envia sinais aos neurônios
conectados através de sinapses:

Sonhos, memórias, movimentos auto-reguladores, reflexos e tudo o que você pensa ou faz é tudo devido a esse processo: milhões ou bilhões de neurônios trabalham em níveis diferentes e criam conexões que criam subsistemas paralelos diferentes e representam uma
rede neural biológica .
Obviamente, essas são todas simplificações e generalizações, mas, graças a elas, podemos descrever uma simples
rede neural:

E descreva-o formalmente usando o gráfico:

Alguns esclarecimentos são necessários aqui. Círculos são neurônios e linhas são conexões entre eles,
e, para não complicar nesta fase, o
relacionamento é um movimento direto de informações
da esquerda para a direita . O primeiro neurônio está atualmente ativo e acinzentado. Também lhe atribuímos um número (1 - se funcionar, 0 - se não). Os números entre os neurônios indicam o
peso da conexão.
Os gráficos acima mostram o momento da rede, para uma exibição mais precisa, é necessário dividi-lo em períodos:
Para criar sua própria rede neural, você precisa entender como os pesos afetam os neurônios e como eles são treinados. Como exemplo, pegue um coelho (coelho de teste) e coloque-o nas condições de um experimento clássico.

Quando um fluxo de ar seguro é direcionado a eles, os coelhos, como as pessoas, piscam:

Este modelo de comportamento pode ser representado graficamente:

Como no diagrama anterior, esses gráficos mostram apenas o momento em que o coelho respira e, dessa forma,
codificamos o golpe como um valor lógico. Além disso, calculamos se o segundo neurônio é acionado com base no valor do peso. Se for 1, então o neurônio sensorial é acionado, piscaremos; se o peso for menor que 1, não piscaremos: o segundo neurônio tem um
limite de 1.
Introduzimos mais um elemento - um sinal sonoro seguro:

Podemos modelar o interesse de um coelho da seguinte maneira:

A principal diferença é que agora o peso é
zero , então não recebemos um coelho piscando, bem, por enquanto, pelo menos. Agora ensine o coelho a piscar no time, misturando
irritantes (sinal sonoro e respiração):

É importante que esses eventos ocorram em diferentes
períodos de tempo; em gráficos, será assim:

O som em si não faz nada, mas o fluxo de ar ainda faz o coelho piscar, e mostramos isso através de pesos multiplicados pelos estímulos (vermelho).
Aprender sobre comportamento complexo pode ser expresso de forma simplista como uma mudança gradual de peso entre os neurônios conectados ao longo do tempo.
Para treinar o coelho, repita as etapas:

Nas três primeiras tentativas, os esquemas terão esta aparência:

Observe que o peso do estímulo sonoro aumenta após cada repetição (destacada em vermelho), esse valor agora é arbitrário - escolhemos 0,30, mas o número pode ser qualquer coisa, até negativo. Após a terceira repetição, você não notará uma mudança no comportamento do coelho, mas após a quarta repetição algo surpreendente acontecerá - o comportamento mudará.

Removemos o efeito do ar, mas o coelho ainda está piscando quando ouviu um sinal sonoro! Esse último comportamento pode explicar esse comportamento:

Treinamos o coelho para responder ao som piscando.
Em um experimento real desse tipo, podem ser necessárias mais de 60 repetições para obter um resultado.Agora vamos deixar o mundo biológico do cérebro e dos coelhos e tentar adaptar tudo o que
aprendeu a criar uma rede neural artificial. Primeiro, vamos tentar fazer uma tarefa simples.
Digamos que temos uma máquina com quatro botões que fornece comida quando você pressiona o botão direito
botões (bem, ou energia, se você é um robô). A tarefa é descobrir qual botão dá a recompensa:

Podemos descrever (esquematicamente) o que o botão faz quando clicado da seguinte maneira:

Esse problema é melhor resolvido na íntegra, então vamos examinar todos os resultados possíveis, incluindo o correto:
Pressione o terceiro botão para jantar.Para reproduzir uma rede neural no código, primeiro precisamos criar um modelo ou gráfico ao qual a rede possa ser associada. Aqui está um gráfico adequado para a tarefa, além disso, ele exibe bem sua contrapartida biológica:

Essa rede neural apenas recebe informações recebidas - nesse caso, será a percepção de qual botão foi pressionado. Além disso, a rede substitui as informações recebidas por pesos e conclui com base na adição de uma camada. Parece um pouco confuso, mas vamos ver como o botão é apresentado em nosso modelo:
Observe que todos os pesos são 0, portanto a rede neural, como uma criança, está completamente vazia, mas completamente interconectada.Assim, comparamos o evento externo com a camada de entrada da rede neural e calculamos o valor em sua saída. Pode ou não coincidir com a realidade, mas por enquanto a ignoraremos e começaremos a descrever a tarefa de maneira amigável ao computador. Vamos começar inserindo pesos (usaremos JavaScript):
var inputs = [0,1,0,0]; var weights = [0,0,0,0];
A próxima etapa é criar uma função que coleta valores e pesos de entrada e calcula o valor na saída:
function evaluateNeuralNetwork(inputVector, weightVector){ var result = 0; inputVector.forEach(function(inputValue, weightIndex) { layerValue = inputValue*weightVector[weightIndex]; result += layerValue; }); return (result.toFixed(2)); }
Como esperado, se executarmos esse código, obteremos o mesmo resultado que em nosso modelo ou gráfico ...
evaluateNeuralNetwork(inputs, weights);
Exemplo ao vivo:
Rede Neural 001 .
O próximo passo para melhorar nossa rede neural será uma maneira de verificar sua própria produção ou valores de resultados comparáveis à situação real,
vamos primeiro codificar essa realidade específica em uma variável:

Para detectar inconsistências (e quantas), adicionamos uma função de erro:
Error = Reality - Neural Net Output
Com ele, podemos avaliar o desempenho de nossa rede neural:

Mais importante, porém, e as situações em que a realidade dá um resultado positivo?

Agora sabemos que nosso modelo de rede neural não funciona (e sabemos quanto), ótimo! Isso é ótimo, porque agora podemos usar a função de erro para controlar nosso aprendizado. Mas tudo isso fará sentido se redefinirmos a função de erro da seguinte maneira:
Error = <b>Desired Output</b> - Neural Net Output
Uma discrepância indescritível, mas tão importante, mostrando tacitamente que
use resultados obtidos anteriormente para comparar com ações futuras
(e para treinamento, como veremos mais adiante). Existe na vida real, cheio de
repetir padrões, para que se torne uma estratégia evolutiva (bem, em
maioria dos casos).
Em seguida, em nosso código de exemplo, adicionaremos uma nova variável:
var input = [0,0,1,0]; var weights = [0,0,0,0]; var desiredResult = 1;
E um novo recurso:
function evaluateNeuralNetError(desired,actual) { return (desired — actual); }
Exemplo ao vivo:
Rede Neural 002 .
Para resumir o subtotal . Começamos com a tarefa, fizemos seu modelo simples na forma de uma rede neural biológica e conseguimos uma maneira de medir seu desempenho em comparação com a realidade ou o resultado desejado. Agora precisamos encontrar uma maneira de corrigir a discrepância - um processo que pode ser considerado como um treinamento para computadores e pessoas.
Como treinar uma rede neural?A base do ensino de redes neurais biológicas e artificiais é a repetição
e
algoritmos de treinamento , portanto, trabalharemos com eles separadamente. Comece com
algoritmos de aprendizagem.
Na natureza, os algoritmos de aprendizado são entendidos como mudanças nas propriedades físicas ou químicas
características dos neurônios após experimentos:

Uma ilustração dramática de como dois neurônios mudam ao longo do tempo no código e nosso modelo “algoritmo de aprendizado” significa que apenas mudaremos algo ao longo do tempo para facilitar nossa vida. Portanto, vamos adicionar uma variável para indicar o grau de facilitação da vida:
var learningRate = 0.20;
E o que isso vai mudar?Isso mudará o peso (como um coelho!), Especialmente o peso da saída que queremos:

Como codificar esse algoritmo é a sua escolha, para simplificar eu adiciono o coeficiente de treinamento ao peso, aqui está na forma de uma função:
function learn(inputVector, weightVector) { weightVector.forEach(function(weight, index, weights) { if (inputVector[index] > 0) { weights[index] = weight + learningRate; } }); }
Quando usada, essa função de aprendizado simplesmente adiciona nosso fator de aprendizado ao vetor de peso do
neurônio ativo , antes e depois do círculo de treinamento (ou repetição), os resultados serão os seguintes:
Exemplo ao vivo:
Rede Neural 003 .
Ok, agora que estamos nos movendo na direção certa, o último detalhe desse quebra-cabeça será a introdução de
repetições .
Não é tão difícil, porque na natureza fazemos a mesma coisa repetidamente, e no código apenas indicamos o número de repetições:
var trials = 6;
E a introdução em nossa rede neural de treinamento da função do número de repetições será assim:
function train(trials) { for (i = 0; i < trials; i++) { neuralNetResult = evaluateNeuralNetwork(input, weights); learn(input, weights); } }
Bem, nosso relatório final:
Neural Net output: 0.00 Error: 1.00 Weight Vector: [0,0,0,0] Neural Net output: 0.20 Error: 0.80 Weight Vector: [0,0,0.2,0] Neural Net output: 0.40 Error: 0.60 Weight Vector: [0,0,0.4,0] Neural Net output: 0.60 Error: 0.40 Weight Vector: [0,0,0.6,0] Neural Net output: 0.80 Error: 0.20 Weight Vector: [0,0,0.8,0] Neural Net output: 1.00 Error: 0.00 Weight Vector: [0,0,1,0]
Exemplo ao vivo:
Rede Neural 004 .
Agora, temos um vetor de peso que fornecerá apenas um resultado (frango para o jantar), se o vetor de entrada corresponder à realidade (pressionar o terceiro botão).
Então, o que é tão legal que acabamos de fazer?Nesse caso específico, nossa rede neural (após o treinamento) pode reconhecer os dados de entrada e dizer o que levará ao resultado desejado (ainda precisamos programar situações específicas):

Além disso, é um modelo escalável, brinquedo e ferramenta para nosso treinamento. Fomos capazes de aprender algo novo sobre aprendizado de máquina, redes neurais e inteligência artificial.
Cuidado para os usuários:
- Não é fornecido um mecanismo de armazenamento para as escalas estudadas; portanto, essa rede neural esquecerá tudo o que sabe. Ao atualizar ou reiniciar o código, você precisa de pelo menos seis tentativas bem-sucedidas para que a rede seja totalmente treinada se você achar que uma pessoa ou uma máquina pressionará botões aleatoriamente ... Isso levará algum tempo.
- As redes biológicas para aprender coisas importantes têm uma velocidade de aprendizado de 1, então você só precisa de uma repetição bem-sucedida.
- Existe um algoritmo de aprendizado muito semelhante aos neurônios biológicos, com um nome atraente: regra de widroff-hoff ou treinamento de widroff-hoff .
- Os limites dos neurônios (1 em nosso exemplo) e os efeitos da reciclagem (com um grande número de repetições, o resultado será superior a 1) não são levados em consideração, mas são muito importantes por natureza e são responsáveis por grandes e complexos blocos de reações comportamentais. Como pesos negativos.
Notas e referências para leitura adicional
Tentei evitar a matemática e termos estritos, mas se você estiver interessado, construímos um
perceptron , que é definido como um algoritmo para aprendizado supervisionado (
ensino com um professor ) de
classificadores duplos - uma coisa difícil.
A estrutura biológica do cérebro não é um tópico simples, em parte por causa da imprecisão, em parte por causa de sua complexidade. É melhor começar com Neurociência (Purves) e Neurociência Cognitiva (Gazzaniga). Modifiquei e adaptei o exemplo do coelho do Gateway to Memory (Gluck), que também é um ótimo guia para o mundo dos gráficos.
Outro recurso maravilhoso, Uma Introdução às Redes Neurais (Gurney), é adequado para todas as suas necessidades relacionadas à IA.
E agora em Python! Agradecimentos a Ilya Andschmidt pela versão do Python fornecida:
inputs = [0, 1, 0, 0] weights = [0, 0, 0, 0] desired_result = 1 learning_rate = 0.2 trials = 6 def evaluate_neural_network(input_array, weight_array): result = 0 for i in range(len(input_array)): layer_value = input_array[i] * weight_array[i] result += layer_value print("evaluate_neural_network: " + str(result)) print("weights: " + str(weights)) return result def evaluate_error(desired, actual): error = desired - actual print("evaluate_error: " + str(error)) return error def learn(input_array, weight_array): print("learning...") for i in range(len(input_array)): if input_array[i] > 0: weight_array[i] += learning_rate def train(trials): for i in range(trials): neural_net_result = evaluate_neural_network(inputs, weights) learn(inputs, weights) train(trials)
E agora em GO! Obrigado por esta versão do Kieran Maher.
package main import ( "fmt" "math" ) func main() { fmt.Println("Creating inputs and weights ...") inputs := []float64{0.00, 0.00, 1.00, 0.00} weights := []float64{0.00, 0.00, 0.00, 0.00} desired := 1.00 learningRate := 0.20 trials := 6 train(trials, inputs, weights, desired, learningRate) } func train(trials int, inputs []float64, weights []float64, desired float64, learningRate float64) { for i := 1; i < trials; i++ { weights = learn(inputs, weights, learningRate) output := evaluate(inputs, weights) errorResult := evaluateError(desired, output) fmt.Print("Output: ") fmt.Print(math.Round(output*100) / 100) fmt.Print("\nError: ") fmt.Print(math.Round(errorResult*100) / 100) fmt.Print("\n\n") } } func learn(inputVector []float64, weightVector []float64, learningRate float64) []float64 { for index, inputValue := range inputVector { if inputValue > 0.00 { weightVector[index] = weightVector[index] + learningRate } } return weightVector } func evaluate(inputVector []float64, weightVector []float64) float64 { result := 0.00 for index, inputValue := range inputVector { layerValue := inputValue * weightVector[index] result = result + layerValue } return result } func evaluateError(desired float64, actual float64) float64 { return desired - actual }