Algoritmos genéticos: aplicación en MATLAB Matı́as Ison, Jacobo Sitt, Marcos Trevisan Guı́a de la materia Sistemas Complejos disponible en www.df.uba.ar/users/mison/genetico.tar.gz November 25, 2005 Abstract Esta guı́a contiene una introducción a los elementos básicos de los algoritmos genéticos y su adaptación a un problema simple de minimización de funciones de dos variables usando código en matlab. Se describe el código con un instructivo básico de su sintaxis y funcionamiento. Se propone una serie de prácticas numéricas ejecutando variaciones del algoritmo. En la última sección se describe una aplicación de los algoritmos genéticos al ajuste de parámetros en el modelado de la voz humana, junto con algunas nociones de paralelización. 1 Algoritmos genéticos Los algoritmos genéticos corresponden a la clase de métodos estocásticos de búsqueda. Mientras la mayorı́a de estos métodos operan sobre una única solución, estos algoritmos operan en una población de soluciones. La idea básica, inspirada en los procesos evolutivos en biologı́a, es que el contenido genético de una población contiene potencialmente la solución, o una solución mejor, a un dado problema de adaptación. Esta solución puede estar inactiva porque la combinación genética adecuada está diseminada entre varios sujetos. Sólo la asociación de genomas distintos puede llevar a la activación de la solución. Crudamente, el mecanismo evolutivo procede ası́: sobre una población, algunos individuos son seleccionados para la reproducción, con más oportunidades para los mejor adaptados al ambiente. Durante la reproducción, los nuevos individuos de la población resultan de modificaciones e intercambio genético de los padres. Una vez que se renueva la población, el proceso recomienza. Es decir que hay dos espacios donde opera la evolución. Por una parte, a nivel de los individuos fı́sicos (fenotipo), que deben adaptarse para ser seleccionados. Y luego, a nivel de la información genética (genotipo), a través de los operadores que intercambian y varı́an la información genética. La información genética está codificada en los cromosomas, que son secuencias de genes, cada uno de los cuales codifica una caracterı́stica particular del individuo. Estas secuencias están escritas en términos de cuatro bases nitrogenadas: adenocina, timina, citocina y guanina. En este alfabeto de base cuatro, [A, T, C, G], está escrita toda la información genética de un individuo. Hay esencialmente dos operadores genéticos. El operador de mutación introduce cierta aleatoriedad en la búsqueda simplemente cambiando unos genes por otros, contribuyendo a una exploración ‘azarosa’ en el espacio genético. El operador de crossover, en cambio, es una recombinación de la información durante la reproducción de los individuos seleccionados. El proceso de evolución, puesto en estos términos, es adaptable a una enorme familia de problemas, incluso ajenos al ámbito biológico. En la próxima sección se describe la adaptación de este esquema de búsqueda de soluciones a un problema matemático sencillo. 1 2 Adaptación a un problema de optimización de funciones En esta sección ilustraremos la adaptación de un algoritmo genético a un problema sencillo de minimización de funciones bidimensionales f (x, y). La interpretación fı́sica del problema es, en este caso, casi trivial: haciendo corresponder la función f a la ‘energı́a’ E asociada al estado (x, y), la evolución del sistema tenderá a minimizarla. A lo largo de esta guı́a nos referiremos más o menos indistintamente, a la función o al ‘paisaje energético’. 12 9 8 10 7 8 6 5 6 4 4 3 2 2 1 0 2 0 2 2 1 1 0 2 1 1 0 0 −1 0 −1 −1 −2 −1 −2 −2 −2 Figura 1: ejemplo de paisaje energético complejo (izquierda) y simple (derecha). En términos crudos, la meta de la exploración genética es encontrar los individuos mejor adaptados a su ambiente. Para eso, los individuos se reproducen buscando, con el intercambio de material genético y las mutaciones, que cada nueva generación mejore la adaptación. Para poder aplicar este esquema al problema de la minimización de funciones, debemos dar las definiciones de individuos, genes, cromosomas y ambiente, y cuantificar la adaptación. Si pensamos a cada individuo de la población como un par (x, y) ∈ [a, b] × [c, d], se puede definir la adaptación como un escalar inversamente proporcional a la función f , de manera que la minimización de f (x, y) corresponderá a la mejor adaptación al medio definido por la función f . En este punto, sólo queda definir la ‘codificación genética’ del individuo (x, y) para aplicar los operadores genéticos. Definimos un cromosoma como el arreglo consecutivo de dos genes, uno para cada número del par (x, y). Este arreglo se construye normalizando cada coordenada según el rango donde puede variar y guardando los primeros n decimales. Por ejemplo, para el par (0.5, 1.34) ∈ {[0, 1] × [0, 2.35]}, la normalización arroja el par (0.5/1, 1.34/2.35) = (0.5, 0.57021276...). La identificación del individuo con su cromosoma resulta, usando cuatro cifras significativas (0.5, 1.34) → [50005702]. En este ‘espacio genético’ se pueden aplicar los operadores de cruzamiento y mutación, que en la evolución suceden en el espacio de las bases nitrogenadas y, aquı́, en la base decimal. Una mutación será el reemplazo de cualquiera de los 8 números del cromosoma por otro, por ejemplo, [23126675] → [23026675]. El cruzamiento consiste en el intercambio, a partir de cualquier posición, de la información de los cromosomas de los individuos seleccionados. Por ejemplo, [12345678]+[87654321] → [12354321]. Con estas definiciones, el algoritmo genético está adaptado al problema y su ejecución consiste en elegir una población inicial de N individuos (xi , yi ), seleccionarlos según su adaptación usando la función f (xi , yi ) y aplicarles los operadores genéticos para generar la nueva población. En las siguientes secciones se describe el código implementado para resolver este problema en matlab. 3 Instructivo Se propone realizar un estudio numérico del código que implementa un algoritmo genético en la minimización de un paisaje energético complejo. Para ello se sugieren los siguientes pasos: 2 • Baje el archivo desde su ubicación en internet: http://www.df.uba.ar/users/mison/genetico.tar.gz • Descomprima el archivo genetico.tar.gz ($tar xvzf genetico.tar.gz) • Edite el programa principal genetico.m (por ejemplo escriba: $xemacs &) • Identifique las distintas partes del código y sus funciones (puede ayudarle ver la sección siguiente) • Inicie el software matlab desde una terminal ($matlab ) • Explore numéricamente el código variando los parámetros relevantes del mismo 3.1 Descripción del código en Matlab 3.1.1 Parámetros genes = 2 = posición x, posición y largo = 4 = longitud del gen. Ngen = cantidad de ciclos (generaciones) en el algoritmo. Nind = cantidad de individuos en la población. cross = tasa de cruzamiento. mut = tasa de mutación. rango := [xmin ymin], [xmax ymax] = Rango de distribución de la población inicial. 3.1.2 Organización: El código a utilizar se encuentra dividido en un código principal (genetico.m) que hace uso de subrutinas o funciones definidas en archivos externos. • código principal genetico.m 1. se introducen los parámetros del algoritmo 2. llamado a fun.m (define el paisaje de energı́a a estudiar) 3. se elige la población inicial de manera aleatoria en ran.m 4. comienza ciclo principal: Para iter desde 1 hasta Ngen hacer – se calcula la función de fitness – llamado a subrutina fentogen.m (toma fenotipo y devuelve genotipo) – llamado a subrutina pareja.m: elige los dos individuos, efectua la mutación y el cruzamiento de manera estocástica – llamado a subrutina gentofen.m (toma genotipo y devuelve fenotipo) – se grafica la población de la generación iter 5. se reproduce la evolución completa de la población 6. se grafica la evolución de la función de fitness 3.2 Preguntas Para tener en cuenta: Un estudio cuantitativo del problema numérico requiere el análisis de un conjunto de evoluciones y no de un evento particular como el que se obtiene directamente del código. Sin embargo creemos que de todas formas es posible realizar un análisis interesante. Por esto se proponen las siguientes preguntas: 3 • En el código, el criterio de selección de los cromosomas tiene una probabilidad p ∝ f (x, y) −1 . Interprete en términos del algoritmo genético y del problema particular. ¿Qué tiene que garantizarse para que, ası́ definida, la probabilidad no genere errores numéricos? Proponga otras funciones de adaptación. • ¿Cómo construirı́a un algoritmo para seleccionar uno (o más) individuos con probabilidad p teniendo en cuenta su adaptación? Considere disponible una función numérica rand(a,b) que le permite elegir números ‘al azar’ en el intervalo (a, b). Verifique si su idea coincide con la sección comentada como ruleta en el código. • Para una cantidad suficiente de generaciones Ngen ¿Qué operador genético subsiste? ¿Qué comportamiento observa? Proponga otros criterios para mejorar la búsqueda. • En este trabajo, el código se ejecuta una cantidad Ngen de veces prefijada por el usuario. ¿Es posible adaptar el código para que cumpla con algún criterio de convergencia antes de detenerse? Proponga alguno e incorpórelo al código. • Suponga que se seleccionan (xp , yp ) y (xm , ym ) como el padre y la madre de un nuevo individuo (xh , yh ). ¿Se puede predecir, por argumentos geométricos, el subespacio de los posibles (x h , yh ) debidos a la acción del operador genético de cruzamiento? ¿Podrá simplificarse el código con esta interpretación? 4 4.1 Adaptación al problema de la producción de voz Fı́sica de la voz - Teorı́a de Fuente Filtro El contenido espectral de los sonidos voceados es relativamente simple, mostrando una serie de picos en ciertos armónicos de la frecuencia fundamental. La teorı́a clásica que permite describir este comportamiento es conocida como fuente-filtro, y puede resumirse ası́: el flujo de aire desde los pulmones a través de la glotis genera oscilaciones de las cuerdas vocales. La perturbación en la presión causada por esta oscilación viaja de ida y vuelta por el trato vocal y es filtrada, generando un sonido definido. Aunque no exista un gran control sobre las oscilaciones de las cuerdas vocales, la geometrı́a del tracto puede ser modificada con los articuladores principales: la lengua y la mandı́bula. En esencia, el filtrado representa el énfasis o la supresión de ciertos armónicos de la frecuencia fundamental de oscilación de las cuerdas vocales. Las frecuencias enfatizadas son conocidas como las formantes, y en el caso de las vocales, es el cociente entre las dos primeras lo que determina la identidad de cada vocal. En el resto del espectro se codifica la información de la identidad del hablante. El estudio de los sonidos voceados puede separarse en dos partes: la dinámica de las cuerdas vocales y el filtrado de una seãl sonora a través de una compleja geometrı́a. Más aun, la dinámica puede resultar extremadamente rica si se agregan los efectos de acople entre la fuente de sonido (las cuerdas vocales) y el filtro. 4.2 Cuerdas vocales: Modelo mı́nimo Existen escencialmente dos modelos [1] para estudiar la dinámica de las cuerdas vocales. Ambos están basados en el mismo principio: las oscilaciones del tejido se inducen por el flujo de aire que pasa a través de ellas. El modelo más simple que da cuenta de este mecanismo es conocido como el modelo de una masa [1]. Cada cuerda vocal se asume como una masa sujeta al tejido principal, caracterizada por un coeficiente de elasticidad y de disipación, y sometida a la presión intraglotal. Para generar el comportamiento oscilatorio, es necesario que la presión durante la apertura de las cuerdas no se compense en el semiciclo de cierre, para que en un ciclo completo pueda entregarse energı́a a las cuerdas oscilantes. Este modelo constituye una buena aproximación mientras que el aire en el tracto tenga propiedades inerciales. 4 Cuando las cuerdas se están separando, el flujo aumenta y la columna de aire en el tracto se acelera, lo cual tiende a abrir más aun las cuerdas. En el semiciclo de cierre, por otra parte, la columna de aire en movimiento tiende a cerrar las cuerdas, y en el ciclo completo se entrega energı́a al tejido. Las ecuaciones de movimiento para este modelo de cuerdas vocales pueden ser escritas como M x00 + Bx0 + Kx = Pg (1) donde M , B y K representan la masa, la constante de disipación y la constante de restitución, por unidad de area, de las cuerdas vocales, y Pg la presión glotal. Si las áreas de entrada y salida al tracto vocal son iguales, como corresponde al modelo de una masa, tenemos Pi = Pg , con Pi la presión a la entrada del tracto vocal. Siempre que la frecuencia fundamental de oscilación de las cuerdas vocales sea menor que la primera resonancia del tracto (primera formante), su impedancia de entrada es inercial [6], de manera que Pi = R2 U + I 2 U 0 (2) con R2 e I2 la resistencia y la constante de inercia del aire en el tracto, y U el flujo. El sistema dinámico queda cerrado, entonces, relacionando las ecuaciones 1 y 2 mediante PL − (R2 U + I2 U 0 ) = kt ρv 2 (3) donde kt es un factor de corrección fenomenológico a la ecuación de Bernoulli. De la integración de las ecs. 1, 2 y 3 se obtiene la serie temporal del flujo de aire a través de las cuerdas vocales. 4.3 Tracto Vocal Según la teorı́a fuente-filtro, las cuerdas vocales están desacopladas acústicamente del tracto vocal, de manera que la señal de voz se genera a través del filtrado de la serie temporal de la presión P i a la entrada del tracto. El modelo más simple consiste en aproximar el tracto por una serie de n tubos de distinta sección a i y longitud li para simular las distintas geometrı́as. En cada interfaz, la onda de presión es parcialmente reflejada y transmitida, de manera que a la salida del último tubo se tiene la señal de la voz. 4.4 Biometrı́a Una vez construido el modelo completo para generar series temporales sintéticas de voz, naturalmente surge ponerlo a prueba como un método biométrico para reconocer la identidad de las personas, aprovechando que sus parámetros están relacionados con magnitudes anatómicas y fisiológicas del sistema de producción de la voz. Sin embargo, dado que el espacio de parámetros es multidimensional, la elección del método de ajuste es delicada. La preferencia por un algoritmo genético se ve justificada por dos razones: es de programación simple y es fácilmente adaptable a la paralelización. El problema de la voz es fácilmente adaptable para ser resuelto por un algoritmo genético. En primer lugar, definimos un individuo como la cadena de números que corresponde a los parámetros del modelo. Ası́, la cadena {M, K, B, R2 , I2 , a1 , ..., an , l1 , ..., ln } es un individuo. M ,K B, R2 e I2 son los parámetros de las cuerdas vocales (ecuaciones 1 y 2); ai y li la sección y longitud del i-ésimo tubo que aproxima al tracto vocal. La expresión de este cromosoma (su fenotipo) es el espectro de potencias que genera. El criterio de selección elegido es trivial: la probabilidad de seleccionar un cromosoma es inversamente proporcional a la diferencia cuadrática entre los espectros de la señal experimental y la sintetizada por el modelo. En la figura 2 se ve un ejemplo de ambos espectros una vez que el algoritmo encontró la mejor solución. Los resultados obtenidos con el modelo de una masa para las cuerdas vocales y la aproximación por tubos del tracto vocal no son concluyentes. Por una parte, las geometrı́as a las que converge el tracto vocal corresponden a las de las vocales utilizadas citadas por la bibliografı́a [3]. Sin embargo, el modelo 5 de una masa parece demasiado simple para dar cuenta de la dinámica de las cuerdas vocales, lo que resulta en una dispersión en los parámetros del modelo que no permiten una distinción unı́voca de la identidad. 1 0.9 0.8 0.7 0.6 0.5 0.4 0.3 0.2 0.1 0 0 10 20 30 40 50 60 70 Figura 2: Espectro experimental de una vocal [o] (barras verticales) y de las mejores series sintéticas (lı́neas) generadas por el modelo usando un algoritmo genético de 500 generaciones y 150 cromosomas, tasa de mutación de 8% y crossover de 40%. La frecuencia está en unidades de 102 Hz y la potencia está normalizada. 4.5 Paralelización del algoritmo genético Una posible implementación en paralelo del algoritmo consiste en definir un nodo principal donde se separa la población inicial de cromosomas en sub-dominios a ser procesados en paralelo por el resto de los nodos (esclavos). Cada uno de los nodos esclavos encuentra la adaptación de cada subpoblación, y esta información es devuelta al nodo principal, que aplica los operadores genéticos a la población completa, generando una nueva población que repetirá el proceso. El algoritmo en paralelo opera según la siguiente secuencia: • Nodo principal 1. calcula espectro de la serie experimental 2. envı́a espectro a nodos esclavos 3. crea población inicial de cromosomas 4. divide en dominios locales • Nodos esclavos 1. recibe espectro experimental del nodo principal • loop generaciones – Nodo principal 1. envı́a cromosomas locales a nodos esclavos 2. recibe diferencias cuadráticas de esclavos 3. operadores genéticos: selección, cross-over, mutación – Nodos esclavos 1. 2. 3. 4. 5. recibe cromosomas locales del nodo principal calcula espectros sintéticos desde cromosomas locales compara espectros sintéticos y experimental calcula diferencias cuadráticas envı́a diferencias cuadráticas al nodo principal • fin loop generaciones 6 4.6 Performance del código en paralelo En la figura 3 se grafica el tiempo de procesamiento contra la cantidad de procesadores utilizados (las simulaciones se ejecutaron usando hasta 30 procesadores en el cluster del CeSEN). 700 600 tiempo de ejecucion (s) 500 400 300 200 100 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 numero de procesadores Figura 3: Tiempo de ejecución vs. cantidad de procesadores para el algoritmo genético usando 500 generaciones, 150 cromosomas, tasa de crossing del 40% y tasa de mutaciones de 8%. Los valores usados resultan del promedio de 2 o 3 corridas. A partir de n = 10 procesadores, la dispersión en los valores es despreciable. A la derecha, detalle y ajuste con T (n) = 8.77 + 686.54/n + 0.05n, n es el número de nodos slaves. A primer orden, se espera que el tiempo de procesamiento Tp en función del número de procesadores n se comporte aproximadamente como Tp (n) ∝ 1/n, mientras que el tiempo de comunicación Tc (n) ∝ n. Ajustando los valores de la figura 3 para T (n) de la forma α (4) T (n) = Tp (n) + Tc (n) = Tpmaster + Tpslaves (n) + Tc (n) = γ + + βn n con n el número de nodos slaves y α = Tpslaves (1) el tiempo de procesamiento de 1 nodo slave. Se asume además que el tiempo de procesamiento del master no cambia con la cantidad de slaves. Los valores obtenidos implican una corrección lineal β muy pequeña frente a α. Para estudiar el factor lineal β se usaron logfiles (información de los tiempos de procesamiento de cada procesador) generados para distinta cantidad procesadores. Lo que se observa, promediando la dispersión de los tiempos de procesamiento ∆Tpsl de los nodos slaves, es que ∆Tpsl (10) (5) 2 es decir que al usar más procesadores la dispersión de los tiempos de procesamiento aumenta. La diferencia, acumulada a lo largo de la ejecución del código, es del orden de 10 β, que es la corrección prevista por la ecuación 4. Esto sugiere que la mayor parte del tiempo de comunicación es el tiempo de ‘espera’ que proviene de la dispersión en los tiempos de procesamiento de las distintas computadoras del cluster. ∆Tpsl (20) > Referencias [1] I. R. Titze, Principles of Voice Production (Prentice-Hall, Englewood Cliffs, NJ, 1993). [2] D. E. Goldberg, Genetic Algorithms in Search, Optimization, and Machine Learning, Addison Wesley, 1989. [3] Rabiner, L., Juang, B. (1993) in Fundamentals of speech recognition (Prentice Hall) pp. 24-256. [4] Press, H. W. et al., Numerical Recipies in C: The art of scientific computing, Cambridge University, 1999. [5] N. MacDonald et al., Writing Message-Passing Parallel Programs with MPI, Course Notes, Edinburgh Parallel Computing Centre, University of Edinburgh. [6] Rothemberg, Vocal Fold Physiology, University of Tokyo Press, Tokyo, 1981, pp. 304-323. 7