Exemple #1
0
 public BpNeuron(int Layer, int NeuronNumber, NeuronClass NeuronType, ArtificialNetwork AINetwork)
 {
     this.Location   = new Vector2(Layer, NeuronNumber);
     this.NeuronType = NeuronType;
     this.Bias       = NeuralFunctions.NextDouble(MIN, MAX);
     this.AINetwork  = AINetwork;
 }
Exemple #2
0
        public async override Task Train(List <double> Inputs, List <double> ExpectedOutputs)
        {
            this.TrainingMode = true;
            NetworkState State = NetworkState.FORWARD_PROPAGATION;

            Console.WriteLine("Setting up network...");
            double LastErrorRate = 0;

            //Inputs = Normalize(Inputs);
            //Console.WriteLine("Done normalizing outputs");
            if (this.Weights.Count == 0 || this.Neurons.Count == 0)
            {
                SetupNetwork(Inputs.Count, ExpectedOutputs.Count, Inputs);
            }
            Program.WriteLine("SizeOf Inputs = " + Inputs.Count + ", SizeOf ExpectedOutputs: " + ExpectedOutputs.Count);
            Console.SetOut(Program.ConsoleOut);
            Console.WriteLine();
            Console.WriteLine("|Initialized Weights size = | " + Weights[0].Count + "," + Weights[1].Count);
            this.ExpectedOutputs = ExpectedOutputs;
            bool          TrainingIsComplete = false;
            List <double> TempOutputs        = new List <double>();
            Stopwatch     watch = new Stopwatch();

            for (int Iterations = 0; Iterations < 1000 || TrainingIsComplete; Iterations++)
            {
                if (State == NetworkState.FORWARD_PROPAGATION)
                {
                    for (int x = 0; x <= this.HiddenLayers; x++)
                    {
                        //propagate to output
                        if (x == HiddenLayers)
                        {
                            Program.WriteLine("Propagating from final hidden layer to output layer");
                            List <Task <double> > Calcs = new List <Task <double> >();
                            for (int i = 0; i < ExpectedOutputs.Count; i++)
                            {
                                Calcs.Add(this.Neurons[x][i].Fire(TempOutputs, State));
                            }
                            TempOutputs.Clear();
                            for (int i = 0; i < ExpectedOutputs.Count; i++)
                            {
                                TempOutputs.Insert(i, await Calcs[i]);
                            }

                            //calculate error
                            double Error = NeuralFunctions.ComputeError(TempOutputs.ToArray(), ExpectedOutputs.ToArray());
                            Console.SetOut(Program.ConsoleOut);
                            Console.WriteLine("****************************Iteration " + Iterations + " Error: " + Error + "****************************");
                            if (Error == LastErrorRate)
                            {
                                throw new BrainFireException("The last few epochs have flatlined. Restarting the network should fix the problem");
                                Program.WriteLine("Retrying");
                                this.Weights = null;
                                this.Neurons = null;
                                await this.Train(Inputs, ExpectedOutputs);

                                this.LearningRate = .1;
                                return;
                            }
                            if (this.MseSeries != null)
                            {
                                DataPoint p = new DataPoint(ImageAI.CURRENT_EPOCH_VIS_POS++, Error);
                                if (Error > 0 && Error < 1000)
                                {
                                    this.MseSeries.Points.Add(p);
                                }
                            }
                            //Refresh Training rate
                            watch.Stop();
                            if (Iterations > 0)
                            {
                                Program.WriteLine("time elapsed: " + watch.Elapsed.TotalMilliseconds);
                                //double DeltaT = NeuralFunctions.ComputeTimeDependantTrainingRate((Error - LastErrorRate), watch.Elapsed.TotalMilliseconds, this.LearningRate, Iterations);
                                if (this.OtherSeries != null)
                                {
                                    //DataPoint p = new DataPoint(Iterations, DeltaT);
                                    //this.OtherSeries.Points.Add(p);
                                }
                                //this.LearningRate += DeltaT;
                                //Program.WriteLine("New training rate: " + this.LearningRate);
                            }
                            watch.Reset();
                            watch.Start();
                            LastErrorRate = Error;
                            Console.SetOut(Program.Debug);
                            if (Double.IsNaN(Error))
                            {
                                throw new BrainFireException("Invalid Error Rate Calculated");
                            }



                            if (Error < .01)
                            {
                                //Trained successfully, return to exit
                                DataPoint pz = new DataPoint(ImageAI.CURRENT_CYCLE++, Iterations);
                                this.OtherSeries.Points.Add(pz);
                                return;
                            }
                            //Set up TempOutputs for BackPropagationNetwork (Give DeltaK values)
                            TempOutputs.Clear();
                            for (int i = 0; i < ExpectedOutputs.Count; i++)
                            {
                                TempOutputs.Add(this.Neurons[x][i].DeltaKOutput);
                            }
                            State = NetworkState.BACK_PROPAGATION;
                            Program.WriteLine("Setting STATE TO BackProp");
                            break;
                        }
                        //propagate input to first neurons
                        else if (x == 0)
                        {
                            Program.WriteLine("Propagating from input layer to initial hidden layer");
                            List <Task <double> > Calcs = new List <Task <double> >();
                            for (int i = 0; i < this.NeuronsPerLayer; i++)
                            {
                                Calcs.Add(this.Neurons[x][i].Fire(Inputs, State));
                            }
                            TempOutputs.Clear();
                            for (int i = 0; i < this.NeuronsPerLayer; i++)
                            {
                                TempOutputs.Insert(i, await Calcs[i]);
                            }
                        }
                        //normal hidden layer
                        else
                        {
                            Program.WriteLine("Propagating from hidden layer to hidden layer");
                            List <Task <double> > Calcs = new List <Task <double> >();
                            for (int i = 0; i < this.NeuronsPerLayer; i++)
                            {
                                Calcs.Add(this.Neurons[x][i].Fire(TempOutputs, State));
                            }
                            TempOutputs.Clear();
                            for (int i = 0; i < this.NeuronsPerLayer; i++)
                            {
                                TempOutputs.Insert(i, await Calcs[i]);
                            }
                        }
                    }
                    State = NetworkState.BACK_PROPAGATION;
                }

                if (State == NetworkState.BACK_PROPAGATION)
                {
                    for (int x = this.HiddenLayers; x >= 0; x--)
                    {
                        if (x >= 1)
                        {
                            Program.WriteLine("BackPropagating from Layer to Layer");
                            List <Task <double> > Calcs = new List <Task <double> >();
                            for (int i = 0; i < this.NeuronsPerLayer; i++)
                            {
                                Calcs.Add(this.Neurons[x - 1][i].Fire(TempOutputs, State));
                            }
                            TempOutputs.Clear();
                            for (int i = 0; i < this.NeuronsPerLayer; i++)
                            {
                                TempOutputs.Insert(i, await Calcs[i]);
                            }
                        }
                        //input neurons
                        else
                        {
                            Program.WriteLine("BackPropagating from Layer to Input");
                            List <Task <double> > Calcs = new List <Task <double> >();
                            for (int i = 0; i < Inputs.Count; i++)
                            {
                                Calcs.Add(this.Neurons[this.Neurons.Count - 1][i].Fire(TempOutputs, State));
                            }
                            TempOutputs.Clear();
                            for (int i = 0; i < Inputs.Count; i++)
                            {
                                await Calcs[i];
                            }
                        }
                    }
                }
                State = NetworkState.FORWARD_PROPAGATION;
            }
        }
