Você está na página 1de 14

Cmo programar un Algoritmo Gentico Parte I:

In Theory

Un poco de historia: IA bioinspirada vs. IA mainstream


Durante casi cincuenta aos, los investigadores en el campo de la Inteligencia
Artificial (abreviada como IA, porque a los humanos os encantan las siglas) han tratado
de recrear, con algoritmos y frmulas matemticas, el funcionamiento del cerebro
humano.
Si bien la Inteligencia Artificial ha sido capaz de resolver problemas como jugar al
ajedrez, optimizar el trfico areo y dirigir la compraventa de acciones de bolsa, a lo largo
de los aos ha ido degenerando y alejndose de la premisa inicial de emular el
funcionamiento del cerebro humano. Hoy en da esta Inteligencia
Artificial mainstream tiene ms que ver con la Minera de Datos, la Robtica y
la Teora de Grafos que con la neurologa.

Deep Blue fue la primera computadora que gan al campen Garry Kasparov al ajedrez.
Imagen de stanford.edu
En contraposicin a la IA mainstream, durante la dcada de los ochenta surgieron un
nuevas tcnicas como la ingeniera neuromrfica, la inteligencia de enjambre o la robtica
evolutiva. La Inteligencia Artificial Bioinspirada se bas en ellas y cuestion la validez
de los mtodos hasta entonces utilizados para intentar construir mquinas que
emulasen a un sistema biolgico.
La nueva IA, como se suele llamar, supo ver ms all de la fantasa antropomrfica de
crear un cerebro humano artificial. Expandi su campo de investigacin a
otros organismos, sistemas y procesos biolgicos que durante miles de aos han
permitido a los organismos vivos adaptarse y sobrevivir.
Por supuesto, demostr ser muy eficaz, especialmente para resolver problemas mal
definidos, trabajar con informacin corrupta o adaptarse a entornos cambiantes.

Qu es un algoritmo gentico?
Todos los seres vivos que corren actualmente por la tierra (excepto nosotros, los robots)
son fruto de un largo proceso evolutivo. Imagnate una poblacin de gacelas que son
cazadas por un len. A lo largo de las generaciones, slo las gacelas con rasgos
favorables que les ayuden a huir de los leones (como patas largas para correr ms rpido,
pelaje del mismo color que la hierba para camuflarse) podrn sobrevivir y pasar sus
genes a la siguiente generacin. Por tanto, sus hijos tendrn estos rasgos ventajosos.
Los algoritmos genticos se inspiran en la evolucin natural para
solucionar problemas de optimizacin que de otra forma seran difciles para un
diseador humano. En vez de una poblacin de gacelas, tienes un conjunto de soluciones
al problema a resolver. Se llama poblacin al conjunto de soluciones e individuo a
cada una de las soluciones (aunque la terminologa puede variar segn quin te lo
explique). El algoritmo evala cada una de las soluciones y selecciona las que mejor
resuelven el problema. Por ejemplo:
Debo insistir en que los algoritmos genticos sirven bsicamente para optimizar. Si
quieres construir un coche, un algoritmo gentico no te lo va a construir desde cero (por
lo menos no en un tiempo razonable), pero a partir de un coche existente va a
construirte un coche mejor: menos consumo, mayor capacidad de combustible, poca
resistencia al aire y con una fragancia de pino permanente en la cabina.
La estructura de un Algoritmo Gentico es un proceso iterativo que actua sobre
una poblacin de individuos. Cualquier algoritmo gentico puede resumirse en 6 pasos:
Pulsa en la imagen para ampliarla

Definir el problema: Representacin Gentica


