0

Neural Network Perceptron

#Java
Samuel Barros
Samuel Barros

Neste artigo é explicado o funcionamento de uma perceptron e exemplificado com um projeto simples e prático utilizando a linguagem Java.

O projeto é de código aberto e está disponível no GitHub.


O que é uma Perceptron?

proposto em 1958 por Frank Rosenblatt, uma perceptron, é um modelo computacional, que, inspirado em um neurônio, é capaz de receber um vetor de dados de entrada e a partir de cálculos matemáticos, retornar um resultado indicando se pertence ou não a alguma classe específica.

O que é uma Rede Neural?

 Redes Neurais Artificiais (RNAs), são modelos computacionais, inspirados pelo sistema nervoso central de um animal, comumente o cérebro, sendo capaz de realizar feitos como aprendizado de máquina e reconhecimento de padrões.

São comumente representadas como um sistema de neurônios interligados, capazes de simular o comportamento de uma rede neural biológica.

O Projeto

Para tomar proveito completo deste artigo, recomendo fortemente que se possível, acesse o projeto no GitHub, baixe ele na sua máquina e tente acompanhar as explicações olhando o código, ao final, execute-o, para ter uma experiência completa e ver na prática o funcionamento da Perceptron. No Readme do projeto estarão mais detalhes e informações como, o que é necessário para rodar o código, versão atual, fontes, dentre outros…


Conversão de dados

Primeiramente devemos começar pela conversão dos dados que serão cedidos para a perceptron.

As redes neurais entendem apenas bits, por isso, de alguma forma, deve ser feita uma conversão dos dados para bits fazendo com que a rede neural seja capaz de compreender e processar os dados, um exemplo simples seria utilizar 1 (Verdadeiro) ou 0 (falso) para indicar se um funcionário está empregado ou desempregado.

No caso desta atividade os dados são letras (nomes de seres vivos e de objetos) porém, como visto, redes neurais não entendem letras, então foi necessário realizar a conversão das palavras para bits.

Possuímos 8 valores (palavras), então foi preciso descobrir com quantos bits se consegue representar até 8 valores, sabendo que:

1 bit consegue representar a 2 valores (0 / 1)

temos 2 (número de valores possíveis para 1 bit) ^ N (quantidade de bits)

logo:

  • 1 bit => 2^1 = 2 valores
  • 0 e 1


  • 2 bits => 2^2 = 4 valores
  • 00, 01, 10, 11


  • 3 bits => 2^3 = 8 valores
  • 000, 001, 010, 011, 100, 101, 110, 111


Conversão de dados



após chegar no resultado, resta escolher qual palavra (valor) cada bit vai representar,

| Nomes | Bits |

Peixe 000 |

Colher 001 |

sapo 010 |

cachorro 100 |

aquário 011 |

pessoa 110 |

agulha 101 |

feijão 111 |

  • como é mostrado neste trecho do código.
System.out.println("----------------------------");  
       System.out.println("//Descubra se é Ser Vivo: //");
       System.out.println("----------------------------");
       System.out.println("+(1)-peixe                 +");
       System.out.println("+(2)-colher                +");
       System.out.println("+(3)-sapo                  +");  
       System.out.println("+(4)-cachorro              +");
       System.out.println("+(5)-aquario               +");
       System.out.println("+(6)-pessoa                +");
       System.out.println("+(7)-agulha                +");
       System.out.println("+(8)-feijao                +");
       System.out.println("----------------------------");
       
       option = tec.nextInt();

       switch (option) {  //converte nome escolhido para bits
             
       case 1:
          x[1] = 0;
          x[2] = 0;
          x[3] = 0;
        
       break;
       
       case 2:
          x[1] = 0;
          x[2] = 0;
          x[3] = 1;
          
       break;
       
       case 3:
          x[1] = 0;
          x[2] = 1;
          x[3] = 0;
          
       break;
       
       case 4:
          x[1] = 1;
          x[2] = 0;
          x[3] = 0;
          
       break;
       
       case 5:
          x[1] = 0;
          x[2] = 1;
          x[3] = 1;
          
       break;
       
       case 6:
          x[1] = 1;
          x[2] = 1;
          x[3] = 0;
          
       break;
       
       case 7:
          x[1] = 1;
          x[2] = 0;
          x[3] = 1;
         
       break;
       
       case 8:
          x[1] = 1;
          x[2] = 1;
          x[3] = 1;
          
       break;
   }

O mesmo vale para o resultado, como os resultados possíveis são apenas 2 ( é um ser vivo ou não), podemos representar com:

  • 1 bit => 2^1
  • 1 (verdadeiro) e 0 (falso)


Arquitetura Perceptron Simples

Não foi fornecido texto alternativo para esta imagem


  • Essa imagem é uma demonstração visual de como a RNA (Rede Neural) trabalha.


  • X = Dados de entrada => bit (1 / 0)
  • [tipo int, pois só são aceitos os valores 1 e 0]
  • W = Pesos Sinápticos que serão usados nas operações matemáticas para obter o resultado
  • [Tipo float, pois o peso pode ter qualquer valor]
  • Bias = Um termo constante que não depende de qualquer valor de entrada.
  • [tipo int, pois só são aceitos os valores 1 e 0]
  • Wb = Peso do Bias
  • [Tipo float, pois o peso pode ter qualquer valor]
  • U = Resultado da Função Combinadora / Somadora
  • [Tipo float, pois o pode ter qualquer valor]
  • g(u) = Função de Transferência (Função Degrau) que resume o resultado em 1 ou 0
  • Y = resultado final (1 ou 0)
  • [tipo int, pois só são aceitos os valores 1 e 0]
  • N = Taxa de Aprendizado, é uma constante e seu valor é aleatório, mas para este código foi escolhido o valor 1.