Exemple #3
0
            public unsafe override async Task <double> Fire(List <double> Inputsf, NetworkState State)
            {
                if (!((BackPropagationNetwork)this.AINetwork).TrainingMode)
                {
                    if (((BackPropagationNetwork)this.AINetwork).HiddenLayers + 1 == this.GetLocation().X)
                    {
                        Program.WriteLine("NeuronType: " + this.ToString());
                        Program.WriteLine("Editing neuron class from HIDDEN to OUTPUT");
                        this.NeuronType = NeuronClass.OUTPUT;
                    }
                }
                //Console.SetOut(Program.Debug);
                //Console.WriteLine("Firing Neuron " + this.ToString());
                List <double> Weights = GetWeights(Inputsf.Count, State);
                //Console.WriteLine("Received Weights, count = " + Weights.Count);
                List <double> Inputs = Inputsf.ToList();

                if (Inputs.Count != Weights.Count)
                {
                    throw new BrainFireException("The number of inputs != the number of weights. Aborting");
                }

                if (State == NetworkState.FORWARD_PROPAGATION)
                {
                    if (NeuronType == NeuronClass.HIDDEN)
                    {
                        //simply multiply and sum. Then run through Sigmoid function
                        double value = 0.0;
                        for (int i = 0; i < Inputs.Count; i++)
                        {
                            value += Inputs[i] * Weights[i];
                        }
                        //Console.WriteLine("Total Sum: " + value);
                        value += this.Bias;
                        //Console.WriteLine("Total Sum (Bias) : " + value);
                        value = NeuralFunctions.SimpleSquash(value);
                        //Console.WriteLine("Sigmoid: " + value);
                        this.Output = value;
                    }
                    else if (NeuronType == NeuronClass.OUTPUT)
                    {
                        //multiply and sum, then calculate this neurons error. Then, update the bias term
                        double value = 0.0;
                        for (int i = 0; i < Inputs.Count; i++)
                        {
                            value += Inputs[i] * Weights[i];
                        }
                        value += this.Bias;
                        //Program.WriteLine("Total Sum: " + value);
                        Console.SetOut(Program.ConsoleOut);
                        this.Output = NeuralFunctions.SimpleSquash(value);
                        Console.SetOut(Program.Debug);
                        //NeuralFunctions.TanSigmoid(value, &value);
                        if (((BackPropagationNetwork)this.AINetwork).TrainingMode)
                        {
                            //Console.WriteLine("Sigmoid: " + value);
                            double T = ((BackPropagationNetwork)this.AINetwork).ExpectedOutputs[this.GetLocation().Y];
                            this.DeltaKOutput = this.Output * (1 - this.Output) * (T - this.Output);
                            //Console.WriteLine("DeltaK: " + this.DeltaKOutput);
                            //Update bias
                            double DeltaBias = this.DeltaKOutput * ((BackPropagationNetwork)this.AINetwork).LearningRate;
                            //Console.WriteLine("Delta Bias: " + DeltaBias);
                            this.DeltaBiasOutput = DeltaBias;
                            this.Bias           += this.DeltaBiasOutput;
                            //Console.WriteLine("New Bias: " + Bias);
                        }
                        //this.Output = this.DeltaKOutput;
                    }
                }
                else if (State == NetworkState.BACK_PROPAGATION)
                {
                    if (NeuronType == NeuronClass.HIDDEN)
                    {
                        //primary role of the neuron in this state is to update weights and biases
                        //required Inputs[] are DeltaK values from output neuron
                        double DeltaX = 0.0;
                        for (int i = 0; i < Inputs.Count; i++)
                        {
                            //Console.WriteLine("Operation[+]: " + Inputs[i] + " x " + Weights[i]);
                            DeltaX += Weights[i] * Inputs[i];
                        }
                        //Console.WriteLine("Total Sum: " + DeltaX);
                        //get previous output
                        DeltaX = DeltaX * (1 - this.Output) * this.Output;
                        //Console.WriteLine("DeltaX: " + DeltaX);
                        double DeltaBias = DeltaX * ((BackPropagationNetwork)this.AINetwork).LearningRate;
                        //Console.WriteLine("Delta Bias: " + DeltaBias);
                        //Console.WriteLine("Old Bias: " + this.Bias);
                        if (this.DeltaW == null)
                        {
                            this.DeltaW = DeltaX * ((BackPropagationNetwork)this.AINetwork).LearningRate * this.Output;
                            for (int i = 0; i < Inputs.Count; i++)
                            {
                                ((BackPropagationNetwork)this.AINetwork).Weights[this.GetLocation().X][i + (this.Location.Y * Inputs.Count)] += this.DeltaW;
                            }
                        }
                        else
                        {
                            double DeltaWCur = DeltaX * ((BackPropagationNetwork)this.AINetwork).LearningRate * this.Output;
                            this.DeltaW = DeltaWCur + (((BackPropagationNetwork)this.AINetwork).Momentum * this.DeltaW); //Momentum term
                            for (int i = 0; i < Inputs.Count; i++)
                            {
                                ((BackPropagationNetwork)this.AINetwork).Weights[this.GetLocation().X][i + (this.Location.Y * Inputs.Count)] += this.DeltaW;
                            }
                        }
                        this.Bias += DeltaBias;
                        //Console.WriteLine("New Bias: " + this.Bias);
                        this.Output = DeltaX;
                    }
                    else if (NeuronType == NeuronClass.INPUT)
                    {
                        for (int i = 0; i < Inputs.Count; i++)
                        {
                            double WeightDelta = Inputs[i] * ((BackPropagationNetwork)this.AINetwork).LearningRate * this.InputNeuronInput;
                            //Console.WriteLine("Weight Before: " + ((BackPropagationNetwork)this.AINetwork).Weights[this.GetLocation().X][i + (this.Location.Y * Inputs.Count)]);
                            //Console.WriteLine("Weight Delta: " + WeightDelta);
                            ((BackPropagationNetwork)this.AINetwork).Weights[this.GetLocation().X][i + (this.Location.Y * Inputs.Count)] += WeightDelta;
                            //Console.WriteLine("New Weight: " + ((BackPropagationNetwork)this.AINetwork).Weights[this.GetLocation().X][i + (this.Location.Y * Inputs.Count)]);
                        }
                    }
                }
                Console.SetOut(Program.Debug);
                Console.WriteLine("Output: " + this.Output);
                return(this.Output);
            }
