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.

domingo, 23 de julio de 2017

Serie armónica.

La serie armónica es la suma de los inversos de los números naturales.











Código java (numeroArmonico.java):

package numeroarmonico;

public class NumeroArmonico {
   public static void main(String[] args) {
      double sum = 0.0;
      int n = 10;     
      for (int k = 1; k <= n; k++) {
         sum += 1.0 / k;
      }
      System.out.printf("H(%d) = %f%n", n, sum);
   }

}

Resultado:

run:
H(10) = 2,928968
BUILD SUCCESSFUL (total time: 0 seconds)


domingo, 19 de marzo de 2017

Discretización basada en Entropía (I).

La entropía calcula el grado de desorden de un sistema. En este ejemplo será calculada en base a dos tipos de clases (A, B).
En minería de datos se utiliza para encontrar la partición con la máxima ganancia de información posible. 



* Procedimiento:

Sea S un conjunto de 1000 pares (AtributoValor, Clase) por ejemplo:

 
S = {(15, A), (280, B), (319, A), (775, B), (801, B), (850, A), (855, B), (880, B)....}

p1 = núm. de atributos de A / 1000 -> (la fracción de pares con clase = A)
p2 = núm. de atributos de B / 1000 -> (la fracción de pares con clase = B)

La entropía (o contenido de información) para S es:

    Entropia(S) = - p1 * log2(p1) – p2 * log2(p2)


* Características resultado:

    - Nos tiene que dar un valor entre 0 y 1.
    - Si la entropía es pequeña, entonces el conjunto esta muy ordenado.
    - Si la entropía es grande, entonces el conjunto esta muy desordenado.
    - En este ejemplo al obtener las clases aleatoriamente, nos debería dar una entropía alta, ya que lo aleatorio es sinónimo de desorden.


Código java (DiscretizarEntropia.java):

package discretizarentropia;

public class DiscretizarEntropia {

   public static void main(String[] args) {

      int nRegistros = 1000;
      Object[][] v = new Object[nRegistros][2];

      int cont = 0;
      for (int i = 0; i < nRegistros; i++) {
         v[i][0] = (int) (Math.random() * 1000);
         v[i][1] = (int) (Math.random() * 2);
         if (v[i][1].equals(0)) {
            cont++;
         }
      }

      double p1 = (float) cont / (float) nRegistros;
      double p2 = ((float) nRegistros - (float) cont) / (float) nRegistros;


      double S = -(p1 * log(p1, 2)) - (p2 * log(p2, 2));

      System.out.println("Número de clases A: " + cont);
      System.out.println("Número de clases B: " + (nRegistros - cont));
      System.out.println("Fracción de pares con clase A (p1) = " + p1);
      System.out.println("Fracción de pares con clase B (p2) = " + p2);
      System.out.println("Entropia(S) = " + S);

   }

   private static Double log(double num, int base) {
      return (Math.log10(num) / Math.log10(base));
   }

}


Resultado:

run:
Número de clases A: 481
Número de clases B: 519
Fracción de pares con clase A (p1) = 0.48100000619888306
Fracción de pares con clase B (p2) = 0.5189999938011169
Entropia(S) = 0.9989581240309595
BUILD SUCCESSFUL (total time: 0 seconds)



Cálculo de logaritmos en distintas bases.

En java no existe ninguna función que nos calcule directamente logaritmos en bases distintas a 10. Para ello habrá que crear nuestra propia función.


Código java (Logaritmos1.java):

//Cálculo de logaritmos en distintas bases.
package logaritmos1;

public class Logaritmos1 {

   public static void main(String[] args) {
      int num = 5;
      for (int base = 0; base < 10; base++) {
         System.out.println("Logaritmo de 5 en base " + base + " = " + log(num, base));
      }
   }

   private static Double log(double num, int base) {
      return (Math.log10(num) / Math.log10(base));
   }


}


Resultado:

run:
Logaritmo de 5 en base 0 = -0.0
Logaritmo de 5 en base 1 = Infinity
Logaritmo de 5 en base 2 = 2.3219280948873626
Logaritmo de 5 en base 3 = 1.4649735207179273
Logaritmo de 5 en base 4 = 1.1609640474436813
Logaritmo de 5 en base 5 = 1.0
Logaritmo de 5 en base 6 = 0.8982444017039273
Logaritmo de 5 en base 7 = 0.8270874753469162
Logaritmo de 5 en base 8 = 0.7739760316291209
Logaritmo de 5 en base 9 = 0.7324867603589637
BUILD SUCCESSFUL (total time: 0 seconds)


viernes, 17 de marzo de 2017

Pasar un array de valores numéricos a escala percentual - atributo continuo -

Siguiendo con el post anterior esta vez se intentará reestructurar el código anterior y añadir la función "DiscretizarFine" que consiste en añadir en el rango mínimo y máximo (que son indeterminados) la media de los espacios que existen entre todos los valores del array. Esto en teoría afinaría en la precisión en el machine learning.


