Un Modelo Conceptual para el Desarrollo de Árboles de Decisión con Programación Genética Leonardo Jiménez Moscovitz Fundación Universitaria Konrad Lorenz Matemático Director: Dr. Nelson Obregón Neira IC, MSc, PhD. Especialización en Informática y Ciencias de la Computación 28 de mayo de 2007 Resumen Este trabajo explora la generación de árboles de decisión siguiendo la metodología de la programación genética. Al observar los algoritmos básicos clásicos como ID3 y algunas de sus limitaciones, surge la inquietud de aplicar la PG de la manera menos restringida posible, para así examinar las soluciones obtenidas. La presentación es conceptual, aunque se muestran aquí algunos fragmentos de código utilizado. 1 Índice Introducción 3 1. Árboles de Decisión y PG en el Marco de la IA 1.1. Inteligencia Artificial . . . . . . . . . . . . . . . . . . . . . . . . . 1.2. Aprendizaje Automático . . . . . . . . . . . . . . . . . . . . . . . 1.3. Reconocimiento de Patrones . . . . . . . . . . . . . . . . . . . . . 1.4. Minería de Datos . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.5. Árboles de Decisión . . . . . . . . . . . . . . . . . . . . . . . . . 1.5.1. Ventajas . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.5.2. Inducción de Árboles de Decisión. . . . . . . . . . . . . . 1.5.3. Algunos Métodos de Validación para Reducir el Sobreajuste. 1.6. Programación Genética . . . . . . . . . . . . . . . . . . . . . . . 1.6.1. Generalidades de la PG . . . . . . . . . . . . . . . . . . . 4 4 4 4 5 5 8 9 12 13 15 2. Generación de Árboles de Decisión con PG. 2.1. Tamaño del Espacio de Búsqueda . . . . . . . . 2.2. Aplicación de la PG a los Árboles de Decisión. 2.2.1. Ciclo Evolutivo General . . . . . . . . . 2.2.2. Generación de la Población Inicial. . . . 2.2.3. Operadores Evolutivos y Mecanismos de 2.2.4. Evaluación de los Árboles de Decisión . 2.2.5. Diseño General de la Solución . . . . . . 25 25 27 29 33 34 38 38 . . . . . . . . . . . . . . . . . . . . . . . . Selección . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3. Conclusiones 43 Referencias 44 2 varios meses varios varios varios meses meses meses varios meses Introducción El presente trabajo exploratorio que representa la investigación desarrollada durante algunos algo más de un mes, referente a la combinación de dos técnicas modernas meses y días de aprendizaje de máquina: los árboles de decisión y la programación genética. Se examinó bibliografía y software existente, y con base en esa exploración se decidió presentar un desarrollo conceptual que sirviera de base a la generación de árboles de decisión mediante programación genética, con la menor cantidad posible de restricciones, y lograr de esta manera la exploración más exhaustiva del espacio de búsqueda. La ciencia está dominada cada vez más por la necesidad de una aplicabilidad inmediata. La era del conocimiento en la cual se está adentrando la humanidad ha incorporado una competitividad comercial cada vez mayor, global e inmediata. Por lo tanto, se buscan afanosamente nuevas técnicas, que tengan aplicabilidad en el menor tiempo posible y además, que tengan interés comercial. Este es el caso de las técnicas de IA, muchas de ellas orientadas hacia la minería de datos. En la medida en que se pueda extraer información útil de una base de datos, más valiosas se hacen las herramientas que se utilizan para ello, y más apoyo reciben los investigadores que las desarrollan. La técnica de los árboles de decisión tiene grán interés por ser de aplicación sencilla y por ser una aplicación de caja blanca: Un árbol de decisión representa un conjunto de reglas si-entonces, y estas reglas se pueden extraer e interpretar de una manera sencilla. La construcción del mejor árbol de decisión es un problema de complejidad exponencial, y para algunos tipos de árbol puede llegar a ser un problema NP Hard [Llo07]. Los árboles que se obtienen pueden adolecer de algunos problemas, tales como el sobreajuste a los datos de entrenamiento o el excesivo tamaño. Los algoritmos tradicionales (ID3, C4.5 por ejemplo) no exploran todo el espacio de búsqueda. En este punto, la programación genética puede intentar un aporte en el proceso de construir un buen árbol de decisión. El modelo conceptual que se elabora intenta en primera instancia dejar que la evolución corra lo más libre posible, con el fin que permita observar los resultados obtenidos bajo esta aproximación. En un árbol de decisión, se espera que un recorrido desde la raíz hasta un nodo terminal no repita nodos con el mismo atributo. Sin embargo, aunque en la generación de los árboles iniciales se pueda restringir esta opción para obtener árboles suficientemente pequeños, no se piensa controlar este aspecto inicialmente. El objetivo que se persigue es que en las primeras implementaciones se pueda observar y examinar el proceso de evolución libre, en el cual la principal o tal vez la única presión evolutiva se deba a la aptitud de los árboles. En la sección 2.2 se presentan los algoritmos principales, y el esqueleto principal de la implementación en C++ mediante algunas clases simples. 3 1. 1.1. Árboles de Decisión y PG en el Marco de la IA Inteligencia Artificial La Inteligencia Artificial (AI) es una de las disciplinas más avanzadas dentro de las nuevas tecnologías de la información, y ha surgido como una respuesta a la necesidad de encontrar modelos y programas del llamado comportamiento inteligente [Mar87]. La AI trata con adaptación, aprendizaje o conducta inteligente, para ser desarrollada en máquinas o computadoras. En el orígen y desarrollo de la AI confluyeron dos puntos de vista: el científico, que intenta simular con el computador la verificación de teorías sobre los mecanismos de la inteligencia; y el de ingeniería, que intenta dar a los computadores capacidades lo más cercanas posibles a las intelectuales [Mar87]. Para ello los usuarios de AI se han debido enfrentar a cuestiones nuevas y muy variadas, y al pretender resolverlas ha desarrollado un enorme conjunto de innovadoras técnicas: representación y modelización del conocimiento, búsqueda heurística, aprendizaje automático, y técnicas de razonamiento aproximado entre muchas otras. Las diferentes técnicas que se han desarrollado a medida que evoluciona la AI no son excluyentes entre sí, sino que más bien se complementan unas a otras. Eventualmente algunas técnicas pueden desaparecer del interés de los investigadores cuando, según el estado del arte en un momento dado, estén suficientemente desarrolladas. 1.2. Aprendizaje Automático Al considerar la AI, es fácil ver que una de las áreas más importantes consiste en lo que se denomina aprendizaje de máquinas o aprendizaje automático (machine learning). Su objetivo fundamental es el desarrollo de técnicas que permitan que una máquina, la computadora, pueda generalizar comportamientos a partir de información no estructurada, y que se suministra en forma de ejemplos. La generalización del comportamiento es lo que se conoce como aprendizaje, que se puede considerar en general, perteneciente a uno de los siguientes dos tipos: inductivo y deductivo. El aprendizaje automático se clasifica dentro del tipo de aprendizaje inductivo, ya que estrae reglas y patrones a partir de conjuntos masivos de datos. 1.3. Reconocimiento de Patrones Esto nos introduce en el concepto de reconocimiento de patrones, como un campo del aprendizaje automático: el reconocimiento de patrones se puede definir como el acto de tomar datos no estructurados de entrada y encontrar en ellos categorías, reglas o patrones ocultos. Es de especial interés que las reglas obtenidas se puedan hacer explícitas y sean almacenadas en el computador, con 4 el fin de que sean utilizadas posteriormente para clasificar adecuadamente un conjunto de datos nuevo. 1.4. Minería de Datos Dentro de los campos de aplicación particulares que existen detrás del aprendizaje automático se puede encontrar principalmente la minería de datos. La disposición de enormes cantidades de información ha hecho crecer un gran interés en manipular dichos datos y extraer de ellos información que puede ser de valor para quien posee la base de datos. 1.5. Árboles de Decisión Dentro del área de la AI, y más exactamente dentro de la sub-área del aprendizaje automático se encuentran los árboles de decisión. Son utilizados principalmente con propósitos de clasificación, pero son también útiles para descubrir características de los datos que no son directamente visibles [Roa06]. Por este motivo, los árboles de decisión son importantes tanto en aplicaciones de clasificación como de minería de datos. Un árbol de decisión es en esencia un modelo predictivo, esto es, permite que las observaciones acerca de las características de un elemento conduzcan a conclusiones acerca de un valor objetivo. La técnica de aprendizaje automático que permite la inducción de un árbol de decisión a partir de un conjunto de datos se llama aprendizaje de árboles de decisión. Si se hace referencia a los árboles de decisión como una técnica, se dice que son un método para aproximar funciones objetivo de valor discreto. Definición 1.1 (Árbol de Decisión) Sea T un grafo acíclico dirigido, en el cual se cumple que cada nodo del grafo es 1. Un nodo no terminal o interno si tiene p nodos hijos, p ≥ 1. Los nodos internos están etiquetados con atributos. 2. un nodo terminal u hoja si el nodo no tiene nodos hijos. Los nodos terminales están etiquetados con clasificaciones. El conjunto de todas las hojas de T se llama T̂ . Cada nodo tiene exactamente un padre, a excepción del nodo superior o raiz, que no tiene padre. Cada arco o rama del grafo que sale de un nodo etiquetado con un atributo ai , está a su vez etiquetado con alguno de los posibles valores v de ai . Los nodos internos equivalen a pruebas de un atributo, y las ramas que salen de un nodo equivalen a las resultados para la prueba. Notación 1.1 Se utilizará la siguiente notación: El tamaño del árbol T se denota por |T | , y el tamaño del conjunto de terminales T̂ se denota por T̂ . 5 A trib u to i V a l_ 1 * * * A trib u to j V a l_ n A tr ib u to k * * * V a l_ 1 * * * V a lo r A t rib u to o b je t iv o V a l_ n 2 V a lo r A tr ib u t o o b je tiv o Figura 1: Estructura de un Arbol de Decisión Al conjunto de todos los atributos que conforman el árbol de decisión se le llamará A, y su tamaño será |A| . Al conjunto de todas las clases se les llama Y , y cada clase tiene asignada un valor entero, de tal manera que C = {0, 1, ..., K − 1} donde K ≥ 2 Por lo tanto, con esta definición, se tiene que la cantidad de nodos del árbol es |T | , mientras que la cantidad de hojas es T̂ . La estructura del árbol de la figura 1 muestra los nodos internos, ramas y hojas. Un nodo interno representa la prueba de un atributo, mientras que las ramas representan los diferentes valores que puede tomar el atributo. Las hojas representan los valores de clasificación para la secuencia de pruebas que va desde el nodo raiz hasta llegar a la hoja. Las entradas del árbol de decisión son un conjunto de características o atributos, que pueden representar objetos o situaciones. La salida correspondiente del árbol es un valor correspondiente del atributo que se desea conocer. Se puede también entender la salida del árbol como un valor booleano Si/No para los diversos valores de atributo de salida. La Tabla 1.1 muestra una tabla de datos usual, tal como se obtiene a partir de las bases de datos originales del usuario. La fila de encabezados de las n primeras columnas muestran todos los atributos considerados y por lo tanto contienen las pruebas para los nodos internos (por ejemplo ¿Cuanto vale el atributo A?). Las filas 1..m de las primeras n columnas son valores para los atributos considerados, y por lo tanto contienen las etiquetas de las ramas. Las 6 filas 1..m de la última columna son los valores de las clasificaciones para las filas correspondientes, y por lo tanto contienen las clases que se asignan para los nodos terminales. Es importante notar que algunos valores se pueden repetir, ya que no es forzoso que todos los m valores de cada columna sean diferentes. Tabla 1.1 Tabla de datos típica con m observaciones. Nombres Atributos → patrón 1 patrón 2 ... patrón m Atributo 1 A a1 a2 ... am Atributo 2 B b1 b2 ... bm ... ... ... ... ... ... Atributo n N n1 n2 ... nm Valor Objetivo CLASE Y1 Y2 ... Ym Definición 1.2 (Partición del Conjunto de Patrones) Una instancia es una entrada o patrón en la tabla de datos. Al conjunto de todos los posibles objetos descritos mediante los atributos se les conoce como espacio de instancias D. El espacio de instancias D se particiona usualmente en dos subconjuntos: un subconjunto de instancias de entrenamiento S y un subconjunto de instancias de validación V, tales que (S ∩ V ) = ∅ y (S ∪ V ) = D. Es conveniente que el tamaño de V sea de por lo menos el 20 % del tamaño de D, porcentaje que se considera aceptable para la mayoría de los casos, aunque otras técnicas proponen porcentajes diferentes (Sección 1.5.3). Si se toma un conjunto de datos con etiquetas, de m entradas, equivale a una secuencia de m parejas de la forma (Xi , Yi ), donde Xi ∈ Rn , siendo n es el número de características de clasificación, y Yi ∈ Y es una etiqueta de clasificación asignada al vector Xi . En la Figura 2, se tiene un espacio de instancias D que está determinado por una sola variable. La última columna contiene el valor objetivo; entre la última columna y las que le preceden existe una función oculta f. Luego la función objetivo f es un morfismo desconocido desde cada elemento del espacio de instancias hacia una etiqueta de clasificación objetivo. El proceso de inducción de los árboles de decisión pretenden hallar una función h, llamada hipótesis, que aproxime a la función f . Dado que existen muchas funciones que pueden aproximar a f , es conveniente definir un espacio de hipótesis H adecuado, en el cual se puedan encontrar todas las posibles hipótesis que se consideren útiles para el caso particular. Cualquier función booleana puede representarse mediante un árbol de decisión [Rus96]. En general, un árbol de decisión equivale a conjuntos de oraciones de implicación, con la forma de reglas Si-Entonces, en la cual se evalúan uno a uno los atributos para el conjunto posible de valores que puede tomar. Para el ejemplo de la tabla 1.1, el árbol de decisión correspondiente representa expresiones de la forma: 7 DATOS ENTRENAMIENTO En una Base de Datos: Y X (Valor Deseado) -0.27795786 -2.99004805 -0.27862448 -2.97802995 -0.27937055 -2.96462983 -0.27941987 -2.96374574 ... ... Función real f OCULTA ex + seno (1 / x) Se Tienen Nuevos Valores para x: Y X (Valor Estimado) -1.3546 ? -0.7903 ? 2.7937 ? 7.9419 ... Y X (Valor Estimado) -1.3546 -0.4149258 -0.7903 -0.50000184 2.7937 16.69172441 ? 7.9419 2812.825146 ... ... Hipótesis h ... Figura 2: Ejemplo de morfismo oculto y una hipótesis (caso de regresión). (A = a2 ) ∧ (N = n1 ) =⇒ Y1 (B = b1 ) ∧ (N = n2 ) =⇒ Y2 ...otras conjunciones... Esto es, el árbol de decisión se puede leer como una disyunción de conjunciones. Sin embargo, dado un problema real pueden existir muchos árboles capaces de representarlos adecuadamente. Algunos de ellos serán mejores que otros a la hora de clasificar correctamente nuevos datos, y se podría eventualmente encontrar el mejor o posiblemente, los mejores árboles árboles que lo hagan: el problema de encontrar un árbol óptimo no es de tipo polinomial sino exponencial; por lo tanto para problemas relativamente complejos, difícilmente o tal vez nunca se podrá garantizar que se ha encontrado un árbol óptimo [Rus96]. Cuando el investigador se enfrenta al problema de tener varios árboles con similar comportamiento, usualmente se utiliza la estrategia de Occam y se toma el árbol más pequeño (con el menor valor |T |). 1.5.1. Ventajas Dentro del conjunto de todas las herramientas de soporte a las decisiones disponibles actualmente, los árboles de decisión tienen algunas ventajas importantes. Los árboles de decisión son modelos de caja blanca: una vez se ha obtenido un modelo, es simple obtener de él una expresión matemática fácilmente interpretable, a diferencia de modelos de caja negra como las redes neuronales. La expresión final tiene una lectura e interpretación muy intuitiva lo que facilita su aplicación en múltiples disciplinas. 8 Soportan ruido en los datos de entrada. Permiten trabajar con pocos datos de entrenamiento: pueden suministrar algunas generalizaciones útiles a partir de pequeñas cantidades de datos. Poco costo computacional: los algoritmos principales y más conocidos para la generación de árboles de decisión (ID3, C4.5, etc) son bastante eficientes y consumen pocos recursos de máquina. Herramienta integrable: finalmente, los árboles de decisión son una herramienta que se puede combinar fácilmente con otras herramientas de minería de datos. 1.5.2. Inducción de Árboles de Decisión. El tipo de aprendizaje que se realiza al construir un árbol de decisión corresponde a un aprendizaje de tipo inductivo, supervisado, en el cual los datos de entrada con los que se realiza el aprendizaje, que se llaman ejemplo, dan siempre el valor esperado de la función. Para el caso de los árboles de decisión, los ejemplos son tuplas (x, f(x)) donde x es un vector de entradas y f(x) es la salida esperada. Como se ha mencionado anteriormente el proceso de inducción consiste en hallar, para un conjunto de datos de entrenamiento que contienen implícitamente una función f , una función h llamada hipótesis que la aproxime lo más posible [Rus96]. La verdadera definición de f se desconoce, y existen por lo general muchas opciones para elegir h, cada una de ellas consistente con el conjunto de datos de entrenamiento. Cualquier preferencia por alguna hipótesis en particular, más allá de esta consistencia, constituye un sesgo en el proceso inductivo, y se conoce como predisposición. Para presentarlo de manera matemática se deben establecer primero unas definiciones: Se llamará D al conjunto completo de instancias o patrones. Definición 1.3 (Hipótesis Consistente) Una hipótesis h se dice consistente con un conjunto de datos de entrenamiento S para la función objetivo f , si y solo si h(x) = y para cada tupla (x, y) ∈ S. Definición 1.4 (Error de Clasificación) Para una muestra de datos D de tamaño m, compuesta por tuplas (x, y) ∈ D, si una hipótesis h genera i clasificaciones incorrectas, entonces el error de clasificación de la hipótesis h se puede i determinar como eh = . Por tanto, 0 ≤ e ≤ 1. m Una hipótesis consistente debe tener un error de clasificación de 0, aunque esto no se pueda obtener en casos reales debido al ruido presente en los datos de entrada. Nótese además que se pueden definir otros tipos de medidas para determinar el error de clasificación. Dada la estructura general de un árbol de decisión, la manera más conveniente de construir un árbol de decisión se basa en un algoritmo clásico que 9 emplea búsqueda descendente (top-down) y egoista en el espacio de búsqueda de los posibles árboles de decisión. El algoritmo general de construcción de un árbol se puede expresar de diversas maneras [Joa07] [Gue04], [Mit97]. Una versión simplificada se observa en el algoritmo 1.1, tomado de [Mit97]. El interrogante que surge en este momento tiene que ver con el criterio que se utiliza para ejecutar la línea del algoritmo: “seleccionar el mejor atributo p del siguiente nodo”. En el caso de que se esté comenzando a construir el árbol, se trata entonces de seleccionar cual debe ser el nodo raiz. Los algoritmos ID3 y C4.5 de Quinlan son dos ejemplos de criterios para seleccionar los nodos de un árbol de decisión. La explicación que se expone a continuación se basa en el algoritmo ID3. Para seleccionar cada nodo, comenzando desde el nodo raíz, el algoritmo ID3 se pregunta: ¿Qué atributo es el mejor clasificador? La respuesta a este interrogante se halla tomando independientemente cada uno de los atributos, y verificando qué tan bien clasifica él solo a los datos del conjunto de entrenamiento S. El atributo que mejor los clasifique es tomado como el nodo raíz; y el árbol se seguirá generando con la misma concepción hasta finalizar. Los posibles valores que puede tomar el atributo seleccionado conforman las nuevas ramas que parten de este nodo hacia abajo [Gue04]. Los ejemplos de entrenamiento son repartidos en los nodos descendientes, de acuerdo con el valor que tengan para el atributo de la raíz. Es decir, se consideran para una determinada rama únicamente los ejemplos que coinciden con el valor del atributo de la raiz especificado en la rama. Algoritmo 1.1 (ID3 Versión Simplificada) Id3(S, C, A ) Ejemplos: Conjunto de patrones de entrenamiento (S). Clase: valor a predecir (C). Atributos: conjunto de atributos para verificar durante aprendizaje (A) 1. Crear raiz para el árbol de decisión 2. Si todos los ejemplos son de clase Ci entonces 3. devolver raiz con etiqueta Ci . 4. Si A = ∅ entonces 5. devolver raı́z con Ck = etiqueta más común en S. 6. En otro caso 7. Aj ←− atributo en A mejor clasificador (criterio de entropía.) 8. raiz ←− Aj 9. Para cada posible valor vi de Aj 10. Adicione rama debajo de raiz, para prueba Aj = vi . 11. sea Svi ,Aj ⊂ S patornes con valor vi para atributo Aj . 12. si Svi ,Aj = ∅ entonces 13. agrege debajo nodo con Ck = etiqueta más común en S. 14. si no es vacío, entonces 15. bajo rama agrege subárbol: Id3(Svi ,Aj , C, A − Aj ) 16. Fin. 10 17. Devuelve raiz. El algoritmo ID3 utiliza los trabajos desarrollados por Shannon para decidir cual es el mejor atributo en cada etapa de inducción del árbol. El método considera la ganancia en información que es capaz de proveer cada atributo. Dado un atributo vi , su probabilidad de ocurrencia es p(vi ). De acuerdo con los trabajos de Shannon, la cantidad de información o entropía asociada a este atributo es: Entropı́a(S) = n p(i) log2 i=1 1 p(i) Es conveniente cuantificar el costo de representar cada entrada de datos de entrenamiento mediante la cantidad de bits de información que se requieren para describirla. Cada bit tiene dos estados posibles, y es por ello que la teoría de la información utiliza logaritmos en base 2 para calcular la entropía. La entropía cuantifica de alguna manera la cantidad de ruido, desorden o impureza que tienen los patrones de una colección de patrones o de un sistema completo. Mientras más entropía tiene un sistema, más desordenado es, y mientras menos entropía se puede decir que presenta un patron más claro. La heurística del algoritmo ID3 utiliza el concepto de entropía para seleccionar el órden en que aparecen los atributos en el árbol. La heurística debe hallar el atributo que reduzca en mayor cantidad la entropía del conjunto de datos, logrando de esta manera que se reduzca la cantidad de información necesaria para describir completamente cada entrada del conjunto de datos de entrenamiento. En otras palabras, se busca el atributo que provea mayor ganancia G, para un conjunto de datos de entrenamiento S y un determinado atributo A: G(S, A) = Entropı́a(S) − |Sv | Entropia(Sv ) v∈A |S| donde |Sv | es el subconjunto de S para los cuales un atributo A toma el valor v, y el valor |S| El atributo que ofrecerá una mayor ganancia de información es aquel que más reduzca la entropía del conjunto de datos. De todos los atributos posibles, el que más ganancia de información ofrezca será seleccionado como nodo raíz, y así sucesivamente. De esta manera, el algoritmo ID3 realiza el proceso de búsqueda en el espacio de hipótesis H, encontrando en este proceso la hipótesis que mejor ajusta a los datos del conjunto de entrenamiento S. A medida que el árbol se va llenando, la hipótesis h es cada vez más compleja. Sin embargo, en el ID3 se presenta sesgo inductivo o preferencia en la búsqueda en los aspectos siguientes: 11 Hipótesis compactas: ID3 tiene preferencia por árboles pequeños sobre árboles grandes, intentando asegurar que la búsqueda termine siempre lo más cerca posible a la raíz. ID3 es un algoritmo egoista, de búsqueda primero en profundidad. De acuerdo con estos aspectos mencionados, es claro que ID3 no intenta explorar todo el espacio de búsqueda. Por lo tanto, se puede discutir si ID3 generaliza más allá de los datos observados. Otra pregunta fundamental es si el árbol encontrado es el menos parsimonioso posible. Dada la complejidad del problema, que es exponencial, los costos de averiguarlo pueden ser prohibitivos en tiempo y recursos de máquina. Por otra parte, existe la posibilidad de que el árbol encontrado mediante el algoritmo ID3 sea sobreajustado, y por lo tanto más que generalizar haya memorizado. Definición 1.5 (Sobreajuste) Dado un espacio de hipótesis H, se dice que h ∈ H está sobreajustado a los ejemplos de entrenamiento, si existe una hipótesis alternativa h ∈ H tal que h tiene error de clasificación menor que h para los patrones de entrenamiento, pero h tiene un error de clasificación mayor que h para la distribución completa de los ejemplares del problema, esto es: eh < eh con los patrones de entrenamiento S. eh > eh con todos los patrones D. Por lo tanto, al evaluar h con el conjunto de datos de validación V , es que se conocerá si hay sobreajuste. El sobreajuste se puede producir por diversos factores, uno de ellos es la presencia de ruido en los datos y el ajuste del árbol a presencia del ruido. Pero tal vez la principal fuente de sobreajuste es disponer de un conjunto de datos de entrenamiento S pequeño: mientras menos datos se tengan para entrenamiento, más fácil es que un modelo aleatorio cualquiera se ajuste a estos datos, a la vez que tiene un comportamiento pobre con los datos de validación. 1.5.3. Algunos Métodos de Validación para Reducir el Sobreajuste. La técnica común de dividir el conjunto de datos en datos de entrenamiento y datos de validación, reduce el conjunto de datos de entrenamiento y por ello contribuye de cierta manera al sobreajuste. Existen diferentes técnicas para reducir el sobreajuste, entre ellos está la poda del árbol. Para ello, se considera cada nodo del árbol como candidato a ser eliminado, y se observa el impacto de esta eliminación en el comportamiento general del árbol. El nodo se elimina solo si el árbol podado se comporta igual o mejor que el original [Rus96]. La técnica de poda del árbol es sin embargo costosa en recursos de computación. Por ello, se proponen otras técnicas para reducir el sobreajuste: la validación cruzada y la validación dejar-uno-fuera (leave-one-out validation). 12 Definición 1.6 (Técnica de la Validación Cruzada) Sea S el espacio de datos de entrenamiento, y sea P una partición de S en K subconjuntos de igual tamaño. El método de la validación cruzada consiste en que para cada Pi , 1 ≤ i ≤ K, se realiza el entrenamiento con la unión de los K − 1 subconjuntos restantes, y empíricamente se determina el error ei en el conjunto Pi , definido como la relación entre los errores de clasificación y el número de patrones en Pi (ver definición 1.4). El error final que devuelve es el valor promedio de todos los ei . En esta técnica se entrena y se evalúa con un conjunto diferente cada vez. El error final esperado de la iteración de aprendizaje deberá ser el valor promedio de todos los ei . Definición 1.7 (Técnica Leave-One-Out) Sea S el espacio de datos de entrenamiento, y sea P una partición de S en |S| subconjuntos. El método de la validación cruzada consiste en que para cada Pi , 1 ≤ i ≤ |S| , se realiza el entrenamiento con la unión de los |S| − 1 subconjuntos restantes, y empíricamente se determina el error ei en el conjunto Pi , definiendo ei = 1 si hubo error y ei = 0 si no lo hubo. El error final que devuelve es |S| ei e = i=1 . |S| La técnica dejar-uno-fuera toma todos los datos excepto uno para entrenamiento, y valida con el único dato disponible para validación. Cada vez se toma un patrón de validación diferente, repitiendo hasta que ha validado con cada uno de los datos disponibles. Las dos técnicas mencionadas son costosas computacionalmente, en particular la técnica leave-one-out, pero esta última reporta mayores beneficios a la hora de reducir el sobreajuste. Sin embargo, en la sección siguiente se definen los elementos básicos de una técnica que teóricamente puede ayudar en el proceso de generación y selección de un buen árbol de decisión. 1.6. Programación Genética A la hora de definir un algoritmo de inducción para un árbol de decisión, bien sea el ID3, el C4.5 o muchos otros, se puede estar definiendo un sesgo inadecuado en la búsqueda de la hipótesis h. Uno de los ingredientes que se han considerado a la hora de elaborar las metodologías de aprendizaje automático es la necesidad de la intuición humana en el análisis de datos. Algunos desarrolladores de sistemas de aprendizaje automático la intentan eliminar, mientras que otros desarrolladores la incorporan al tomar una aproximación colaborativa para la interacción hombre-máquina. Sin embargo, si se considera que el Ingeniero de Conocimiento debe especificar aspectos vitales como por ejemplo la representación de los datos y los mecanismos de búsqueda de patrones, se llega a la conclusión de que el factor humano y por tanto la intuición, no se puede eliminar totalmente [Mar87]. 13 La programación genética (PG) [Koz92] proporciona una técnica para reducir sustancialmente algunos sesgos propios de la orientación algorítmica o heurística de la solución. Se basa en reproducir computacionalmente algunas técnicas propias de la naturaleza que resultan en una mejor exploración de soluciones dentro de todo el espacio de búsqueda posible para un problema determinado. La PG es una extensión de la técnica de los algoritmos genéticos, donde los individuos que evolucionan son estructuras de tipo árbol que pueden modelar muchos tipos de problemas diferentes. Los árboles que evolucionan pueden representar expresiones matemáticas, programas de computador, secuencias de pasos para realizar una labor cualquiera, etc. Mediante técnicas como la PG, se reduce sustancialmente el sesgo inadecuado en la exploración del espacio de búsqueda de una solución. Estas técnicas evitan que el programa se quede examinando exclusivamente alguna zona del espacio de búsqueda: se produce una exploración más general del mismo, si bien por razones obvias de complejidad y tiempo computacional no se explora todo el espacio de búsqueda. Al igual que los árboles de decisión, la PG es un modelo de caja blanca: la solución que se halla es expresable, y en caso de tener una complejidad alta, se puede en muchos casos simplificar utilizando metodologías adecuadas de postprocesamiento de datos. Desde el punto de vista comparativo con la biología, la PG tiene preferencia por algunas de las características del pensamiento neo-darwiniano, que ha resumido Mayr [May88] y se presentan a continuación. Este grupo de características participan en la constitución del marco de la programación genética en general: El individuo es el objetivo primordial de la selección. La variación genética es en gran medida un fenómeno aleatorio: los procesos estocásticos juegan un papel significante en la evolución. La variación genotípica es principalmente un producto de la recombinación, y en últimas de la mutación. La evolución gradual puede incorporar discontinuidades fenotípicas. No todos los cambios son necesariamente consecuencias de selección natural ad hoc. La evolución es un cambio en adaptación y diversidad, no simplemente un cambio en las frecuencias de los genes. La selección es probabilística, no determinística. Los diferentes desarrollos de PG comparten gran cantidad de propiedades comunes con los modelos biológicos de la evolución:: 14 La PG utiliza procesos de aprendizaje colectivo de una población de individuos. Cada individuo representa o codifica uno de los puntos del espacio de búsqueda de las soluciones potenciales de un problema. Los descendientes son individuos generados por procesos aleatorios que pretenden emular la mutación y el cruce. La mutación se puede asimilar a un proceso de autoreplicación errada, en la cual cambios pequeños tienen mayor probabilidad de ocurrir que los cambios grandes. El cruce intercambia información entre (usualmente) dos individuos. Mediante la evaluación de los individuos en su ambiente, se puede asignar un valor de calidad o aptitud a cada uno de los individuos. El mínimo requerimiento es que los valores de aptitud sean comparables, de tal manera que se pueda conocer cual es mejor. De acuerdo con la medida de aptitud, el proceso de selección favorece los mejores individuos para que se reproduzcan más a menudo que los peores. La fortaleza de la metodología de la PG radica, entre muchos otros factores, en la diversidad y diferencias entre los individuos. Esa diversidad facilita que se explore mejor el espacio de búsqueda, y que durante el proceso evolutivo el sistema converja adecuadamente, es decir que se encuentre un individuo satisfactorio. Cuando por algún motivo los individuos de la población van perdiendo diversidad, por ejemplo cuando los buenos individuos dominan excesivamente la evolución, se habla de convergencia prematura. Si este es el caso, el proceso evolutivo puede quedar atrapado en un mínimo local y no se obtiene el resultado esperado, siendo necesario reiniciar el proceso. 1.6.1. Generalidades de la PG A continuación se van a examinar los elementos principales que intervienen en la técnica de la PG, con el fin de conocer algunos aspectos conceptuales generales importantes. Se expondrán algunas definiciones, por sencillas que parezcan, con el fin de hacer claridad en el uso de la terminología. En esta sección se tratarán los aspectos generales, mientras que detalles adicionales que han de definir los algoritmos se especifican en la sección 2.2. Se denomina población a un grupo de individuos que pueden interactuar juntos. Cada individuo es una solución potencial a un problema y su estructura en PG es de tipo árbol n-ario (figura 5). La principal manera en que interactuan los individuos es en los procesos de competencia entre ellos (torneo), y el los procesos de creación de una nueva generación. El ambiente o entorno es todo aquello que rodea a un individuo, y lo presiona de cierta manera al verificar si tiene el comportamiento esperado. El genotipo denomina a la composición genética de un individuo y que define sus potencialidades; en PG el genotipo determina la representación del problema en la estructura propia del individuo, el árbol. Por otra parte, el fenotipo denomina los rasgos observables del individuo. Durante el proceso 15 evolutivo en PG, debe existir una función que permita observar el fenotipo a que da lugar un determinado genotipo. La capacidad de computación actual permite que en PG esta función sea la más simple posible, ya que se puede operar de manera eficiente con estructuras computacionales complejas que se asemejan mucho al problema real y requieren la menor cantidad de codificación. (esto no vale para todas las técnicas, ya que por ejemplo los algoritmos genéticos sí requieren una alta codificación del problema). Desde el punto de vista del ambiente, la aptitud de un individuo es una función que permite evaluar su comportamiento, esto es, verificar en qué proporción cumple con determinadas habilidades y qué tan bueno es con respecto a los demás. Para el interés del propio individuo, la aptitud se define como la probabilidad de que el individuo viva y sea seleccionado para reproducirse (viabilidad), o también como una función del número de descendientes que este tiene (fertilidad del individuo). En la terminología de koza [Koz92], se denomina paisaje de aptitudes (fitness landscape) a la hipersuperficie obtenida al graficar la función de aptitud aplicada a cada punto del espacio de búsqueda explorado. La selección es el proceso mediante el cual algunos individuos de la población son seleccionados para reproducirse. Este proceso se lleva típicamente mediante una combinación de técnicas aleatorias y probabilísticas. Dentro de los tipos de selección, se pueden resaltar dos de ellos que son la selección dura y la selección blanda. La selección dura solo permite que los mejores individuos se mantengan para conformar una nueva generación. La selección blanda tiene lugar cuando se utilizan métodos probabilísticos que de alguna manera permiten que individuos de aptitud baja también participen en la formación de una nueva generación. Se llama generación a cada iteración que obtiene una nueva población al aplicar operadores evolutivos. Una nueva generación implica una nueva medida de la aptitud (fig 3). Los operadores evolutivos que se trabajarán aquí son principalmente tres: operador de cruce, de clonación y de mutación, si bien el proceso de selección también es considerado como un operador genético. El operador de cruce forma un nuevo cromosoma (individuo en PG) combinando partes de cada uno de los cromosomas (individuos) padre. El operador de mutación forma un nuevo individuo mediante alteraciones aleatorias de parte de la estructura del individuo padre. El operador de clonación crea una réplica del padre en la nueva generación. Este operador es la base del elitismo, que es una técnica que garantiza que el mejor individuo (o los mejores individuos) de cada generación, pase a la generación siguiente sin modificaciones, asegurando que la aptitud máxima obtenida en la población nunca decrezca. Estos elementos descritos se pueden ver de manera gráfica en la figura 3. De manera más formal Bäck y otros autores han definido algunos de los elementos que conforman el marco de trabajo para PG así [Bac00]: Notación 1.2 Sea I el espacio arbitrario de todos los individuos a ∈ I. Sea F : I → R una función de aptitud para los individuos. 16 Población Inicial (Generación Aleatoria): + x Aplicar Función de Aptitud (Evaluación) + + * cos 7 exp seno x / exp x x 1 x ¿Alguno Cumple Condición Aptitud=UMBRAL? tan + * tan x 3 3 Operadores Evolutivos * Nueva Generación: senh + x inv m + inv m exp seno x / + * ln x 3 1 x x ln 3 3 Figura 3: Esquema gráfico del proceso evolutivo en PG Sea µ el tamaño de la población de padres. Sea λ el tamaño de la población de hijos. Sea P (t) = (a1 (t), a2 (t), ..., aµ (t)) ∈ I µ una caracterización de la población en la generación t. Sean s : I λ → I µ , m : I κ → I λ , r : I µ → I κ operadores evolutivos de selección, mutación y cruce respectivamente. Sean θι , θr , θm , θ conjuntos de parámetros para condiciones de terminación, de los operadores de cruce y mutación y generales. Es importante notar que para el caso del presente trabajo, se puede tener a convenciencia µ = λ = κ. El diagrama de flujo general de la PG se observa en la figura 4, mientras que [Bac00] propone un algoritmo en pseudocódigo con algunas modificaciones, tal como aparece en el algoritmo 2.1. La población está conformada por individuos o árboles, cuya aptitud debe ser medible por el entorno. Lo que se exige en primera instancia, es que la estructura del árbol sea sintácticamente correcta para modelar el problema deseado, y que esa corrección sintáctica se mantenga a medida que progresa la evolución. Además, en cualquier algoritmo de PG es importante tener en cuenta dos aspectos muy importantes: 1. La aptitud de la nueva generación debe estar relacionada con la aptitud de la generación de padres. Si esto no fuera así, el proceso degeneraría en una búsqueda aleatoria. 17 Generación = 0 Crear Población Inicial Evaluar Aptitud de Cada Individuo ¿Cumple Criterio Terminación? Si Generar Resultado No Fin Individuo = 0 Generación = Generación + 1 Si ¿Individuo = M? No Seleccionar Probabilísticamente Operador Genético Clonación / Mutación Seleccionar Un Individuo Probabilísticamente y por Aptitud (Torneo) Clonación Cruce Seleccionar Dos Individuos Probabilísticamente y por Aptitud (Torneo) Mutación Individuo = Individuo +1 Realizar Reproducción Realizar Mutación Realizar Cruce Insertar Nuevos Individuos en Nueva Población Insertar Nuevos Individuos en Nueva Población Individuo = Individuo +1 Figura 4: Diagrama de flujo para la PG (Modificado de [Koz92]) 18 Regla: B b1 b2 E 2 2 d1 e2 d3 3 e1 D 1 Si O Si O Si O Si O Si B=b1 y D=d1 entonces 1 b=b1 y D=d2 entonces 3 B=b1 y D=d3 entonces 2 B=b2 y E=e1 entonces 2 B=b2 y E=e2 entonces 3 3 Figura 5: Ejemplo de árbol de decisión representado en PG. 2. Cualquier variación heredable puede ser introducida en la aptitud de la nueva generación. Si no fuera así, no sería posible un mejoramiento contínuo en la búsqueda de un óptimo. Al igual que en los árboles de decisión, los individuos de la población en PG son árboles con nodos internos, ramas y nodos terminales. En el caso general, los nodos internos de un árbol en PG representan funciones, y las ramas enlazan con otros nodos hijos que son los diferentes argumentos que puede tener una función determinada; los nodos terminales representan ya sea constantes o variables que toman su valor de los datos de entrada (que se lee en el momento de la verificación de la aptitud del individuo, de validación o en la aplicación final). Los nodos y ramas de un árbol de PG puede representar objetos muy diferentes. En la figura 5 se observa un árbol que representa una árbol de decisión típico. Los nodos terminales y no terminales se construyen a partir de un conjunto de funciones llamadas funciones primitivas, que pueden por ejemplo funciones matemáticas típicas o funciones construidas a gusto del diseñador. El sistema evlutivo debe construirse de tal manera que cumpla con el requisito de clausura [Koz92], que especifica que un nodo terminal acepte cualquier valor posible del conjunto de datos de entrada, y que un nodo no terminal acepte de los nodos hijo cualquier valor que ellos puedan suministrar y que utilice el sistema. Generación de la Población Inicial. Una característica propia de la PG es la metodología que sigue para generar los individuos y evolucionarlos, es que que se basa en todo momento, en métodos probabilísticos. Para generar la población inicial, se define previamente un tamaño de población m, cuyo valor recomendado varía de acuerdo con diferentes factores entre ellos la complejidad del problema. Un valor típico de m puede estar en el rango comprendido de 300 19 a 500 individuos. Luego, se comienza a crear lo que se llama población inicial donde cada uno de los m individuos es generado de manera aleatoria en buen grado. De manera resumida se puede ver que el proceso de generación de cada individuo de la población inicial consiste en establecer probabilísticamente los tipos de nodo (terminales y no terminales), escoger probabilísticamente las funciones o tipos de nodo terminal según corresponda, y así sucesivamente hasta completar el individuo con nodos terminales. El algoritmo se puede observar en la sección 2.2. Datos de Entrenamiento y Validación. Todo sistema de aprendizaje automático requiere un conjunto de valores de entrenamiento o aprendizaje S. Para el caso de la PG, la filosofía es la misma que para la inducción de árboles de decisión: se dispone de un conjunto de datos D, del cual se toma un subconjunto S para entrenamiento y un subconjunto V para validación, tal que cumplan con la definición 1.2. Evaluación de los individuos. Una vez que se ha generado la población, y se dispone tanto del conjunto de datos de entrenamiento y validación, el paso siguiente consiste en evaluar los individuos para verificar qué tambien ajustan a los datos. Esta medida se llama medida de aptitud. Esta medida debe ser capaz de evaluar cualquier individuo posible que se encuentre en la población, con cualquiera de los datos disponibles. Para ello, se toma cada uno de los individuos y se les suministra como entrada cada una de las entradas en S. Para cada individuo, se calcula el error cometido al evaluarlos con todas las tuplas de datos en S. Las diferentes maneras de cuantificar el error nos dan diferentes medidas posibles de aptitud. Operadores Evolutivos. Los operadores evolutivos son principalmente: selección, cruce, mutación y clonación. Se pueden definir nuevos operadores evolutivos de acuerdo con la conveniencia del investigador. En la reproducción, un individuo es seleccionado probabilísticamente, de acuerdo con su aptitud, para ser replicado en la nueva generación. En la mutación, un individuo es seleccionado probabilísticamente de acuerdo con su aptitud. Aleatoriamente se selecciona un nodo cualquiera del árbol, diferente del nodo raiz. Todo el subárbol que se encuentra bajo el nodo seleccionado se elimina, y su lugar es reemplazado por un nuevo árbol generado probabilísticamente, de la misma manera como se genera cualquier árbol de la población inicial. El nuevo individuo obtenido pasa a formar parte de la nueva generación (Figura 6). En el cruce, que se puede observar en la figura 7, la diferencia consiste en que se seleccionan dos individuos. En cada uno de ellos, se selecciona alatoriamente un nodo no raiz. Los subárboles ubicados bajo cada nodo seleccionado se intercambian. Los dos individuos resultantes pasan a formar parte de la nueva generación. 20 HIJO PADRE SELECCIONADO 3 1 2 1 E 3 1 3 e2 Nodo con atributo X d3 X 1 D d1 1 e1 e1 3 c3 c2 b1 c1 e2 2 E C e2 d3 1 ARBOL NUEVO E d1 D b2 b1 b2 PUNTO DE MUTACION B NUEVA GENERACIÓN e1 B GENERACIÓN ACTUAL 2 x x=Resultado de evaluar X 1 Clasificación Figura 6: Mutación de un árbol de decisión. Elitismo. Un concepto importante en la evolución artificial es el elitismo. Se puede pensar que no tiene mucho sentido que se pierda el mejor individuo al crear una nueva generación, ya que muy posiblemente ha sido el fruto de un proceso evolutivo y el sistema debería posiblemente trabajar mucho para obtener un individuo similar. Siendo así, las evoluciones artificiales consideran típicamente replicar o clonar el mejor individuo de una generación, en la generación siguiente. Selección de Individuos. La selección de los nuevos individuos se puede realizar mediante estrategias diferentes; en el presente trabajo se considerará únicamente la selección por torneo. La literatura de PG básica, por ejemplo [Koz92] compendia algunas técnicas principales de selección, aunque existen diferentes variantes para implementarlas: 1. Selección Proporcional (fitness proportionate): los individuos se eligen de acuerdo con la contribución de su aptitud respecto de la aptitud total de la población. Esta técnica tiene diferentes implementaciones: La técnica de la ruleta, la técnica del sobrante estocástico, la técnica universal estocástica, y la técnica del muestreo determinístico. Sin embargo, se debe tener en cuenta que si existe una supersolución en la población, esto es, un individuo excepcionalmente bueno con respecto a todo el resto de invididuos, una selección basada en la aptitud escogerá muy probablemente 21 INDIVIDUO SELECCIONADO 1 INDIVIDUO SELECCIONADO 2 GENERACIÓN ACTUAL C A e1 b1 f2 e1 e1 b1 d1 c1 3 3 e2 1 1 E F e2 d3 3 E e2 1 E 2 1 B b2 b2 D 1 PUNTO DE CRUCE C B PUNTO DE CRUCE c3 c1 c2 a1 a2 1 2 NUEVA GENERACIÓN HIJO 1 HIJO 2 A C c1 1 2 e1 d1 c1 1 E E 3 1 e2 e1 b1 b2 X 1 C F Nodo con atributo X 3 f2 x=Resultado de evaluar X c2 c1 x 1 3 1 Clasificación 2 Figura 7: Cruce de árboles de decisión. 22 e2 B d3 b2 b1 1 D C B c3 c2 a1 a2 2 2 la misma solución; la población perderá rápidamente diversidad y se tendrá una convergencia pramatura hacia una solución subóptima.Por otra parte, si en la selección proporcional todos los individuos tienen aptitudes muy parecidas, el proceso se asemeja a una selección aleatoria. El método proporcional trata de evitar estos problemas utilizando un esquema de escalamiento y mapeo de la aptitud de cada individuo predefinido [Gol89]. 2. Selección por Torneo: El torneo consiste en seleccionar aleatoriamente dos o más individuos, y hacerlos competir con base en la aptitud de cada uno. El que tenga la mejor aptitud, es seleccionado. El método del torneo ayuda a evitar en gran parte uno de los problemas que puede enfrentar la PG simple: la convergencia prematura. Mediante la realización del torneo, cualquier individuo, incluso un mal individuo, puede participar en la nueva generación (esto es garantizado por la selección aleatoria inicial de los dos individuos). Si los individuos utilizados para crear una nueva generación se seleccionaran únicamente con base en la aptitud, al cabo de unas cuantas generaciones se tendría una población excesivamente homogénea, conformada por individuos idénticos o muy parecidos, usualmente los mejores individuos encontrados en las primeras evoluciones. Se tienen 2 métodos para aplicar la selección mediante torneo: a) El método determinístico: se escoge el número de invididuos a seleccionar, se eligen estos de manera aleatoria y luego se comparan con base en la aptitud. Este esquema puede manejar tanto problemas de minimización como de maximización sin necesidad de cambios estructurales en la función de aptitud, además de poderse paralelizar fácilmente [Bac00]. b) El método probabilístico: similar al anterior, excepto que se generan valores aleatorios que tendrán mayor probabilidad de seleccionar el individuo más apto. Una característica de la PG es que utiliza intensivamente métodos aleatorios y métodos probabilísticos. En diferentes procedimientos se deben generar aleatoriamente, valores de un tipo y un rango seleccionable por parte del usuario. En el caso de la selección de un individuo para aplicar un operador genético por ejemplo, PG realiza lo que se denomina torneo. Selecciona aleatoriamente un individuo y luego otro, y los pone a competir. Para ello, genera un número aleatorio entre 1 y el tamaño de la población. El entero retornado indica cual es el primer individuo seleccionado. Repite el proceso, cuidando de no seleccionar el mismo individuo. Una vez que se tienen los dos individuos para el torneo, se pueden aplicar varios métodos para determinar cual es el ganador: uno de ellos consiste en competir directamente basados en la aptitud. El otro método consiste en normalizar las aptitudes en la escala (0, 1) para luego hallar un valor aleatorio entre 0 y 1. El individuo que corresponda al rango donde cae el valor aleatorio, es el individuo seleccionado. 23 Otro caso similar ocurre cuando se trata de seleccionar cual operador evolutivo aplicar al individuo. Cada operador evolutivo tiene una probabilidad de ocurrencia ubicada en el rango [0, 1]. En todo caso, la suma de las probabilidades consideradas debe ser 1. Se segmenta el intervalo [0, 1] y a cada probabilidad se le asigna un segmento dentro de ese valor (tal como una ruleta). Se genera un valor aleatorio, y se verifica a qué operador evolutivo corresponde el intervalo donde cae dicho valor, para retornarlo como operador seleccionado. Ejemplo 1.1 Este ejemplo utiliza el método de la ruleta para seleccionar un operador evolutivo. Si PX = Prob. de Cruce, PC = Prob. de Reproducción o Clonación y PM = Prob. de Mutación, entonces si se tienen los valores para las probabilidades: PX = 0,95, PC = 0,03, PM = 0,02. Los rangos se pueden establecer: cruce = 0 − 0, 95; clonacion = 0,95 − 0, 98; mutación = 0,98 − 1. Si es el caso que por ejemplo, se genere un valor aleatorio de 0, 961, entonces el operador seleccionado es la clonación. Para seleccionar individuos el proceso es análogo, pero en este caso se trabaja con un valor de probabilidad del individuo i, que se puede llamar Pi y cuyo valor está asociado a la aptitud del mismo. Una vez asignados los valores de probabilidad para cada individuo de la población, o para cada individuo que participa en un torneo, el programa continúa de manera similar a la que se acaba de mostrar. Criterio de Terminación. La población continuará evolucionando hasta tanto no se cumpla un criterio que nos diga o bien que ha pasado una cantidad de generaciones excesiva, o se ha logrado un individuo que aproxima suficientemente bien al conjunto de datos de entrenamiento y validación. En cualquiera de los dos casos, el programa devuelve el mejor individuo encontrado hasta el momento. 24 2. Generación de Árboles de Decisión con PG. En este capítulo se va a explorar una técnica que combinan la aplicación de árboles de decisión, los cuales van a ser generados mediante técnicas de GP: Por una parte, se aplican los árboles de decisión como una representación de un conjunto de reglas que se pueden extraen de unos datos de entrenamiento. Por otra parte, se trata de utilizar la programación genética como mecanismo para generar y buscar un buen árbol; esto es, un árbol que represente un conjunto de reglas que clasifiquen correctamente los datos de entrenamiento, validación y los nuevos datos que lleguen. Bajo esta perspectiva, se reducen o eliminan sustancialmente algunos de los problemas inherentes a los árboles de decisión utilizando algoritmos como el ID3 o C4.5. Por ejemplo, se reduce el sesgo inductivo, por cuanto la programación genética explora más libremente. Existen trabajos en esta área, tanto teóricos como de aplicación práctica, por ejemplo [Llo07] quienes presentan alguna teoría y aplicaciones con el algoritmo GALE (Genetic and Artificial Life Environment) para evolución paralela de árboles de decisión. En [Dim06] se presenta una propuesta de técnicas evolutivas para construir árboles de decisión generalizados. El esquema que se va a trabajar es el de generar un diseño conceptual de un sistema evolutivo que permita trabajar con árboles de decisión, que incorpore las técnicas básicas, aunque tenga posibilidad de crecimiento futuro. Al incorporar la menor cantidad de heurísticas posibles, se espera observar el proceso evolutivo de los árboles en condiciones de máxima “libertad” posible. 2.1. Tamaño del Espacio de Búsqueda A continuación se propone una manera de estimar el tamaño del espacio de búsqueda para la solución de problemas mediante árboles de decisión para atributos binarios. La expresión se ha desarrollado inductivamente. Ello se basa en algunos supuestos: 1. Inicialmente se supone, por simplicidad, que todos los atributos son de tipo binario. 2. Cada árbol se puede llenar con plena libertad. Esto incluye, al menos teóricamente, que se puedan generar árboles con un único nodo, el nodo raíz, y que obviamente su valor debe corresponder a uno de los valores de clasificación. 3. Se supone que se tiene una tabla de patrones, y que en ella se identifican |A| atributos diferentes. Cada uno de ellos puede tener una cantidad diferente de valores posibles para sus atributos. Sea vAi el conjunto de los valores que puede tomar un atributo Ai , y sea |vAi | la cantidad de dichos atributos. 4. Sea rL la cantidad de ramas por nivel L. Para el nivel 0 se toma r0 = 1, y para los nodos siguientes, se toma r1 = 2, r2 = 4. 25 5. Para el primer nivel, el nodo raíz, se tienen |A| + T̂ maneras distintas, donde T̂ es la cantidad de tipos de nodo terminal que se dispone. 6. El nivel máximo que puede alcanzar el árbol, sin repetir atributos en un recorrido cualquiera es |A| , siendo el nodo raiz el nodo 0. Las opciones para escoger un nodo determinado en cada nivel L son de: |A| − L + T̂ Mientras que las opciones para llenar desde el nodo raiz hasta los nodos de un nivel L, dada una selección previa del nodo raíz, son de: rL−1 (|A| − (L − 2))L! · |A| − (L − 1) + T̂ 7. La cantidad aproximada de árboles puede estimarse como 2L! · 3rL−1 · |A| + T̂ . Esto no indica que sean árboles diferentes, ya que muchos de dichos árboles serán equivalentes entre sí, disminuyendo la cantidad de árboles diferentes. Sin embargo, esta expresión da una idea aproximada de la magnitud del espacio de búsqueda. Ejemplo 2.1 Se dispone de 2 atributos binarios y 2 clasificaciones posibles. Se desea calcular cuantos árboles distintos se pueden generar. Se tiene |A| = 2, el nivel máximo P = 2, T̂ = 2. Para llenar el nodo raíz L = 0 se dispone de |A|+ T̂ = 4 opciones. Además r0 = 1 22! ∗ 32 ∗ 2 + 2 = 74 Ejemplo 2.2 Se dispone de 3 atributos binarios y 2 clasificaciones posibles. Se desea estimar cuantos árboles distintos se pueden generar. Se tiene |A| = 3, el nivel máximo P = 3, T̂ = 2. Para llenar el nodo raíz L = 0 se dispone de |A|+ T̂ = 5 opciones. Además r0 = 1 23! ∗ 34 ∗ 3 + 2 = 15 554 Estos ejemplos muestran como el espacio de búsqueda crece enormemente con pequeños cambios en la cantidad de atributos o de clases. En los ejemplos de esta sección se han considerado además que todos los atributos tienen valores binarios, lo que reduce además el espacio de búsqueda, si bien en los problemas reales es común que se encuentren atributos que pueden tomar 3 o más valores. La aridad de las funciones, en la expresión que se ha utilizado para la estimación, afecta los exponentes y por tanto tiene un impacto alto en la cantidad de árboles que se pueden encontrar. Es por ello que la búsqueda o verificación del mejor árbol no puede hacerse de manera exhaustiva en casos reales, por el alto costo computacional que ello implica. 26 2.2. Aplicación de la PG a los Árboles de Decisión. Como todo problema abordado mediante la técnica de la PG, la generación de árboles de decisión mediante requiere definir lo siguiente: 1. Seleccionar el mecanismo de representación de los árboles de decisión en PG.. 2. Conjunto de nodos terminales. Estos corresponden a las diferentes clases que se pueden extraer de la tabla de patrones de entrada. 3. Conjunto de Nodos no terminales. Estos corresponden a los diferentes atributos, que se extraen habitualmente de los encabezados de las columnas de la base de datos o tabla de patrones. La solución del problema se aborda desde el paradigma de la programación orientada a objetos y metodologías y herramientas relacionadas, tal como lo es UML, ya que esta última permite un modelamiento conceptual tanto del problema como de la solución. Se presentará en esta sección algunas generalidades que permitan interpretar mejor algunos segmentos de código que se presentan. En primera instancia, se requiere modelar como va a interactuar un usuario con el sistema final. Al examinar esta interacción, lo que se conoce como caso de uso general, y se observa en la figura 8. Cada uno de los óvalos muestra una función u operación principal, que requiere una descripción más detallada. Dentro de los productos finales que se obtienen a partir de los diagramas de casos de uso se encuentran los principales algoritmos y por tanto las diferentes funciones que se incluirán en el programa. Además, el diagrama general de casos de uso sirve de ayuda al momento de definir la estructura del programa principal. Es así como a partir del diagrama de la figura 8, se puede expandir la información de cada uno de ellos. El desarrollo de las técnicas de modelamiento con UML por una parte sugieren algunas clases, y la traducción algorítmica dentro del lenguaje final seleccionado y la estructura de clases decidida finalmente origina un código. Es neceario definir como se va a representar el árbol de decisión a evolucionar dentro de la PG. En la figura 9, los recuadros son nodos y las flechas son apuntadores; al observar la estructura del nodo padre, se ve que solo tiene 3 apuntadores: al propio padre, al primer hijo y al hermano. Luego al observar cómo se relaciona un nodo con los demás nodos que conforman un árbol se tiene la mecánica de ciertas funciones que requieren recorrer los nodos de un árbol.: Las funciones que ubican nodos Por ejemplo, el nodo padre solo puede conocer al nodo hijo 2 a través del nodo hijo 1. La solución se puede ver en la figura 10. No es un gráfico UML, pretende mostrar no solo los objetos y sus relaciones entre sí, sino algunas de las funciones que se requieren para el correcto funcionamiento del programa final. Por una parte, el entorno evalúa a cada árbol de decisión. Para ello, el programa debe leer la base de datos original para luego construir las tablas de 27 Cargar Parametros Modificar Parametros Cargar Datos Aplicar Torneo Usuario Generar Poblacion Aplicar Elitismo <<include>> evolucionar Aplicar Operador Evolutivo Clonar Cruzar Evaluar Poblacion Mutar <<extend>> Terminar Evolucion Figura 8: Diagrama general de casos de uso. datos de entrenamiento o validación. El programa debe examinar la base de datos original para extraer de allí los diferentes atributos, y para cada atributo debe identificar y extraer cada uno de los valores posibles. Con esta información se llena un objeto de tipo DT (Figura 10) La tabla DT es examinada cada vez que se desea construir un árbol de decisión, con el fin de determinar el número máximo de nodos que puede corresponder a cada atributo. Por ejemplo, para un atributo A, se tienen i valores posibles. La última columna Y corresponde a la clase que se debe asignar a cada patrón de entrada para los datos de entrenamiento y validación. En este ejemplo, se tienen k clases diferentes para ser asignadas a cada patrón. Bajo esta perspectiva, evaluar un árbol es en gran manera equivalente a realizar cada uno de los recorridos que indica el patrón de datos, del árbol partiendo del nodo raiz. Cuando se encuentra una clasificación (nodo terminal), se contrasta con la clase presente en el patrón de entrenamiento. Si coinciden, se anota un acierto 28 Nodo Padre Nulo Nodo Padre Nodo Hermano Nulo Nodo Hijo Nodo Raiz Nodo Hijo 1 Nodo Hijo 2 Nulo Nulo Figura 9: Estructura computacional de un nodo raiz con dos hijos. (hit [Koz92]). Una posible medida final de la aptitud es la propuesta en 1.4. 2.2.1. Ciclo Evolutivo General El caso de uso evolucionar representa el ciclo principal del programa en el cual se tiene una población de árboles de decisión en evolución. Se ha definido de forma bastante abstracta en primera instancia, aunque iteraciones posteriores lo deben detallar y mejorar. El flujo de eventos de este caso de uso se expresa en los algoritmos 2.1 y 2.2. El primero es una versión general de los algoritmos evolutivos que se aplicar muy bien al caso de la PG, mientras que el segundo corresponde de manera general a la propuesta de Koza [Koz92] con algunas modificaciones y simplificaciones. Algoritmo 2.1 (Algoritmo Evolucionario Básico) Describe el ciclo principal de la PG, según modelo propuesto en [Bac00]. Input: Output: µ, λ, θι , θr , θm , θ, F (t) θ ι : parámetros de configuración de condiciones de terminación. ι(P (t), θ ι ) condición de terminación ι que dependen de P (t) y θ ι a∗ , el mejor individuo encontrado durante la ejecución. P ∗ , la mejor población encontrada. 29 Objeto de Clase Entorno (CDTEnv) Resultados evaluación Datos del mejor Parámetros Evolución ... evalua carga Tamaño de Poblacion Probabilidad Operadores Probabilidad Nodos … Archivo de Parámetros Objetos de Clase CParam consulta Selecciona Y aplica Operador Evolutivo A B Y a1 a2 a3 … ai b1 b2 b3 … bi Y1 Y2 Y3 … Yi consulta Prueba o Atributo (nodo) Resultado de prueba (ramas) ... alimenta Objetos de Clase Arbol (CDTree) Atributos Extraidos Patrones para: Entrenamiento (S) (V) Valores Validación Posibles Extraidos Estructura DT Tabla de Datos para Entrenamiento (S) Tabla de Datos para Validación (V) Figura 10: Estructura inicial propuesta de la solución. 1. t ←− 0 /* genera población inicial e inicializa */ 2. P (t) ←− inicialice(µ) 3. F (t) ←− inicialice(P (t), µ) 4. Mientras Que (ι(P (t), θι ) = true) haga 5. P (t) ←− cruzar(P (t), θr ) 6. P (t) ←− mutar(P (t), θ m ) 7. F (t) ←− evaluar(P (t), λ) 8. P (t + 1) ←− seleccionar(P (t), F (t), µ, θ) 9. t ←− t + 1 10. Fin Mientras 11. devuelve a∗ , P ∗ En este algoritmo [Bac00] la población P (t) está conformada por µ individuos, P (t) por κ individuos y P (t) por λ individuos. Al observar el pseudocódigo, se puede observar que P (t) es la población en la generación actual, mientras que P (t + 1) indica una nueva generación en formación (offspring). P (t) es la subpoblación obtenida por cruce, mientras que P (t) es la población obtenida por mutación de individuos cruzados. Una diferencia clara respecto del diagrama de flujo de la figura 4 consiste en que en este último P (t) ←− mutar(P (t), θ m ) se aplica a los individuos resultantes del cruce, pero se encuentran esquemas en 30 Base de Datos Original los cuales P (t) ←− mutar(P (t), θm ) teniendo en cuenta que se debe controlar la relación entre los tamaños de las poblaciones µ y λ. El algoritmo 2.1 muestra la inicialización de t, de P (t) con tamaño µ y de la función de evaluación. El criterio de teminación t depende de gran cantidad de parámetros, que son representados por θt . Luego entra en el ciclo principal, donde el sistema puede operar con la selección, el cruce o la mutación, que depende de otra cantidad de parámetros. En el algoritmo se tiene que si λ = κ = µ. Si κ = µ.indica que no hay cruce, y si κ = λ no hay mutación. El operador de selección selecciona µ individuos de P (t) de acuerdo con los valores de aptitud F (t). Se considerará ahora la generación de la población inicial con el método grow [Koz92]. Sin embargo, mediante nuevas instricciones si-entonces o case, se pueden incorporara nuevos algoritmos de generación de la población inicial (full, ramped half-half [Koz92]). Básicamente, el algoritmo de generación de la población inicial consiste en un ciclo for con µ iteraciones, para cada uno de los individuos de la población. En este escrito se trabaja una versión modificada, equivalente a la versión propuesta por Koza, de acuerdo con la figura 3. En este algoritmo, la población inicial se evalúa con el fin de verificar si efectivamente uno de los individuos generados hace cumplir con la condición de terminación ι(P (t), θι ) y por lo tanto no se continúa con el proceso evolutivo. Si se continúa la evolución, se realiza un proceso de selección que da como resultado un conjunto de individuos a los cuales se les debe aplicar el operador evolutivo, uno a la vez, hasta completar una nueva generación. Algoritmo 2.2 (Algoritmo Evolucionario Básico) Describe el ciclo principal de la PG. Input: µ, λ, θι , θr , θm , θ, F (t) θ ι : parámetros de configuración de condiciones de terminación. ι(P (t), θ ι ) : condición de terminación ι que depende de P (t) y de θι . Φ = {φc , φm , φr ...} : conjunto de operadores evolutivos Output: a∗ , el mejor individuo encontrado durante la ejecución. P ∗ , la mejor población encontrada. 1. t ←− 0 /* genera población inicial y la inicializa */ 2. P (t) ←− inicialice(µ) 3. F (t) ←− inicialice(P (t), µ) 4. F (t), a∗ ←− evaluar(P (t), µ) 5. Mientras_Que (ι(P (t), θι ) = true) haga 6. a1 ←− clonar(a∗ ) /*elitismo*/ 7. Para cada ai con i = 2 hasta µ 8. operador = ruleta(Φ) 9. {a1 , ...} ←− seleccionar(P (t), F (t), µ, θ) 10. si operador = cruzar entonces 11. (ai , aj ) ←− cruzar({a1 , ..., aφ }, θ r ) 31 12. 13. 14. 15. 16. 17. 18. si operador = mutar entonces ak ←− mutar(ak , θm ) Fin_para F (t) ←− evaluar(P (t)) t ←− t + 1 Fin_Mientras devuelve a∗ , P ∗ Para codificar finalmente este algoritmo, se debe tener en cuenta la representación del árbol de decisión dentro de la PG. La estructrua de árbol de los individuos en PG facilita de manera inherente el diseño de funciones recursivas de creación, eliminación y en general, manipulación. Aún cuando computacionalmente las funciones recursivas tienen más exigencia de recursos computacionales (stack por ejemplo), son funciones más compactas en su diseño. Listado 2.1 (Programa Principal) Ciclo principal /*pPop, pNewPopulation son apuntadores a la población actual y nueva*/ /*pEnv es un apuntador a un objeto de tipo entorno*/ 1. int main(int argc, char ∗ argv[]) 2. g.generation = IN IT IAL; 3. pP op = new CDT ree[g.population]; 4. pN ewP opulation = new CDT ree[g.population]; 5. for (ind = 0; ind < g.population; ind + +) 6. (pP op)− > f illT ree(pP op + ind, ...); /*completa recursivamente*/ 7. ... 8. while (g.generation < pEnv− > getMaxGeneration()) 9. pEnv− > setN umBestT ree(pEnv− > evalP opulation()); /*evalua*/ 10. if (pEnv− > getStopCriteria() == true) 11. ... /*termina evolución*/ 12. newInd = 0; 13. pEnv− > clone(pEnv− > getNumBestT ree(), newInd); 14. newInd + +; 15. while (newInd < pEnv− > getP opulation()) 16. geneticOperator = pEnv− > operatorSel(); 17. if (geneticOperator == CROSS) 18. /*...cruzar individuos 19. else if (geneticOperator == REP RODUCT ION ) 20. /*...clonar individuo*/ 21. else if (geneticOperator == M U T AT ION) 22. /*... mutar individuo*/ 23. g.generation + +; 24. delP opulation(); 25. pEnv− > setN umBestT ree(pEnv− > evalP opulation()); 26. return pEnv− > getN umBestT ree(); 32 En el listado 2.1, la función fillT ree() es una función recursiva que va generando de una manera aleatoria o probabilística (según los parámetros) cada uno de los µ individuos que conforman la población. La función evalP opulation() igualmente evalúa cada uno de los árboles de decisión de manera recursiva. 2.2.2. Generación de la Población Inicial. Se disponen de diferentes maneras de generar la población inicial, se describe el algoritmo y su expresión en C++ para una función que genera la población inicial utilizando el método grow. Algoritmo 2.3 (Grow) Algoritmo recursivo GROW para generar población inicial. Input: θ p : profundidad máxima inicial, F = {f1 , ..., fm } : funciones primitivas T = {t1 , ..., tm } : nodos terminales a ←− seleccionar probabilisticamente una raiz fi ∈ F Output: a : individuo de P /* ciclo principal de generación de la población inicial: /* para individuo = 1 hasta µ /* a ←− seleccionar probabilisticamente raiz fi ∈ F /* a ←− grow(a , altura ); /* fin_para 1. grow(a, altura) 2. Si altura = θp entonces 3. devuelve a ←− seleccionar probabilisticamente nodo ti ∈ T 4. Si no entonces 5. n ←− seleccionar probabilisticamente tipo de nodo F o T 6. si n ∈ F 7. a ←− seleccionar probabilisticamente fi ∈ F 8. nueva_altura = altura + 1 9. repetir según aridad de fi 10. grow(a , nueva_altura) 11. fin repetir 12. si n ∈ T 13. devuelve a ←− seleccionar probabilisticamente ti ∈ T Al examinar este pseudocódigo, se observa que el método grow genera los individuos de la población inicial de manera libre, y podrían crecer bastante en profundidad de no ser por uno de los parámetros iniciales, que limita la profundidad máxima para cada árbol generado inicialmente. La presión evolutiva posterior es la que tiende a controlar que los árboles no sean demasiado grandes, aunque no se excluye la posibilidad de que dicho límite se imponga a la fuerza mediante codificación. La codificación en C++ se puede realizar como se observa en el listado 2.2, donde idx es el índice que corresponde a una determinada función o terminal 33 según una tabla de funciones y terminales; la variable level indica el nivel a que se encuentran los nodos que se están completando en ese momento, y pN y pT son apuntadores a la estructura árbol y la estructura DT respectivamente. Listado 2.2 (Generación de Población Inicial) 1. createDT ree(CDT ree ∗ pN, DT ∗ pT, int idx, int level) { 2. if (pN ! = N UL_) 3. { switch(idx) { 4. case TERMINAL: 5. pN->setNDT(0); 6. pN->setLblValueIdx(randGenerator(0, (pT->arity)-1)); ...} 7. if (idx > T ERM IN AL){ 8. level++; 9. pN − > insChild(newCDT ree); //inserta hijo 10. if (level >= g.maxLevel) {TypeN = TERMINAL;} 11. else {TypeN = (randGenerator(T Y P E_1, LAST ));} 12. pN->createDTree(pN->getChild(), pT, TypeN, level);} 13. if (idx > U NARY ){ 14. pN = pN− > getChild(); //se desplaza 15. for (n = 2; n <= idx; n + +) { 16. pN − > insBrother(newCDT ree); 17. if (level >= g.maxLevel) {TypeN = TERMINAL; } 18. else {TypeN = randGenerator(T ERM IN AL, g.maxLevel); } } 19. pN=pN->getBrother(); 20. /*llamada recursiva:*/ 21 pN->createDTree(pN->getChild(), pT, TypeN, level); } } 22. else { /*ERROR*/ } } 2.2.3. Operadores Evolutivos y Mecanismos de Selección El primer operador evolutivo al que se hace referencia es al operador de selección, que se presentó previamente en la sección 1.6.1. La implementación que se expone en el algoritmo 2.4 corresponde a la implementación del método del torneo con ruleta. El algoritmo 2.4 es una implementación abstracta del mecanismo de selección generl para individuos, correspondiente al esquema propuesto por [Bac00]. Algoritmo 2.4 (Selección [Bac00]) Describe un mecanismo de seleccion para PG. Input: µ, λ, q, P (t) ∈ I µ , P (t) ∈ Iιλ , F (t) s : I λ → I µ , m : I κ → I λ, r : I µ → I κ Output: P (t) = {a1 , a2 , ..., aµ } ∈ I µ 1. 2. 3. para i←− 1 hasta µ ai (t) ←− ssel (P (t), P (t), F (t), q) devolver {a1 (t), ..., aµ (t)} 34 La implementación del mecanismo general de selección se basa en un procedimiento aleatorio o probabilístico, o una combinación de ambos. Algoritmo 2.5 (Seleccionar) Describe el procedimiento general de selección de individuos. Input: P (t) = {a1 , ...aµ } Output: /* 1. 2. 3. a ∈ P (t) La función torneo(s, a1 , ..., ai ) se explica en los algoritmos 2.7 y 2.8*/ a1 , ...ai ∈ I µ ←− aleatorio(1, µ) a ←− torneo(s, a1 , ..., ai ) devuelve a Para determinar cual operador evolutivo se va a aplicar a la población de padres en un momento determinado, también se puede utilizar un método similar a la ruleta. Esto implica que cada operador evolutivo tiene un porcentaje de probabilidad de ocurrir, y mediante la ruleta se determina cual operador será el que se aplique en última instancia. Algoritmo 2.6 (Ruleta) Describe el procedimiento de la ruleta PG. Input: Pr = Distribución de probabilidad de individuos Output: a = P (t) 1. 2. 3. 4. 5. 6. 7. 8. 9. ruleta(Pr ) n ←− 1 suma ←− Pr (n) azar(0, 1) Mientras Que suma < azar n ←− (n + 1) suma ←− suma + Pr (n) Fin Mientras devuelve(n) Algoritmo 2.7 (Torneo Determinístico) Describe el mecanismo de torneo determinístico para PG. s = tamaño del torneo. Input: P (t) ∈ I λ , s ∈ {1, 2, ..., λ} Output: P (t) 1. 2. 3. 4. torneo(s, a1 , ..., aλ ) para i←− 1 hasta λ ai (t) ←− mejor de s individuos de P (t) devolver {a1 (t), ..., aλ (t)} 35 Algoritmo 2.8 (Torneo Probabilístico) Describe el mecanismo de torneo probabilístico para PG. s = tamaño del torneo Input: P (t) ∈ I λ , s ∈ {1, 2, ..., λ} Output: P (t) 1. 2. 3. 4. torneo(s, a1 , ..., aλ ) para i←− 1 hasta λ ai (t) ←− ruleta(P (r)) devolver a1 (t), ..., aλ (t) La implementación del torneo determinístico se encuentra en el listado 2.3. Listado 2.3 (Selección de Individuos) 1. tournament() { /*selección aleatoria de individuos para torneo*/ /*int indA, indB: número de individuo dentro de población*/ 2. int indA = randGenerator(0, p.populationSize − 1); 3. int indB = randGenerator(0, p.populationSize − 1); /*si es torneo determinístico*/ 4. if (getEval(indA) > getEval(indB)) 5. { return indA; } 6. else return indB; } Algoritmo 2.9 (Cruce) Describe el mecanismo de cruce para PG. Input: a, b ∈ P (t) ∈ I λ Output: a , b ∈ P (t) (a , b ) ←− cruce(a, b) /* Las funciones subarbol(arbol, posicion), y la función */ /* insertar(arbos, subarbol, posicion) devuelven árboles completo */ /* La función eliminar(arbos, posicion) devuelve un árbol incompleto */ /* La funcion aleatorio(min, max) devuelve valor aleatorio con*/ /* distribución uniforme dentro del rango (min, max).*/ 1. ς a ←− aleatorio(1, longitud(a)) 2. ς b ←− aleatorio(1, longitud(b)) 3. a ←− subarbol(a, ς a ) 4. b ←− subarbol(b, ς b ) 5. a ←− eliminar(a, ς a ) 6. b ←− eliminar(b, ς b ) 7. a ←− insertar(a, b , ς a ) 8. b ←− insertar(b, a , ς b ) En el algoritmo 2.9, para las funciones subarbol, eliminar e insertar, la estructura de detallada de los algoritmos depende entre otros factores del lenguaje de programación y la metodología que se empleo dentro del lenguaje seleccionado. La función subarbol() extrae un subárbol válido de una posición válida de 36 un árbol dado. la función eliminar() devuelve el árbol de entrada tras eliminar un subárbol completo de una posición válida dentro del mismo. Por lo tanto, eliminar() devuelve un árbol incompleto y que debe ser llenado en el punto de eliminación para que sea válido. La función insertar() copia un subárbol válido en una posición válida de un árbol. Por lo tanto, el algoritmo debe combinar eliminar() con insertar() para que no se pierda la validez sintáctica o estructural de los árboles. El código en C++ se encuentra en el listado 2.4. Listado 2.4 (Cruce) ... 1. cross(CDT ree ∗pA, CDT ree ∗pB, int hA, int hB){ 2. CDT ree * pSPrA, * pSPrB, * pSHA,* pSHB; /*selecciona aleatoriamente puntos de cruce*/ 3. crossP ointA = randGenerator(2, getP opSizes(prA) − 1); 4. crossP ointB = randGenerator(2, getP opSizes(prB) − 1); /*ubica apuntadores a nodos en puntos de cruce*/ 5. pSP rA = pP op− > findN ode(pP op + prA, crossP ointA, 0); 6. pSP rB = pP op− > findN ode(pP op + prB, crossP ointB, 0); 7. pSHA = pN ewP op− > f indN ode(pN ewP op + hA, crossP ointA, 0); 8. pSHB = pNewP op− > findN ode(pN ewP op + hB, crossP ointB, 0); /*funcion que intercambia apuntadores a subarboles:*/ /*(lineas 5,6,7,8 algoritmo 2.9)*/ 9. interxSubT ree(pN ewP op + hA, pSHA, pP op + prB, pSP rB); Algoritmo 2.10 (Mutación) Describe el mecanismo de mutación para PG. Input: a, b ∈ P (t) ∈ I λ Output: a , b ∈ P (t) (a ) ←− mutacion(a) /* insertar(arbos, subarbol, posicion) devuelven árboles completo */ /* La función eliminar(arbos, posicion) devuelve un árbol incompleto */ /* La funcion aleatorio(min, max) devuelve valor aleatorio con*/ /* distribución uniforme dentro del rango (min, max).*/ 1. ς a ←− aleatorio(1, longitud(a)) 2. a ←− eliminar(a, ς a ) 3. a ←− insertar(a, b , ς a ) La traducción a código en C++ da como resultado el listado 2.5. Listado 2.5 (Mutacion) mutate(intm){ 1. CDTree* pMutant, * pNode, * pNodePM, * pCh, * pTem; 2. mutN ode = randGenerator(2, mutantSize)); 3. pN ode = (pMutant)− > f indN ode(pM utant, mutN ode, 0);/*ubica nodo*/ 4. level = pNode− > getLevel();/*nivel del nodo a mutar*/ 5. numCh = pNode− > getN umChild(); 37 6. pNodeP M = pN ode− > getP arent(); 7. idx = randGenerator(0, g.numLabels);/*asigna atributo a nodo*/ 8. pT em = newCDT ree; 9. pT em− > createDT ree(pT em, pDT able, idx, level); 10. if (numCh == 1){ 11. pNodeP M − > insChild(pT em); 12. pT em− > setBrother(pNode− > getBrother()); } 13. else if (numCh > 1){ 14. pCh = pN odeP M − > getChild(); 15. while(pCh− > getN umChild() < numCh − 1){ 16. pCh = pCh− > getBrother(); } 17. pCh− > insBrother(pT em); 18. pT em− > setBrother(pNode− > getBrother()); } 19. else{/ ∗ ERROR ∗ /}; Dentro de los algoritmos más importantes para la evolución se encuentra el que determina la función de aptitud F (t). En PG la representación de un individuo es usualmente una función, un programa o en el presente caso de interés, un árbol de decisión que se puede transformar en una disyunción de conjunciones de expresiones si-entonces. Los resultados de la evaluación del árbol son comparados mediante alguna función de error con los resultados esperados para cada patrón de datos de entrenamiento y validación. La función de evaluación puede retornar un valor que indica que tanto cumple el árbol con la clasificación esperada. Dicho valor es utilizado para guiar el proceso de selección, principalmente en la escogencia de los padres a los cuales se les podrá aplicar cualquiera de los operadores evolutivos. 2.2.4. Evaluación de los Árboles de Decisión La evaluación del árbol es un aspecto decisivo en el proceso evolutivo, ya que es la que le da la dirección adecuada en busca de los individuos más aptos, de la manera más rápida y menos parsimoniosa posible. Algoritmo 2.11 (Evaluar) 1. leer patrón 2. realizar el recorrido según el patrón 3. mientras que (recorrido existe) 4. si (nodo = terminal) 5. si (clasificacion arbol = clasificacion patrón) 6. aciertos = aciertos + 1 7. retorna aciertos 2.2.5. Diseño General de la Solución De acuerdo con esto, el exámen del problema ha sugerido una estructura de clases que se ha simplificado para el presente ejercicio de la siguiente manera: 38 1. Clase CDTree: clase que define la estructura y operaciones de los árboles de decición, que son los individuos a evolucionar. 2. Clase CDTEnv: clase que define la estructura y operaciones del entorno, que ejerce influencia sobre los individuos de la clase CDT ree seleccionando algunos de ellos y permitiendo su influencia en la nueva generación. 3. Clase CParam: clase auxiliar que define el objeto encargado de almacenar y verificar la consistencia de los parámetros que guían la generación de la población inicial y de la evolución en general. 4. Estructura DT: estructura auxiliar que permite el almacenamiento de información relativa a cada uno de los nodo. La clase CDT ree representa los objetos a evolucionar, los árboles de decisión. La clase CDT ree intenta definirlos de manera adecuada para que su manipulación sea sencilla y clara. El concepto se basa en la idea de árboles n-arios. La aridad de cada nodo del árbol tiene que ver con la cantidad de valores que puede tomar un atributo determinado. Este diseño tiene algunas implicaciones a la hora de diseñar los algoritmos: por una parte, cada nodo conoce de manera directa a su primer nodo hijo, a su hermano inmediatamente siguiente, y a su padre. Esto implica que por ejemplo, si un nodo tiene al menos tres hijos, para acceder al hijo 3 debe acceder primero al nodo hijo, y desplazarse a través de éste visitando al hermano siguiente y luego al siguiente. Los principales atributos y funciones de la clase CDT ree se observan en la figura 11. La clase CDTree contiene principalmente: Un apuntador a un objeto tipo DT , que es la tabla que contiene el resumen de caractarísticas de la tabla de decisión, Un valor nDT que informa cual entrada de la tabla de atributos es la que utiliza el nodo considerado. Al aplicar este valor al apuntador pDT able, le da la posibilidad de acceder a toda la información relacionada con el atributo propio del nodo: el nombre del atributo, la aridad, los posibles valores, etc. La clase CDT Env representa al entorno evolutivo, donde se observan sus atributos y funciones principales. Se le puede considerar como un objeto de categoría más alta que el propio árbol o individuo; tiene a su cargo dirigir la evolución de acuerdo con un conjunto de parámetros elegidos. Se encarga por lo tanto de: Cargar los archivos de parámetros y de datos. Debe verificar si los parámetros están dentro de rango. Generar la población inicial de acuerdo con los parámetros que la controlan. Evaluar cada individuo de la población, 39 CDTree -pDTable: DT -nDT: int -lblValueIdx: int -pChild: CDTree -pParent: CDTree -pBrother: CDTree -numChild: int +setPDTable(: DT): void +getPDTable(): DT +setNDT(: int): void +getNDT(): int +setLblValueIdx(: int): void +getLblValueIdx(): int +getChild(): CDTree +insChild(: CDTree): void +getParent(): CDTree +setParent(: CDTree): void +getBrother(): CDTree +insBrother(: CDTree): void +setBrother(: CDTree): void +setNumChild(: int): void +getNumChild(): int +createDTree(: CDTree, : DT, : int, : int): void +findNode(: CDTree, : int, : int): CDTree Figura 11: Clase CDTree (árbol n-ario) Aplicar torneo para decidir cuales individuos participaran en la formación de una nueva generación, Aplicar operadores evolutivos y Decidir cuando terminar el proceso evolutivo. Un objeto de la clase CDT Env contendrá principalmente: Un apuntador a un objeto tipo DT , que es la tabla que contiene el resumen de caractarísticas de la tabla de decisión, Un apuntador a la población actual pP op, Un apuntador a la población de la generación siguiente, Valores generales recolectados durante el proceso de evaluación de la población: longitud de cada individuo (árbol), nivel máximo, cual individuo es el mejor y el resultado de la evaluación del mejor, entre otros. Se disponen de algunas clases y estructuras auxiliares, cuya función es apuyar a las dos clases principales en algunas tareas. Por una parte, estas clases le dan 40 CDTEnv -pDTable: DT -pPop: CDTree -pNewPop: CDTree -popSizes: int -popLevels: int -popEvals: double -numBest: int -evalBest: double -levelBest: int +setPDTable(: DT): void +getPDTable(): DT +setPop(): void +getPop(): CDTree +setPopSizes(: int, : int): void +getPopSizes(: int): int +setPopLevels(: int, : int): void +getPopLevels(: int): int +setPopEvals(: int, : double): void +getPopEvals(: int): double +evalPopulation(): int +setEval(: int): void +getEval(: int): double +setNumBest(: int): void +getNumBest(): int +setEvalBest(: double): void +getEvalBest(): double +setLevelBest(: int): void +getLevelBest(): int +operatorSel(): int +tournament(): int +delDSubTree(: CDTree): void +mutate(: int): void +clone(: CDTree, : CDTree): void +cross(: int, : int, : int, : int): void +interxSubTree(: CDTree, : CDTree, : CDTree, : CDTree): void +dataLoad(): void +setStopCriteria(: int): int +getStopCriteria(): int Figura 12: Clase CDTEnv (entorno evolutivo). al sistema la capacidad de almacenar y modificar datos y parámetros de manera segura. La clase CP aram, cuyos valores y funciones principales se observan en la figura 13, está encargada de almacenar y verificar la consistencia de los parámetros que guían la generación de la población inicial y guiar la evolución. Le da capacidad al sistema de modificar estos datos de manera segura. Sus principales valores son: populationSize: Tamaño de la población. Almacena la cantidad de individuos que debe tener la población. La versión final del programa verifica que sea un valor consistente. terminalP rob: Durante los procesos de generación de la población inicial y mutación, se generan nuevos individuos. Para cada nodo del árbol, se debe decidir si este será un nodo terminal o no-terminal. El valor terminalProb 41 CParam -populationSize: int -terminalProb: double -crossProb: double -mutationProb: double -cloneProb: double Figura 13: Clase Parametros indica la probabilidad de que el nuevo nodo sea de tipo terminal. El nodo no-terminal tendrá una probabilidad 1-terminalProb. crossP rob, mutationP rob, cloneP rob: indican la probabilidad de que el operador evolutivo cruce, mutación y clonación respectivamente, sean seleccionados. Cuando la clase CDT Env (el entorno) lanza los dados buscando un valor aleatorio entre 0 y 1 para decidir cual operador evolutivo aplica, el valor que obtiene al lanzar los dados se verifica contra los rangos de valores de estas probabilidades, en el proceso llamado ruleta. Se debe cumplir la condición crossP rob + mutationP rob + cloneP rob = 1 En cuanto a la estructura DT , se tiene que una copia de esta candidata a clase, es referenciada y sus valores actualizados dentro de cada uno de los nodos del árbol. El objetivo es que cada nodo lea estos valores de la tabla que contiene el resumen de caractarísticas de la tabla de decisión, y los actualice internamente (para evitar llamar permanentemente al apuntador a la tabla DT ). Esta clase contendrá los valores: tipo de nodo, el nombre del atributo, la aridad, y los valores posibles del atributo. El tipo de nodo es un valor de T o F, según el nodo sea terminal o no terminal. 42 3. Conclusiones Este es un trabajo de tipo exploratorio, y es necesario implementar finalmente el modelo conceptual para verificar su utilidad. Sin embargo, dada la relativamente larga trayectoria de aplicación de la PG en diversas áreas, se espera que se tenga un resultado aceptable. Se debe considerar que el sistema propuesto intenta ser lo más simple posible, incorporando la menor cantidad de heurísticas de búsqueda, limitación de búsqueda o cualquier restricción posible para examinar los resultados obtenidos tras una exploración libre del espacio de búsqueda compuesto por árboles de decisión que solucionan un problema. Aún cuando el sistema no incorpore heurísticas de uso actual en PG, su estructura permite adaptarse a nuevos requerimientos y condiciones. Por ejemplo, se puede imponer la restricción de que ningún árbol duplique atributos en un nuevo nodo, al momento de la generación inicial. Sin embargo, puede ser complicado e improductivo verificar que al aplicar un operador evolutivo, ningún nodo del subárbol sea repetido al insertar o cruzar un nodo. Es más, esto podría en un momento dado hacer imposible que continúe la evolución o hacerla extremadamente lenta. Por supuesto que finalmente será necesario imponer restricciones con alguna heurística, pero la exploración libre permitirá observar cómo son los árboles de decisión generados siguiendo estos lineamientos. Por estos dos motivos, libertad de exploración y facilidad de evolución, el sistema no ha incorporado inicialmente ningún control sobre la evolución. Por otra parte, los individuos que forman parte de la población en los problemas de programación genética, representan de una manera muy natural los árboles de decisión, lo cual facilitará y simplificará la implementación final. Pueder ser interesante además, considerar hacia un futuro la implementación de estrategias para permitir que el sistema de PG genere árboles de decisión oblicuos o multivariados [Llo07]. Un esquema similar de clases y funciones aquí presentado ha sido utilizado por el autor del presente trabajo para implementar un sistema de regresión simbólica funcional, así que se espera que con la implementación de algunos módulos generales, el programa quede totalmente operativo. El sistema finalmente debe entregar como resultado el conjunto de reglas, como programa, que permitan la aplicación sencilla del modelo resultante a un nuevo conjunto de datos para clasificación. 43 Referencias [Llo07] X. Llorá, J. Garrel, Evolution of Decision Trees. Universidad Ramon Llull, {xevil,josepmg}@salleURL.edu [Mar87] Autores Varios, Inteligencia Artificial. Boixareu Editores, Madrid. (1987). [Kec01] V. Keckman. Learning and Soft Computing. MIT Press, USA (2001). [Roa06] C. Roach, Building Decision Trees in Python. http://www.onlamp.com/pub/a/python/2006/02/09/ai_decision_trees.html. (2006). [Rus96] S. Russell, P. Norvig, Inteligencia Artificial. Prentice-Hall, México. (1996). [Joa07] T. Joachims. Notas de Clase. Cornell University. (2007). [Gue04] A. Guerra, Aprendizaje www.uv.mx/aguerra. (2004). Automático: Árboles de Decisión. [Koz92] J. Koza, Genetic Programming. (1992). [Dim06] D. Dimitrescu, A. Joó, Generalized Decision Trees Built with Evolutionary Techniques. Universidad Babes-Bolyai, Universidad Sapientia, Rumania. [Mit97] T. Mitchell, Machine Learning. McGraw-Hill, New York (1997). [May88] E. Mayr, Toward a New Philosophy of Biology: Observations of an Evolutionist. Belknap, Cambridge-MA (1988). [Bac00] T. Bäck, Evolutionary Algorithms in Theory and Practice..Oxford, New York (2000). [Gol89] D. Goldberg, Genetic Algorithms in Search, Optimization and Machine Learning. Addisson-Wesley, Reading-MD (1989). [Luk01] S. Luke, L. Panait, A Survey and Comparison of Tree Generation Algorithms. Internet (2001) 44