Olá, estou implementando um GA do zero mas encontrei uma pedra: Na operação de crossover minha função acaba retornando diversos indivíduos iguais e não consigo identificar o porquê; Segue partes importantes para identificar o problema:
Notem que atribuo fitness randômicas a fim de teste e o código é relativamente maior mas o meu problema parece se encontrar aqui!
Peço que ignorem a "cara" dos meus indivíduos, é um GA para um problema bem específico incluindo um step de clusterização e seleção de features de cada cluster.
import random
import string
import pandas as pd
import numpy as np
class Agent:
def __init__(self, Ncluster, Nfeatures, Nsamples):
self.tamanho = Ncluster * Nfeatures
self.Ncluster = Ncluster
self.Nfeatures = Nfeatures
self.Nsamples = Nsamples
self.indiv = []
for _ in range(self.tamanho):
self.indiv.append(random.choice([0,1]))
for _ in range(Nsamples):
self.indiv.append(random.choice(range(Ncluster)))
self.fitness = random.choice([0,1])
def __str__(self):
return 'Features: ' + f'{self.indiv[:self.Ncluster*self.Nfeatures]}' +' Cluster/Sample: ' + f'{self.indiv[self.Ncluster*self.Nfeatures:]}'
def __len__(self):
return self.Ncluster * self.Nfeatures + self.Nsamples
def init_agents(population,Ncluster, Nfeatures, Nsamples):
return [Agent(Ncluster, Nfeatures, Nsamples) for _ in range(population)]
def crossover(agents, population):
offspring = []
filho1 = agents[0]
filho2 = agents[0]
for _ in range((population - len(agents)) // 2):
mask = []
for _ in range(len(agents[0])):
mask.append(random.choice([0,1]))
pai, mae = random.sample(agents, 2)
for bit in range(len(mask)):
if mask[bit] == 1:
filho1.indiv[bit] = pai.indiv[bit]
else:
filho1.indiv[bit] = mae.indiv[bit]
if mask[bit] == 1:
filho2.indiv[bit] = mae.indiv[bit]
else:
filho2.indiv[bit] = pai.indiv[bit]
offspring.append(filho1)
offspring.append(filho2)
agents.extend(offspring)
return agents
Antes de executar o crossover eu executo um processo de seleção de indivíduos, então o crossover é o responsável por criar novos indivíduos baseado nos selecionados(que é a própria lista agents) até o meu número "population" (que é o total de indivíduos de cada geração)