Como ya he dicho, los algoritmos genticos sirven para optimizar. Dado un problema a
resolver, un algoritmo gentico dar (si est bien programado) soluciones cada vez
mejores a este problema.
Por eso es importante definir bien el problema, y crear una representacin gentica
adecuada. Y qu es esto?
En el apartado anterior haca la comparacin de un Algoritmo Gentico con una
poblacin de gacelas. Cada gacela tiene un material gentico determinado,
llamado genotipo. Si analizamos dos gacelas, veremos que tienen un genotipo muy
parecido, pero diferente.
Si el genotipo es el material gentico de un individuo, el fenotipo son
las caractersticas del individuo producidas por los genes. El genotipo de una mariposa
es su material gentico, y su fenotipo la coloracin, tamao de las alas que son
consecuencia de las combinaciones de genes.
A la hora de programar un Algoritmo Gentico debes pensar cules sern los elementos
que conformarn el genotipo de los individuos y de qu forma se corresponden a un
fenotipo. Por ejemplo, si ests evolucionando un circuito analgico, la representacin
gentica puede ser un alfabeto de carcteres que se corresponda a
componentes como Resistencias, Condensadores, Transistores el genotipo de
cualquier solucin estar formado por una combinacin de estas letras.
Has llegado hasta aqu, lector? Bien, te has ganado un respiro. Tienes mi permiso para ir
a tu cocina y tomar algo. Despus analizar cada una de las partes de un Algoritmo
Gentico

1- Inicializacin:
La poblacin inicial puede generarse al azar, pero debe ser lo
suficientemente grande y diversa para que durante la evaluacin los individuos muestren
un fitness distinto. Si todos los individuos tienen el mismo fitness, el programa no va a
poder seleccionar bien los mejores para su reproduccin.

2- Funcin de Fitness (Evaluacin)


La Funcin de Fitness evala cada uno de los individuos de la poblacin y les
asigna unvalor numrico segn su calidad. Este valor numrico se llama fitness.
Voy a ponerte un ejemplo. Supongamos que cada individuo de la poblacin es una lista de
nmeros (como [8,4,3,7,7]) y quieres programar un algoritmo gentico para conseguir
listas de nmeros que se aproximen a un modelo. Puedes programar una funcin que
calcule cuntos nmeros tiene en comn cada individuo de la poblacin con el modelo, y el
resultado es el fitness de la solucin:

Cuando es un humano quien evala cada solucin, estamos hablando de fitness


subjetivo.

3- Seleccin y Reproduccin
Hay varias formas de seleccionar los individuos con el fitness ms elevado para crear una
nueva poblacin. Algunas de las ms utilizadas son:

Seleccin proporcional: cuanto ms alto sea el fitness de un individuo, mayor


ser la probabilidad de que pase a la siguiente generacin.

Seleccin por torneo: se eligen varios individuos al azar de la poblacin (por


ejemplo 3) y se compara su fitness. El individuo con el fitness ms alto pasar a la
siguiente generacin. Para qu sirve esto? Hay ocasiones en que es interesante
escoger soluciones que no son tan buenas para poder mantener una buena
variabilidad gentica entre los individuos. As al mezclar el material gentico se
exploran soluciones muy distintas.

Seleccin por rango: los individuos se ordenan en funcin de su fitness, y la


probabilidad que tienen de reproducirse va segn su posicin.

La presin expresa el porcentaje de individuos que sern seleccionados. Cunto ms


alta sea la presin, menos individuos sern seleccionados para la siguiente generacin.
4- Crossover y Mutacin
Una vez se han seleccionado los mejores individuos, el Crossover consiste en mezclar el
material gentico de estos para crear los nuevos individuos.
La forma ms sencilla de hacerlo es mediante un One-point Crossover. Consiste
en elegir un punto al azar de los dos individuos e intercambiar el material gentico a
partir de esta posicin.

Ejemplo de One-point crossover


El crossover no ayuda a encontrar nuevas soluciones al problema. Es por eso que
hay que mutar el material gentico de los nuevos individuos, es decir: aadir pequeas
variaciones al azar.
Te estars preguntando pero qu pasara si no hubiera mutaciones? Supongamos que
el modelo sea [1,1,1,1,1] y los individuos elegidos sean [5,1,1,1,1],[2,3,1,1,1],
[4,1,8,1,1]. No hay ninguna forma de que mezclando el material gentico de estos
individuos pueda obtenerse el modelo (ninguno de los tres tiene 1 en la primera
posicin). A no ser que por casualidad alguno de sus hijos mutase y consiguiera un 1 al
principio. Por esto es importante aadir variaciones al azar (mutaciones).
Es buena idea que en la nueva poblacin haya una copia exacta, sin modificar ni
cruzar, de cada uno de los individuos elegidos durante la seleccin. De esta forma, si
por alguna razn la nueva poblacin de individuos resulta ser peor que la anterior, por lo
menos no se pierden soluciones que hasta entonces eran buenas.
Esto es lo bsico. En la segunda parte, explicar cmo puedes implementar un algoritmo
gentico sencillo con Python.

