コード例 #1
0
def continuous_ga(model,
                  weights,
                  hparams,
                  NGEN=40,
                  nb_indiv=80,
                  nb_threads=1,
                  cxpb=0.7,
                  mutpb=0.4,
                  mu=0,
                  sigma=0.3,
                  indpb=0.05,
                  alpha=0.1,
                  tournsize=3,
                  stric_interval=False,
                  log_file=None,
                  recover_file=None,
                  **kwargs):
    """
	Main function to run the genetic algorithm for continuous optimization

	Parameters:
		model (python callable) evaluation function 
		weights (tuple): weights of the metrics of the python callable
		hparams (python dict with specific structure): parameter space, the format is presented in the __main__ function
		NGEN (Integer): Number of generations/iterations
		nb_indiv (Integer):Number of individuals in the population
		nb_thread (Integer): number of processes that will run in parallel (allows a lot of speed up if the test function is costly)
		cxpb (Float between 0 and 1): probability of crossing two individuals
		mutpb (Float between 0 and 1): probability of mutating one individual
		mu (Float): expectancy of the mutation
		sigma (Float): variance of the mutation
		indpb (float between 0 and 1): probability of mutating one gene
		tournsize (Integer): size of the tournament for selection
		strict_interval (Bool): If True the solutions are constrained to the design space defined in hparams, if False the GA can evolve outside the bounds
		log_file (str): string of the log file to create to register all the executions and the relations between individuals
		recover_file (str): If you want to resume the computation from a log_file
		**kwargs: extra arguments forwarded to the model
	Outputs:
		pops (list of populations(list of individuals)) this object is written in the pickle file but you can have it unpickled as the output of the algorithm


	"""
    #if we are resuming the computation from a log_file
    if recover_file:
        with open(recover_file, 'rb') as pickle_file:
            hparams = pickle.load(pickle_file)
            translator = Continous_DNA(hparams, stric_interval=stric_interval)
            pops = pickle.load(pickle_file)

            #creating Individual and Fitness class
            creation_deap_classes(creator, weights)

            #toolbox object from deap: allows to define functions in one line for operations on the individual
            toolbox = base.Toolbox()

            #registering the operators for running the algorithm
            creation_tools(toolbox, model, translator, creator, weights, alpha,
                           mu, sigma, indpb, tournsize, nb_threads, **kwargs)

            #recovering the population from the log_file
            population = recover_last_gen(pops, creator, translator)

            #Performing selection and cross and mutation to create the new generation
            population = toolbox.select([
                indiv
                for indiv in population if translator.is_dna_viable(indiv)
            ],
                                        k=nb_indiv)
            population = algorithms.varAnd(population,
                                           toolbox,
                                           cxpb=cxpb,
                                           mutpb=mutpb)
    #otherwise initialize from
    else:
        translator = Continous_DNA(hparams, stric_interval=stric_interval)
        #creating Individual and Fitness class
        creation_deap_classes(creator, weights)

        #toolbox object from deap: allows to define functions in one line for operations on the individual
        toolbox = base.Toolbox()

        creation_tools(toolbox, model, translator, creator, weights, alpha, mu,
                       sigma, indpb, tournsize, nb_threads, **kwargs)
        #we are now creating the population
        population = toolbox.population(n=nb_indiv)

        pops = []

    init_integer = len(pops)

    #Starting the main loop for the genetic algorithm
    for gen in range(init_integer, NGEN):
        print('Generation: ' + str(gen + 1))

        #creating ids if needed
        for l, ind in enumerate(population):
            ind.age += 1
            if ind.mutated != None or ind.parents != None or gen == 0:
                ind.id = str(gen + 1) + "." + str(l)

        #Evaluation of the individuals
        fits = toolbox.map(toolbox.evaluate, population)
        #assigning fitnesses
        for fit, ind in zip(fits, population):
            ind.fitness.values = fit

        # Printing the best individual
        top1 = tools.selBest(population, k=1)
        print(translator.dna_to_phen(top1[0]))
        print(top1[0].fitness.values)

        #Registering the information in the pickle file
        pops.append([{
            "phen": translator.dna_to_phen(indiv),
            "fits": indiv.fitness.values,
            "age": indiv.age,
            "id": indiv.id,
            "parents": indiv.parents,
            "mutated": indiv.mutated
        } for indiv in population if translator.is_dna_viable(indiv)])

        #Selection of the individuals
        population = toolbox.select(
            [indiv for indiv in population if translator.is_dna_viable(indiv)],
            k=len(population))

        #Crossing and mutating
        population = algorithms.varAnd(population,
                                       toolbox,
                                       cxpb=cxpb,
                                       mutpb=mutpb)
        if log_file:
            with open(log_file, 'wb') as pickle_file:
                pickle.dump(hparams,
                            pickle_file,
                            protocol=pickle.HIGHEST_PROTOCOL)
                pickle.dump(pops,
                            pickle_file,
                            protocol=pickle.HIGHEST_PROTOCOL)
    #at the end we return all the executions even though they might have been registered in the pickle file
    return pops
