Advertisement

Retarded Bugs need help. Still needing somehelp.

Started by April 19, 2003 05:19 AM
15 comments, last by WILL at RedAnt 21 years, 7 months ago
Ok, if you have read Fupster's tutorials you'll know exactly what I'm trying to accomplish. What I am basically doing is taking a population of bugs each with it's own NN and setting them in a small 2D world where they move around and eat food. I'm using a GA to teach them to go after the food. Eventually after a good few generations(20-40 in fupster's program) they should be very good at getting the food and you can see the major difference. Well I'm not so lucky. For some reason despite my best efforts I have not been able to determine why my bugs just don't learn properly. The darn things just twirl in one direction or if I'm lucky go in a basic straight line. They don't really react to the food as they should. And high score from bugs eating the food seems to be pure fluke. Anyone that knows Pascal or Delphi(or just wants to help), I'd truly appreciate it. I've been at this darn program for months and I've looked at, I think everything. It all seems to check out ok. But the program doesn't work. :/ I have just updated the program today with a new binary and source. You can download it from here: http://aiworkshop.tripod.com/ It is called "AI Bug World" Build 9. I'd appreciate any feed back or assistance you may provide. I, myself am stumped. If you do now know what I'm talking about then please visit www.ai-junkie.com and read the tutorial on GAs and then his one on NNs and you'll see his program and you then can see what it is that I'm trying to mimic. Thanks, WILL [edited by - WILL at RedAnt on April 24, 2003 3:40:02 PM]
How many hidden layers do your bug ANN''s have? And how many nodes are there in a layer? I''ve been experimenting with FUP''s demo and I get the best results with one hidden layer with between 2 and 8 nodes.

If I run FUP''s demo with more than one hidden layer of nodes, I get exactly the results you just described.

Sander Maréchal
[Lone Wolves GD][RoboBlast][Articles][GD Emporium][Webdesign][E-mail]

<hr />
Sander Marechal<small>[Lone Wolves][Hearts for GNOME][E-mail][Forum FAQ]</small>

Advertisement
I use 2 layers and simulate the input layer with an array of Reals.

4 - inputs(array of reals not neurons)
6 - hidden layer
2 - output layer

Here is my NNs execution code:

procedure TNeuralNet.Execute(Input: Array of Real; var Output: Array of Real);
var i, j: Integer;
inBuffer, outBuffer: Array of Real;
begin
if (Length(Input) = NumberOfInputs) then
begin
SetLength(outBuffer, Layers[0].NumberOfNeurons);
Layers[0].Execute(Input, outBuffer);
if (NumberOfLayers > 1) then
for i := 1 to NumberOfLayers - 1 do
begin
SetLength(inBuffer, Layers.NumberOfNeurons);<br> for j := 0 to Length(inBuffer) - 1 do<br> inBuffer[j] := outBuffer[j];<br><br> SetLength(outBuffer, Layers<i>.NumberOfNeurons);<br> Layers.Execute(inBuffer, outBuffer);<br> end;<br> {Resolve Output}<br> for i := 0 to NumberOfOutputs - 1 do<br> if (DigitalOutput) then<br> begin<br> if (outBuffer > 0) then<br> Output := 1<br> else<br> Output := 0;<br> end<br> else<br> Output := outBuffer;<br> end;<br> inBuffer := Nil;<br> outBuffer := Nil;<br>end; </i>
I had a similar problem with my AI project - evolving decision making animats, it may help to track down the problem by altering your fitness function so that the agents with connection weights closest to say, 0.5, scored highest. This will enable you to see whether they are evolving(provided you can see the weights.) If the weights are not tending toward 0.5 the problem is in the selection/cross-breeding/mutation, if they are, the problem is elsewhere (vision system/movement control maybe). Thats what i did anyway, i found the error and it now works brilliantly(ish).

Hope that all makes sense.
Ok, that can be done. It does make sense, but does that mean that the weights will only lean towards +0.5 or will they tend toward -0.5 too? My weights all very from -1 to +1. Mind you it has ben suggested that I allow them to go beyond that.

I''ll check that out and post my findings here after. Thanks.
Just had a look at your code, i dont know anything about pascal or delphi but it looks like your mutation isnt taking into account the original value. When you mutate weights you should be changing them slightly rather than replacing them with a random value. something like +-0.1 for every weight is what i have used in the past.

{- Mutation Rate -}
for j := 0 to NewPopulation.NumberOfValues - 1 do
if (Random <= Mutation_Rate) then
NewPopulation.Values[j] := (Random * 2) - 1;<br> end;<br><br>try this instead<br><br> NewPopulation.Values[j] := NewPopulation.Values[j]+(Random/5) - 0.1;<br> </i>
Advertisement
I don''t know delphi so i don''t really understand your code thourougly but it looks OK to me. I guess the real problem must lie with your GA code, most probabey with your selection method. Are you using roulette wheel selection? Bugs with higher fitness should have a larger chance to produce offspring. This is the basis for evolution and improvements.


Sander Maréchal
[Lone Wolves GD][RoboBlast][Articles][GD Emporium][Webdesign][E-mail]

<hr />
Sander Marechal<small>[Lone Wolves][Hearts for GNOME][E-mail][Forum FAQ]</small>

Well, some part of my code is lying.

