Para ello primero la red debe pasar una etapa de entrenamiento en la que se irán a recogiendo los movimientos que hace el usuario, es decir, que la red va a intentar aprender de lo que hace el jugador en este proceso de entrenamiento. Una vez entrenado, el juego debe enfrentarse contra lo que ha aprendido.
El juego está implementado en el lenguaje de programación Java y se hace uso de un framework de software libre neuroph. El juego se divide en tres etapas:
- Etapa de entrenamiento: El juego almacena lo que hace el usuario. En este punto, se recogen las acciones del usuario para poder pasárselas en una etapa posterior a la red neuronal.
- Etapa de aprendizaje: Se entrena la propia red neuronal, pasándole los valores entrenados con el valor deseado. Es por tanto una red con aprendizaje supervisado. Se emplea una red de tipo BackPropagation con Momentum para agilizar el proceso de aprendizaje.
- Etapa de juego: El juego se enfrenta con lo que ha aprendido. Se deduce que mientras más juegue el usuario en la etapa de aprendizaje, mejor entrenada estará la red y mejor será jugando en esta última etapa.
Interfaz gráfica
La interfaz gráfica consta de dos partes principales:
- Un panel de dibujo donde estará la pelota y la raqueta de juego.
- Una zona de control, donde estarán varios botones para el entrenamiento y el testeo del juego.
La clase ControlPanel corresponde con la creación de los botones y etiquetas con información. La clase MarcoPong es la encargada de componer todos los elementos de la ventana y de registrar los eventos de los botones como oyentes de la clase PanelDibujo. Es por ello, que la clase PanelDibujo también implementa las interfaz ActionListener.
Por último, la clase Test, instancia la clase MarcoPong y registra el exit para salir.
Clase Test
1 import java.awt.event.*;
2 import javax.swing.*;
3
4 public class Test {
5
6 public static void main( String args[]) {
7 MarcoPong frame = new MarcoPong("Pong Game");
8 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
9 frame.setVisible(true);
10 }
11 }
Clase MarcoPong
1 import java.awt.*;
2 import java.awt.event.*;
3 import javax.swing.*;
4
5 public class MarcoPong extends JFrame {
6
7 public static final int WIDTH = 400;
8 public static final int HEIGHT = 300;
9
10 public MarcoPong(String t) {
11 super(t);
12 setSize(WIDTH, HEIGHT);
13 JPanel panel = new PanelContenedor();
14 Container contentPanel = this.getContentPane();
15 contentPanel.add(panel);
16 }
17 }
18
19 class PanelContenedor extends JPanel {
20 PanelDibujo pd;
21 ControlPanel cp;
22
23 public PanelContenedor() {
24 pd = new PanelDibujo();
25 cp = new ControlPanel();
26 setLayout(new BorderLayout());
27 add(BorderLayout.CENTER, pd);
28 add(BorderLayout.EAST, cp);
29 cp.bTraining.addActionListener(pd);
30 cp.bStop.addActionListener(pd);
31 cp.bPlay.addActionListener(pd);
32 Thread t = new Thread(pd);
33 t.start();
34 }
35 }
Clase ControlPanel
1 import java.awt.*;
2 import java.awt.event.*;
3 import javax.swing.*;
4
5 public class ControlPanel extends JPanel {
6
7 public JButton bTraining;
8 public JButton bPlay;
9 public JButton bStop;
10 public static JLabel labelT;
11 public static JLabel labelG;
12 public static JLabel labelF;
13
14 public ControlPanel() {
15 // setLayout (new BorderLayout());
16 setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
17 setLayout(new GridLayout(8, 1, 2, 3));
18 bTraining = new JButton("Training");
19 bPlay = new JButton("Play");
20 bStop = new JButton("Stop");
21 labelT = new JLabel("Total: 0");
22 labelG = new JLabel("Goods: 0");
23 labelF = new JLabel("Failure: 0");
24 add(bTraining);
25 add(bStop);
26 add(bPlay);
27 add(labelT);
28 add(labelG);
29 add(labelF);
30 }
31 }
32
Entrada de datos
Al pulsar el botón Training comenzará la fase de recogida de datos que serán entregados a la red neuronal. Los datos a recoger son:
- La posición según eje x de la pelota.
- La dirección a la que va la pelota: 0 para la izquierda y 1 para la derecha.
El único dato de salida es:
- La posición x a la que tiene que ir la pelota.
Por tanto, a la entrada de datos, para cada par (x, dirección) se le asocia una salida que es la posición x de la raqueta.
Para representar los datos de entrada, se ha hecho la clase NetData que cuenta con los siguientes atributos:
- int dir : dirección de la pelota.
- double xracket: valor entre 0 y 1, pues la red neuronal trabaja con estos valores. Entonces se tiene que hacer es escalado a la entrada y salida de este dato.
¿Cómo se asocian los datos?
Se almacena el par (x, dir) cuando la pelota está en y = 10. Esto es una línea en la parte superior de la zona de juego tal y como se ve en la figura (la línea azul). A este par (x, dir) se le asocia como salida la x de la raqueta normalizada, esto es, dividiendo la x de la raqueta entre MAXX (constante en el programa que indica la dimensión de las x del panel de dibujo).
Entrenamiento MomentumBackpropagation
Se ha usado una topología de red multicapa fullconection con entretamiento tipo Backpropagation y función de activación sigmoide. El número de capas son 3: la capa de entrada a a red, la capa oculta que cuenta con 4 neuronas y la capa de salida con una neurona.
Creación de la red
78 multiLaterPerceptron = new MultiLayerPerceptron (TransferFunctionType.SIGMOID, 2, 4, 1);
Entrenamiento
357 mb = new MomentumBackpropagation(multiLaterPerceptron); 358 mb.setMomentum(0.9); 359 mb.setMaxError(0.1E-90); 360 mb.setMaxIterations(3000); 361 long t1, t2; 362 t1 = System.currentTimeMillis(); 363 mb.learn(trainingSet); 364 t2 = System.currentTimeMillis();
Salida de datos
Accedemos a esta parte pulsando el botón PLAY (previamente de tiene que haber entrenado). A partir de este momento, la salida x de la raqueta se obtiene tras haber introducido como entrada a la red la x y la dirección por la que va la pelota cuando y = 10. Es decir, cuando la pelota esté en y = 10, se obtiene la dirección de la pelota y su valor en el eje x. Esto se le pasa como entrada a la red neuronal y devuelve un valor de salida. éste, es un valor normalizado que habrá que multiplicar por MAXX para obtener la posición X de la raqueta.Referencias:
Código fuente completo:
Para compilar es necesario el compilador de java-sun. Además es necesario incluir el directorio org del framework neuroph en el directorio donde estén los fuentes de juego.


0 comentarios:
Publicar un comentario en la entrada