コード例 #2
0
def run_evolution(model,
                  hparams,
                  NGEN=40,
                  mut_rate=0.05,
                  tourn_size=3,
                  cxpb=0.5,
                  mutpb=0.3,
                  nb_indiv=80,
                  nb_threads=1,
                  log_file=None,
                  recover_file=None,
                  gray_code=False,
                  **kwargs):
    """
	Arguments:

		model (python callable): black box function to be optimized: python function that returns the fitness as first argument it must take one configuration of the hyperparameters 
		hparams (python dictionnary): parameter space defined in the following format:	
		 hparams={
						"character1":[1,2,3],
						"character2":["relu","sig"]
			}
		mut_rate (float between 0 and 1): the probability of mutating one gene
		tourn_size (int): the size of the tournament
		cxpb (float between 0 and 1): probability of crossing two individuals, otherwise the individuals are kept as such
		mutpb (float between 0 and 1): probability to mutate an individual
		nb_indiv (int): number of individuals per generation
		nb_thread (int): number of processes needed for	the GA to run
		log_file (str): name of the file for saving the generations
		recover_file (str): name of the log_file that you want to recover from
		gray_code (bool): binary encoding technique: if True gray code is used, binary encoding if False

		**kwargs is all the extra arguments that need to be passed to the model (a data reader for instance)
	Outputs:
		pops (list of populations(list of individuals)) this object is written in the pickle file but you can have it unpickled as the output of the algorithm


	"""
    if recover_file:
        with open(recover_file, 'rb') as pickle_file:
            hparams = pickle.load(pickle_file)
            translator = DNA_creator(hparams, gray_code=gray_code)
            pops = pickle.load(pickle_file)

            #creating Individual and Fitness class
            creation_deap_classes(creator)

            #toolbox object from deap: allows to define functions in one line for operations on the individual
            toolbox = base.Toolbox()

            #registering the operators for running the algorithm
            creation_tools(toolbox, model, translator, creator, mutpb,
                           tourn_size, nb_threads, **kwargs)

            population = recover_last_gen(pops, creator, translator)

            #Performing selection and cross and mutation to create the new generation

            population = toolbox.select([
                indiv
                for indiv in population if translator.is_dna_viable(indiv)
            ],
                                        k=nb_indiv)
            population = algorithms.varAnd(population,
                                           toolbox,
                                           cxpb=cxpb,
                                           mutpb=mutpb)
    else:
        translator = DNA_creator(hparams, gray_code=gray_code)

        #creating Individual and Fitness class
        creation_deap_classes(creator)

        #toolbox object from deap: allows to define functions in one line for operations on the individual
        toolbox = base.Toolbox()
        #registering the operators for running the algorithm
        creation_tools(toolbox, model, translator, creator, mutpb, tourn_size,
                       nb_threads, **kwargs)
        #we are now creating the population
        population = toolbox.population(n=nb_indiv)
        pops = []

    init_integer = len(pops)

    #We are running the genetic algorithm
    for gen in range(init_integer, NGEN):
        print('Generation: ' + str(gen + 1))

        #creating ids if needed
        for l, ind in enumerate(population):
            ind.age += 1
            if ind.mutated != None or ind.parents != None or gen == 0:
                ind.id = str(gen + 1) + "." + str(l)

        #Evaluation of the individuals
        fits = toolbox.map(toolbox.evaluate, population)
        #assigning fitness
        for fit, ind in zip(fits, population):
            ind.fitness.values = fit

        # Printing the best individual
        top1 = tools.selBest(population, k=1)
        print(translator.dna_to_phen(top1[0]))
        print(top1[0].fitness.values)

        #Registering the information in the pickle file
        pops.append([{
            "phen": translator.dna_to_phen(indiv),
            "fits": indiv.fitness.values,
            "age": indiv.age,
            "id": indiv.id,
            "parents": indiv.parents,
            "mutated": indiv.mutated
        } for indiv in population if translator.is_dna_viable(indiv)])

        #Selection of the individuals
        population = toolbox.select(
            [indiv for indiv in population if translator.is_dna_viable(indiv)],
            k=len(population))

        population = algorithms.varAnd(population,
                                       toolbox,
                                       cxpb=cxpb,
                                       mutpb=mutpb)

        if log_file:
            with open(log_file, 'wb') as pickle_file:
                pickle.dump(hparams,
                            pickle_file,
                            protocol=pickle.HIGHEST_PROTOCOL)
                pickle.dump(pops,
                            pickle_file,
                            protocol=pickle.HIGHEST_PROTOCOL)
    return pops
