DEAP / deap

Distributed Evolutionary Algorithms in Python
http://deap.readthedocs.org/
GNU Lesser General Public License v3.0
5.75k stars 1.12k forks source link

How to customize the specified initial individual #339

Open ViesLink opened 5 years ago

ViesLink commented 5 years ago

Hi there! Recently I am trying to run an basic immune genetic algorithm based on DEAP。 (For FeatureSelection)

background

The basic principle is to calculate the selected probability of each feature based on the previous calculation result, and then form a custom initial individual through external processing, and pass it to the next GA operation. (You should also know this process)

issue

The current problem is that I got the result of the last GA operation and performed external processing, but I don't know how to pass it as a variable to the next GA operation.

Operating environment

WIN_7_64 bit Python 3.6 DEAP 1.0.2

Any reply would be helpful...

showkeyjar commented 4 years ago

+1

showkeyjar commented 4 years ago

I use those method to gen population, 'fun1' return a list toolbox.register('population', fun1) but got error: ind.fitness.values = fit AttributeError: 'list' object has no attribute 'fitness'

showkeyjar commented 4 years ago

ok, I figure it out, but it's a little complicated.

  1. create a list class that can add attribute;

`

class IndividualList(list):
  def __new__(self, *args, **kwargs):
    return super(IndividualList, self).__new__(self, args, kwargs)

  def __init__(self, *args, **kwargs):
    if len(args) == 1 and hasattr(args[0], '__iter__'):
        list.__init__(self, args[0])
    else:
        list.__init__(self, args)
    self.__dict__.update(kwargs)

  def __call__(self, **kwargs):
    self.__dict__.update(kwargs)
    return self

`

2.create a class that implement base.Fitness:

`

class IndividualFitness(base.Fitness):
  weights = (1,)

  def __init__(self, *args, **kwargs):
    base.Fitness.__init__(self, *args, **kwargs)

`

3.then you can customize then individual:

`

def create_individual(x):
  x = ast.literal_eval(x)
  fitness = eval_vrptw(x)
  genes = IndividualList(x, fitness=IndividualFitness(values=fitness))
  return genes

`

4.so you can call your self define function in deap:

toolbox.register('population', some_df.apply(create_individual,axis=1))

hope it helps.

fmder commented 4 years ago

You can pass any function to initialize an individual. See the particle example from the documentation tutorial part 1. There are also a fes questions on the mailing list about that.

Le dim. 10 nov. 2019 08 h 37, Starved Midnight notifications@github.com a écrit :

ok, I figure it out, but it's a little complicated.

1.

create a list class that can add attribute; ` class IndividualList(list): def new(self, *args, *kwargs): return super(IndividualList, self).new*(self, args, kwargs)

def init(self, *args, *kwargs): if len(args) == 1 and hasattr(args[0], 'iter'): list.init(self, args[0]) else: list.init(self, args) self.dict*.update(kwargs)

def call(self, *kwargs): self.dict*.update(kwargs) return self `

2.create a class that implement base.Fitness: ` class IndividualFitness(base.Fitness): weights = (1,)

def init(self, *args, *kwargs): base.Fitness.init(self, args, **kwargs)

`

3.then you can customize then individual: def create_individual(x): x = ast.literal_eval(x) fitness = eval_vrptw(x) genes = IndividualList(x, fitness=IndividualFitness(values=fitness)) # genes.fitness.weights = (1.0,) return genes

4.so you can call your self define function in deap: toolbox.register('population', some_df.apply(create_individual,axis=1))

hope it helps.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/DEAP/deap/issues/339?email_source=notifications&email_token=AAHKXQSHKPWDOBBM6FKTMIDQTAFBDA5CNFSM4HDF7OI2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEDU5LZI#issuecomment-552195557, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAHKXQQWNRQCOVBDFR5ROCTQTAFBDANCNFSM4HDF7OIQ .

SantiagoAndre commented 4 years ago

Here is a simpler way to customize initial generation:

    creator.create("FitnessMin", base.Fitness, weights=(-1.0,))
    creator.create("Individual", array.array, typecode='b', fitness=creator.FitnessMin)
    # structure initializers
    # population: customize pop generation
    toolbox.register("population",load_individuals, creator.Individual)

where load_individuals is the function that creates the initial custom generation Here is an example of load_individuals:

def load_individuals(creator,n):
    individuals = []
    for i in range(n):
        with open("individuals/{0}.txt".format(i),"r") as tsp_data:
            individual = eval(tsp_data.readline()) <= load  individual from file, it returns an list thanks to 'eval' function
        individual = creator(individual) <= transform list to Individual, Individual was defined in the previous one, and passed by parameter
        individuals.append(individual)
    return individuals