Não foi fornecido texto alternativo para esta imagem




Dados de Entrada

Para os dados de entrada (X) será necessário um vetor com o tamanho equivalente a quantidade de bits, que nesse caso são 3 bits por palavra, então precisamos de um vetor com 3 posições.

int[] x = new int [4];


Não foi fornecido texto alternativo para esta imagem


  • Modelo de Um neurônio


Pesos Sinápticos

Para os pesos (W) será necessário um vetor com o tamanho equivalente aos dados de entrada (X), ou seja, para cada bit (posição) do vetor X será necessário um peso (posição) do vetor W, neste caso como vetor X tem 3 posições, o vetor W terá 3 posições.

float [] w =  new float [4];


Um detalhe a se destacar, é que o peso inicia com um valor aleatório, neste caso foi decidido que todos os pesos iniciariam com o valor 0 e o mesmo vale para o peso do bias, como mostrado na imagem acima e neste trecho de código onde “c” é o contador :

	for (int c = 1; c == 3; c++){
            w[c]= 0;
        }


Não foi fornecido texto alternativo para esta imagem


  • Foi Selecionado o primeiro exemplo (000) e o modelo foi preenchido


Função Combinadora / Somadora

O primeiro cálculo será feito utilizando a Função Combinadora / Somadora, que realiza uma soma ponderada entre o produto de cada entrada e seu peso sináptico equivalente e somaremos com o produto entre o bias e seu peso sináptico:

  • produto de cada entrada e seu peso sináptico
  • X[1] * W[1]
  • soma ponderada
  • ( X[1] * W[1] + X[2] * W[2] ...)
  • somaremos com o produto entre o bias e seu peso sináptico.
  • ( Bias * WBias)
  • como resultado temos:
  • U = (X[i] * W[i]) + Bias * Wb
  • Como é representado no código:
  u = ( x[1] * w[1] + x[2] * w[2] + x[3] * w[3] ) + b * wB;



Não foi fornecido texto alternativo para esta imagem


  • Após os dados serem preenchidos, agora eles começam a ser processados passando pela Função Combinadora / Somadora


Função de Transferência (Função Degrau)

Para obtermos o resultado final (1 ou 0) utilizaremos uma Função de Transferência, existem várias, porém será usada a Função Degrau, que basicamente funciona assim:

  • Se o “U” (resultado) for MENOR que 0 o resultado final (Y) será 0 => se U < 0 então Y será = 0
  • Já se o “U” (resultado) for IGUAL OU MAIOR que 0 o resultado final (Y) será 1 => se U >= 0 então Y será = 1

Como é representado neste trecho do código:

  if (u<0){            

            y = 0;
            
        }else{
        
            y = 1;
            
   }


Não foi fornecido texto alternativo para esta imagem


  • Função de Transferência sendo aplicada.


Algoritmo de Aprendizado (Correção de Erro)

O método de aprendizagem trabalhado, é o método de Aprendizagem Supervisionada, onde nos é dado um conjunto de dados rotulados que já sabemos qual é a nossa saída correta e que deve ser semelhante ao conjunto, tendo a ideia de que existe uma relação entre a entrada e a saída (Fonte: Opensanca (Pedro Barros))

Sendo assim o cálculo do erro será feito da seguinte forma:


Cálculo do Erro

A função deste cálculo é verificar se a rede neural acertou ou não.

O cálculo do Erro (Et) será dado pela diferença entre o resultado correto (Yc) e o resultado da Rede Neural (Y):

  • Et = Yc - Y

Como mostra o trecho do código:

	 er = e - y;


se Et for igual a 0 significa que a rede neural acertou, porém o algoritmo de aprendizagem ainda deve ser executado, pois se tudo estiver correto o algoritmo irá manter o mesmo valor para os pesos..

Não foi fornecido texto alternativo para esta imagem


  • Aplicando o cálculo de erro, para verificar se a rede neural acertou


Não foi fornecido texto alternativo para esta imagem


  • Neste caso a Rede Neural errou


Algoritmo de Aprendizado(Regra Delta)

A função deste cálculo é reajustar os pesos sinápticos de acordo com cálculo do Erro (Et), para isso existem vários algoritmos, mas, para este código foi usado a Regra delta, o mesmo vale para o peso do Bias:

  • W[i] = W[i] + N * Et * X[*i]

Onde “N” é a taxa de Aprendizado.

Veja o Exemplo a seguir:

  • W[1] = W [1] + 1 * Et * X[1]

Nó código está escrito desta forma:

	for (int c = 1; c == 3; c++){      
                w[c] = w[c]+n*er*x[c];
                System.out.println(w[c]);
            }
        
        wB = wB+n*er*b;


Não foi fornecido texto alternativo para esta imagem


  • Reajustando o primeiro Peso Sináptico


Não foi fornecido texto alternativo para esta imagem


  • Reajustando o Segundo Peso Sináptico


Não foi fornecido texto alternativo para esta imagem


  • Reajustando o terceiro Peso Sináptico


Não foi fornecido texto alternativo para esta imagem


  • Reajustando o Peso Sináptico do Bias


Não foi fornecido texto alternativo para esta imagem


  • Reajustando o Peso Sináptico do Bias


  • Agora é só repetir o algoritmo até que a Rede Neural consiga acertar


Dá uma olhada por aqui :)

|| LinkedIn || GitHub || Upwork || 99Freelas ||

Samuel Ricardo Cabral de Barros - Programador FullStack


Fontes:

0
1

Comentários (0)

Nascido em

Brasil