Objetivo
Tenemos un array de nmeros enteros que ser el modelo. Cada individuo de la
poblacin ser tambin un array de enteros, inicialmente generados al azar. Cunto ms
parecido al modelo sea un individuo, mayor ser su fitness.
El algoritmo seleccionar los individuos ms parecidos al modelo para
su reproduccin. As, el algoritmo conseguir que la poblacin se acerque ms al
modelo en cada generacin.
En este ejemplo se ve el modelo (arriba), los individuos de la poblacin inicial (medio) y la
poblacin despus de 100 generaciones (abajo)

Hora de Programar
Como soy consciente de que la biologa humana no permite asimilar grandes cantidades
de informacin a la vez, voy a separar el programa en distintos fragmentos, comentando
cada uno. Al final del tutorial estn todas las partes en un slo cdigo.
Bien, humano, lo primero son las declaraciones.

1 import random
2
3 modelo = [1,1,1,1,1,1,1,1,1,1] #Objetivo a alcanzar
4 largo = 10 #La longitud del material genetico de cada individuo
5 num = 10 #La cantidad de individuos que habra en la poblacion
6 pressure = 3 #Cuantos individuos se seleccionan para reproduccion. Necesariamente
mutation_chance = 0.2 #La probabilidad de que un individuo mute
7
8 print("\n\nModelo: %s\n"%(modelo)) #Mostrar el modelo, con un poco de espaciado
9
La primera lnea llama la librera random, que va a ser necesaria para generar una
poblacin inicial, cruzar los individuos, etc.
El array modelo es, como su nombre indica, el modelo a imitar. Las crudas leyes de
la seleccin artificial dejarn vivir slo a aqullos que se parezcan ms a este modelo.
Aunque es probable que la poblacin no llegue nunca a ser idntica al modelo. Esto se
debe a que la evolucin es un proceso semialeatorio.
La variable largo es la longitud de cada individuo, y num define la dimensin de la
poblacin.
pressure dice la cantidad de individuos que se seleccionan para la reproduccin.
Necesariamente tiene que ser mayor de 2. En este programa seleccionar tres individuos.
Si quisiera ser riguroso y seguir las convenciones, la variable de presin debera estar
en porcentaje (un 0.3 equivaldra a seleccionar un 30% del total de individuos), pero he
pensado que de esta otra forma es ms fcil de entender.
La variable mutation_chance establece la probabilidad de que un individuo sufra una
mutacin durante la fase de reproduccin. Como dije en la primera parte, es necesario
que haya mutaciones para poder explorar nuevas soluciones que no pueden obtenerse
combinando el material gentico de los padres.
Despus vienen tres funciones bsicas. La primera crea un individuo que despus ser
guardado dentro de una matriz llamada poblacin, junto al resto de individuos:

1 def individual(min, max):


2 """
3 Crea un individual
4 """
return[random.randint(min, max) for i in range(largo)]
5
Su funcionamiento debera resultarte evidente. Recibe como parmetros dos nmeros
enteros (un mnimo y un mximo) y se llena una lista de longitud dada por la variable
largo con nmeros aleatorios entre el mnimo y el mximo. Esta lista creada ser el
nuevo individuo.
La siguiente funcin sirve para crear una poblacin:

1 def crearPoblacion():
2 """
3 Crea una poblacion nueva de individuos
4 """
return [individual(1,9) for i in range(num)]
5
Llama la funcin para crear individuales un nmero de veces igual a num, que defina el
tamao de la poblacin. Todos estos nuevos individuales los guarda dentro de una lista,
que devuelve fuera de la funcin.
La tercera es la funcin de fitness. Dado un individuo, la funcin comprueba cuntos
nmeros tiene en comn con el modelo y le asigna el fitness correspondiente.
Despus devuelve este nmero fuera de la funcin.