ok, I figure it out, but it's a little complicated.

1. create a list class that can add attribute;

`

class IndividualList(list):
  def __new__(self, *args, **kwargs):
    return super(IndividualList, self).__new__(self, args, kwargs)

  def __init__(self, *args, **kwargs):
    if len(args) == 1 and hasattr(args[0], '__iter__'):
        list.__init__(self, args[0])
    else:
        list.__init__(self, args)
    self.__dict__.update(kwargs)

  def __call__(self, **kwargs):
    self.__dict__.update(kwargs)
    return self

`

2.create a class that implement base.Fitness:

`

class IndividualFitness(base.Fitness):
  weights = (1,)

  def __init__(self, *args, **kwargs):
    base.Fitness.__init__(self, *args, **kwargs)

`

3.then you can customize then individual:

`

def create_individual(x):
  x = ast.literal_eval(x)
  fitness = eval_vrptw(x)
  genes = IndividualList(x, fitness=IndividualFitness(values=fitness))
  return genes

`

4.so you can call your self define function in deap:

toolbox.register('population', some_df.apply(create_individual,axis=1))

hope it helps.

jmmcd commented 4 years ago

@SantiagoAndre it looks like toolbox.individual and toolbox.attr_bool are just unused in this, is that correct? (If you have a complete, short example, please post it :)

SantiagoAndre commented 4 years ago

in fact, toolbox.individual is used when a random population is generated. toolbox.individual generates a random individual. this is a complete example https://gitlab.com/santiagoandre/deap-customize-population-example

rand0x0m commented 4 years ago
    creator.create("FitnessMax", base.Fitness, weights=(1.0,))
    creator.create("Individual", list, fitness=creator.FitnessMax)

    # register individual
    generate_individual = partial(replace_nan_with_random, user)
    toolbox.register("individual", lambda ind, ind_gen: ind(ind_gen()), creator.Individual,
                     generate_individual)

    # define the population to be a list of individuals
    toolbox.register("population", tools.initRepeat, list, toolbox.individual)

This did the magic for me, lambda ind, ind_gen: ind(ind_gen()). Where replace_nan_with_random returns a list and user is an nd.array

Mohammad-H93 commented 3 years ago

Here is a simpler way to customize initial generation:

    creator.create("FitnessMin", base.Fitness, weights=(-1.0,))
    creator.create("Individual", array.array, typecode='b', fitness=creator.FitnessMin)
    # structure initializers
    # population: customize pop generation
    toolbox.register("population",load_individuals, creator.Individual)

where load_individuals is the function that creates the initial custom generation Here is an example of load_individuals:

def load_individuals(creator,n):
    individuals = []
    for i in range(n):
        with open("individuals/{0}.txt".format(i),"r") as tsp_data:
            individual = eval(tsp_data.readline()) <= load  individual from file, it returns an list thanks to 'eval' function
        individual = creator(individual) <= transform list to Individual, Individual was defined in the previous one, and passed by parameter
        individuals.append(individual)
    return individuals

ok, I figure it out, but it's a little complicated.

1. create a list class that can add attribute;

`

class IndividualList(list):
  def __new__(self, *args, **kwargs):
    return super(IndividualList, self).__new__(self, args, kwargs)

  def __init__(self, *args, **kwargs):
    if len(args) == 1 and hasattr(args[0], '__iter__'):
        list.__init__(self, args[0])
    else:
        list.__init__(self, args)
    self.__dict__.update(kwargs)

  def __call__(self, **kwargs):
    self.__dict__.update(kwargs)
    return self

2.create a class that implement base.Fitness:

class IndividualFitness(base.Fitness):
  weights = (1,)

  def __init__(self, *args, **kwargs):
    base.Fitness.__init__(self, *args, **kwargs)

3.then you can customize then individual:

def create_individual(x):
  x = ast.literal_eval(x)
  fitness = eval_vrptw(x)
  genes = IndividualList(x, fitness=IndividualFitness(values=fitness))
  return genes

4.so you can call your self define function in deap: toolbox.register('population', some_df.apply(create_individual,axis=1))` hope it helps.

Thanks for the code. I am looking for a way to use the specific variables as individuals. Creating a series of individuals from the desired set, array or file is really hard to have. I tried your code but I got the error : AttributeError: 'builtin_function_or_method' object has no attribute 'array and I have no idea about this line of code (creator(individual))! how does it work?