Exemple #4
0
        public const double MAX = 1;  //.6 for squash
        public void SetupNetwork(int NumberOfInputs, int NumberOfOutputs, List <double> Inputs)
        {
            if (this.Weights == null)
            {
                this.Weights = new List <List <double> >();
            }
            if (this.Neurons == null)
            {
                this.Neurons = new List <List <BpNeuron> >();
            }
            for (int i = 0; i <= this.HiddenLayers + 1; i++)
            {
                //input layer
                if (i == 0)
                {
                    // add weights
                    List <double> Weights = new List <double>();
                    Program.WriteLine("# of inputs: " + NumberOfInputs);
                    Program.WriteLine("# of NPL" + this.NeuronsPerLayer);
                    for (int x = 0; x < NumberOfInputs; x++)
                    {
                        for (int y = 0; y < this.NeuronsPerLayer; y++)
                        {
                            Weights.Add(NeuralFunctions.NextDouble(MIN, MAX));
                        }
                    }
                    Program.WriteLine("SizeOf Weights: " + Weights.Count);
                    this.Weights.Add(Weights);
                }

                //output layer
                else if (i == this.HiddenLayers + 1)
                {
                    //Add output neurons to final layer
                    List <BpNeuron> NeuronLayer = new List <BpNeuron>();
                    for (int y = 0; y < NumberOfOutputs; y++)
                    {
                        NeuronLayer.Add(new BpNeuron(i, y, NeuronClass.OUTPUT, this));
                    }
                    this.Neurons.Add(NeuronLayer);
                }

                //hidden layer
                else
                {
                    //Add neurons to layer
                    List <BpNeuron> NeuronLayer = new List <BpNeuron>();
                    for (int y = 0; y < this.NeuronsPerLayer; y++)
                    {
                        NeuronLayer.Add(new BpNeuron(i, y, NeuronClass.HIDDEN, this));
                    }
                    this.Neurons.Add(NeuronLayer);

                    //add weights inbound to next layer
                    if (i < this.HiddenLayers)
                    {
                        List <double> Weights = new List <double>();
                        for (int x = 0; x < this.NeuronsPerLayer; x++)
                        {
                            for (int y = 0; y < this.NeuronsPerLayer; y++)
                            {
                                Weights.Add(NeuralFunctions.NextDouble(MIN, MAX));
                            }
                        }
                        this.Weights.Add(Weights);
                    }
                    else
                    {
                        List <double> Weights = new List <double>();
                        for (int x = 0; x < this.NeuronsPerLayer; x++)
                        {
                            for (int y = 0; y < NumberOfOutputs; y++)
                            {
                                Weights.Add(NeuralFunctions.NextDouble(MIN, MAX));
                            }
                        }
                        this.Weights.Add(Weights);
                    }
                }
            }

            //finally, add input neurons to the END of the array
            List <BpNeuron> InputNeurons = new List <BpNeuron>();

            for (int i = 0; i < NumberOfInputs; i++)
            {
                InputNeurons.Add(new BpNeuron(0, i, NeuronClass.INPUT, this));
                InputNeurons[i].InputNeuronInput = Inputs[i];
            }
            this.Neurons.Add(InputNeurons);
        }