• fullscreen
  • Ant.pde
  • Coordinate.pde
  • GA.pde
  • Genome.pde
  • NeuralNet.pde
  • Params.pde
  • Simulation.pde
  • neural_network.pde
  • shape_animation.pde
  • class Ant 
    { 
    
      NeuralNet brain; 
      Coordinate position = new Coordinate(); 
      Coordinate direction = new Coordinate(); 
    
      double rotation; 
      double speed; 
    
      int fitness; 
    
      int closestMinePosition = 0; 
    
      void setGenome(double[] w) 
      { 
        brain.setGenome(w); 
        Reset(); 
      } 
    
      Ant(NeuralNet net) 
      { 
        brain = net; 
        rotation = random(1) * TWO_PI;
        fitness = 0; 
        position = new Coordinate(random(SIMULATION_WIDTH), random(SIMULATION_HEIGHT)); 
      } 
    
      double[] getGenome() 
      { 
        return brain.getGenome(); 
      } 
    
      void Reset() 
      { 
        position = new Coordinate(random(SIMULATION_WIDTH), random(SIMULATION_HEIGHT)); 
        fitness = 0; 
        rotation = random(1) * TWO_PI; 
      } 
    
      int checkForMine(Coordinate[] mines) 
      { 
        Coordinate DistToObject = new Coordinate(position.x - mines[closestMinePosition].x, position.y - mines[closestMinePosition].y); 
    
        if (VectorLength(DistToObject) < 5) 
        { 
          return closestMinePosition; 
        } 
    
        return -1; 
      } 
    
      Coordinate GetClosestMine(Coordinate[] mines) 
      { 
        double closestSoFar = Double.MAX_VALUE; 
    
        Coordinate closestObject = new Coordinate(0, 0); 
    
        for (int i = 0; i < mines.length; i++) 
        { 
          double lengthToObject = VectorLength(new Coordinate(mines[i].x - position.x, mines[i].y - position.y)); 
    
          if (lengthToObject < closestSoFar) 
          { 
            closestSoFar = lengthToObject; 
    
            closestObject = new Coordinate(position.x - mines[i].x, position.y - mines[i].y); 
    
            closestMinePosition = i; 
          } 
        } 
    
        return closestObject; 
      } 
    
      double VectorLength(Coordinate v) 
      { 
        return Math.sqrt((v.x * v.x) + (v.y * v.y)); 
      } 
    
      void update(Coordinate[] mines) 
      { 
        double[] inputs = new double[4]; 
    
        Coordinate closestMine = GetClosestMine(mines); 
        Vec2DNormalize(closestMine); 
    
        inputs[0] = closestMine.x; 
        inputs[1] = closestMine.y; 
    
        inputs[2] = direction.x; 
        inputs[3] = direction.y; 
    
        double[] output = brain.evaluate(inputs); 
    
        double RotationForce = output[0] - output[1]; 
    
        if (RotationForce < -MAXIMUM_TURNING_RATE) 
        { 
          RotationForce = -MAXIMUM_TURNING_RATE; 
        } 
        if (RotationForce > MAXIMUM_TURNING_RATE) 
        { 
          RotationForce = MAXIMUM_TURNING_RATE; 
        } 
    
        rotation += RotationForce; 
    
        speed = (output[0] + output[1]); 
    
        direction.setLocation(-Math.sin(rotation), Math.cos(rotation)); 
    
        position.setLocation(position.x + (direction.x * speed), position.y + (direction.y * speed)); 
    
        if (position.x > SIMULATION_WIDTH) 
        { 
          position.x -= SIMULATION_WIDTH; 
        } 
        if (position.x < 0) 
        { 
          position.x += SIMULATION_WIDTH; 
        } 
        if (position.y > SIMULATION_HEIGHT) 
        { 
          position.y -= SIMULATION_HEIGHT; 
        } 
        if (position.y < 0) 
        { 
          position.y += SIMULATION_HEIGHT; 
        } 
      } 
    
      void Vec2DNormalize(Coordinate v) 
      { 
        double vector_length = VectorLength(v); 
        v.setLocation(v.x / vector_length, v.y / vector_length); 
      }
    
      void draw(PGraphics g)
      {
        g.pushMatrix();
        g.translate((float)position.x,(float)position.y);
        g.rotate((float)rotation);
        g.ellipse(0,-2,4,4);
        g.ellipse(0,-6,4,4);
        g.ellipse(0,-10,4,4);
        g.line(-2,-2,-4,-3);
        g.line(2,-2,4,-3);
        g.line(-2,-6,-4,-7);
        g.line(2,-6,4,-6);
        g.line(-2,-10,-4,-11);
        g.line(2,-10,4,-11);
        g.line(0,0,-2,2);
        g.line(0,0,2,2);
        g.popMatrix();
      }
    }
    
    
    
    class Coordinate 
    { 
    
      double x; 
      double y; 
    
      public Coordinate() 
      { 
        x = 0; 
        y = 0; 
      } 
    
      public Coordinate(double x, double y) 
      { 
        this.x = x; 
        this.y = y; 
      } 
    
      public void setLocation(double x, double y) 
      { 
        this.x = x; 
        this.y = y; 
      } 
    } 
    
    
    class GA 
    { 
        double totalFitness; 
        Genome[] population; 
        int fittestGenome; 
        double maximumFitness; 
        double minimumFitness; 
        double averageFitness; 
         
        GA() 
        { 
        } 
     
        private void Mutate(double[] chromo) 
        { 
            for (int i = 0; i < chromo.length; i++) 
            { 
                if (random(1) < MUTATION_RATE) 
                { 
                    chromo[i] = chromo[i] + (random(-1,1) * MAXIMUM_PERTURBATION); 
                } 
            } 
        } 
     
        private Genome GetChromoRoulette() 
        { 
            double Slice = random(1) * totalFitness; 
     
            Genome TheChosenOne = null; 
     
            double FitnessSoFar = 0; 
     
            for (int i = 0; i < population.length; i++) 
            { 
                FitnessSoFar += population[i].fitness; 
                if (FitnessSoFar >= Slice) 
                { 
                    TheChosenOne = population[i]; 
                    break; 
                } 
     
            } 
            return TheChosenOne; 
        } 
     
        private void Crossover(double[] mum, double[] dad, double[] baby1, double[] baby2) 
        { 
            if ((random(1) > CROSSOVER_RATE) || (mum == dad)) 
            { 
                for (int i = 0; i < mum.length; i++) 
                { 
                    baby1[i] = mum[i]; 
                    baby2[i] = dad[i]; 
                } 
                return; 
            } 
     
            int cp = int(random(mum.length + 1)); 
     
            for (int i = 0; i < cp; ++i) 
            { 
              baby1[i] = mum[i]; 
              baby2[i] = dad[i]; 
            } 
     
            for (int i = cp; i < mum.length; i++) 
            { 
              baby1[i] = dad[i]; 
              baby2[i] = mum[i]; 
            } 
        } 
             
        private void CalculateBestWorstAvTot() 
        { 
            totalFitness = 0; 
     
            maximumFitness = 0; 
            minimumFitness = Double.MAX_VALUE; 
     
            for (int i = 0; i < population.length; i++) 
            { 
                if (population[i].fitness > maximumFitness) 
                { 
                    maximumFitness = population[i].fitness; 
                    fittestGenome = i; 
                } 
     
                if (population[i].fitness < minimumFitness) 
                { 
                    minimumFitness = population[i].fitness; 
                } 
     
                totalFitness += population[i].fitness; 
            } 
     
            averageFitness = totalFitness / population.length; 
        } 
     
        private void Elitism(double[][] Pop) 
        { 
          for (int i = 0; i < 4; i++) 
            Pop[i] = population[i].genome; 
        } 
     
        public double[][] evolve(Genome[] oldPopulation) 
        { 
            population = oldPopulation; 
     
            java.util.Arrays.sort(population); 
     
            CalculateBestWorstAvTot(); 
     
            double[][] newPopulation = new double[oldPopulation.length][]; 
             
            Elitism(newPopulation); 
             
            int pos = ELITISM; 
     
            while (pos < newPopulation.length) 
            { 
                Genome mum = GetChromoRoulette(); 
                Genome dad = GetChromoRoulette(); 
     
                double[] baby1 = new double[mum.genome.length]; 
                double[] baby2 = new double[mum.genome.length]; 
     
                Crossover(mum.genome, dad.genome, baby1, baby2); 
     
                Mutate(baby1); 
                Mutate(baby2); 
     
                if (pos < newPopulation.length) 
                { 
                  newPopulation[pos] = baby1; 
                  pos++; 
                } 
                if (pos < newPopulation.length) 
                { 
                  newPopulation[pos] = baby2; 
                 pos++; 
                } 
            } 
     
            return newPopulation; 
        } 
    }
    
    class Genome implements Comparable 
    { 
      double[] genome; 
      int fitness; 
    
      Genome(double[] genome, int fitness) 
      { 
        this.genome = genome; 
        this.fitness = fitness; 
      } 
    
      public int compareTo(Object o) 
      { 
        Genome g = (Genome) o; 
        if (this.fitness < g.fitness) 
        { 
          return 1; 
        } 
        if (this.fitness > g.fitness) 
        { 
          return -1; 
        } 
        return 0; 
      } 
    }
    
    
    class NeuralNet 
    { 
      ArrayList layers = new ArrayList(); 
      int largestLayer = 0; 
      int connections = 0; 
      double largestWeight = Double.MIN_VALUE; 
      double smallestWeight = Double.MAX_VALUE; 
    
      NeuralNet() 
      { 
      } 
    
      void setGenome(double[] genome) 
      { 
        largestWeight = Double.MIN_VALUE; 
        smallestWeight = Double.MAX_VALUE; 
    
        int pos = 0; 
    
        for (int i = 1; i < layers.size(); i++) 
        { 
          Node[] layer = (Node[])layers.get(i); 
          for (int j = 0; j < layer.length; j++) 
          { 
            for (int k = 0; k < layer[j].weights.length; k++) 
            { 
              layer[j].weights[k] = genome[pos]; 
              if (genome[pos] > largestWeight) largestWeight = genome[pos];  
              else if (genome[pos] < smallestWeight) smallestWeight = genome[pos]; 
              pos++; 
            } 
          } 
        } 
      } 
    
      double[] getGenome() 
      { 
        double[] genome = new double[connections]; 
        int pos = 0; 
    
        for (int i = 1; i < layers.size(); i++) 
        { 
          Node[] layer = (Node[])layers.get(i); 
          for (int j = 0; j < layer.length; j++) 
          { 
            for (int k = 0; k < layer[j].weights.length; k++) 
            { 
              genome[pos] = layer[j].weights[k]; 
              pos++; 
            } 
          } 
        } 
    
        return genome; 
      } 
    
      void addLayer(int neurons) 
      { 
        if (neurons > largestLayer) largestLayer = neurons; 
    
        Node[] nodes = new Node[neurons]; 
        for (int i = 0; i<neurons; i++) 
        { 
          double[] weights; 
          if (layers.size() > 0) 
          { 
            Node[] prevLayer = (Node[]) layers.get(layers.size() - 1); 
            weights = new double[prevLayer.length + 1]; 
            for (int j = 0; j < weights.length; j++) 
            { 
              weights[j] = random(NEURAL_NETWORK_INITIAL_LOW, NEURAL_NETWORK_INITIAL_HIGH); 
    
              if (weights[j] > largestWeight) largestWeight = weights[j];  
              else if (weights[j] < smallestWeight) smallestWeight = weights[j]; 
    
              connections++; 
            } 
          } 
          else 
          { 
            weights = null; 
          } 
          nodes[i] = new Node(weights); 
        } 
        layers.add(nodes); 
      } 
    
      double[] evaluate(double[] inputs) 
      { 
        for (int currentLayer = 1; currentLayer < layers.size(); currentLayer++) 
        { 
          Node[] layer = (Node[])layers.get(currentLayer); 
          double[] outputs = new double[layer.length]; 
          for (int node = 0; node < layer.length; node++) 
          { 
            outputs[node] = layer[node].output(inputs); 
          } 
          inputs = outputs; 
        } 
        return inputs; 
      } 
    } 
    
    class Node 
    { 
      double[] weights; 
    
      Node(double[] weights) 
      { 
        this.weights = weights; 
      } 
    
      double output(double[] inputs) 
      { 
        double output = 0; 
        for (int i = 0; i < inputs.length; i++) 
        { 
          output += inputs[i] * weights[i]; 
        } 
        output -= weights[weights.length-1]; 
    
        return sigmoid(output); 
      } 
    
      double sigmoid(double a) 
      { 
        return 1/(1+Math.pow(Math.E,-a)); 
      } 
    } 
    
    
    
    //Program Parameters 
    int FRAMERATE = 100; 
    int WINDOW_WIDTH = 900; 
    int WINDOW_HEIGHT = 700; 
    
    //Simulation Parameters 
    int SIMULATION_WIDTH = 400; 
    int SIMULATION_HEIGHT = 400; 
    int NUMBER_OF_ANTS = 30; 
    int NUMBER_OF_MINES = 80; 
    int NUMBER_OF_STEPS_PER_GENERATION = 2000; 
    
    //Neural Network Parameters 
    int[] NEURAL_NETWORK_LAYERS = new int[] 
    { 
      4,15,15,15,2 
    }; 
    float NEURAL_NETWORK_INITIAL_LOW = -10; 
    float NEURAL_NETWORK_INITIAL_HIGH = 10; 
    
    //Ants Parameters 
    double MAXIMUM_TURNING_RATE = 0.3; 
    
    //GA Parameters 
    double CROSSOVER_RATE = 0.7; 
    double MUTATION_RATE = 0.1; 
    double MAXIMUM_PERTURBATION = 0.3; 
    int ELITISM = 4;
    
    
    class Simulation 
    { 
      Ant[] ants; 
      Coordinate[] mines; 
      GA evolution; 
      int ticks; 
      int generation; 
    
      Simulation() 
      { 
        evolution = new GA(); 
        ticks = NUMBER_OF_STEPS_PER_GENERATION; 
        generation = 1; 
    
        ants = new Ant[NUMBER_OF_ANTS]; 
    
        for (int i = 0; i < NUMBER_OF_ANTS; i++) 
        { 
          NeuralNet net = new NeuralNet(); 
          for (int j = 0; j < NEURAL_NETWORK_LAYERS.length; j++) 
          { 
            net.addLayer(NEURAL_NETWORK_LAYERS[j]); 
          } 
    
          ants[i] = new Ant(net); 
        } 
    
        mines = new Coordinate[NUMBER_OF_MINES]; 
        resetMines(); 
        displayInformation(generation, 0, 0, 0, ants[0].brain); 
        drawNeuralNet(ants[0].brain); 
      } 
    
      void resetMines() 
      {     
        for (int i = 0; i < NUMBER_OF_MINES; i++) 
        { 
          mines[i] = new Coordinate(random(SIMULATION_WIDTH), random(SIMULATION_HEIGHT)); 
        } 
      } 
    
      void step() 
      { 
        drawSimulation(ants, mines); 
    
        for (int i = 0; i < ants.length; i++) 
        { 
          ants[i].update(mines); 
          int mineEaten = ants[i].checkForMine(mines); 
    
          if (mineEaten > -1) 
          { 
            ants[i].fitness++; 
            mines[mineEaten] = new Coordinate(random(SIMULATION_WIDTH), random(SIMULATION_HEIGHT)); 
          } 
        } 
    
        drawSimulation(ants, mines); 
    
        ticks--; 
    
        if (ticks > 0) return; 
    
        generation++; 
    
        ticks = NUMBER_OF_STEPS_PER_GENERATION; 
    
        Genome[] genomes = new Genome[ants.length]; 
    
        for (int i = 0; i < ants.length; i++) 
        { 
          genomes[i] = new Genome(ants[i].getGenome(), ants[i].fitness); 
        } 
    
        double[][] newChromos = evolution.evolve(genomes); 
    
        for (int i = 0; i < ants.length; i++) 
        { 
          ants[i].setGenome(newChromos[i]); 
        } 
    
        resetMines(); 
        displayInformation(generation, (int)Math.floor(evolution.maximumFitness), (int)Math.floor(evolution.minimumFitness), evolution.averageFitness, ants[0].brain); 
        drawNeuralNet(ants[0].brain); 
      } 
    } 
    
    
    
    Simulation sim; 
    int translateX;
    int translateY;
    PGraphics simGraphics;
    
    void setup() 
    { 
      size(WINDOW_WIDTH, WINDOW_HEIGHT,P2D); 
      background(0); 
      ellipseMode(CENTER); 
      frameRate(FRAMERATE); 
      textFont(loadFont("bitstream.vlw"), 15); 
      sim = new Simulation();
      smooth();
      translateX = width - (SIMULATION_WIDTH + 5); 
      translateY = height - (SIMULATION_HEIGHT + 7);
      simGraphics = createGraphics(SIMULATION_WIDTH, SIMULATION_HEIGHT, P2D);
      simGraphics.smooth();
      rectMode(CORNER);
      stroke(255); 
      fill(0); 
      rect(translateX - 1, translateY - 1, SIMULATION_WIDTH + 2, SIMULATION_HEIGHT + 2); 
    } 
    
    void draw() 
    { 
      sim.step(); 
    } 
    
    public void drawNeuralNet(NeuralNet net) 
    { 
      int numOfLayers = net.layers.size(); 
      int sizex = width - (SIMULATION_WIDTH + 30); 
      int sizey = height - 30; 
    
      stroke(0); 
      fill(0); 
      rect(0,0,sizex + 30, sizey + 30); 
    
      int spaceBetweenLayers = sizey / (net.layers.size() - 1); 
      int spaceBetweenNodes = sizex / (net.largestLayer - 1); 
    
      fill(255); 
      Node[] previousNeurons = null; 
      int previousXStart = 0; 
    
      for (int i = 0; i < net.layers.size(); i++) 
      { 
        stroke(255); 
        Node[] neurons = (Node[]) net.layers.get(i); 
        int xstart = ((sizex / 2) - ((spaceBetweenNodes * (neurons.length)) / 2)) + (spaceBetweenNodes / 2); 
    
        for (int j = 0; j < neurons.length; j++) 
        { 
          ellipse(15 + xstart + (spaceBetweenNodes * j), 15 + spaceBetweenLayers * i, 10, 10); 
        } 
    
        if (i == 0) 
        { 
          previousNeurons = neurons; 
          previousXStart = xstart; 
          continue; 
        } 
    
        double midWeight = (net.smallestWeight + net.largestWeight) / 2; 
        double midToEdge = net.largestWeight - midWeight; 
    
        for (int x = 0; x < neurons.length; x++) 
        { 
          for (int y = 0; y < previousNeurons.length; y++) 
          { 
            if (neurons[x].weights[y] == midWeight) stroke(0, 0, 255); 
            if (neurons[x].weights[y] > midWeight) 
            { 
              stroke(0, Math.round(255 * ((neurons[x].weights[y] - midWeight) / midToEdge)),255); 
            } 
            else 
            { 
              stroke(Math.round(255 * ((midWeight - neurons[x].weights[y]) / midToEdge)),0,255); 
            } 
    
            line(15 + xstart + (spaceBetweenNodes * x), 15 + spaceBetweenLayers * i, 15 + previousXStart + (spaceBetweenNodes * y), 15 + spaceBetweenLayers * (i - 1)); 
          } 
        } 
    
        previousNeurons = neurons; 
        previousXStart = xstart; 
      } 
    } 
    
    void drawSimulation(Ant[] ants, Coordinate[] mines) 
    {
      simGraphics.beginDraw();
      simGraphics.stroke(0);
      simGraphics.fill(0);
      simGraphics.rect(0,0,SIMULATION_WIDTH - 1, SIMULATION_HEIGHT - 1);
      simGraphics.stroke(255, 0, 0);
      simGraphics.fill(255,0,0);
      for (int i = 0; i < mines.length; i++) 
      { 
        simGraphics.ellipse((float)mines[i].x, (float)mines[i].y, 4, 4); 
      } 
    
      simGraphics.stroke(128, 255, 128);
      simGraphics.fill(0,0,255);
      for (int i = 0; i < ants.length; i++) 
      { 
        ants[i].draw(simGraphics);
      }
      simGraphics.endDraw();
      image(simGraphics,translateX,translateY);
    } 
    
    void displayInformation(int generation, int max, int min, double average, NeuralNet net) 
    { 
      stroke(0); 
      fill(0); 
      rect(width - SIMULATION_WIDTH, 15, SIMULATION_WIDTH, height - (SIMULATION_HEIGHT + 8)); 
      drawText("Evolution", 1); 
      drawText("Current generation: " + generation, 3); 
      drawText("Previous generation statistics:", 5); 
      drawText("Maximum fitness: " + max, 6); 
      drawText("Minimum fitness: " + min, 7); 
      drawText("Average fitness: " + average, 8); 
      drawText("Best network from previous generation:", 10); 
      drawText("Largest weight:  " + net.largestWeight, 11); 
      drawText("Smallest weight: " + net.smallestWeight, 12);   
    } 
    
    void drawText(String text, int line) 
    { 
      int translateX = width - SIMULATION_WIDTH; 
      int translateY = 15; 
    
      fill(255); 
      text(text, translateX, translateY + (15 * line) + (5 * (line - 1))); 
    } 
    
    
    
    
    
    
    
    void setup()
    {
      size(500, 500,P2D);
      smooth();
      background(0);
      strokeWeight(2);
      frameRate(25);
    }
    
    float phaseIncInc = TWO_PI/10000;
    float phaseInc = phaseIncInc;
    
    float radiusInc = 2;
    
    void draw()
    {
      translate(width >> 1, height >> 1);
      background(0);
    
      float phase = 0;
      float radius = 0;
    
      float prevX = 0;
      float prevY = 0;
      float newX, newY;
    
      for (int i = 0; i < 200;i++)
      {
        newX = cos(phase) * radius;
        newY = sin(phase) * radius;
    
        stroke(cos(phase)*128+128,sin(phase)*128+128,sin(phase-HALF_PI)*128+128);
    
        line(prevX, prevY, newX, newY);
        prevX = newX;
        prevY = newY;
    
        phase += phaseInc;
        radius += radiusInc;
      }
    
      phaseInc += phaseIncInc;
      if (phaseInc > TWO_PI) phaseInc -= TWO_PI;
    }
    
    
    
    

    code

    tweaks (0)

    license

    advertisement

    Report Sketch

    Report for inappropriate content

    Please provide details if possible:

    Your have successfully reported the sketch. Thank you very much for helping to keep OpenProcessing clean and tidy :)

    Make a Copyright Infringement claim

    Cedric Mamo

    Artificial Neural Network & Genetic Algorithm

    Add to Faves Me Likey@! 23
    You must login/register to add this sketch to your favorites.

    The simulation at the bottom right shows a group of ants (green dots) whose aim is to collect food (red dots). Each ant is controlled by a neural network. After a predefined amount of time, the genetic algorithm is run on the current population creating a new population of (hopefully) better ants. At the top right are shown some information from the previous generation. The diagram on the left shows the best performing neural network from the previous generation. Circles are neurons, lines are the connections between them. The colour of the lines represents the strength of the connection.

    Callum Rogers
    31 Aug 2009
    Very, very interesting - I like the way that you have used neural networks to perfect the lifespan of simulated ants and then combined it with a genetic algorithm. Much more interesting than what I built neural networks for - adding and converting Cartesian to Polar co-ordinates. I feel almost inspired to make my old NN code into something visual by this!
    Cedric Mamo
    31 Aug 2009
    not really the lifespan... i haven't coded their death if they don't eat enough... just to collect as much food as possible
    Alasdair Turner
    31 Aug 2009
    It's a very nice sketch! If you've never studied it, one book you should definitely look at (if you haven't already) is Braitenberg's Vehicles. It's inspiration rather than textbook, and takes a tour through a host of ideas for sensorimotor linkages... and also take a look at Beer's classic paper on evolving dynamical neural networks for a few tips on evolving neural nets (Google will find it).
    Cedric Mamo
    31 Aug 2009
    10x for the info :)
    cornelius
    1 Nov 2010
    Nice, but also a little bit scarry, since i wrote pretty much the same programm a few years ago (back then in delphi/pascal).

    However my "ants" never got really(significantly) better:(
    Does your net have a pacemaker???

    Greetings, Cornelius
    Cedric Mamo
    1 Nov 2010
    no there isn't really any pacemaker. They do get significantly better with time though. I left it running overnight and found all the ants turning towards the food as fast as they can. Couldn't get them to perform much better in this version. I did make another version once where they were aware of the 2 closest pieces of food and the 2 closest ants to them, and the relative distance to each one (with the farthest one having a value of 1 and the others in proportion to that depending on how closer they are). It took longer to evolve good behavior, but they did tend towards avoiding other ants as well eventually... I lost that version though and can't bother to write it again as i'm working on other stuff xD
    bejoscha
    10 Aug 2011
    Very cool. I like the simplistic yet appealing graphics!
    Dan Purcell
    12 Sep 2011
    Cool. I've just uploaded something similar. I like that the neural network is visible .. How did you decide on that number of layers and neurons per layer? One thing I'm struggling to find info on is how much complexity of behaviour can be expected from a given topography.
    Cedric Mamo
    12 Sep 2011
    Hehe... i know this sounds silly... but in this particular sketch i chose the number of nodes according to how awesome it looked on screen... i could have done with less, It is proven that you don't need more than one hidden layer to approximate any mathemetical function. Therefore i could have done with a single hidden layer, and maybe 10 nodes in the hidden layer or something like that.

    As I said I wanted a visual effect as well for this sketch, so i chose the number of layers and nodes arbitrarily just for it to look cool :D
    You need to login/register to comment.