Click here to Skip to main content
15,893,564 members
Articles / Artificial Intelligence

AI : Neural Network for beginners (Part 2 of 3)

Rate me:
Please Sign up or sign in to vote.
4.87/5 (130 votes)
29 Jan 2007CPOL8 min read 333.9K   9.5K   279  
AI : An Introduction into Neural Networks (Multi-layer networks / Back Propagation)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using dotnetCHARTING.WinForms;

namespace Backprop_ANN_XOR
{
    #region frmMain CLASS
    /// <summary>
    /// Provides a GUI to show the results of this article which is
    /// to use a <see cref="NN_Trainer_XOR">trainer</see> to train a 
    /// <see cref="NeuralNetwork">NeuralNetwork </see>to solve the XOR
    /// logic problem. 
    /// </summary>
    public partial class frmMain : Form
    {
        #region Instance Fields
        private int trainingLoop = 0;
        private int trainingNo = 0;
        private NeuralNetwork nn;
        private Series[] series_Training;
        private SeriesCollection SC_Training;
        private Series[] series_Trained;
        private SeriesCollection SC_Trained;
        #endregion
        #region Constructor
        /// <summary>
        /// Creates a new frmMain, and ensures its as flicker free as it can be
        /// </summary>
        public frmMain()
        {
            InitializeComponent();
            SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw |
                     ControlStyles.DoubleBuffer | ControlStyles.UserPaint, true);
        }
        #endregion
        #region private methods
        /// <summary>
        /// Carries out the main function of this article which is
        /// to use a <see cref="NN_Trainer_XOR">trainer</see> to train a 
        /// <see cref="NeuralNetwork">NeuralNetwork </see>to solve the XOR
        /// logic problem. 
        /// The results are also used to show within this example GUI form
        /// </summary>
        /// <param name="sender">btnDoXOR</param>
        /// <param name="e">the event args</param>
        private void btnDoXOR_Click(object sender, EventArgs e)
        {

            try
            {
                trainingNo = int.Parse(txtTraining.Text);
                txtResults.Text = "START OF TRAINING\r\n";
                setGuiState(false);
                trainingLoop = 0;
                initCharts();
                nn = new NeuralNetwork(2, 2, 1);
                nn.Change += new NeuralNetwork.ChangeHandler(nn_Change);
                NN_Trainer_XOR trainer = new NN_Trainer_XOR(ref nn);
                trainer.Change += new NN_Trainer_XOR.ChangeHandler(trainer_Change);
                btnDoXOR.Enabled = false;
                trainer.doTraining(trainingNo);
                txtResults.Text += "END OF TRAINING " + "\r\n";
                trainer.doActualRun();
                btnDoXOR.Enabled = true;
                setGuiState(true);
                fillCharts();
            }
            catch (Exception ex)
            {
                MessageBox.Show("you must enter an integer for the traning number",
                                 "error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// Initislaise the charts
        /// </summary>
        private void initCharts()
        {
            initialiseChartData(
                "Neural Network training for XOR",
                ref SC_Training,
                ref series_Training,
                ref chartTraining);
            initialiseChartData(
                "Neural Network trained for XOR",
                ref SC_Trained,
                ref series_Trained,
                ref chartTrained);
        }

        /// <summary>
        /// Fill the charts with data
        /// </summary>
        private void fillCharts()
        {
            fillGraphDataTargsVsOuts(ref SC_Training,
                ref series_Training,
                ref chartTraining);
            fillGraphDataTargsVsOuts(ref SC_Trained,
                ref series_Trained,
                ref chartTrained);
        }

        /// <summary>
        /// Fills a chart object using the parameters provided
        /// </summary>
        /// <param name="SC">The chart series collection</param>
        /// <param name="series">The chart series</param>
        /// <param name="chart">The chart</param>
        private void fillGraphDataTargsVsOuts(ref SeriesCollection SC,
                                              ref Series[] series, ref Chart chart)
        {
            SC.Clear();
            chart.SeriesCollection.Clear();
            SC.Add(series[0]);
            SC.Add(series[1]);
            chart.SeriesCollection.Add(SC);
            chart.RefreshChart();
        }


        /// <summary>
        /// Fills a chart object using the parameters provided
        /// </summary>
        /// <param name="SC">The chart series collection</param>
        /// <param name="series">The chart series</param>
        /// <param name="chart">The chart</param>
        private void fillGraphDataErrors(ref SeriesCollection SC,
                                              ref Series[] series, ref Chart chart)
        {
            SC.Clear();
            chart.SeriesCollection.Clear();
            SC.Add(series[2]);
            chart.SeriesCollection.Add(SC);
            chart.RefreshChart();
        }


        /// <summary>
        /// Configures a chart object using the parameters provided
        /// </summary>
        /// <param name="title">The chart title</param>
        /// <param name="SC">The chart series collection</param>
        /// <param name="series">The chart series</param>
        /// <param name="chart">The chart</param>
        private void initialiseChartData(String title, ref SeriesCollection SC, 
                                                    ref Series[] series, ref Chart chart)
        {
            SC = new SeriesCollection();
            //create some new series data for the chart
            series = new Series[3];
            series[0] = new Series("Target");
            series[1] = new Series("Output");
            series[2] = new Series("Error");
            // nullify the chart data
            chart.SeriesCollection.Clear();
            SC.Clear();
            //set the  formatting properties
            chart.Title = title;
            chart.Type = ChartType.Scatter;
            chart.Use3D = false;
            chart.DefaultSeries.DefaultElement.Transparency = 20;
            chart.DefaultSeries.DefaultElement.Marker.Type = ElementMarkerType.None;
            chart.ChartArea.LegendBox.Template = "%Name%Icon";
            chart.DefaultSeries.Line.Width = 2;

        }

        /// <summary>
        /// Sets the tab and view config button
        /// enabled state to be the state of the enabled 
        /// input parameter
        /// </summary>
        /// <param name="enabled">the enabled state</param>
        private void setGuiState(bool enabled)
        {
            tabs.Enabled = enabled;
            btnViewNNConfig.Enabled = enabled;
        }

        /// <summary>
        /// The Change event which is raised by the 
        /// <see cref="NN_Trainer_XOR">trainer</see>
        /// This method simplu updates the trainingLoop with
        /// the current trainers loop number
        /// </summary>
        /// <param name="sender">The <see cref="NN_Trainer_XOR">trainer</see></param>
        /// <param name="nne">The event args</param>
        private void trainer_Change(object sender, TrainerEventArgs te)
        {
            trainingLoop = te.TrainingLoop;
        }

        /// <summary>
        /// Uses the data contained in the event args, to add to the 
        /// live values text box, and also create the required chart
        /// data from the data
        /// </summary>
        /// <param name="nne">The event args</param>
        private void show_NeuralNetwork_Results(NeuralNetworkEventArgs nne)
        {
            this.Invoke(new EventHandler(delegate
            {
                GenerateChartData(nne);
                double[] targOuts = nne.TargetOuts;
                double[] outputs = nne.Outputs;
                for (int i = 0; i < targOuts.Length; i++)
                {
                    txtResults.Text += (NeuralNetwork.isInTraining ? "Training Loop " + trainingLoop + " " : "");
                    txtResults.Text += "Output : " + outputs[i].ToString("#,##0.00")
                        + " / Target Output : " + targOuts[i] + "\r\n";
                }
            }));
            this.Invalidate();
            Application.DoEvents();
        }
        

        /// <summary>
        /// The Change event which is raised by the 
        /// <see cref="NeuralNetwork">NeuralNetwork</see>
        /// This method then calls the show_NeuralNetwork_Results()
        /// method
        /// </summary>
        /// <param name="sender">The <see cref="NeuralNetwork">NeuralNetwork</see></param>
        /// <param name="nne">The event args</param>
        private void nn_Change(object sender, NeuralNetworkEventArgs nne)
        {
            if (NeuralNetwork.isInTraining)
            {
                //only show every 100th result
                if (trainingLoop % 100 == 0)
                {
                    show_NeuralNetwork_Results(nne);
                }
            }
            else
            {
                //not in traning, so show ALL results
                show_NeuralNetwork_Results(nne);
            }
        }

        /// <summary>
        /// Calls the setGuiState with a false parameter
        /// </summary>
        /// <param name="sender">The rmMain</param>
        /// <param name="e">the event args</param>
        private void frmMain_Load(object sender, EventArgs e)
        {
            setGuiState(false);
            txtTraining.Focus();
        }

        /// <summary>
        /// Shows a new <see cref="frmNeuralNetworkConfig">frmNeuralNetworkConfig</see> 
        /// form for the current <see cref="NeuralNetwork">NeuralNetwork</see> 
        /// </summary>
        /// </summary></see> 
        /// </summary>
        /// <param name="sender">btnViewNNConfig</param>
        /// <param name="e">the event args</param>
        private void btnViewNNConfig_Click(object sender, EventArgs e)
        {
            frmNeuralNetworkConfig fNNCfg = new frmNeuralNetworkConfig();
            fNNCfg.NeuralNetworkCfg = this.nn;
            fNNCfg.ShowDialog(this);
        }




        /// <summary>
        /// Create chart data based on the results from the 
        /// <see cref="NeuralNetwork">NeuralNetwork</see> 
        /// </summary>
        /// <param name="nne"></param>
        private void GenerateChartData(NeuralNetworkEventArgs nne)
        {

            Element eTarget = new Element("Training loop No " + trainingLoop + " target ", DateTime.Now, nne.TargetOuts[0]);
            Element eOutput = new Element("Training loop No " + trainingLoop + " output ", DateTime.Now, nne.Outputs[0]);
            Element eError = new Element("Training loop No " + trainingLoop + " error ", 
                                            DateTime.Now, Math.Sqrt(Math.Pow((nne.TargetOuts[0] - nne.Outputs[0]),2)));

            if (NeuralNetwork.isInTraining)
            {
                series_Training[0].Elements.Add(eTarget);
                series_Training[1].Elements.Add(eOutput);
                series_Training[2].Elements.Add(eError);
            }
            else
            {
                series_Trained[0].Elements.Add(eTarget);
                series_Trained[1].Elements.Add(eOutput);
                series_Trained[2].Elements.Add(eError);
            }
        }

        /// <summary>
        /// Fills the chartTraining chart, with the training targets/outputs
        /// </summary>
        /// <param name="sender">the btnTrainingTargetVsOuts button</param>
        /// <param name="e">the event args</param>
        private void btnTrainingTargetVsOuts_Click(object sender, EventArgs e)
        {
            fillGraphDataTargsVsOuts(ref SC_Training,
                                     ref series_Training,
                                     ref chartTraining);
        }

        /// <summary>
        /// Fills the chartTraining chart, with the training errors
        /// </summary>
        /// <param name="sender">the btnTrainingErrors button</param>
        /// <param name="e">the event args</param>
        private void btnTrainingErrors_Click(object sender, EventArgs e)
        {
            fillGraphDataErrors(ref SC_Training,
                                ref series_Training,
                                ref chartTraining);
        }

        /// <summary>
        /// Fills the chartTrained chart, with the trained targets/outputs
        /// </summary>
        /// <param name="sender">the btnTrainedTargetVsOuts button</param>
        /// <param name="e">the event args</param>
        private void btnTrainedTargetVsOuts_Click(object sender, EventArgs e)
        {
            fillGraphDataTargsVsOuts(ref SC_Trained,
                                     ref series_Trained,
                                     ref chartTrained);
        }

        /// <summary>
        /// Fills the chartTrained chart, with the training errors
        /// </summary>
        /// <param name="sender">the btnTrainedErrors button</param>
        /// <param name="e">the event args</param>
        private void btnTrainedErrors_Click(object sender, EventArgs e)
        {
            fillGraphDataErrors(ref SC_Trained,
                                ref series_Trained,
                                ref chartTrained);
        }
        #endregion

    }
    #endregion
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United Kingdom United Kingdom
I currently hold the following qualifications (amongst others, I also studied Music Technology and Electronics, for my sins)

- MSc (Passed with distinctions), in Information Technology for E-Commerce
- BSc Hons (1st class) in Computer Science & Artificial Intelligence

Both of these at Sussex University UK.

Award(s)

I am lucky enough to have won a few awards for Zany Crazy code articles over the years

  • Microsoft C# MVP 2016
  • Codeproject MVP 2016
  • Microsoft C# MVP 2015
  • Codeproject MVP 2015
  • Microsoft C# MVP 2014
  • Codeproject MVP 2014
  • Microsoft C# MVP 2013
  • Codeproject MVP 2013
  • Microsoft C# MVP 2012
  • Codeproject MVP 2012
  • Microsoft C# MVP 2011
  • Codeproject MVP 2011
  • Microsoft C# MVP 2010
  • Codeproject MVP 2010
  • Microsoft C# MVP 2009
  • Codeproject MVP 2009
  • Microsoft C# MVP 2008
  • Codeproject MVP 2008
  • And numerous codeproject awards which you can see over at my blog

Comments and Discussions