mancpato_PuntosRNA/Neurona.pde
/* 
    Perceptrón simple
    
    Programa de ejemplo de Redes Neuronales Artificiales.
    Clasificador para tres clases separadas en el plano.
    
    Miguel Angel Norzagaray Cosío
    UABCS/DSC
*/

class RNA {
  int ni, nh, nk;  // neuronas por capa
  float [][] wh;
  float [][] wy;
  float [] bh;
  float [] by;
  float [] fh;
  float [] fy;
  
  float Alfa;    // Tasa de aprendizaje

  RNA(int n, int h, int k, float Tasa) {
    ni = n;
    nh = h;
    nk = k;
    Alfa = Tasa;
    wh = new float[n][h];
    wy = new float[h][k];
    bh = new float[h];
    by = new float[k];
    fh = new float[h];
    fy = new float[k];
    Alfa = Tasa;

    for ( int i=0; i<ni ; i++)
        for ( int j=0 ; j<nh ; j++ )
            wh[i][j] = PesoInicial();
    for ( int i=0; i<nh ; i++)
        for ( int j=0 ; j<nk ; j++ )
            wy[i][j] = PesoInicial();

    for ( int i=0; i<nh ; i++)
        bh[i] = PesoInicial();
    for ( int i=0; i<nk ; i++)
        by[i] = PesoInicial();
  }
  
  float PesoInicial() {
    return random(1);
  }

  void Clasificar(float[] x) 
  {
    float Sum;

    for ( int j=0 ; j < nh ; j++ ) {
        Sum = bh[j];
        for ( int k=0 ; k < ni ; k++ )
            Sum += x[k]*wh[k][j];
        fh[j] = f(Sum); //<>//
    }

    for ( int j=0 ; j < nk ; j++ ) {
        Sum = by[j];
        for (int k=0; k < nh ; k++)
            Sum += fh[k]*wy[k][j];
        fy[j] = f(Sum);
    }
    for ( int j=0; j < nk ; j++ )
        y[j] = round(fy[j]);
  }

  float f(float Suma) {
    return 1/(1+exp(-Suma));
  }
  float df(float x) {
    return f(x) * (1 - f(x));
  }

  float Entrenar(float[] x, int[] Correcto) {
    float SError = 0;
    float [] dh;
    float [] dy;

    Clasificar(x);
    
    // Cambio en la capa de salida 
    dy = new float[K];   
    for ( int j=0 ; j<nk ; j++) { //<>//
        float Error = Correcto[j] - y[j];
        dy[j] = Error*df(fy[j]);
        SError += Error*Error;
    }
    // Cambio en la capa oculta
    dh = new float[H];
    for ( int j=0 ; j<nh ; j++) {
        float Error = 0;
        for( int k=0 ; k<nk ; k++ )
            Error += dy[k]*wy[j][k];
        dh[j] = Error*df(fh[j]);
    }

    // Actualización de pesos wy
    for (int j=0; j<nk; j++) {
        by[j] += dy[j]*Alfa;
        for (int k=0; k<nh ; k++)
            wy[k][j] += fh[k]*dy[j]*Alfa;
    }
    // Actualización de pesos wh
    for ( int j=0 ; j<nh ; j++) {
        bh[j] += dh[j]*Alfa;
        for ( int k=0; k<ni ; k++) 
            wh[k][j] += x[k]*dh[j]*Alfa;
    }
    return sqrt(SError);
  }
  
  void MostrarPesos() {
  
    println("Pesos hacia la capa oculta");
    for ( int i=0; i<nh ; i++) {
        for ( int j=0 ; j<nk ; j++ )
            print(wy[i][j]+" \t");
        println("");
    }
    println("Sesgos hacia la capa oculta");
    for ( int i=0; i<nh ; i++)
        print(bh[i]+"\t");
    println("");
    
    println("Pesos hacia la capa de salida");
    for ( int i=0; i<ni ; i++) {
        for ( int j=0 ; j<nh ; j++ )
            print(wh[i][j]+" \t");
        println("");
    }
    println("Sesgos hacia la capa de salida");
    for ( int i=0; i<nk ; i++)
        print(by[i]+" \t");
    println("");
  }
}

/* Fin de archivo */