コード例 #3
0
def run_constrained_hybrid_ga(model,
                              weights,
                              hparams,
                              NGEN=40,
                              nb_indiv=80,
                              nb_threads=1,
                              cxpb=0.7,
                              mutpb=0.4,
                              discrete_cx=tools.cxTwoPoint,
                              discrete_cx_kwargs={},
                              continuous_cx=tools.cxBlend,
                              continuous_cx_kwargs={"alpha": 0.1},
                              discrete_mut=tools.mutFlipBit,
                              discrete_mut_kwargs={"indpb": 0.05},
                              continuous_mut=tools.mutGaussian,
                              continuous_mut_kwargs={
                                  "mu": 0.,
                                  "sigma": 0.1,
                                  "indpb": 0.05
                              },
                              selection_op=tools.selTournament,
                              selection_kwargs={"tournsize": 3},
                              stric_interval=False,
                              log_file=None,
                              recover_file=None,
                              gray_code=True,
                              constraints=[],
                              **kwargs):
    if recover_file:
        with open(recover_file, 'rb') as pickle_file:
            hparams = pickle.load(pickle_file)
            translator = HybridDNA(hparams,
                                   stric_interval=stric_interval,
                                   gray_code=gray_code)
            pops = pickle.load(pickle_file)

            creator.create("FitnessHidden", FitnessReg, weights=weights)
            creator.create("FitnessMax",
                           ConstrainedFitness,
                           base_fit=creator.FitnessHidden)
            #weight is the weights given to the different fitnesses (incase you have a multiobjective optimization to make)
            creator.create("Individual",
                           list,
                           fitness=creator.FitnessMax,
                           parents=None,
                           mutated=None,
                           id=None,
                           age=0)
            #toolbox object from deap: allows to define functions in one line for operations on the individual
            toolbox = base.Toolbox()
            toolbox.register("individual",
                             generate,
                             translator=translator,
                             creator=creator)
            toolbox.register("population", tools.initRepeat, list,
                             toolbox.individual)
            #funtion that retruns the fitness from an individual
            #the output is a tuple to match the format of the weights given just above in fitnessMax definition

            #deap basic funtion to cross a population
            toolbox.register("evaluate",
                             evaluate,
                             model=model,
                             translator=translator,
                             weights=weights,
                             **kwargs)
            toolbox.register("mate",
                             decorator_cross(hybrid_cx),
                             discrete_cx=discrete_cx,
                             discrete_cx_kwargs=discrete_cx_kwargs,
                             continuous_cx=continuous_cx,
                             continuous_cx_kwargs=continuous_cx_kwargs)
            toolbox.register("mutate",
                             decorator_mut(hybrid_mut),
                             discrete_mut=discrete_mut,
                             discrete_mut_kwargs=discrete_mut_kwargs,
                             continuous_mut=continuous_mut,
                             continuous_mut_kwargs=continuous_mut_kwargs)
            toolbox.register("select", decorator_selection(selection_op),
                             **selection_kwargs)
            population = recover_last_gen(pops, creator, translator)
            #nb_indiv=len(population)

            #Performing selection and cross and mutation to create the new generation

            population = toolbox.select([
                indiv
                for indiv in population if translator.is_dna_viable(indiv)
            ],
                                        k=nb_indiv)
            population = algorithms.varAnd(population,
                                           toolbox,
                                           cxpb=cxpb,
                                           mutpb=mutpb)
    else:
        translator = HybridDNA(hparams,
                               stric_interval=stric_interval,
                               gray_code=gray_code)
        creator.create("FitnessHidden", FitnessReg, weights=weights)
        creator.create("FitnessMax",
                       ConstrainedFitness,
                       base_fit=creator.FitnessHidden)
        #weight is the weights given to the different fitnesses (incase you have a multiobjective optimization to make)
        creator.create("Individual",
                       list,
                       fitness=creator.FitnessMax,
                       parents=None,
                       mutated=None,
                       id=None,
                       age=0)
        #toolbox object from deap: allows to define functions in one line for operations on the individual
        toolbox = base.Toolbox()
        toolbox.register("individual",
                         generate,
                         translator=translator,
                         creator=creator)
        toolbox.register("population", tools.initRepeat, list,
                         toolbox.individual)
        #funtion that retruns the fitness from an individual
        #the output is a tuple to match the format of the weights given just above in fitnessMax definition

        #deap basic funtion to cross a population
        toolbox.register("evaluate",
                         evaluate,
                         model=model,
                         translator=translator,
                         weights=weights,
                         **kwargs)
        toolbox.register("mate",
                         decorator_cross(hybrid_cx),
                         discrete_cx=discrete_cx,
                         discrete_cx_kwargs=discrete_cx_kwargs,
                         continuous_cx=continuous_cx,
                         continuous_cx_kwargs=continuous_cx_kwargs)
        toolbox.register("mutate",
                         decorator_mut(hybrid_mut),
                         discrete_mut=discrete_mut,
                         discrete_mut_kwargs=discrete_mut_kwargs,
                         continuous_mut=continuous_mut,
                         continuous_mut_kwargs=continuous_mut_kwargs)
        toolbox.register("select", decorator_selection(selection_op),
                         **selection_kwargs)
        #we are now creating the population
        population = toolbox.population(n=nb_indiv)

        pops = []

    init_integer = len(pops)

    if nb_threads > 1:
        pool = multiprocessing.Pool(processes=nb_threads)
        toolbox.register("map", pool.map)
    #We are running the genetical algorithm
    for gen in range(init_integer, NGEN):
        print('Generation: ' + str(gen + 1))

        #creating ids if needed
        for l, ind in enumerate(population):
            ind.age += 1
            if ind.mutated != None or ind.parents != None or gen == 0:
                ind.id = str(gen + 1) + "." + str(l)

        #Evaluation of the individuals
        fits = toolbox.map(toolbox.evaluate, population)
        for fit, ind in zip(fits, population):
            ind.fitness.values = fit
        for ind in population:
            if translator.is_dna_viable(ind):
                phen = translator.dna_to_phen(ind)
                ind.fitness.constraints = [
                    const(phen, ind.fitness.values) for const in constraints
                ]
            else:
                ind.fitness.constraints = [False for _ in constraints]

        # Printing the best individual
        top1 = tools.selBest(population, k=1)
        print(translator.dna_to_phen(top1[0]))
        print(top1[0].fitness.values)

        #Registering the information in the pickle file
        pops.append([{
            "phen": translator.dna_to_phen(indiv),
            "fits": indiv.fitness.values,
            "age": indiv.age,
            "id": indiv.id,
            "parents": indiv.parents,
            "mutated": indiv.mutated,
            "constraints": ind.fitness.constraints
        } for indiv in population if translator.is_dna_viable(indiv)])

        #Selection of the individuals
        population = toolbox.select(
            [indiv for indiv in population if translator.is_dna_viable(indiv)],
            k=len(population))

        population = algorithms.varAnd(population,
                                       toolbox,
                                       cxpb=cxpb,
                                       mutpb=mutpb)
        if log_file:
            with open(log_file, 'wb') as pickle_file:
                pickle.dump(hparams,
                            pickle_file,
                            protocol=pickle.HIGHEST_PROTOCOL)
                pickle.dump(pops,
                            pickle_file,
                            protocol=pickle.HIGHEST_PROTOCOL)
    return pops
