New to Neural Networks and before I move on to gradient descent I would like to make sure I have got basic idea right. (Sorry that the class is called perceptron I know that this isnt technically right, I adapted this code from and AND gate NN). This NN is made to learn the XOR function.
#include <iostream>
#include <ctime>
#include <stdlib.h>
#include <valarray>
#define POPSIZE 100
using namespace std;
float randfloat();
float Sigmoid(float A);
class Perceptron{
public:
Perceptron()
{
weights[0] = randfloat();
weights[1] = randfloat();
weights[2] = randfloat();
weights[3] = randfloat();
weights[4] = randfloat();
weights[5] = randfloat();
weights[6] = randfloat();
weights[7] = randfloat();
weights[8] = randfloat();
CalculateError();
}
float FeedForward(int A, int B)
{
float Sum1 = A*weights[0] + B*weights[1] + bias*weights[4];
float Sum2 = A*weights[2] + B*weights[3] + bias*weights[5];
float Sum3 = Sigmoid(Sum1)*weights[6]
+ Sigmoid(Sum2)*weights[7]
+ bias*weights[8];
return Sigmoid(Sum3);
}
void PrintStats()
{
cout << "weights =" << weights[0] << " " << weights[1] << " " << weights[2];
cout << "\nerror= " << normalisedError;
}
void CalculateError()
{
error = abs(0-FeedForward(1,1)) +
abs(1-FeedForward(1,0)) +
abs(1-FeedForward(0,1)) +
abs(0-FeedForward(0,0));
normalisedError = error*10;
}
float GetNormalisedError()
{
return normalisedError;
}
void SetFitnessScore(int i)
{
fitnessScore = i;
}
int GetFitnessScore()
{
return fitnessScore;
}
friend void CrossOver(Perceptron A, Perceptron B, Perceptron &C);
friend void TransferGenes(Perceptron A, Perceptron &B);
friend int ChooseFittestSpecies(Perceptron pop[POPSIZE]);
private:
float weights[9];
int bias = 1;
float error =0;
int normalisedError;
int fitnessScore;
};
int ChooseParent(Perceptron pop[POPSIZE]);
int ChooseFittestSpecies(Perceptron pop[POPSIZE]);
int ChooseWorstSpecies(Perceptron pop[POPSIZE]);
void Reproduce(Perceptron pop[POPSIZE], Perceptron C[POPSIZE]);
int main()
{
srand(time(0));
Perceptron pop[POPSIZE];
Perceptron Children[POPSIZE];
for(int x =0 ; x < 100 ; x++){
Reproduce(pop, Children);
for(int i = 0 ; i < POPSIZE ; i ++)
{
TransferGenes(Children[i], pop[i]);
pop[i].CalculateError();
}
}
int alphaSpecies = ChooseFittestSpecies(pop);
cout << "Most fit species is: " << alphaSpecies << endl;
cout << "inputs:" << endl;
cout << "1 1 : " << pop[alphaSpecies].FeedForward(1,1) << endl;
cout << "0 1 : " << pop[alphaSpecies].FeedForward(0,1) << endl;
cout << "1 0 : " << pop[alphaSpecies].FeedForward(1,0) << endl;
cout << "0 0 : " << pop[alphaSpecies].FeedForward(0,0) << endl;
return 0;
}
void TransferGenes(Perceptron A, Perceptron &B)
{
for(int i = 0 ; i < 9 ; i++)
{
B.weights[i] = A.weights[i];
}
}
void Reproduce(Perceptron pop[POPSIZE], Perceptron C[POPSIZE])
{
int ParentA, ParentB;
for(int i = 0; i < POPSIZE ; i++)
{
ParentA = ChooseParent(pop);
ParentB = ChooseParent(pop);
CrossOver(pop[ParentA], pop[ParentB], C[i]);
}
}
void CrossOver(Perceptron A, Perceptron B, Perceptron &C)
{
int random;
for(int i = 0 ; i < 9 ; i ++)
{
random = rand()%2;
if(random)
{
C.weights[i] = A.weights[i];
}else{
C.weights[i] = B.weights[i];
}
}
}
int ChooseParent(Perceptron pop[POPSIZE])
{
int GreatestError = pop[0].GetNormalisedError();
for(int i = 1; i < POPSIZE ; i++)
{
if(pop[i].GetNormalisedError() > GreatestError)
{
GreatestError = pop[i].GetNormalisedError();
}
}
int totalFitness=0;
for(int i =0 ; i < POPSIZE ; i++)
{
pop[i].SetFitnessScore(GreatestError + 1 - pop[i].GetNormalisedError());
totalFitness = totalFitness + pop[i].GetFitnessScore();
}
int random = rand()%totalFitness +1;
int ParentSelector = 0;
int ParentIndex;
for(int i=0;ParentSelector<random;i++)
{
ParentSelector = ParentSelector + pop[i].GetFitnessScore();
ParentIndex = i;
}
return ParentIndex;
}
float randfloat()
{
float f = static_cast <float> (rand()) / (static_cast <float> (RAND_MAX/10));
int Pos_or_Neg = rand()%2;
if(Pos_or_Neg)
{
return f;
}else{
return -f;
}
}
float Sigmoid(float A)
{
return 1/(1+exp(-2*A));
}
int ChooseFittestSpecies(Perceptron pop[POPSIZE])
{
int MostFitParent = 0;
for(int i = 0; i < POPSIZE ; i++)
{
if(pop[i].error < pop[MostFitParent].error)
{
MostFitParent = i;
}
}
return MostFitParent;
}