Algoritmo Genético para Seleção de Variáveis

Felipe Corrêa
Data Hackers
Published in
4 min readMay 16, 2024

Se você está familiarizado com o estudo de Inteligência Artificial (IA), sabe da importância que a seleção de variáveis possui para o correto funcionamento de um modelo. Aqui e aqui você encontrará de forma bem didática os motivos que tornam esse processo tão importante.

Outra questão abordada nesse artigo tem a ver com Algoritmos Genéticos (AG). Eles fazem parte do arcabouço da IA e, em resumo, pretendem simular o comportamento dos organismos baseada no conceito de que "aqueles que melhor se adaptam a seu ambiente têm maiores chances de ter suas características reproduzidas em uma nova geração". (Inteligência Artificial, FACELI et al.)

Como esse artigo não tem o objetivo de aprofundar nos meandros do funcionamento e porquês desses dois assuntos, assim como no caso de seleção de atributos, seguem alguns links mais detalhados e didáticos sobre AG que podem ser encontrados aqui, aqui e aqui.

Mas pra quem ainda está aqui e deseja ter uma ideia do funcionamento os AGs possuem 7 processos essenciais, que são observados nessa imagem:

Fonte: https://slideplayer.com.br/slide/359318/ — Prof. Luis Otávio Alvares II/UFGRS
  • Gerar uma população: Inicia-se a população com a quantidade de indivíduos desejada.
  • Avaliar a população (fitness): Valorar o indivíduo de acordo com a função objetivo.
  • Seleção: Selecionar os indivíduos conforme algum critério.
  • Reprodução (cruzamento / crossover): Após selecionados esses indivíduos gerarão novos.
  • Mutação: Induz uma alteração nos indivíduos de forma estocástica para adicionar diversidade genética.
  • Condição de parada: Pode ser o valor um valor máximo de avaliação, quantidade de gerações, etc.
  • Melhores indivíduos: Escolha dos melhores indivíduos gerados.

Você leitor deve estar se perguntando, porque utilizar AG para esse tipo de problema?

Pois bem, te respondo. Diferente de alguns métodos em que a variável independente é analisada individualmente para se obter a importância dela para a variável resposta, a utilização de uma AG consegue fazer isso com um conjunto delas.

Esse trabalho se utilizou a base a base de classificação German Credit que tem o objetivo de verificar se certo usuário possui um perfil para obtenção ou não de crédito. Ela possui 20 variáveis independentes, 1 dependente em 1000 registros.

Foram testados 3 diferentes modelos e a métrica escolhida foi o score médio da acurária em uma validação cruzada. Para se estabelecer uma comparação com o AG em, primeiro lugar, os modelos foram executados com todas as variáveis do conjunto de dados.

# Create models
random_state = 42
models = [
(AdaBoostClassifier(random_state=random_state), 'AdaBoost'),
(RandomForestClassifier(random_state=random_state, n_jobs=-1),
'RandomForest'),
(SVC(random_state=random_state), 'SupportVectorMachine')]

# Running Baseline
for mdl in models:
scores = cross_val_score(mdl[0], x, y, cv=5, n_jobs=-1)

Ah e todo o código pode ser encontrado aqui.

O algoritmo desenvolvido possui 3 tipos de seleção e 3 de reprodução que podem ser escolhidos conforme o usuário deseja:

def selection(self):
selection = {
'elitism': self._elitism,
'roulette': self._roulette,
'tournament': self._tournament}
selection[self.selection_method]()

def crossover(self):
cross = {
'one-point': self._one_point_cross,
'two-points': self._two_point_cross,
'uniform': self._uniform_cross}
new_pop = cross[self.crossover_method]()
self.pop += new_pop

Aqui e aqui você encontrará informações sobre esses temas.

E por ser feito de forma a funcionar com outras bases a função objetivo (função fit) é sobrescrita dentro do arquivo main.py:

# Overwrite fit method
def fit(self):
for ind in self.pop:
if ind[-1] is None:
ccols = get_cols(x, ind)
scores = cross_val_score(mdl, x[ccols], y, cv=5, n_jobs=-1)
ind[-1] = mean(scores)
g.fit = MethodType(fit, g)

Uma última observação antes dos resultados é que essa função garante que os indivíduos não tenham somente cromossomos 1 ou 0:

def _check_pop_croms(self, pop):
for i in pop:
if (i[0:self.crom].count(0) == 0) or (i[0:self.crom].count(1) == 0):
temp = self._get_rand_crom()
i[temp] = int(not i[temp])
return pop

Resultado do baseline:

Resultados baseline — O autor

No repositório você encontrará a tabela completa com os resultados, mas aqui apresento os 5 melhores e quais variáveis foram selecionadas:

Resultados AG — O autor

Podemos ver que dos 5 melhores casos SVM apresentou o melhor resultado em 4 deles. Esses modelos apesar de não passarem por nenhum processo de hiperparametrização apresentaram uma redução de 12% na quantidade de variáveis e uma melhoria na acurácia de 6% quando comparado com o pior caso do baseline.

Conclusão:

Apesar de ser um processo computacionalmente oneroso ele possui suas qualidades e pode ser uma opção a mais na hora de verificar as variáveis que mais fazem sentido em seu projeto.

Vou ficando por aqui, mas me pinguem caso queiram discutir…

https://www.linkedin.com/in/felipe-israel-correa/

--

--