将一层所有节点连接到下一层所有节点的算法



我正在尝试使用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();
    }
}

这是我为NeuralNet编写的其余代码,其中一些是伪代码,或者只是在我尝试连接工作时打印语句。

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层是隐藏层,最后一层是输出层。

我在想一个好的算法时遇到了很多麻烦,这个算法可以循环遍历第一层的每个神经元并将它们连接到第二层的每个神经元,以此类推。我假设它需要递归并以某种方式使用我的'numLayers'变量。

正如你在我的使用代码中看到的,我调用neuralNet.MakeConnections(),我对添加连接的想法持开放态度,因为我添加了额外的层;如果有人能找到一个好地方可以这样做。

这是我最初的想法,但当我卡住时,我给自己画了一张图,并决定在这个函数中做可能更简单。

提前感谢您的帮助!

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一次性完成它们,要么在飞行中完成它们。

最新更新