* Ejemplo gráfico para ver las diferencias entre los distintos modelos:




Código Java 1 (BloggerDiscretizar2.java):

package bloggerdiscretizar2;

import java.util.Arrays;


public class BloggerDiscretizar2 {
  
   public static void main(String[] args) {

      Array arr = new Array();

      double v_inicial[] = new double[16];
      double v_discretizar[] = new double[16];
      double v_discretizarFine[] = new double[16];

      for (int i = 0; i < v_inicial.length; i++) {
         v_inicial[i] = (double) Math.random() * 512;
      }
     
      //copiar v_inicial
      System.arraycopy(v_inicial, 0, v_discretizar, 0, v_inicial.length);
      System.arraycopy(v_inicial, 0, v_discretizarFine, 0, v_inicial.length);

      //discretizar percentual
      v_discretizar = arr.toDiscretizar(v_inicial);
      v_discretizarFine = arr.toDiscretizarFine(v_inicial);
     
      //ordenar arrays de menor a mayor
      Arrays.sort(v_inicial);
      Arrays.sort(v_discretizar);
      Arrays.sort(v_discretizarFine);
     
      //mostrar resultados
      System.out.println("vector inicial:");
      for (int i = 0; i < v_inicial.length; i++) {        
         System.out.println(v_inicial[i]);        
      }
     
      System.out.println("\nvector discretizado (atributo discreto):");
      for (int i = 0; i < v_discretizar.length; i++) {
         System.out.println(v_discretizar[i]);
      }
     
      System.out.println("\nvector discretizado_fino (atributo continuo):");
      for (int i = 0; i < v_discretizarFine.length; i++) {
         System.out.println(v_discretizarFine[i]);
      }

   }

}


Código Java 2 (Array.java):

bloggerdiscretizar2;

public class Array {

     /*
   Transformar un campo numérico a categórico usando percentiles
   Atributo discreto tiene un número finito o contable de valores   
    */

   public double[] toDiscretizar(double[] array) {
      double[] array2 = new double[array.length];
      //obtener min y max apartir del array base
      double min = this.getMin(array);
      double max = this.getMax(array);
      for (int i = 0; i < array.length; i++) {
         array2[i] = (array[i] - min) / (max - min);
      }
      return array2;
   }

   /*
   Transformar un campo numérico a categórico usando percentiles (afinado)
   Atributo continuo tiene un número indeterminado de valores (no se sabe el valor min ni el max)
    */

   public double[] toDiscretizarFine(double[] array) {
      double[] array2 = new double[array.length];
      double[] array3 = new double[array.length + 2];
      for (int i = 0; i < array.length - 1; i++) {
         array2[i] = array[i] - array[i + 1];//distancia entre valores
      }
      System.arraycopy(array, 0, array3, 2, array.length);

      //calculo aproximado del min y max y se añade al array
      array3[0] = this.getMin(array) - this.getMed(array2); //min
      array3[1] = this.getMax(array) + this.getMed(array2); //max
      return this.toDiscretizar(array3);
   }

   public double getMin(double[] array) {
      double min = array[0];
      for (int i = 0; i < array.length; i++) {
         if (min > array[i]) {
            min = array[i];
         }
      }
      return min;
   }

   public double getMax(double[] array) {
      double max = array[0];
      for (int i = 0; i < array.length; i++) {
         if (max < array[i]) {
            max = array[i];
         }
      }
      return max;
   }

   public double getMed(double[] array) {
      double med = 0;
      for (int i = 0; i < array.length; i++) {
         med = med + array[i];
      }
      return med / array.length;
   }

}



Resultado:

run:
vector inicial:
6.915959656
27.4665411
106.4488495
111.8923782
146.6526326
178.1616741
185.2529849
203.4995067
223.2984554
250.5640114
262.7295496
272.2483547
319.3729241
436.0795028
441.7362144
461.5955789

vector discretizado (atributo discreto):
0
0.045197938
0.218907744
0.230879974
0.307329968
0.376629405
0.392225685
0.432356188
0.475901023
0.535867546
0.562623833
0.583559025
0.687202486
0.943881197
0.95632229
1

vector discretizado_fino (atributo continuo):
0
0.030742192
0.073161163
0.236190529
0.247426653
0.319176167
0.38421477
0.398852123
0.436515226
0.477382733
0.533662252
0.558773445
0.578421449
0.675692456
0.916589435
0.928265595
0.969257808
1
BUILD SUCCESSFUL (total time: 0 seconds)


Nota: Atributo continuo: Tiene un rango indeterminado de valores posibles.

jueves, 16 de marzo de 2017

Pasar un array de valores numéricos a escala percentual - atributo discreto -

