Tras los posts anteriores (visualizaciones esquemáticas de formulas) el siguiente paso pasa por realizar el cálculo real de todas las variables (salidas, errores y pesos actualizados) partiendo de un dataset(D) de un sólo registro.
Código Java:
package perceptron_p;
import java.util.ArrayList;
import java.util.List;
public class Perceptron_p {
   public static void main(String[] args) {
      //sketch: num neuronas
      List<Integer> nN = new ArrayList<>();
      nN.add(2);
      nN.add(3);
      nN.add(2);
      nN.add(1);
      double µ = 0.001;
      int r = 0; // num. registro del dataset
      int nK = nN.size(); // num. de capas = 4
      int nE = nN.get(0); // num. de entradas = 2
      int nS = nN.get(nK - 1); // num. de salidas = 1
      int max = nN.stream().mapToInt(i -> i).max().getAsInt(); // num. max. neuronas por capa
      String tmp;
      double d_tmp;
      // Inicializar dataset (sólo 1 registro o fila)
      double[][] D = new double[1][3];
      D[0][0] = 0.48d; // entrada 1
      D[0][1] = 0.33d; // entrada 2
      D[0][2] = 0.81d; // salida  1
      // Inicializar pesos W, WBias, Y
      double[][][] W = new double[nK][max][max];
      double[][] WB = new double[nK][max];
      double[][] Y = new double[nK][max];
      double[][] E = new double[nK][max];
      System.out.println("Inicializar pesos con valores aleatorios:\n");
      for (int k = 1; k < nK; k++) {
         for (int j = 0; j < nN.get(k); j++) {
            for (int i = 0; i < nN.get(k - 1); i++) {
               W[k][j][i] = Math.random();
               System.out.format("W[%d][%d][%d] = %f\n", k, j, i, W[k][j][i]);
            }
            WB[k][j] = Math.random();
            System.out.format("WB[%d][%d] = %f\n\n", k, j, WB[k][j]);
            Y[k][j] = 0.f;
            E[k][j] = 0.f;
         }
      }
      // 0.0:-------------------------------------------------------------------
      System.out.println("Forward:\n");
      int k = 1;
      for (int j = 0; j < nN.get(k); j++) {
         tmp = "";
         d_tmp = 0f;
         for (int i = 0; i < nE; i++) {
            tmp += String.format("( D[%d][%d] * W[%d][%d][%d] ) + ", r, i, k, j, i);
            d_tmp += D[r][i] * W[k][j][i];
         }
         Y[k][j] = F(d_tmp + (-1 * WB[k][j]), 0);
         System.out.format("Y[%d][%d] = F{ %s( -1 * WB[%d][%d] ) } = ", k, j, tmp, k, j);
         System.out.println(Y[k][j]);
      }
      // 0.1:-------------------------------------------------------------------
      System.out.println("");
      for (k = 2; k < nK; k++) {
         for (int j = 0; j < nN.get(k); j++) {
            tmp = "";
            d_tmp = 0f;
            for (int i = 0; i < nN.get(k - 1); i++) {
               tmp += String.format("( Y[%d][%d] * W[%d][%d][%d] ) + ", k - 1, i, k, j, i);
               d_tmp += Y[k - 1][i] * W[k][j][i];
            }
            System.out.format("Y[%d][%d] = F{ %s( -1 * WB[%d][%d] ) } = ", k, j, tmp, k, j);
            Y[k][j] = F(d_tmp + (-1 * WB[k][j]), 0);
            System.out.println(Y[k][j]);
         }
         System.out.println("");
      }
      // 1.0:------------------------------------------------------------------- 
      System.out.println("Backward:\n");
      k = nK - 1;
      for (int j = 0; j < nS; j++) {
         E[k][j] = D[r][nE + j] - Y[k][j];
         System.out.format("E[%d][%d] = ( D[%d][%d] - Y[%d][%d] ) = ", k, j, r, nE + j, k, j);
         System.out.println(E[k][j]);
      }
      // 1.1:-------------------------------------------------------------------
      System.out.println("");
      for (k = k - 1; k > 0; k--) {
         for (int j = nN.get(k); j > 0; j--) {
            tmp = "";
            d_tmp = 0.d;
            for (int i = nN.get(k + 1); i > 0; i--) {
               tmp += String.format("( E[%d][%d] * W[%d][%d][%d] ) + ", k + 1, i - 1, k + 1, i - 1, j - 1);
               d_tmp += E[k + 1][i - 1] * W[k + 1][i - 1][j - 1];
            }
            System.out.format("E[%d][%d] = %s%s = ", k, j - 1, tmp, "0 ");
            System.out.println(d_tmp);
            E[k][j - 1] = d_tmp;
         }
         System.out.println("");
      }
      // 2.0:-------------------------------------------------------------------
      System.out.println("Ajuste pesos:\n");
      k = 1;
      for (int j = 0; j < nN.get(k); j++) {
         for (int i = 0; i < nE; i++) {
            W[k][j][i] += (µ * E[k][j] * F(Y[k][j], 1) * D[r][i]);
            System.out.format("W'[%d][%d][%d] = W[%d][%d][%d] + ( µ * E[%d][%d] * F'(Y[%d][%d]) * D[%d][%d] ) = ", k, j, i, k, j, i, k, j, k, j, r, i);
            System.out.println(W[k][j][i]);
         }
         WB[k][j] += (µ * E[k][j] * F(Y[k][j], 1) * -1);
         System.out.format("WB'[%d][%d] = WB[%d][%d] + ( µ * E[%d][%d] * F'(Y[%d][%d]) * (%d) ) = ", k, j, k, j, k, j, k, j, - 1);
         System.out.println(WB[k][j] + "\n");
      }
      // 2.1:-------------------------------------------------------------------
      System.out.println("");
      for (k = 2; k < nK; k++) {
         for (int j = 0; j < nN.get(k); j++) {
            for (int i = 0; i < nN.get(k - 1); i++) {
               W[k][j][i] += (µ * E[k][j] * F(Y[k][j], 1) * Y[k - 1][i]);
               System.out.format("W'[%d][%d][%d] = W[%d][%d][%d] + ( µ * E[%d][%d] * F'( Y[%d][%d] ) * Y[%d][%d] ) = ", k, j, i, k, j, i, k, j, k, j, k - 1, i);
               System.out.println(W[k][j][i]);
            }
            WB[k][j] += (µ * E[k][j] * F(Y[k][j], 2) * (-1));
            System.out.format("WB'[%d][%d] = WB[%d][%d] + ( µ * E[%d][%d] * F'(Y[%d][%d]) * (%d) ) = ", k, j, k, j, k, j, k, j, -1);
            System.out.println(WB[k][j] + "\n");
         }
         System.out.println("");
      }
   }
   // Función Activación - Derivada
   private static double F(double n, int op) {
      double fx;
      switch (op) {
         case 0: // función sigmoide
            fx = 1.0 / (1.0 + Math.pow(Math.E, -n));
            break;
         case 1: // derivada función sigmoide
            fx = 1.0 / (1.0 + Math.pow(Math.E, -n));
            fx = fx * (1 - fx);
            break;
         default:
            fx = 0.f;
            break;
      }
      return fx;
   }
}
Resultado:
run:
Inicializar pesos con valores aleatorios:
W[1][0][0] = 0,835049
W[1][0][1] = 0,308429
WB[1][0] = 0,052288
W[1][1][0] = 0,217787
W[1][1][1] = 0,348034
WB[1][1] = 0,588298
W[1][2][0] = 0,961801
W[1][2][1] = 0,796138
WB[1][2] = 0,044188
W[2][0][0] = 0,994101
W[2][0][1] = 0,211034
W[2][0][2] = 0,711812
WB[2][0] = 0,952732
W[2][1][0] = 0,423756
W[2][1][1] = 0,953356
W[2][1][2] = 0,249125
WB[2][1] = 0,973105
W[3][0][0] = 0,842807
W[3][0][1] = 0,794736
WB[3][0] = 0,290240
Forward:
Y[1][0] = F{ ( D[0][0] * W[1][0][0] ) + ( D[0][1] * W[1][0][1] ) + ( -1 * WB[1][0] ) } = 0.6107146316470909
Y[1][1] = F{ ( D[0][0] * W[1][1][0] ) + ( D[0][1] * W[1][1][1] ) + ( -1 * WB[1][1] ) } = 0.40880474360914854
Y[1][2] = F{ ( D[0][0] * W[1][2][0] ) + ( D[0][1] * W[1][2][1] ) + ( -1 * WB[1][2] ) } = 0.6637837549590786
Y[2][0] = F{ ( Y[1][0] * W[2][0][0] ) + ( Y[1][1] * W[2][0][1] ) + ( Y[1][2] * W[2][0][2] ) + ( -1 * WB[2][0] ) } = 0.5530844896875817
Y[2][1] = F{ ( Y[1][0] * W[2][1][0] ) + ( Y[1][1] * W[2][1][1] ) + ( Y[1][2] * W[2][1][2] ) + ( -1 * WB[2][1] ) } = 0.46028147962310223
Y[3][0] = F{ ( Y[2][0] * W[3][0][0] ) + ( Y[2][1] * W[3][0][1] ) + ( -1 * WB[3][0] ) } = 0.6322090580829307
Backward:
E[3][0] = ( D[0][2] - Y[3][0] ) = 0.17779094191706935
E[2][1] = ( E[3][0] * W[3][0][1] ) + 0  = 0.14129683962211012
E[2][0] = ( E[3][0] * W[3][0][0] ) + 0  = 0.1498433870202291
E[1][2] = ( E[2][1] * W[2][1][2] ) + ( E[2][0] * W[2][0][2] ) + 0  = 0.1418609770496571
E[1][1] = ( E[2][1] * W[2][1][1] ) + ( E[2][0] * W[2][0][1] ) + 0  = 0.16632825764793913
E[1][0] = ( E[2][1] * W[2][1][0] ) + ( E[2][0] * W[2][0][0] ) + 0  = 0.2088347664166445
Ajuste pesos:
W'[1][0][0] = W[1][0][0] + ( µ * E[1][0] * F'(Y[1][0]) * D[0][0] ) = 0.8350717767495889
W'[1][0][1] = W[1][0][1] + ( µ * E[1][0] * F'(Y[1][0]) * D[0][1] ) = 0.3084447906938308
WB'[1][0] = WB[1][0] + ( µ * E[1][0] * F'(Y[1][0]) * (-1) ) = 0.05224031629899943
W'[1][1][0] = W[1][1][0] + ( µ * E[1][1] * F'(Y[1][1]) * D[0][0] ) = 0.21780595558207116
W'[1][1][1] = W[1][1][1] + ( µ * E[1][1] * F'(Y[1][1]) * D[0][1] ) = 0.34804701774866154
WB'[1][1] = WB[1][1] + ( µ * E[1][1] * F'(Y[1][1]) * (-1) ) = 0.5882576504954621
W'[1][2][0] = W[1][2][0] + ( µ * E[1][2] * F'(Y[1][2]) * D[0][0] ) = 0.9618160101133663
W'[1][2][1] = W[1][2][1] + ( µ * E[1][2] * F'(Y[1][2]) * D[0][1] ) = 0.7961484238865005
WB'[1][2] = WB[1][2] + ( µ * E[1][2] * F'(Y[1][2]) * (-1) ) = 0.04415614986229021
W'[2][0][0] = W[2][0][0] + ( µ * E[2][0] * F'( Y[2][0] ) * Y[1][0] ) = 0.9941217290526374
W'[2][0][1] = W[2][0][1] + ( µ * E[2][0] * F'( Y[2][0] ) * Y[1][1] ) = 0.21104869817169436
W'[2][0][2] = W[2][0][2] + ( µ * E[2][0] * F'( Y[2][0] ) * Y[1][2] ) = 0.7118355488714299
WB'[2][0] = WB[2][0] + ( µ * E[2][0] * F'(Y[2][0]) * (-1) ) = 0.9527319900854492
W'[2][1][0] = W[2][1][0] + ( µ * E[2][1] * F'( Y[2][1] ) * Y[1][0] ) = 0.4237764313332067
W'[2][1][1] = W[2][1][1] + ( µ * E[2][1] * F'( Y[2][1] ) * Y[1][1] ) = 0.953369304782218
W'[2][1][2] = W[2][1][2] + ( µ * E[2][1] * F'( Y[2][1] ) * Y[1][2] ) = 0.2491472992670435
WB'[2][1] = WB[2][1] + ( µ * E[2][1] * F'(Y[2][1]) * (-1) ) = 0.9731049511389623
W'[3][0][0] = W[3][0][0] + ( µ * E[3][0] * F'( Y[3][0] ) * Y[2][0] ) = 0.8428289253648974
W'[3][0][1] = W[3][0][1] + ( µ * E[3][0] * F'( Y[3][0] ) * Y[2][1] ) = 0.7947544171128877
WB'[3][0] = WB[3][0] + ( µ * E[3][0] * F'(Y[3][0]) * (-1) ) = 0.29024004297076156
BUILD SUCCESSFUL (total time: 2 seconds) 
Una forma sencilla y rápida de aprender JAVA, observando y deduciendo cómo se comporta el lenguaje a través de ejemplos prácticos.
Suscribirse a:
Enviar comentarios (Atom)
Con la tecnología de Blogger.
 
No hay comentarios:
Publicar un comentario