18.119.103.130@hermano.com.br:~$ ls ./estudos/redes_neurais/MLP

..   00-leia.txt   mlp.jpg   mlp.png   multilayerperceptron.txt  

18.119.103.130@hermano.com.br:~$ cat ./estudos/redes_neurais/MLP/multilayerperceptron.txt

#!/usr/bin/perl

# Multilayer Perceptron
# 09/11/2009
# Autor: Hermano Pereira
# www.hermano.com.br

use strict;

# Valores de entrada
my @en = ([0,0],   # Paulo
          [0,1],   # Joao
          [1,0],   # Tiago
          [1,1]);  # Pedro

my @yd = (1,       # Tecnico
          0,       # Analista
          0,       # Analista
          1);      # Tecnico

my @funcionario = (["Paulo",
                    "Joao"],
                    ["Tiago",
                    "Pedro"]);

my @funcao = ("Analista",
              "Tecnico");

my @s_en; # Entradas sorteadas
my @s_yd; # Saidas sorteadas

my @c_en; # Entradas selecionadas
my $c_yd; # Saida selecionada

my $max = 20000;       # Maximo de iteracoes
my $taxa = 0.5;        # Taxa de aprendizado
my $iter = 0;          # Contador de iteracoes
my $bias = 1;
my $soma_erro = 0.0;   # Somatorio de percentual de erros
my $erro_tole = 0.1;   # Percentual de erro tolerado
my $erro_medio = 0.0;  # Erro medio

# Dados do Perceptron 1
my $p1_w0 = rand(2)-1; # Peso para entrada 0
my $p1_w1 = rand(2)-1; # Peso para entrada 1
my $p1_wb = rand(2)-1; # Peso para bias
my $p1_y;              # Saida de P1
my $p1_grad;           # Gradiente de P1

# Dados do Perceptron 2
my $p2_w0 = rand(2)-1; # Peso para entrada 0
my $p2_w1 = rand(2)-1; # Peso para entrada 1
my $p2_wb = rand(2)-1; # Peso para bias
my $p2_y;              # Saida de P2
my $p2_grad;           # Gradiente de P2

# Dados do Perceptron 3
my $p3_w0 = rand(2)-1; # Peso para entrada 0 - saida de P1
my $p3_w1 = rand(2)-1; # Peso para entrada 1 - saida de P2
my $p3_wb = rand(2)-1; # Peso para bias
my $p3_y;              # Saida de P3
my $p3_grad;           # Gradiente de P3

# Executar RNA:

&treinar;
&testar(0,0);
&testar(0,1);
&testar(1,0);
&testar(1,1);

# Esta funcao faz o treinamento da RNA
sub treinar {
   my $parar = 0;
   my $qt_en = 0;
   while ($iter < $max && !($parar)) { # Criterio de parada
      $iter = $iter + 1;
      &sortear;
      $qt_en = scalar(@s_en);
      for (my $i = 0; $i < $qt_en; $i++) {
         &selecionar;
         &propagar;
         &retropropagar(&calcular_erro);
      }
      $erro_medio = $soma_erro / $iter;
      if ($erro_medio < $erro_tole) {
         $parar = 1;
      }
      if ($iter % 100 == 0) {
         &imprimir;
      }
   }
   &imprimir;
}

#  Esta funcao faz o sorteio das entradas
sub sortear {
   @s_en = ();
   @s_yd = ();
   my @ord;
   my @n_ord;
   for (my $i = 0; $i < scalar(@en); $i++) {
      push (@ord,$i);
   }
   for (my $i = scalar(@ord); $i > 0; $i--) {
      my $sorteio = int(rand($i));
      push (@n_ord, $ord[$sorteio]);
      delete $ord[$sorteio];
      @ord = reverse(sort(@ord));
   }
   for (my $i = 0; $i < scalar(@en); $i++) {
      $s_en[$i] = \@{$en[$n_ord[$i]]};
      $s_yd[$i] = $yd[$n_ord[$i]];
   }
}

# Esta funcao seleciona uma entrada
sub selecionar {
   @c_en = ();
   $c_yd = "";
   @c_en = ($s_en[0][0],$s_en[0][1]);
   shift @s_en;
   $c_yd = shift @s_yd;
}

# Funcao de propagacao
sub propagar {
   # Camada oculta - Perceptron 1
   my $v = ($c_en[0] * $p1_w0) + ($c_en[1] * $p1_w1) + ($p1_wb * $bias);
   my $y = (1 / (1 + exp(-$v)));
   $p1_y = $y;
   # Camada oculta - Perceptron 2
   $v = ($c_en[0] * $p2_w0) + ($c_en[1] * $p2_w1) + ($p2_wb * $bias);
   $y = (1 / (1 + exp(-$v)));
   $p2_y = $y;
   # Camada de saida - Perceptron 3
   $v = ($p1_y * $p3_w0) + ($p2_y * $p3_w1) + ($p3_wb * $bias);
   $y = (1 / (1 + exp(-$v)));
   $p3_y = $y;
}