En machine learning se le llama "discretizar array por percentiles", que consiste en uniformizar los valores numéricos de un array a escala [0:1]. Esta transformación es usada para ayudar en el aprendizaje automático de máquinas (machine learning) ya que adapta los términos absolutos del array a términos porcentuales.

Ejemplo:

Arrays iniciales:

    array1 (numérico):    0        1       2       5       7       10
    array2 (numérico):    653.7    1382    2403    4214    8890    9935
    ...
    ...

Arrays ya uniformizados (discretizados por percentiles):

    array1 (percentil):    0%      0.1%    0.2%    0.5%    0.7%    1%   
    array2 (percentil):    0%      0.07%   0.18%   0.38%   0.89%   1%
    ...
    ...

La diferencia entre los valores del array1 y array2 iniciales son dispares. Una vez transformados los campos numéricos a percentiles se observa de que los campos son más semejantes entre sí (misma escala).


Código java: (DiscretizarNormalizar.java)

//Transformar un campo numérico a categórico usando percentiles
package discretizarnormalizar;

public class DiscretizarNormalizar {

   public static void main(String[] args) {

      int nRegistros = 10;
      double[] v = new double[nRegistros];

      //crear array aleatorio
      for (int i = 0; i < nRegistros; i++) {
         v[i] = Math.random() * 10000;
      }

      //buscar valores minimos y maximos del array
      double min = v[0];
      double max = v[0];
      for (int i = 0; i < nRegistros; i++) {
         if (min > v[i]) {
            min = v[i];
         }
         if (max < v[i]) {
            max = v[i];
         }
      }

      //normalizacion-descretizar?
      double[] v2 = new double[nRegistros];
      for (int i = 0; i < nRegistros; i++) {
         v2[i] = (v[i] - min) / (max - min);
      }


      //mostrar resultado
      System.out.println("Array inicial:\t\tArray transformado:");
      for (int i = 0; i < nRegistros; i++) {
         System.out.println(i + "- " + v[i] + "\t" + v2[i]);
      }

   }

}


Resultado:

run:

Array inicial:          Array transformado:
0- 7671.886736201123    0.8019001791662852
1- 9479.117533535893    1.0
2- 4876.0856974944645   0.4954381126326166
3- 6808.418910630855    0.7072510497947576
4- 356.28849851238044   0.0
5- 6556.185784681601    0.6796024854096415
6- 5931.890253043281    0.6111702557535137
7- 8510.956094814934    0.8938748676529962
8- 589.2424296425359    0.02553527313027795
9- 1432.7279151298521   0.11799403589444743
BUILD SUCCESSFUL (total time: 0 seconds)


Nota: Atributo discreto: tiene un rango finito o contable de valores.

miércoles, 15 de marzo de 2017

Copiar arrays. Uso de la instrucción "System.arraycopy".

Código java (CopiaArray.java):

package copiaarray;

public class CopiaArray {

   public static void main(String[] args) {

      double[] array1 = new double[5];
      double[] array2 = new double[10];
      double[] array3 = new double[array1.length + array2.length];

      //rellena array1
      for (int i = 0; i < array1.length; i++) {
         array1[i] = i;
      }


      //rellena array2
      for (int i = 0; i < array2.length; i++) {
         array2[i] = Math.random();
      }

      /*
         Parametros del System.arraycopy:
         Array origen,
         Posición inicial del array origen,
         Array destino,
         Posición incial en el array de destino,
         Numero de elementos a copiar del array origen al array destino
       */

     
      System.arraycopy(array1, 0, array3, 0, array1.length);
      System.arraycopy(array2, 0, array3, array1.length, array2.length);


      //mostrar resultados
      System.out.println("\nArray1");
      for (int i = 0; i < array1.length; i++) {
         System.out.println(i + "- " + array1[i]);
      }


      System.out.println("\nArray2");
      for (int i = 0; i < array2.length; i++) {
         System.out.println(i + "- " + array2[i]);
      }


      System.out.println("\nArray3");
      for (int i = 0; i < array3.length; i++) {
         System.out.println(i + "- " + array3[i]);
      }

   }

}



Resultado:

run:

Array1
0- 0.0
1- 1.0
2- 2.0
3- 3.0
4- 4.0

Array2
0- 0.5287887048803938
1- 0.46771014928163135
2- 0.8333523729100707
3- 0.4965787587571521
4- 0.26861092247251583
5- 0.822652997195613
6- 0.5053721779352607
7- 0.896713025382418
8- 0.9093387247823286
9- 0.8910677970677133

Array3
0- 0.0
1- 1.0
2- 2.0
3- 3.0
4- 4.0
5- 0.5287887048803938
6- 0.46771014928163135
7- 0.8333523729100707
8- 0.4965787587571521
9- 0.26861092247251583
10- 0.822652997195613
11- 0.5053721779352607
12- 0.896713025382418
13- 0.9093387247823286
14- 0.8910677970677133
BUILD SUCCESSFUL (total time: 0 seconds)


Con la tecnología de Blogger.