コード例 #4
0
def run_hybrid_ga(model,
                  weights,
                  hparams,
                  NGEN=40,
                  nb_indiv=80,
                  nb_threads=1,
                  cxpb=0.7,
                  mutpb=0.4,
                  discrete_cx=tools.cxTwoPoint,
                  discrete_cx_kwargs={},
                  continuous_cx=tools.cxBlend,
                  continuous_cx_kwargs={"alpha": 0.1},
                  discrete_mut=tools.mutFlipBit,
                  discrete_mut_kwargs={"indpb": 0.05},
                  continuous_mut=tools.mutGaussian,
                  continuous_mut_kwargs={
                      "mu": 0.,
                      "sigma": 0.1,
                      "indpb": 0.05
                  },
                  selection_op=tools.selTournament,
                  selection_kwargs={"tournsize": 3},
                  stric_interval=False,
                  log_file=None,
                  recover_file=None,
                  gray_code=True,
                  **kwargs):
    if recover_file:
        with open(recover_file, 'rb') as pickle_file:
            hparams = pickle.load(pickle_file)
            translator = HybridDNA(hparams,
                                   stric_interval=stric_interval,
                                   gray_code=gray_code)
            pops = pickle.load(pickle_file)

            #Creation of class FitnessMax and individual
            creation_deap_classes(creator, weights)
            #toolbox object from deap: allows to define functions in one line for operations on the individual
            toolbox = base.Toolbox()
            #creation of operators
            creation_tools(toolbox, model, translator, creator, weights,
                           discrete_cx, discrete_cx_kwargs, continuous_cx,
                           continuous_cx_kwargs, discrete_mut,
                           discrete_mut_kwargs, continuous_mut,
                           continuous_mut_kwargs, selection_op,
                           selection_kwargs, nb_threads, **kwargs)
            population = recover_last_gen(pops, creator, translator)

            #Performing selection and cross and mutation to create the new generation

            population = toolbox.select([
                indiv
                for indiv in population if translator.is_dna_viable(indiv)
            ],
                                        k=nb_indiv)
            population = algorithms.varAnd(population,
                                           toolbox,
                                           cxpb=cxpb,
                                           mutpb=mutpb)
    else:
        translator = HybridDNA(hparams,
                               stric_interval=stric_interval,
                               gray_code=gray_code)
        #Creation of class FitnessMax and individual
        creation_deap_classes(creator, weights)
        #toolbox object from deap: allows to define functions in one line for operations on the individual
        toolbox = base.Toolbox()
        #creation of operators
        creation_tools(toolbox, model, translator, creator, weights,
                       discrete_cx, discrete_cx_kwargs, continuous_cx,
                       continuous_cx_kwargs, discrete_mut, discrete_mut_kwargs,
                       continuous_mut, continuous_mut_kwargs, selection_op,
                       selection_kwargs, nb_threads, **kwargs)
        #we are now creating the population
        population = toolbox.population(n=nb_indiv)

        pops = []

    init_integer = len(pops)

    #We are running the genetical algorithm
    for gen in range(init_integer, NGEN):
        print('Generation: ' + str(gen + 1))

        #creating ids if needed
        for l, ind in enumerate(population):
            ind.age += 1
            if ind.mutated != None or ind.parents != None or gen == 0:
                ind.id = str(gen + 1) + "." + str(l)

        #Evaluation of the individuals
        fits = toolbox.map(toolbox.evaluate, population)
        for fit, ind in zip(fits, population):
            ind.fitness.values = fit

        # Printing the best individual
        top1 = tools.selBest(population, k=1)
        print(translator.dna_to_phen(top1[0]))
        print(top1[0].fitness.values)

        #Registering the information in the pickle file
        pops.append([{
            "phen": translator.dna_to_phen(indiv),
            "fits": indiv.fitness.values,
            "age": indiv.age,
            "id": indiv.id,
            "parents": indiv.parents,
            "mutated": indiv.mutated
        } for indiv in population if translator.is_dna_viable(indiv)])

        #Selection of the individuals
        population = toolbox.select(
            [indiv for indiv in population if translator.is_dna_viable(indiv)],
            k=len(population))

        population = algorithms.varAnd(population,
                                       toolbox,
                                       cxpb=cxpb,
                                       mutpb=mutpb)
        if log_file:
            with open(log_file, 'wb') as pickle_file:
                pickle.dump(hparams,
                            pickle_file,
                            protocol=pickle.HIGHEST_PROTOCOL)
                pickle.dump(pops,
                            pickle_file,
                            protocol=pickle.HIGHEST_PROTOCOL)
    return pops