NSGA II - print best individuals and their fitness

391 views
Skip to first unread message

Annika Magnasco

unread,
Jan 4, 2016, 9:23:10 AM1/4/16
to deap-users
Hey there,

I used the NSGA II algorithm for my multi-obective optimization.
I am wondering how to get the best results (individual+fitness) per generation. Should I add a hall of fame, and if so,  how can I do it?
So far I tried it with this code:

best = max(pop, key=attrgetter("fitness"))

But I dont know how to get the fitness of it.
Thanks!


François-Michel De Rainville

unread,
Jan 7, 2016, 8:50:35 AM1/7/16
to deap-users
Hi,

In multi-objective optimisation there is not a single best solution, but a set of optimal solutions that are compromises between the multiple objectives. The set of best solutions is called the Pareto front. To get this set on every generation you can use the ParetoFront hall of fame which will contain  every undominated individual produced up until the current generation (so it might get pretty big if no similarity function is given). Otherwise, to get only the undominated individuals of the current generation, you can use directly the sort(Log)NonDominated function with first front only set to true.

Cheers,
François-Michel De Rainville



--
You received this message because you are subscribed to the Google Groups "deap-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to deap-users+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

annikam...@gmail.com

unread,
Jan 8, 2016, 11:40:58 AM1/8/16
to deap-users
Thank you François-Michel.

I tried implementing both options in my code like this:
pareto = tools.ParetoFront(similar=operator.__eq__)
or
pareto = tools.ParetoFront()

pareto.update(pop)

and
best=tools.sortLogNondominated(pop,1, first_front_only = True)

I am a bit confused because the amount of individuals in my pareto front changes every generation. I thought it would save the best set of undominated individuals for all generations. So at the end I get an amount of like NGEN*number of undominated sets in the pareto front. But the length of pareto front gets bigger and smaller during the optimization. Is it correct like this?

With the sort(Log)NonDominated function I get more than one set as a result, even though I put k as 1. How do I cange it?
And how can I print/save the results of my fitness functions for the best set in each generation, so with the first set from sort(Log)NonDominated? My fitness functions are all to be minimized.

François-Michel De Rainville

unread,
Jan 11, 2016, 2:51:11 PM1/11/16
to deap-users
I am a bit confused because the amount of individuals in my pareto front changes every generation. I thought it would save the best set of undominated individuals for all generations.
So at the end I get an amount of like NGEN*number of undominated sets in the pareto front. But the length of pareto front gets bigger and smaller during the optimization. Is it correct like this?

Yes, the number changes because the individuals of the front are getting dominated by the new individuals.
 
With the sort(Log)NonDominated function I get more than one set as a result, even though I put k as 1. How do I cange it?

This is strange, the code is explicit as to return a single front set when first_front_only is set to True. How is your population layed out?

Setting k to 1 will return a single set containing a single (compromise) individuals. It will not be the best individual.
 
And how can I print/save the results of my fitness functions for the best set in each generation, so with the first set from sort(Log)NonDominated? My fitness functions are all to be minimized.

Iterate over your front and print them

for ind in best:
    print(ind)
    print(ind.fitness)

You can also pickle your front.

import pickle
pickle.dump(best, open("best.pkl", "w"))

Best regards,
François-Michel

Annika

unread,
Jan 12, 2016, 11:27:48 AM1/12/16
to deap-users
Thanks for your response.
Is it sufficient if I tell you that population is defined as
pop = toolbox.population(n=MU)
and I changed MU, ranging from 10 to 50. Same result. However, it is of oriority to solve this now.

Just one last question to clearify if I understood. The result in the Pareto front are all equally good right? If my objectives do all the use the same functions, just for different users, can I  build the sum of each solution at the end to choose the final solution candidate?

Best wishes !
Anni

François-Michel De Rainville

unread,
Jan 16, 2016, 4:22:19 PM1/16/16
to deap-users
Can you email the call and the result of sortNonDominated?

Just one last question to clearify if I understood. The result in the Pareto front are all equally good right?

Yes
 
If my objectives do all the use the same functions, just for different users, can I  build the sum of each solution at the end to choose the final solution candidate?

That is one way to do it and it is completely up to you as it depends on the objectives.
 

Best regards,
François-Michel

François-Michel De Rainville

unread,
Jan 20, 2016, 2:16:45 PM1/20/16
to Annika, deap-users
I don't see any problem. The Pareto front you sent me are valid. They contain the undominated individuals.

But I see where the confusion comes from. sortNonDominated always returns complete fronts whatever k is. It only stops when there are more than k individuals because it cannot make any decision on Pareto equal solutions.

With NSGA2 the cut in the last front to return exactly k individuals is made using a crowding distance favouring solution that are far away from other solutions.

I hope it answers your question,
François-Michel

2016-01-19 13:09 GMT-05:00 Annika <annika.ma...@gmail.com>:
Hey François-Michel,

thank you once again for taking you time to assist me! I am working on my master thesis and therefore I use Python for the very first time.

I copied both calls and results, each with a different variable individual. I am not sure if it will help you, but i will also copy the fitness result.

best=tools.sortLogNondominated(pop,1, first_front_only = True)   

result:
[array('f', [0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0]), array('f', [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0]), array('f', [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0]), array('f', [0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0]), array('f', [0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0]), array('f', [0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0]), array('f', [0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0]), array('f', [0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0])] B

best=tools.sortLogNondominated(pop,len(pop), first_front_only = True)   
result
[0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0]), array('f', [0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0]), array('f', [0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0]), array('f', [0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0]), array('f', [0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0]), array('f', [0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0]), array('f', [0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0]), array('f', [0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])]] B

And for the same optimization run the pareto front with this code: pareto = tools.ParetoFront(similar=operator.__eq__), pareto.update(pop)
pareto:
[array('f', [0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0]), array('f', [0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0]), array('f', [0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0]), array('f', [0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0]), array('f', [0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0]), array('f', [0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0]), array('f', [0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0]), array('f', [0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0]), array('f', [0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0]), array('f', [0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0]), array('f', [0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])]
for ind in best:
print("fitness",ind.fitness)
fitness (1693.41, 3281.84, 17911895.96, 1087.43, 17910362.95, 76120907.33, 35822643.91, 65.533522060603687) fitness (1693.41, 3291.84, 35823460.66, 1087.43, 17910362.95, 76120907.33, 35822643.91, 65.53347624386042) fitness (1693.41, 3291.84, 35823460.66, 1087.43, 17910362.95, 76120907.33, 35822643.91, 65.53347624386042) fitness (4127.45, 460.76, 17914115.84, 17912796.0, 17909772.03, 98507072.05, 58213301.95, -55.568365014845128) fitness (4127.45, 460.76, 17914115.84, 17912796.0, 17909772.03, 98507072.05, 58213301.95, -55.568365014845128) fitness (4127.45, 2893.07, 17912223.56, 17912246.07, 35817530.45, 58208439.67, 58213287.71, -38.074448147170216) fitness (4127.45, 3382.56, 2823.31, 551.75, 35815605.92, 35821704.71, 58213301.95, -67.661410958086023) fitness (4351.52, 17912077.67, 17914115.84, 17912796.0, 17909772.03, 98507072.05, 17911997.15, -0.85924680423396183)


Have a good day!

Anni
Reply all
Reply to author
Forward
0 new messages