# Funcao que calculo erro da RNA
sub calcular_erro {
   my $erro = $c_yd - $p3_y;
   $soma_erro += (($erro ** 2) / 2);
   return $erro;
}

# Funcao que atraves da retropropagacao
# reajusta os pesos de acordo com os erros
sub retropropagar {
   my $erro = shift;

   # Perceptron 3  
   my $y = $p3_y * (1 - $p3_y);
   $p3_grad = $erro * $y;

   # Perceptron 2
   my $tgrad = 0;
   $tgrad = $p3_grad * $p3_w1;
   $y = $p2_y * (1 - $p2_y);
   $p2_grad = $y * $tgrad;

   # Perceptron 1
   $tgrad = $p3_grad * $p3_w0;
   $y = $p1_y * (1 - $p1_y);
   $p1_grad = $y * $tgrad;

   # Ajustando pesos Perceptron 1
   my $delta;
   $delta = $taxa * $p1_grad * $c_en[0];
   $p1_w0 += $delta;
   $delta = $taxa * $p1_grad * $c_en[1];
   $p1_w1 += $delta;
   $delta = $taxa * $p1_grad * $bias;
   $p1_wb += $delta;

   # Ajustando pesos Perceptron 2
   $delta = $taxa * $p2_grad * $c_en[0];
   $p2_w0 += $delta;
   $delta = $taxa * $p2_grad * $c_en[1];
   $p2_w1 += $delta;
   $delta = $taxa * $p2_grad * $bias;
   $p2_wb += $delta;

   # Ajustando pesos Perceptron 3
   $delta = $taxa * $p3_grad * $p1_y;
   $p3_w0 += $delta;
   $delta = $taxa * $p3_grad * $p2_y;
   $p3_w1 += $delta;
   $delta = $taxa * $p3_grad * $bias;
   $p3_wb += $delta;

}

# Imprimir o que esta ocorrendo com a RNA
sub imprimir {
   system("clear");
   print "+-----------------------------------------------------------------------+\n";
   print "Iteracoes : $iter\n";
   print "Erro medio: $erro_medio\n";
   print "+-----------------------------------------------------------------------+\n";
   print "  Camada de Entrada:\n";
   print "    Entrada 1      = ".$c_en[0]."\n";
   print "    Entrada 2      = ".$c_en[1]."\n";
   print "    Bias           = 1\n";
   print "    Saida desejada = ".$c_yd."\n";
   print "  Camada Oculta:\n";
   print "    Perceptron (1)\n";
   print "                 - peso w0 = ".$p1_w0."\n";
   print "                 - peso w1 = ".$p1_w1."\n";
   print "                 - peso wb = ".$p1_wb."\n";
   print "                         y = ".$p1_y."\n";
   print "    Perceptron (2)\n";
   print "                 - peso w0 = ".$p2_w0."\n";
   print "                 - peso w1 = ".$p2_w1."\n";
   print "                 - peso wb = ".$p2_wb."\n";
   print "                         y = ".$p2_y."\n";
   print "  Camada de Saida:\n";
   print "    Perceptron (3)\n";
   print "                 - peso w0 = ".$p3_w0."\n";
   print "                 - peso w1 = ".$p3_w1."\n";
   print "                 - peso wb = ".$p3_wb."\n";
   print "                         y = ".$p3_y."\n";
   print "                 resultado = ".int($p3_y+0.5)."\n";
   print "+-----------------------------------------------------------------------+\n";
   <STDIN>;
}

# Testar a RNA depois de treinada!
sub testar {
   $c_en[0] = shift;
   $c_en[1] = shift;
   &propagar;
   print "+-----------------------------------------------------------------------+\n";
   print " Qual a funcao de ".$funcionario[$c_en[0]][$c_en[1]]."?\n";
   print "\n";
   print "    Camada de Entrada: ".$c_en[0].",".$c_en[1]." \n";
   print "    Camada Oculta    :\n";
   print "                       Perceptron 1 = ".$p1_y."\n";
   print "                       Perceptron 2 = ".$p2_y."\n";
   print "    Camada de Saida  : ".int($p3_y+0.5)."\n";
   print "                       Perceptron 3 = ".$p3_y."\n";
   print "\n";
   print " Resposta: ".$funcionario[$c_en[0]][$c_en[1]]." = ".$funcao[int($p3_y+0.5)].".\n";
   print "+-----------------------------------------------------------------------+\n";
   <STDIN>;
}


18.119.103.130@hermano.com.br:~$ clear_