The deep neural network constructor begins by copying its input parameter values to the corresponding class members:
public DeepNeuralNetwork(int numInput, int numHiddenA, int numHiddenB, int numOutput) { this.numInput = numInput; this.numHiddenA = numHiddenA; this.numHiddenB = numHiddenB; this.numOutput = numOutput;
Next, space for the inputs array is allocated:
inputs = new double[numInput];
Then space for the three weights matrices is allocated, using helper method MakeMatrix:
iaWeights = MakeMatrix(numInput, numHiddenA); abWeights = MakeMatrix(numHiddenA, numHiddenB); boWeights = MakeMatrix(numHiddenB, numOutput);
Method MakeMatrix is defined as:
private static double[][] MakeMatrix(int rows, int cols) { double[][] result = new double[rows][]; for (int r = 0; r < result.Length; ++r) result[r] = new double[cols]; return result; }
The constructor allocates space for the three biases arrays:
aBiases = new double[numHiddenA]; bBiases = new double[numHiddenB]; oBiases = new double[numOutput];
Next, the local and final output arrays are allocated:
aOutputs = new double[numHiddenA]; bOutputs = new double[numHiddenB]; outputs = new double[numOutput];
The constructor concludes by instantiating the Random object and then calling helper method InitializeWeights:
rnd = new Random(0); InitializeWeights(); } // ctor
Method InitializeWeights is defined as:
private void InitializeWeights() { int numWeights = (numInput * numHiddenA) + numHiddenA + (numHiddenA * numHiddenB) + numHiddenB + (numHiddenB * numOutput) + numOutput; double[] weights = new double[numWeights]; double lo = -0.01; double hi = 0.01; for (int i = 0; i < weights.Length; ++i) weights[i] = (hi - lo) * rnd.NextDouble() + lo; this.SetWeights(weights); }
Method InitializeWeights assigns random values in the interval -0.01 to
+0.01 to each weight and bias variable. You might want to pass the
interval values in as parameters to InitializeWeights. If you refer back
to Listing 1, you'll notice that the Main method calls method
SetWeights immediately after the DeepNeuralNetwork constructor is
called, which means that initial random weights and bias values are
immediately overwritten. However, in a normal, non-demo scenario where
SetWeights isn't called in the Main method, initializing weights and
bias values is almost always necessary.