0

I am trying to implement a Genetic Algorithm which will recreate a given image by positioning, sizing and colouring 1000 circles. However, I found that when the fitness reaches a certain value (around 0.37 in my case) it stop increasing. In other words it just converges on the value.

I can't think of a way to improve this

enter image description here

Some Details

population size: 50

mutation rate: 0.025

the genes of each child is an 1000 element array with element type CircleData, which contains the size, color and position of a circle

Fitness Function

I loop through every pixels on the target image and the canvas the algorithm drew on. For each pixel, I map the RGB value to a point in 3D space and calculate the distance between the two points. The distance will then be summed up for every pixels and normalise to get a fitness value in [0, 1], where 1 means each pixel are identical. Finally I take the value of pow(fitness, 2) as the final fitness value.

Selection

I sort the children base on their fitness, and drop the worse 2/3. For the remaining children, I use Fitness Proportionate Selection to select two parents

Crossover

I use one point crossover with random crossover point


Update

I suspect the problem is due to local maximum, still trying to fix that...

Some SO questions on local maximum in GA:

How to prevent genetic algorithm from converging on local minima?

How can I prevent my program from getting stuck at a local maximum (Feed forward artificial neural network and genetic algorithm)

Max Fitness stuck at local maxima in genetic algorithm implementation

Community
  • 1
  • 1
hklel
  • 1,624
  • 23
  • 45
  • Stupid question: are you sure that you *can* do much better with only 1000 circles? – ruakh Jan 01 '17 at 07:15
  • So, before squaring, your fitness actually converges against `0.6`? – Hermann Döppes Jan 01 '17 at 07:18
  • @ruakh not sure, but I think the circles are already covering pretty much the whole canvas. Anyway I will try to increase this later and see if the result will get better – hklel Jan 01 '17 at 07:21
  • @HermannDöppes Yes. I ran it for 8hrs and it's still around 0.6, so I did the square hoping it would help – hklel Jan 01 '17 at 07:22
  • How exactly “around”? Slightly above? Always below? Varying? I ask, because `3/5` doesn't feel very random, it might be some systematic error. – Hermann Döppes Jan 01 '17 at 07:26
  • also, you could try to do better by hand. Just change those circles in the upper left to actually resemble the background colours, I feel like this might already increase the fitness significantly. – Hermann Döppes Jan 01 '17 at 07:28
  • @HermannDöppes It was varying between like 0.59 and 0.64 – hklel Jan 01 '17 at 07:33
  • 2
    I doubt your crossover is clever enough. Can new colours easily come into existence? – Malcolm McLean Jan 01 '17 at 07:44
  • @MalcolmMcLean Sorry but how is crossover related to the introduction of new colors? for crossover I just take part of the genes from one parent and combine it with another partial genes from another parent. For introducing new colors, in mutation 2.5% of the DNAs will be replaced by randomly generated one – hklel Jan 01 '17 at 08:08
  • Did you sanity check your fitness function by submitting the target image and checking that the result is 1? – samgak Jan 01 '17 at 09:28
  • @samgak yeah I did that and the fitness is 1 – hklel Jan 01 '17 at 09:45
  • Looks like your fitness function is badly broken. There's no code here, so I can't say how it's broken. At least your pixel distances should be squared *before* summing, instead of squaring the sum. If you did the distance calc right, this just means removing the square root you're already applying. – Matt Timmermans Jan 01 '17 at 13:55
  • Also, you are obviously not at a local maximum unless your fitness function is badly broken. The color of each circle can be nudged toward the average color behind the part of it that shows, and each such nudge should result in an incremental improvement in fitness. – Matt Timmermans Jan 01 '17 at 14:04
  • @MattTimmermans the distance I mentioned in the question is the distance in 3D space (`dist = sqrt(deltaX^2 + deltaY^2 + deltaZ^2)`). You can check the actual implementation of the fitness function [here](https://gist.github.com/hkalexling/8fa2cbaccfafa4d97aa7d7ef697fe56d) – hklel Jan 01 '17 at 14:16
  • vectorDistance() is wrong. convert those unsigned chars to signed double or int *before* subtracting. – Matt Timmermans Jan 01 '17 at 14:26
  • @MattTimmermans Thanks for pointing it out! it does gives incorrect fitness value. After correcting this it's still converging thought... – hklel Jan 01 '17 at 15:56
  • Have you tried different images? Have you tried *an image consisting of 1000 circles*? – Hermann Döppes Jan 01 '17 at 18:16
  • In your call to `map` (a reasonably bad name, I guess?) you switched `destMin` and `destMax`. Also, you can just do `count = height*width`. – Hermann Döppes Jan 01 '17 at 18:44
  • As we have pointed out, only changing the colours of the circles towards the average colour of the area covered by each circle should already be an improvement. Your example hardly looks like a local maximum due to that. – Hermann Döppes Jan 01 '17 at 20:30
  • 4
    1000 circles is too hard to reason about. To debug your algorithm try with 1 or 2 circles first. What is the behavior? How fast does 1 circle converge? Is the convergence rate better than random? Tweak you parameters. Then see what happens when you scale up to 10,100, 1000. – Ray Jan 03 '17 at 17:37

0 Answers0