Yes, I am using Roulette Wheel Selection. I, as far as I know, am giving every bug a chance at getting into the next generation, but the chance goes up by one part based on the fitness score.

Here is the entire GA procedure I use in my code:

procedure Apply_Basic_Algorithm(var Population: Array of TChromosome; NumberOfPopulation, ChromoSize: Integer);
var i, j, k: Integer;
NewPopulation: Array of TChromosome;
TotalFitness: Integer;
RandomSelectionA, RandomSelectionB: Real;
SelectionA, SelectionB: Array of Real;
AFitness, BFitness: Integer;
SplitPos: Integer;
begin
{- Initalizing NewPopulation and getting Total Fitness -}
SetLength(NewPopulation, Length(Population));
TotalFitness := 0;
for i := 0 to NumberOfPopulation - 1 do
begin
NewPopulation := TChromosome.Init(ChromoSize);

inc(Population.FitnessScore);{Every creature has 1 peice of the pie!}<br><br> inc(TotalFitness, Population.FitnessScore);<br> end;<br><br> SetLength(SelectionA, ChromoSize);//Another Address problem!!!<br> SetLength(SelectionB, ChromoSize);<br> for i := 0 to NumberOfPopulation - 1 do<br> begin<br> {- Roulette Wheel Selection -}<br> {Select A}<br> RandomSelectionA := Random * TotalFitness;<br> j := 0;<br> repeat<br> begin<br> if (j > NumberOfPopulation - 1) then<br> j := 0;<br> RandomSelectionA := RandomSelectionA - Population[j].FitnessScore;<br> inc(j);<br> end;<br> until (RandomSelectionA < Population[j - 1].FitnessScore);<br><br> for k := 0 to Population[j - 1].NumberOfValues - 1 do<br> SelectionA[k] := Population[j - 1].Values[k];<br> AFitness := Population[j - 1].FitnessScore;<br><br> {Select B}<br> RandomSelectionB := Random * TotalFitness;<br> j := 0;<br> repeat<br> begin<br> if (j > NumberOfPopulation - 1) then<br> j := 0;<br> RandomSelectionB := RandomSelectionB - Population[j].FitnessScore;<br> inc(j);<br> end;<br> until (RandomSelectionB < Population[j - 1].FitnessScore);<br><br> for k := 0 to Population[j - 1].NumberOfValues - 1 do<br> SelectionB[k] := Population[j - 1].Values[k];<br> BFitness := Population[j - 1].FitnessScore;<br><br> {- Cross-Over Rate -}<br> if (Random <= CrossOver_Rate) then<br> begin<br> SplitPos := Round(Random * Population.NumberOfValues);<br> {First Half from A}<br> for j := 0 to SplitPos - 1 do<br> NewPopulation.Values[j] := SelectionA[j];<br> {Second Half from B}<br> for j := SplitPos to Population.NumberOfValues - 1 do<br> NewPopulation.Values[j] := SelectionB[j];<br> end<br> else<br> begin<br> if (AFitness > BFitness) then<br> for j := 0 to NewPopulation.NumberOfValues - 1 do<br> NewPopulation.Values[j] := SelectionA[j]<br> else<br> for j := 0 to NewPopulation.NumberOfValues - 1 do<br> NewPopulation.Values[j] := SelectionB[j];<br> end;<br><br><br> {- Mutation Rate -}<br> for j := 0 to NewPopulation.NumberOfValues - 1 do<br> if (Random <= Mutation_Rate) then<br> NewPopulation.Values[j] := (Random * 2) - 1;<br>// NewPopulation.Values[j] := NewPopulation.Values[j] + ((Random * 2) - 1); // Unlimit Bounds…<br> end;<br><br><br> {- Update Chromosomes -}<br> for i := 0 to NumberOfPopulation - 1 do<br> for j := 0 to Population.NumberOfValues - 1 do<br> begin<br> Population.Values[j] := NewPopulation.Values[j];<br> Population.FitnessScore := 0;<br> end;<br><br> {- Destroy Temporary Objects -}<br> for i := 0 to NumberOfPopulation - 1 do<br> NewPopulation.DeInit;<br> NewPopulation := nil;<br> SelectionA := nil;<br> SelectionB := nil;<br>end;<br> </i>
My best guess is that the blame lies with your randomizer function. From the code you posted I undersstand that it doesn''t return a value between 0 and 1 but some other value (that''s why you keep reselecting a value until it is within the population size).

If Delphi is anything like QBasic the random function probabely returns an integer value between 0 and some value (I assume 65536 here, but you should look this up).

This integer randomizer and the ongoing reselection causes only a few individuals from your population to be selected. You should write your own randomizer that returns a value between 0 and 1. Here''s how (in C, hope you can follow):

float function MyRandomizer()
{
return (IntegerRandom / 65536)
}

This gives you a random value between 0 and 1

Sander Maréchal
[Lone Wolves GD][RoboBlast][Articles][GD Emporium][Webdesign][E-mail]

<hr />
Sander Marechal<small>[Lone Wolves][Hearts for GNOME][E-mail][Forum FAQ]</small>

If its because of a random number not being generated correctly my guess would be since you are not calling randomize or setting the randseed its always returning the same values each time.

Just add:

Randomize;

BR

This topic is closed to new replies.

Advertisement