Voy a crear un algoritmo de aprendizaje (en este caso una puerta logica OR). Para ello voy a utilizar un tipo de neurona artificial llamada perceptrón con 2 entradas.
Hay que tener encuenta que en este ejemplo, la salida (Y1) solo admite los valores 1 y -1, siguiendo la siguiente regla:
1 si f(wx) >= θ
-1 si f(wx) < θ
Para el aprendizaje de la puerta logica OR nos hará falta crear una "tabla de la verdad" del mismo:
En este nuevo ejemplo de neurona aparecen 2 nuevos valores a tener encuenta:
E = Factor de aprendizaje
θ = Umbral
Y una nueva formula que servirá para ajuste de pesos:
W = W + 2E * T * X
Codigo:
//Aprendizaje puerta logica OR. (Muestra datos paso a paso)
package neuronaOR;
import java.util.Random;
import java.util.Scanner;
public class NeuronaOR {
public static void main(String[] args) {
//Tabla de la verdad (X1,X2,Y1)
int[][] tv = {{1, 1, 1}, {1, -1, 1}, {-1, 1, 1}, {-1, -1, -1}};
System.out.println("\nInicializar pesos:\n");
double w1 = new Random().nextDouble() / 2.5;//valores proximos a 0
double w2 = new Random().nextDouble() / 2.5;
double θ = -0.4;
double y = 0;
final double E = 0.6;//Factor de aprendizaje
System.out.println("w1: " + w1);
System.out.println("w2: " + w2);
System.out.println("θ: " + θ);
System.out.println("\nIniciando fase de aprendizaje puerta logica OR...\n");
int i = 0;
int cont = 1;
while (i < tv.length && cont < 100) {
y = Math.tanh((tv[i][0] * w1) + (tv[i][1] * w2) + (-1 * θ));
y = (y >= θ) ? 1 : -1;
System.out.println("Entrada[" + tv[i][0] + "," + tv[i][1]
+ "]) Valor esperado[" + tv[i][2]
+ "] Salida[" + (int) y + "]");
if (y == tv[i][2]) {
i++;
} else {
System.out.println("Valor esperado difiere de la salida. Hay que reajustar pesos...");
//Ajuste de pesos
w1 = w1 + 2 * E * tv[i][2] * tv[i][0];
w2 = w2 + 2 * E * tv[i][2] * tv[i][1];
θ = θ + 2 * E * tv[i][2] * (-1);
System.out.println("\nAjuste de pesos (" + cont + "):");
System.out.println("w1: " + w1);
System.out.println("w2: " + w2);
System.out.println("θ: " + θ + "\n");
cont++;
i = 0;
}
}
if (cont <= 9999) {
System.out.println("\nFase de aprendizaje terminado con exito ");
System.out.println("\nResultados:");
System.out.println("w1: " + w1);
System.out.println("w2: " + w2);
System.out.println("θ: " + θ);
System.out.println("\nIniciando fase de testeo...");
System.out.println("Introduce Entrada 1 (X1): ");
Scanner leerX1 = new Scanner(System.in);
double x1 = Double.parseDouble(leerX1.next());
System.out.println("Introduce Entrada 2 (X2): ");
Scanner leerX2 = new Scanner(System.in);
double x2 = Double.parseDouble(leerX2.next());
y = Math.tanh((x1 * w1) + (x2 * w2) + (-1 * θ));
y = (y >= θ) ? 1 : -1;
System.out.println("\nSalida: " + (int)y);
} else {
System.out.println("\nFase de aprendizaje ha fallado\n");
}
}
}
Resultado:
run:
Inicializar pesos:
w1: 0.3223614553902566
w2: 0.11581465997718018
θ: -0.4
Iniciando fase de aprendizaje puerta logica OR...
Entrada[1,1]) Valor esperado[1] Salida[1]
Entrada[1,-1]) Valor esperado[1] Salida[1]
Entrada[-1,1]) Valor esperado[1] Salida[1]
Entrada[-1,-1]) Valor esperado[-1] Salida[1]
Valor esperado difiere de la salida. Hay que reajustar pesos...
Ajuste de pesos (1):
w1: 1.5223614553902567
w2: 1.31581465997718
θ: 0.7999999999999999
Entrada[1,1]) Valor esperado[1] Salida[1]
Entrada[1,-1]) Valor esperado[1] Salida[-1]
Valor esperado difiere de la salida. Hay que reajustar pesos...
Ajuste de pesos (2):
w1: 2.7223614553902564
w2: 0.1158146599771801
θ: -0.4
Entrada[1,1]) Valor esperado[1] Salida[1]
Entrada[1,-1]) Valor esperado[1] Salida[1]
Entrada[-1,1]) Valor esperado[1] Salida[-1]
Valor esperado difiere de la salida. Hay que reajustar pesos...
Ajuste de pesos (3):
w1: 1.5223614553902565
w2: 1.31581465997718
θ: -1.6
Entrada[1,1]) Valor esperado[1] Salida[1]
Entrada[1,-1]) Valor esperado[1] Salida[1]
Entrada[-1,1]) Valor esperado[1] Salida[1]
Entrada[-1,-1]) Valor esperado[-1] Salida[1]
Valor esperado difiere de la salida. Hay que reajustar pesos...
Ajuste de pesos (4):
w1: 2.7223614553902564
w2: 2.5158146599771802
θ: -0.40000000000000013
Entrada[1,1]) Valor esperado[1] Salida[1]
Entrada[1,-1]) Valor esperado[1] Salida[1]
Entrada[-1,1]) Valor esperado[1] Salida[1]
Entrada[-1,-1]) Valor esperado[-1] Salida[-1]
Fase de aprendizaje terminado con exito
Resultados:
w1: 2.7223614553902564
w2: 2.5158146599771802
θ: -0.40000000000000013
Iniciando fase de testeo...
Introduce Entrada 1 (X1):
1
Introduce Entrada 2 (X2):
-1
Salida: 1
BUILD SUCCESSFUL (total time: 3 minutes 25 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.
Archivo del blog
-
►
2012
(38)
- ► septiembre (3)
-
▼
2014
(34)
-
▼
febrero
(7)
- Neurona Artificial (I). Perceptrón Simple.
- Neurona Artificial (II). Aprendizaje (puerta lógic...
- Neurona artificial (III). Aprendizaje (puerta lógi...
- Neurona artificial (IV). Perceptrón Multicapa.
- Operaciones matemáticas. Sumatorio.
- Operaciones matemáticas. Multiplicación de un vect...
- Neurona Artificial (V). Puerta lógica XOR.
-
▼
febrero
(7)
-
►
2020
(12)
- ► septiembre (1)
Suscribirse a:
Enviar comentarios (Atom)
Con la tecnología de Blogger.
Buen Día,
ResponderEliminarExcelente trabajo amigo, pero puedo preguntar de donde tomaste la teoría, me puedes ayudar con eso por fa.
Gracias!!
Inteligencia Artificial - Un Enfoque Moderno. Russel Norving
ResponderEliminarUna pregunta, Esto es aprendizaje no supervisado del perceptron?
ResponderEliminarConsidero que la forma en la que programaste el algoritmo no es la más eficiente (ni la más optima, en realidad), pues, a simple vista se puede ver que la red tiende a caer en mínimos locales y no en mínimos globales.
ResponderEliminarSiendo una red tan básica y con sólo 5 registros no es necesario tal optimización. Así también evitamos el exceso de código.
ResponderEliminarPara una red más compleja y con muchos más registros es evidente que este código no sería el idóneo.
Gracias por el apunte.
disculpe de donde salio el 2.5
ResponderEliminaren mis datos de entrada pongo -1 y -1 y el resultado me dá 1, algo anda mal.
ResponderEliminarerror mío
Eliminar