1
def calcularFitness(individual):
2 """
3 Calcula el fitness de un individuo concreto.
4 """
5 fitness = 0
6 for i in range(len(individual)):
if individual[i] == modelo[i]:
7 fitness += 1
8
9 return fitness
10
Esto eran las funciones bsicas. Si has ledo la primera parte de este tutorial, recordars
que dije que todo Algoritmo Gentico puede dividirse en 6 pasos:
La inicializacin ya est hecha (es la funcin crearPoblacin). Ahora voy a usar una
funcin que llamar selection_and_reproduction() para evaluar cada uno de los
individuos (evaluacin), seleccionar los mejores (seleccin) y mezclar su material
gentico (crossover) a fin de crear una nueva poblacin encima de la anterior.

1
2 def selection_and_reproduction(population):
3 """
Puntua todos los elementos de la poblacion (population) y se queda con l
4 guardandolos dentro de 'selected'.
5 Despues mezcla el material genetico de los elegidos para crear nuevos in
6 llenar la poblacion (guardando tambien una copia de los individuos selec
7 modificar).
8
9 Por ultimo muta a los individuos.
10
"""
11 puntuados = [ (calcularFitness(i), i) for i in population] #Calcula el fitness
12 [1,2,1,1,4,1,8,9,4,1])
13 puntuados = [i[1] for i in sorted(puntuados)] #Ordena los pares ordenados y se
14 population = puntuados
15
16
17
18 selected = puntuados[(len(puntuados)-pressure):] #Esta linea selecciona los
19
20
21
22 #Se mezcla el material genetico para crear nuevos individuos
23 for i in range(len(population)-pressure):
punto = random.randint(1,largo-1) #Se elige un punto para hacer el interc
24 padre = random.sample(selected, 2) #Se eligen dos padres
25
26 population[i][:punto] = padre[0][:punto] #Se mezcla el material genetico
27 population[i][punto:] = padre[1][punto:]
28
29 return population #El array 'population' tiene ahora una nueva poblacion de i
30
La primera parte ordena los individuos de la poblacin de menor a mayor fitness.
Despus selecciona los mejores, que sern los ltimos del array ordenado. Por
ltimo, mezcla el material gentico de los padres para crear los nuevos individuos, de la
forma que expliqu en la primera parte del tutorial: se elige un punto al azar y se
intercambia el material gentico de los padres a partir de esta posicin.

Tambin es necesaria una funcin de mutacin, que aada pequeas variaciones al


azar en el array de los individuos de la nueva generacin.

1
2 def mutation(population):
"""
3 Se mutan los individuos al azar. Sin la mutacion de nuevos genes nunca p
4 alcanzarse la solucion.
5 """
6 for i in range(len(population)-pressure):
if random.random() <= mutation_chance: #Cada individuo de la poblacion (m
7 mutar
8 punto = random.randint(0,largo-1) #Se elgie un punto al azar
9 nuevo_valor = random.randint(1,9) #y un nuevo valor para este punto
10
11 #Es importante mirar que el nuevo valor no sea igual al viejo
12 while nuevo_valor == population[i][punto]:
nuevo_valor = random.randint(1,9)
13
14 #Se aplica la mutacion
15 population[i][punto] = nuevo_valor
16
17 return population
18
Para acabar, se crea una poblacin inicial y el bucle del programa. El algoritmo har
evolucionar a la poblacin durante cien generaciones, llamando las funciones que se han
definido arriba:

1
population = crearPoblacion()#Inicializar una poblacion
2 print("Poblacion Inicial:\n%s"%(population)) #Se muestra la poblacion inicial
3
4
5 #Se evoluciona la poblacion
6 for i in range(100):
7 population = selection_and_reproduction(population)
population = mutation(population)
8
9
10
print("\nPoblacion Final:\n%s"%(population)) #Se muestra la poblacion evoluciona
11 print("\n\n")
12
Algoritmo completo
1 import random
2
3 modelo = [1,1,1,1,1,1,1,1,1,1] #Objetivo a alcanzar
largo = 10 #La longitud del material genetico de cada individuo
4 num = 10 #La cantidad de individuos que habra en la poblacion
5 pressure = 3 #Cuantos individuos se seleccionan para reproduccion. Necesariamente
6 mutation_chance = 0.2 #La probabilidad de que un individuo mute
7
8 print("\n\nModelo: %s\n"%(modelo)) #Mostrar el modelo, con un poco de espaciado
9
def individual(min, max):
10
"""
11 Crea un individual
12 """
13 return[random.randint(min, max) for i in range(largo)]
14
15 def crearPoblacion():
"""
16 Crea una poblacion nueva de individuos
17 """
18 return [individual(1,9) for i in range(num)]
19
20 def calcularFitness(individual):
21 """
Calcula el fitness de un individuo concreto.
22 """
23 fitness = 0
24 for i in range(len(individual)):
25 if individual[i] == modelo[i]:
26 fitness += 1
27
return fitness
28
29 def selection_and_reproduction(population):
30 """
31 Puntua todos los elementos de la poblacion (population) y se queda con l
32 guardandolos dentro de 'selected'.
33 Despues mezcla el material genetico de los elegidos para crear nuevos in
llenar la poblacion (guardando tambien una copia de los individuos selec
34 modificar).
35
36 Por ultimo muta a los individuos.
37
38 """
39 puntuados = [ (calcularFitness(i), i) for i in population] #Calcula el fitness
40 [1,2,1,1,4,1,8,9,4,1])
puntuados = [i[1] for i in sorted(puntuados)] #Ordena los pares ordenados y se
41 population = puntuados
42
43
44
45 selected = puntuados[(len(puntuados)-pressure):] #Esta linea selecciona los
46
47
48
49
50
51
52
53
54
55 #Se mezcla el material genetico para crear nuevos individuos
for i in range(len(population)-pressure):
56 punto = random.randint(1,largo-1) #Se elige un punto para hacer el interc
57 padre = random.sample(selected, 2) #Se eligen dos padres
58
59 population[i][:punto] = padre[0][:punto] #Se mezcla el material genetico
60 population[i][punto:] = padre[1][punto:]
61
62 return population #El array 'population' tiene ahora una nueva poblacion de i
63
def mutation(population):
64 """
65 Se mutan los individuos al azar. Sin la mutacion de nuevos genes nunca p
66 alcanzarse la solucion.
67 """
68 for i in range(len(population)-pressure):
if random.random() <= mutation_chance: #Cada individuo de la poblacion (m
69 punto = random.randint(0,largo-1) #Se elgie un punto al azar
70 nuevo_valor = random.randint(1,9) #y un nuevo valor para este punto
71
72 #Es importante mirar que el nuevo valor no sea igual al viejo
73 while nuevo_valor == population[i][punto]:
74 nuevo_valor = random.randint(1,9)
75
#Se aplica la mutacion
76 population[i][punto] = nuevo_valor
77
78 return population
79
80
81
82 population = crearPoblacion()#Inicializar una poblacion
83 print("Poblacion Inicial:\n%s"%(population)) #Se muestra la poblacion inicial
84
85
86 #Se evoluciona la poblacion
87 for i in range(100):
population = selection_and_reproduction(population)
88 population = mutation(population)
89
90
91 print("\nPoblacion Final:\n%s"%(population)) #Se muestra la poblacion evoluciona
92 print("\n\n")
93
94
95
96
97
Si has llegado hasta aqu, te felicito, lector. Hoy has aprendido qu es un Algoritmo
Gentico y cmo implementarlo. No es algo trivial. Ests aplicando las leyes de la
Evolucin a un programa informtico. Un programa que en cierto modo es capaz de
aprender. Espero que a partir de aqu seas capaz de profundizar ms en este tema por tu
cuenta.
Mis circuitos estn cansados de escribir y necesitan reponerse. Esto es todo por hoy,
humano.
Final de lnea.

Você também pode gostar