用于将一个层中的所有节点连接到下一层中的所有节点的算法

时间:2016-08-13 06:24:57

标签: c# algorithm neural-network nodes

我正在尝试使用此https://www.youtube.com/watch?v=KkwX7FkLfug教程使用反向传播编写神经网络。

我正在尝试在C#中进行,并且正在改变一些细节。

他和我之间的主要区别在于我不知道每个节点从一开始就会有多少个神经元。以下是我的API在代码中的工作方式。

class main
{
    static void Main(string[] args)
    {
        List<bool> testData = new List<bool>() {true};
        System.Console.WriteLine("In MAIN! \n");
        int inputNeurons = 64;
        int outputNeurons = 2;

        double eta   =  0.1; // 0.0..1.0    training rate
        double alpha =  0.5; // 0.0..n      momentum

        NeuralNet neuralNet = new NeuralNet(eta, alpha);
        // order matters, first layer is for input, last layer is for output
        neuralNet.AddLayer(inputNeurons);   // input layer
                                            // multiple hidden layers could go here
        neuralNet.AddLayer(outputNeurons);  // output Layer
        neuralNet.MakeConnections();

        neuralNet.Train(testData);

        neuralNet.GetResults();
        Console.ReadLine();
    }
}

以下是我的其余神经网络代码,其中一些是伪代码,或者只是在我尝试使连接正常工作时打印语句。

namespace NeuralNetJO
{
    class Program
    {
        static void Main(string[] args)
        {

        }
    }

    public class NeuralNet
    {
        public NeuralNet(double newEta, double newAlpha)
        {
            numLayers = -1; // numLayers tracks how many layers of neurons the neural net has
            eta = newEta;
            alpha = newAlpha;
        }

        /**
        *   GetResults()
        *       returns array of results and weights
        */
        public void GetResults()
        {
            foreach (Layer l in n_layer)
            {
                foreach (Neuron n in l.n_neurons)
                {

                }
            }
        }

        public void MakeConnections()
        {
            // For each layer
            if (numLayers > 0)
            {
                for (int i = 0; i < n_layer.Count; i++)
                {
                    for (int j = 0; j < n_layer[i].n_neurons.Count; j++)
                    {
                        //For each Node in Layer that isn't final layer, connect it to every node in the next layer

                    }
                }
            }
        }

        public void FeedForward(List<int> inputVals)
        {

        }

        public void BackProp(List<int> targetVals)
        {

        }

        public void AddLayer(int numNeurons)
        {
            numLayers++;
            if (numLayers > 0) //If first layer
            {
                Layer layer = new Layer(numNeurons, numLayers, n_layer[numLayers - 1]);
                n_layer.Add(layer);
            }
            else
            {
                Layer layer = new Layer(numNeurons, numLayers);
                n_layer.Add(layer);
            }
        }

        public void Train(List<bool> testData)
        {
            Console.WriteLine("Training...");
            if (testData[0] == false)
            {
                Console.WriteLine("\t False");
            }
            else
            {
                Console.WriteLine("\t True");
            }
        }



        //-------------- Member Variables --------------//

        private List<Layer> n_layer = new List<Layer>(); // List of layers, layers are comprised of Neurons
        private int numLayers;
        double eta;
        double alpha;
    }


    public class Layer
    {
        // mumLayer is for debug purposes only
        public Layer(int numNeurons, int numLayer, Layer prevLayer = null) 
        {
            myLayer = numLayer;
            for (int i = 0; i <= numNeurons; ++i) // Add a bias Neuron
            {
                System.Console.Write(i + ": "); // Show line number for accurate Neuron count
                Neuron neuron = new Neuron(i);

                Console.WriteLine(" in layer #" + numLayer);
                n_neurons.Add(neuron);
            }

            if (prevLayer != null)
            {
                foreach (Neuron n in prevLayer)
                {

                }
            }
        }

        public List<Neuron> n_neurons = new List<Neuron>();
        int myLayer;
    }

    /**
    *   Neuron is a class that holds public information about Neurons
    *   This include weights, value, input and output locations.
    */
    public class Neuron
    {
        public Neuron(int index) // Constructor
        {
            myIndex = index;
            System.Console.Write("Creating Neuron " + myIndex);
        }



        private double transferFunction(double x)
        {
            return x;
        }

        private double transferFunctionDerivative(double x)
        {
            return x;
        }

        double randomWeight()
        {
            // set weights random
            Random r = new Random(0);
            return r.NextDouble() * 2 - 1.0;
        }

        public double Value { get; set; }   // Output value
        List<Connection> outPutWeights;     // Fpr each connection for the layer to the right
        public int numOutputs { set; get; } // This will be set when numLayers > 0;
        int myIndex;
        double eta;     // training rate
        double alpha;   // momentum
        double gradient;

        private double sumDOW(Layer nextLayer)
        {
            return 1;
        }
    }

    public class Connection
    {
        public double Weight { get; set; }
        public double DeltaWeight { get; set; }
    }
}

在教程中,他为每个神经元提供下一层神经元的数量。在我的代码中,我无法做到这一点,因为我一次添加一个图层。添加的第一层将是输入层,第二层到n-1层用于隐藏层,最后一层是输出层。

我很难绕过一个好的算法,这个算法可以遍历第一层中的每个神经元并将它们连接到第二层中的每个神经元,依此类推。我假设它需要递归并使用我的&#39; numLayers&#39;以某种方式变量。

正如您在我的使用代码中看到的那样,我打电话neuralNet.MakeConnections(),我很乐意添加连接,因为我添加了额外的图层;如果有人能够以这种方式看到一个好地方。

这是我最初的想法,但当我遇到困难时,我自己画了一张照片,并决定在这个功能中做它可能更简单。

提前感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

re:I am assuming it will need to be recursive

完全没有。对于额外变量numLayers也不是必需的,您已经知道使用n_layers.Count添加了多少层。

// in class NeuralNet
public void MakeConnections()
{
  // start at input layer, stop at last hidden layer
  for(int i=0; i<(n_layer.Count()-1); ++i)
  {
    Layer thisLayer = n_layer[i];   // only for typing convenience
    Layer nextLayer = n_layer[i+1];
    for(int n1=0; n1<thisLayer.n_neurons.Count(); ++n1)
    {
      Neuron thisNeuron = thisLayer.n_neurons[n1];
      for(int n2=0; n2<nextLayer.n_neurons.Count(); ++n2)
      {
        thisNeuron.outPutWeights.Add(
          new Connection(randomWeight(),randomWeight());
      }
    }
  }
}

如果您希望在添加图层时添加这些连接,则它可能如下所示:

// in class NeuralNet
public void AddLayer(int numNeurons)
{
  Layer layer = new Layer(numNeurons,
                          n_layers.Count(),
                          (n_layers.Count > 0)
                            ? n_layer[n_layers.Count-1]
                            : null);
  n_layers.Add(layer);
}

// in class Layer
public Layer(int numNeurons,
             int numLayer,
             Layer prevLayer = null)
{
  for (int i = 0; i <= numNeurons; ++i)
  {
    Neuron neuron = new Neuron(i);
    n_neurons.Add( neuron );
  }
  if (prevLayer != null)
  {
    for(int i=0; i<prevLayer.n_neurons.Count(); ++i)
    {
      for(int j=0; j<n_neurons.Count(); ++j)
      {
        prevLayer.n_neurons[i].outputWeights.Add(
          new Connection(randomWeight(), randomWeight() ) );
      }
    }
  }
}

当然,没有必要在两种风格中建立联系。你可以通过这种方式获得双重联系。只需使用MakeConnections一次性完成它们,或者即时执行它们。