import numpy as np
from ..coevolution.ccea import CCEA
from ..fitness.penalty import SubsetSizePenalty
from ..evaluation.wrapper import WrapperEvaluation
from ..cooperation.best import SingleBestCollaboration
from ..cooperation.random import SingleRandomCollaboration
from ..initialization.binary import RandomBinaryInitialization
from ..optimizers.genetic_algorithm import BinaryGeneticAlgorithm
[docs]
class CCGA(CCEA):
"""Cooperative Co-Evolutionary Genetic Algorithm.
Attributes
----------
subcomp_sizes : list
Number of features in each subcomponent.
feature_idxs : np.ndarray
Shuffled list of feature indexes.
"""
def _init_collaborator(self):
"""Instantiate collaboration method."""
self.best_collaborator = SingleBestCollaboration()
self.random_collaborator = SingleRandomCollaboration(seed=self.seed)
def _init_evaluator(self):
"""Instantiate evaluation method."""
evaluator = WrapperEvaluation(
task=self.conf["wrapper"]["task"],
model_type=self.conf["wrapper"]["model_type"],
eval_function=self.conf["evaluation"]["eval_function"],
eval_mode=self.eval_mode,
n_classes=getattr(self.data, "n_classes", None),
store_estimators=False, # SubsetSizePenalty fitness function does not need estimators
cache_size=self.conf["wrapper"].get("cache_size", 0),
use_subprocess=self.conf["wrapper"].get("use_subprocess", False)
)
self.fitness_function = SubsetSizePenalty(
evaluator=evaluator,
weights=self.conf["evaluation"]["weights"]
)
def _init_subpop_initializer(self):
"""Instantiate subpopulation initialization method."""
self.initializer = RandomBinaryInitialization(
data=self.data,
subcomp_sizes=self.subcomp_sizes,
subpop_sizes=self.subpop_sizes,
collaborator=self.random_collaborator,
fitness_function=self.fitness_function,
n_workers=self.evaluation_workers
)
def _init_optimizers(self):
"""Instantiate evolutionary algorithms to evolve each subpopulation."""
self.optimizers = list()
# Instantiate an optimizer for each subcomponent
for i in range(self.n_subcomps):
optimizer = BinaryGeneticAlgorithm(
subpop_size=self.subpop_sizes[i],
n_features=self.subcomp_sizes[i],
conf=self.conf
)
self.optimizers.append(optimizer)
def _evaluate_evolved_subpopulations(
self,
collaborators_getter: object,
build_context_vector: object
) -> tuple:
"""Evaluate each individual of the evolved subpopulations."""
current_fitness = list()
current_context_vectors = list()
for i in range(self.n_subcomps):
subpop_context_vectors = list()
for j in range(self.subpop_sizes[i]):
collaborators = collaborators_getter(
subpop_idx=i,
indiv_idx=j
)
context_vector = build_context_vector(collaborators)
subpop_context_vectors.append(context_vector)
fitness_values = self._evaluate_context_vectors(subpop_context_vectors)
current_fitness.append(fitness_values)
best_idx = int(np.argmax(fitness_values))
current_context_vectors.append(subpop_context_vectors[best_idx].copy())
return current_fitness, current_context_vectors