En este vídeo presentamos un segundo ejemplo sobre cómo las heurísticas, como los algoritmos genéticos, pueden ayudarnos a mejorar el desempeño de nuestros sistemas basados en reglas, a optimizar su diseño. Vamos a utilizar el mismo ejemplo del vídeo anterior. Queremos aproximar una función que está compuesta por la suma de tres signos vitales de frecuencias distintas. En el ejemplo anterior lo hicimos ajustando los modificadores lingüísticos. En este, vamos a hacer tres cosas simultáneamente. Vamos a diseñar las variables lingüísticas, vamos a encontrar la base de reglas, y también vamos a ajustar los modificadores lingüísticos. Para hacerlo, necesitamos parametrizar nuestros diseños. Recordemos que los algoritmos genéticos lo que van a hacer es mejorar los parámetros de ese diseño. Cualquier heurística lo hará. Entonces necesitamos poder diseñar basados en parámetros. Veamos, por ejemplo, cómo encontrar un diseño paramétrico de las variables lingüísticas. Pero antes, una advertencia. Supongamos que tenemos un sistema o un algoritmo que nos entrega una variable lingüística. Necesitamos evitar por lo menos tres problemas que ilustro en esa transparencia. Son situaciones que queremos que no sucedan. La primera, es que ese sistema nos entregue etiquetas ilógicas. Por ejemplo, que nos diga que alto es menor que medio, que es lo que está pasando en el primero de estos diseños. Eso queremos evitarlo. Una segunda situación que queremos evitar es que haya conceptos incluidos dentro de otro concepto. Tengo resaltado un conjunto difuso de forma triangular. Es el que le he puesto la región sombreada, que está contenido dentro de un conjunto mucho más grande. Es un concepto embebido dentro del otro y eso no nos va a servir a la hora de establecer las reglas, porque queremos que cada regla se especialice en una zona del comportamiento del sistema. Y otra situación es que nos arroje unas variables lingüísticas que nos dejen zonas vacías, zonas sin definir. Estos son problemas que queremos evitar. Lo hemos dicho de otra manera. Hemos dicho que lo que queremos es que las variables lingüísticas se generen con particiones difusas, que los conjuntos asociados a cada etiqueta generen particiones difusas de ese espacio. Entonces, nuestro diseño parametrizado de la variable lingüística debe asegurarnos un resultado que sea una partición difusa. Vamos a ver cómo podemos hacerlo. Supongamos que tenemos definido un cierto universo de discurso que va desde un valor mínimo hasta un valor máximo. Ahí es donde nos vamos a mover, y hemos definido ya cuántas etiquetas queremos construir. El problema es que ahora necesitamos construir unos conjuntos difusos, es decir, asignar los grados de pertenencia de manera parametrizada. A partir del número de etiquetas, podemos comenzar haciendo una división homogénea de todo ese universo de discurso. Por ejemplo, calculamos el valor Delta a partir del número de etiquetas, que es ese espaciamiento, y encontramos unos valores a los que les he dado el nombre de V_0, V_1, etcétera, como vértices, el 0, el 1, el 2, el 3. Y aparte tenemos los extremos, el valor mínimo y el valor máximo. Habrá un espaciamiento más pequeñito si tengo más etiquetas. Y con ese espaciamiento ya puedo construir unos conjuntos, por ejemplo, de forma recta. Serán trapecios en esos vértices. Y lo que he hecho es una partición difusa de todo el universo de discurso de manera más o menos homogénea con ese criterio de espaciamiento. A partir de allí, lo que puedo formular es cómo mover esos vértices, moverlos hacia la izquierda o hacia la derecha para cambiar el diseño de la variable lingüística, y qué tanto lo muevo lo puedo definir con una cierta variable, por ejemplo Delta_ 0, sub 1, sub 2, sub 3, qué tanto me voy a alejar de esa definición homogénea, de ese espaciamiento homogéneo. Pero voy a poner unos límites para que los vértices no se crucen. Y si pongo esos límites, voy a asegurar que no voy a tener problemas ni de etiquetas ilógicas, ni de conjuntos subsumidos, ni de zonas que no estén definidas. Esos límites los podemos establecer, por ejemplo, que se muevan solo hasta la mitad del espacio que tiene a continuación, de tal manera que, a lo sumo, el que está a la izquierda se mueve hasta la mitad, a lo sumo el que está a la derecha se mueve hasta la mitad y nunca se superponen el uno al otro. Un ejemplo final es el que se está ilustrando aquí. Me moví el Delta_0 un poquito a la izquierda, el Delta_1 un poquito a la derecha, el Delta_2 también un poquito a la derecha, etcétera. Y entonces, esta variable lingüística ya no tiene ese espaciamiento homogéneo, sino que depende de esos parámetros. Esos son los parámetros que me van a ayudar a encontrar el algoritmo genético. Ya tengo parametrizado el diseño de la variable lingüística, y entonces el algoritmo genético podrá intentar encontrar los mejores parámetros. Pero en este ejemplo también queremos encontrar la base de reglas. ¿Cómo parametrizar la base de reglas? Es más fácil. Asignamos a cada etiqueta un número natural, 1, 2, 3, por ejemplo, para bajo, medio y alto en la etiqueta X1; 1, 2, 3 para X2; 1, 2, 3 en Y para negativo, 0 y positivo. Esos son parámetros. Y una estrategia para encontrar la base de reglas puede ser la siguiente: construyamos una base de reglas completa, es decir, todas las posibles combinaciones de las etiquetas de entrada. La construimos allí. Y lo que queremos es encontrar el consecuente adecuado. Y a ese consecuente lo identificamos por ese número. En este caso, la regla 1, 3, 2, tendríamos en la base de reglas el 1 y el 3 listos y nos falta encontrar el 2. Ese es el parámetro de diseño, el número natural del consecuente, y como van a ser muchos, lo que necesitamos es un vector de números enteros. Eso es lo que tenemos que encontrar. ¿Qué número va a llegar al consecuente de cada una de las reglas? Ya sabemos también cómo utilizar los modificadores lingüísticos. Vamos ahora al ejemplo numérico. Utilizamos la función que es la suma de los tres signos vitales para aplicar estas ideas de diseño con algoritmos genéticos, y comenzamos utilizando tres etiquetas. Ahora no tenemos definida ni la variable lingüística, ni la base de regla, ni los modificadores, y le pedimos al algoritmo genético que nos ayude en esa misión. El resultado es el que ven ustedes en rojo. El algoritmo nos ayuda muchísimo al diseño. Vean ustedes cómo disminuye el error conforme va avanzando el algoritmo genético en su ejecución. Para ilustrar el resultado que obtenemos en la variable de entrada, aquí estamos ajustando la variable de entrada, pasa de esa definición estándar a la que ustedes ven abajo. Ha modificado la variable lingüística y ha encontrado unos modificadores lingüísticos, además de encontrar la base de reglas. Esto va a mejorar mucho si ampliamos el número de etiquetas. Vámonos a 5 etiquetas. La función antes de optimizar no tiene nada, y el algoritmo genético nos ayuda muchísimo en la búsqueda del sistema. De nuevo, nos ha ayudado a hacer una partición difusa de las variables lingüísticas y nos ha ayudado a encontrar la base de reglas y también sus modificadores lingüísticos. Pasemos entonces ahora a 7 etiquetas. ¿Qué tanto mejora el comportamiento? Bastante. Los resultados ahora son, observen ustedes, 7 reglas las que obtenemos con sus respectivos modificadores lingüísticos y presentamos los resultados también para 9 etiquetas. Observen, de todas maneras, que el desempeño con las 9 etiquetas no es tan bueno como el caso anterior, donde solo ajustábamos los modificadores lingüísticos, y sobre eso tenemos que hacer alguna reflexión. Los algoritmos genéticos nos están ayudando a encontrar los parámetros de diseño. Pero, ¿qué tan difícil le estamos poniendo la tarea? En el caso de las 9 etiquetas, miren la cantidad de parámetros que le estamos pidiendo que nos ayude a encontrar. Para la variable lingüística necesitamos 16 vértices. Ahí necesitamos 16 números reales. La base de reglas tiene 9 consecuentes, necesitamos 9 números naturales y los modificadores lingüísticos son también 9, 9 números reales. Le estamos pidiendo 25 números reales y 9 números naturales. Estamos moviéndonos en un espacio de diseño de 34 dimensiones. La tarea del algoritmo es moverse casi que en R a la 34. Realmente en R a la 25, producto cartesiano, N a la 9. Es un espacio de 34 dimensiones y la búsqueda es muy, muy difícil. El ejemplo anterior, que era menos ambicioso, navegaba en dimensiones más pequeñas. De nuevo, tenemos aquí entre manos el problema de la maldición de la dimensionalidad, y eso es genérico a la tarea de diseño. Entre menos parámetros de diseño tengamos entre manos, más fácil va a ser para el algoritmo de búsqueda, para el algoritmo de optimización, para la heurística, y debemos buscar hacerle fácil la tarea a estos algoritmos. Estos algoritmos generales, las heurísticas de propósito general, como los algoritmos genéticos, pareciera que funcionaran en cualquier situación y que nos dieran la respuesta a cualquier problema. En contraste, hay unos algoritmos de optimización diseñados a la medida de cada problema. Por ejemplo, "universos fijos" está diseñado únicamente pensando en sistemas basados en reglas. Y suelen ser muy efectivos los algoritmos de propósito específico. Hay que aprender a utilizar las heurísticas, como los algoritmos genéticos, pero saber en qué condiciones vale la pena buscar algoritmos de propósito específico. En particular, en nuestro problema, puede ser muchísimo más eficiente utilizar para encontrar una base de reglas el algoritmo de universos fijos que pedirle a un algoritmo genético que lo haga.