Como criar uma rede neural em JavaScript com apenas 30 linhas de código

Nikolas Brandão
Machina Sapiens
Published in
5 min readAug 22, 2017
Uma estranha imagem criada pela rede neural do Google Dream

Nota: Este post é uma tradução do artigo do Per Harald Borgen, o original encontra-se aqui.

Neste artigo, eu irei mostrar como você pode criar e treinar uma rede neural usando Synaptic.js, que permite que você aplique deep learning utilizando Node.JS e o navegador.

Vamos criar a rede neural mais simples o possível: uma que consiga resolver a equação XOR.

Mas, antes de olhar o código, vamos passar pelos princípios básicos das redes neurais.

Neurônios e Sinapses

O primeiro tijolo na construção de uma rede neural são os neurônios.

Um neurônio é como uma função, aceita algumas entradas e devolve algumas saídas.

Existem diferentes tipos de neurônios. Nossa rede irá utilizar neurônios do tipo sigmoide, que levam qualquer número e o comprime para um valor entre 0 ou 1.

O círculo na imagem abaixo ilustra um neurônio do tipo sigmoide. Sua entrada é 5 e sua saída é 1. A seta é a sinapse, que conectam os neurônios as outras camadas da rede.

Então, por que o número 5 está vermelho ? Por que ele é a soma de três sinapses que estão se conectando ao neurônio como podemos ver pelas setas a esquerda. Vamos destrinchar isso.

Na extrema esquerda vemos dois valores positivos que podem ser obtidos das sinapses. Os números 1 e 0 são esses valores. A bias é o valor -2 com número marrom.

Primeiro, as duas entradas são multiplicadas pelo seus pesos, que são 7 e 3 como mostrado nos números azuis.

Por fim somamos isso as nossas entradas com a nossa bias e terminamos com o resultado 5. Esta será a nossa entrada para o neurônio artificial.

Como esse é neurônio sigmoide nós temos que espremer a nossa entrada para qualquer valor entre 0 e 1, nossa saída foi comprimida para 1.

Se você criar uma rede com estes neurônios interconectados, você terá uma rede neural. Ela irá propagar as entradas até as saídas através de neurônios que estão conectados uns aos outros através de sinapses. Como na imagem abaixo:

O objetivo de uma rede neural é treiná-la para que ela faça generalizações, como o reconhecimento de palavras digitadas ou spam de e mail. E para ser bom em realizar generalizações, é importante que os pesos e bias tenham os valores calculados corretamente através da rede.

Ao treinar a rede, você está simplesmente mostrando uma série de exemplos, tais como dígitos escritos à mão, e obtém a rede para prever a resposta certa.

Após cada previsão, você vai calcular o quão errado a previsão foi, e ajustará os pesos e os valores das bias para que a rede consiga ser um pouco mais correta na próxima previsão. O processo de aprendizado é chamado de backpropagation. Faça isso milhares de vezes e sua rede será boa em fazer generalização.

Como o backpropagation tecnicamente funciona está fora do escopo deste tutorial, mas aqui estão as três melhores fontes que encontrei para entender isso:

O código

Agora que você obteve uma básica introdução, vamos pular para o código. A primeira coisa que nós precisamos fazer é criar as layers. Nós fazemos isso declarando a função new Layer() obtida na Synaptic. O número passado para a função determina quantos neurônios cada layer deve ter.

Se você está confuso sobre o que é uma Layer, confira esse screencast.

const { Layer, Network } = window.synaptic;var inputLayer = new Layer(2);
var hiddenLayer = new Layer(3);
var outputLayer = new Layer(1);

Em seguida, conectamos as Layers acima e criamos uma nova rede, como esta:

inputLayer.project(hiddenLayer);
hiddenLayer.project(outputLayer);
var myNetwork = new Network({
input: inputLayer,
hidden: [hiddenLayer],
output: outputLayer
});

Então, temos uma rede 2–3–1, que pode ser visualizada assim:

Agora, vamos treinar a rede.

// train the network - learn XORvar learningRate = .3;for (var i = 0; i < 20000; i++) {
// 0,0 => 0
myNetwork.activate([0,0]);
myNetwork.propagate(learningRate, [0]);
// 0,1 => 1
myNetwork.activate([0,1]);
myNetwork.propagate(learningRate, [1]);
// 1,0 => 1
myNetwork.activate([1,0]);
myNetwork.propagate(learningRate, [1]);
// 1,1 => 0
myNetwork.activate([1,1]);
myNetwork.propagate(learningRate, [0]);
}

No código acima estamos executando a rede 20.000 vezes. Cada vez que propagamos para frente e para trás quatro vezes, passamos as quatro entradas possíveis para esta rede: [0,0] [0,1] [1,0] [1,1].

Nós começamos executando o myNetwork.activate([0,0]) , onde [0,0] é o data point que estamos enviando para a rede. Está é uma propagação direta, também chamada de ativação de rede. Após cada propagação de rede nós precisamos fazer uma backpropagation, onde a rede irá atualizar seus próprios pesos e bias.

A backpropagation é feita nessa linha de código:
myNetwork.propagate(learningRate, [0]), onde a learningRate é uma constante que diz a rede o quanto ela deve ajustar nos seus pesos toda vez. O segundo parâmetro 0 representa a saída correta dada a entrada [0,0].

A rede em seguida compara sua previsão com o valor correto. Isso vai informar o quão certa ou errada foi a previsão.

Ela usa a comparação como base para corrigir seus próprios pesos e valores de bias, para que ela possa prever um pouco mais correto na próxima vez.

Depois de executar o processo 20.000 vezes, nós iremos checar o quão bem nossa rede aprendeu ativando a rede com as quatro possíveis entradas abaixo.

console.log(myNetwork.activate([0,0])); 
-> [0.015020775950893527]
console.log(myNetwork.activate([0,1]));
->[0.9815816381088985]
console.log(myNetwork.activate([1,0]));
-> [0.9871822457132193]
console.log(myNetwork.activate([1,1]));
-> [0.012950087641929467]

Se rodarmos esses valores para o inteiro mais próximo, obteremos as respostas corretas para a equação XOR. Hurra!

E é isso. Acabamos de arranhar a superfície das redes neurais, isso deve lhe dar o suficiente para começar a utilizar o Synaptic e continuar aprendendo por conta própria. A wiki do Synaptic contém tutoriais muito bons.

Por fim, certifique-se de compartilhar seu conhecimento, criando um screencast no Scrimba ou escrevendo um artigo quando você aprender algo novo! :)

Nota do tradutor: Gostaria de agradecer aos professores Josenildo Costa da Silva e Raimundo Osvaldo Vieira do Instituto Federal de Ciência e Tecnologia do Maranhão por tirarem duvidas, ajudar na revisão e incentivarem a tradução do artigo.

--

--

Nikolas Brandão
Machina Sapiens

Estudante de Sistemas de Informação (IFMA) e Desenvolvedor no TCE-MA