7.0 SUMMARY AND CONCLUSIONS
7.0.11 Effects of High Efficiency Lighting on the Entire School
En este epígrafe se explica cómo se realizará la implementación de las redes neuronales recurrentes como un clasificador que utiliza el algoritmo BPTT en su entrenamiento a partir del diseño que se describió anteriormente. Permitiendo la posibilidad de ampliación del software Weka. Se discute además la forma en que se implementan los principales métodos de cada clase.
II.3.1. Redes Neuronales Recurrentes para Clasificación.
La implementación de la RNR como clasificador se realiza en la clase
RecurrentNeuralNetwork que se encuentra dentro de las funciones del paquete
weka.classifiers.functions. Esta clase se implementa a partir de la metodología descrita en el epígrafe anterior. Basándonos en la implementación de la clase
MultilayerPerceptron que se encuentra ubicada en el paquete antes mencionado se hace un estudio detallado de los tipos de neuronas que se utilizan para la creación de las topologías que se proponen como posibles procesamientos de las salidas.
NeuralConnection es la clase abstracta que define la generalidad de las neuronas artificiales la cual posee los métodos necesarios para la creación, conexión y desconexión de las neuronas. Las conexiones de entrada y de salida se
41
almacenan en una lista de conexiones de forma tal que se conoce cuantas conexiones existen hacia y desde ella respectivamente. NeuralNode es la clase que representa a las neuronas de las capas ocultas de cualquier tipo de red y posee una lista de los pesos asociados a las conexiones de entrada a ellas, en esta lista el primer valor es el del umbral que se adiciona cuando se crea la neurona, los demás pesos se añaden según el orden de las conexiones que se vayan haciendo. Se implementan los métodos básicos para el cálculo de las salidas, errores y variación de los pesos. Además posee un atributo del tipo
NeuralMethod que indica a que tipo de neurona representa. NeuralMethod es una interface que implementa las funciones de cómputo para las neuronas de forma que las clases que la implementen, representen un tipo de neurona en específico por la función que empleen para calcular los valores de las salidas y los errores. Un ejemplo de estas clases son LinearUnit y SigmoidUnit que representan a las neuronas de tipo lineal y sigmoidal, usando para su cálculo las funciones (y=x y la mostrada en ecuación I.2) respectivamente. La clase NeuralEnd define los nodos de las capas de entrada y de salida; son las encargadas de relacionar a los atributos y clases obtenidas desde el fichero de los datos con las capas ocultas. A diferencia de las neuronas de la capa oculta estas no van a calcular los pesos ni los errores sino que los va a tomar de cierto modo del fichero en cuestión. Para su uso solo puede estar conectada a las clases ó los atributos, pero nunca a ambas a la vez. El atributo m_link es el que representa el valor de la clase o atributo representado. buildClassifier() implementa el algoritmo descrito para la aplicación del Backpropagation Through Time de una forma muy dependiente de la topología que se utilice porque es en dicha topología que se realizarán los cálculos necesarios. En la clase NeuralNode se implementa el método SetWeights() que permite introducir una lista de pesos de forma ordenada. Este método se utiliza para la replicación de los pesos en la red desplegada. Se debe tener cuidado al hacer uso del mismo porque si los pesos que se desean copiar no tienen el orden debido puede producirse un error de concepto en la replicación.
42
II.3.1.1. Topologías.
Como se explicó en la fase de diseño las topologías se agregan dentro del paquete weka.classifiers.functions.rnn.topology y está conformado por tres clases. La clase abstracta Topology es la que define la mayor parte de la topología de la red porque como se diría anteriormente es la que está compuesta por los nodos de entradas y las capas ocultas. Esto sucede porque la topología de las redes para las que se pensó la implementación de las redes recurrentes no difiere en esta parte de la modelación sino en la forma en que se conectan las salidas. A continuación se realiza un bosquejo de cómo se crea esta parte de la topología a la vez que se indican los métodos implementados y su funcionalidad.
Los métodos fundamentales son los siguientes:
setData() se utiliza para la inicialización de la matriz de conexiones de la red, que consiste en una matriz de cadenas que indica como se conectarán las neuronas. La figura 2.1 muestra como está conformada esta matriz.
La matriz de la figura 2.1 representa las conexiones tanto de la red original (m_conexion) como de la red desplegada (m_uconexion). Esta última es la misma red original pero replicada en el tiempo añadiendo las conexiones entre los diferentes tiempos según los operadores de desplazamiento. En esta matriz las filas representan las capas que tiene la red y las columnas las neuronas. Como se muestra en la figura en cada celda (c, n), donde n representa la neurona de la
Matriz de Conexiones 0 1 2 C 0 1 2 N
C – Cantidad de Capas de la Topología N – Cantidad de Neuronas por Capa
<capa>,<neurona>,< operador de desplazamiento> [ ;<capa>,<neurona>,<operador de desplazamiento>]
43
capa c, se tiene la información de todas las conexiones que parten desde la neurona n. Esta información se representa como sigue:
<capa>,<neurona>,<operador de desplazamiento>
[;<capa>,<neurona>,< operador de desplazamiento >]
Donde capa y neurona definen el destino de la conexión.
Unfolding() crea la matriz de la red desplegada m_uconexion que es la que se utilizará para crear las conexiones reales entre las neuronas de las capas de la red desplegada.
Hasta el momento sólo tenemos las matrices que nos indican como se enlazarán las neuronas. Teniendo esto en cuenta, antes de crear la red neuronal real (crear las neuronas y conectarlas) se verifica que no existan ciclos porque la existencia de alguno impediría la ejecución del algoritmo BPTT. Para esto se implementa el método Acycles() siguiendo los estándares de los grafos, recorriendo los nodos con una búsqueda primero en profundidad desde cada uno de los nodos de la red. En el caso de que exista un ciclo se lanza una excepción indicando el camino que representa el mismo, para que el usuario pueda corregir el error en la creación de la topología. OrganizeConnections() organiza las conexiones de la red de modo que, para tiempos distintos, las conexiones que se hacen a las neuronas análogas (que ocupan la misma posición en diferentes tiempos) tengan el mismo orden. Esto se hace porque, como se dijo en el epígrafe anterior, los pesos de las neuronas están asociados con las conexiones que se hacen hacia ellas. Si las conexiones no tienen el mismo orden, en el momento de replicar los pesos de la red, se comete el error de asignarle pesos diferentes a conexiones semejantes en neuronas homólogas. Con tal propósito se aplica una función de ordenamiento según la siguiente fórmula:
valor = |operador de desplazamiento| * 100000000 + capa * 1000 + neurona (2.1)
capa y neurona hacen referencia a la capa y neurona de destino que son las que se definen en la matriz de conexiones. Se ordenan los valores obtenidos de forma ascendente obteniéndose una lista que comienza por los enlaces de menor
44
retardo hasta los de mayor retardo modularmente. Pero queda un problema por resolver, cuando varias neuronas tienen el mismo valor se debe crear un orden adecuado. Se procede entonces al ordenamiento por los valores obtenidos en (2.1) y luego según las capas y neuronas desde las que se realiza la conexión en orden ascendente. Por ejemplo tenemos la siguiente matriz de conexiones.
0 1 2 tiempo 0 “4,1,1” “1,2,0;4,1,1” - 1 - “1,2,0” “2,0,1” 2 “1,0,0;2,1,0” - - 0 3 - “4,2,0” - 4 “0,0,-1” “4,2,0” - 5 “4,0,0;5,1,0” - - 1
Al ordenar según la estrategia trazada se obtiene la lista de conexiones ordenadas que se observa en la tabla 1.2 y que corresponde a las conexiones de las capas ocultas de la figura 2.1 Capa de origen Neurona de origen Capa de destino Neurona de destino Retardo de la conexión Valor obtenido Orden de conexión 0 0 4 1 1 100004001 10 0 1 1 2 0 1002 2 0 1 4 1 1 100004001 11 1 1 1 2 0 1002 3 1 2 5 0 1 100005000 12 2 0 1 0 0 1000 1 2 0 2 1 0 2001 4 3 1 4 2 0 4002 6 4 0 0 0 -1 100000000 9 4 1 4 2 0 4002 7 5 0 4 0 0 4000 5 5 0 5 1 0 5100 8
Tabla 1.1. Ejemplo de matriz de conexiones.
45
Luego de encontrar el orden en que se enlazarán los nodos es que se crea la red y se realizan los enlaces a los nodos creados, las conexiones anteriormente vistas fueron una representación de cómo serían los enlaces pero no los enlaces en sí.
En esta clase la red original no es creada como tal sino que se tiene una matriz
m_connect_changeinweights para almacenar los
∆
w, que son la sumatoria de los∆
w de los nodos semejantes de los diferentes tiempos y una matriz de los pesos de la misma. Este es un modo de ahorrar memoria pues no se crean estructurasLeyenda
Conexión con desplazamiento 0 +1 desplazamiento positivo o negativo según se indique Capa 2 Capa 1 Capa 0 -1 -2 Entradas Salidas 0 1 2 0 1 0 1 11 9 5 6 7 8 1 2 10 3 4 tiempo 0 tiempo 1 Capa 0 Capa 1 Capa 2 Capa 3 Capa 4 Capa 5 0 1 2 0 1 2 0 1 0 1 0 1 0 1 12 Capas ocultas de la red desplegada en 2 tiempos
46
innecesariamente. ActualizeWeights() es el método que se encarga de replicar los pesos en la red desplegada y hace una copia de estos en la matriz de pesos que representa a la red original m_conect_weights.
II.3.1.2. Posibles procesamientos de las salidas de redes
neuronales recurrentes para ser usadas como clasificadores.
Para el procesamiento de las salidas de las redes implementadas en este paquete se tiene en cuenta el tipo de red que se utiliza. En el caso de la red
Topology_FSCF que se muestra en la figura 2.3 se puede utilizar una de las funciones que se mencionaron cuando se trataba la problemática de diseño para el procesamiento de las salidas.
Para esto se implementa el paquete weka.functions.rnn.functions en el que se encuentran una interfaz y tres clases que la implementan. La interfaz
NeuralFunction contiene un solo método llamado Calculate() que es el encargado de dada una matriz que contenga los vectores de salida de los n tiempos en que se despliega la red devolver un solo vector que procesa las salidas en dependencia de la función que se implemente en la misma. Las clases
f f +1 -1 t t+1 t-1
47 AverageFunction, Max_ProbFunction y ModeFunction implementan las funciones del average, máxima probabilidad y moda en ese orden. Por otra parte para la clase Topology_CFSS el procesamiento de las salidas es distinto. En dicha clase se implementa una capa fija que debe ser la que actúa como capa de salida y a la que se conectan las capas de salida de la red pero tomando a estas como capas ocultas. La figura 2.4 muestra como se harían las conexiones.