pythondeap

Use np.arange when generating a population with Deap?


Given this dictionary:

gene_space = [
    {"name": "length",'high':110,'low':10,'step':10},
    {"name": "emaLength",'high':34,'low':1,'step':2},
    {"name": "averageLength",'high':110,'low':10,'step':10},
    {"name": "factor",'high':0.5,'low':0.02,'step':0.02},
    {"name": "criticalValue",'high':60,'low':-50,'step':10},
]

...how can I create a population of genes that are randomly selected among those ranges so that they can be used with Deap?

You can see my attempts below:

# Define a maximizing fitness function
creator.create("FitnessMax", base.Fitness, weights=(1.0,))

# We'll create a list of the current population
creator.create("Individual", list, fitness=creator.FitnessMax)

# Create toolbox instance
toolbox = base.Toolbox()

list_of_attrs = []

# Iterate through the gene space
for i in range(len(gene_space)):
    
    # Register the current gene attribute (by name), which is just a np.arange between low and high, steping each way
    # Attempt 1 - Doesn't work as the "population" later is just the actual ranges, not selections from the range
    # toolbox.register(gene_space[i]["name"], np.arange, gene_space[i]['low'], gene_space[i]['high'], gene_space[i]['step'])
    
    # Attempt 2 - Getting better, however this now only selects 1 random choice for the population, and I want more.
    # Defined n=10 below, but doesn't work?
    # toolbox.register(gene_space[i]["name"], random.choice, np.arange(gene_space[i]['low'], gene_space[i]['high'], gene_space[i]['step']))
    
    # Attempt 3 - Tried to make several random selections which is more in line with what I want, but get the error:
    # TypeError: Population must be a sequence or set.  For dicts, use list(d).
    toolbox.register(gene_space[i]["name"], random.sample, np.arange(gene_space[i]['low'], gene_space[i]['high'], gene_space[i]['step']), 10)

    list_of_attrs.append(gene_space[i]["name"])

# Register the individual (full of the attributes)
toolbox.register("individual", tools.initCycle, creator.Individual, (getattr(toolbox, key) for key in list_of_attrs), n=10) # n=10 here does nothing?

# Now register the population
toolbox.register("population", tools.initRepeat, list, toolbox.individual, n=10)

toolbox.register("mate", tools.cxTwoPoint)
toolbox.register("mutate", tools.mutGaussian, mu=0, sigma=1, indpb=0.1)
toolbox.register("select", tools.selTournament, tournsize=3)
toolbox.register("evaluate", evaluate)

I need the population to be the same class type that Deap uses from their examples. I've modified their "main" algorithm to generate the population I need as a list of lists, but then it runs into more errors later because then each gene is just a list, and not a deap class object. Hoping to resolve this using one of the attempts above before I start re-coding a new main method.


Solution

  • Looks like the way to do this is like so (inspiration taken from here):

    dataset = []
    for _ in range(300):
        current_chromosome = []
        for j in range(len(gene_space)):
            current_chromosome.append(random.choice(np.arange(gene_space[j]['low'], gene_space[j]['high'], gene_space[j]['step'])))
        dataset.append(current_chromosome)
    
    # toolbox.register("random_sampling", random.sample, dataset, 1)
    toolbox.register("random_sampling", lambda x,y: random.sample(x,y)[0], dataset, 1)
    toolbox.register("individual", tools.initIterate, creator.Individual, toolbox.random_sampling)