public void ConstructorTest() { // Create a Bernoulli function with sigmoid's alpha = 1 BernoulliFunction function = new BernoulliFunction(); // Computes the function output (sigmoid function) double y = function.Function(x: 0.4); // 0.5986876 // Draws a sample from a Bernoulli distribution with // mean given by the function output y (given as before) double z = function.Generate(x: 0.4); // (random, 0 or 1) // Here, z can be either 0 or 1. Since it follows a Bernoulli // distribution with mean 0.59, it is expected to be 1 about // 0.59 of the time. // Now, please note that the above is completely equivalent // to computing the line below (remember, 0.5986876 == y) double w = function.Generate2(y: 0.5986876); // (random, 0 or 1) // We can also compute the derivative of the sigmoid function double d = function.Derivative(x: 0.4); // 0.240260 // Or compute the derivative given the functions' output y double e = function.Derivative2(y: 0.5986876); // 0.240260 Assert.AreEqual(0.5986876, y, 1e-7); Assert.AreEqual(0.2402607, d, 1e-7); Assert.AreEqual(0.2402607, e, 1e-7); }
public void NetworkTest2() { // Create some sample inputs and outputs. Note that the // first four vectors belong to one class, and the other // four belong to another (you should see that the 1s // accumulate on the beginning for the first four vectors // and on the end for the second four). double[][] inputs = { new double[] { 1,1,1,0,0,0 }, // class a new double[] { 1,0,1,0,0,0 }, // class a new double[] { 1,1,1,0,0,0 }, // class a new double[] { 0,0,1,1,1,0 }, // class b new double[] { 0,0,1,1,0,0 }, // class b new double[] { 0,0,1,1,1,0 }, // class b }; double[][] outputs = { new double[] { 1, 0 }, // indicates the inputs at this new double[] { 1, 0 }, // position belongs to class a new double[] { 1, 0 }, new double[] { 0, 1 }, // indicates the inputs at this new double[] { 0, 1 }, // position belongs to class b new double[] { 0, 1 }, }; // Create a Bernoulli activation function var function = new BernoulliFunction(alpha: 0.5); // Create a Restricted Boltzmann Machine for 6 inputs and with 1 hidden neuron var rbm = new RestrictedBoltzmannMachine(function, inputsCount: 6, hiddenNeurons: 2); // Create the learning algorithm for RBMs var teacher = new ContrastiveDivergenceLearning(rbm) { Momentum = 0, LearningRate = 0.1, Decay = 0 }; // learn 5000 iterations for (int i = 0; i < 5000; i++) teacher.RunEpoch(inputs); // Compute the machine answers for the given inputs: double[] a = rbm.Compute(new double[] { 1, 1, 1, 0, 0, 0 }); // { 0.99, 0.00 } double[] b = rbm.Compute(new double[] { 0, 0, 0, 1, 1, 1 }); // { 0.00, 0.99 } // As we can see, the first neuron responds to vectors belonging // to the first class, firing 0.99 when we feed vectors which // have 1s at the beginning. Likewise, the second neuron fires // when the vector belongs to the second class. // We can also generate input vectors given the classes: double[] xa = rbm.GenerateInput(new double[] { 1, 0 }); // { 1, 1, 1, 0, 0, 0 } double[] xb = rbm.GenerateInput(new double[] { 0, 1 }); // { 0, 0, 1, 1, 1, 0 } // As we can see, if we feed an output pattern where the first neuron // is firing and the second isn't, the network generates an example of // a vector belonging to the first class. The same goes for the second // neuron and the second class. Assert.IsTrue(((a[0] > a[1]) && (b[0] < b[1])) ^ ((a[0] < a[1]) && (b[0] > b[1]))); }
public void RunTest() { // Example from Edwin Chen, Introduction to Restricted Boltzmann Machines // http://blog.echen.me/2011/07/18/introduction-to-restricted-boltzmann-machines/ double[][] inputs = { new double[] { 1,1,1,0,0,0 }, new double[] { 1,0,1,0,0,0 }, new double[] { 1,1,1,0,0,0 }, new double[] { 0,0,1,1,1,0 }, new double[] { 0,0,1,1,0,0 }, new double[] { 0,0,1,1,1,0 } }; BernoulliFunction activation = new BernoulliFunction(); BernoulliFunction.Random = new ThreadSafeRandom(2); RestrictedBoltzmannMachine network = new RestrictedBoltzmannMachine(activation, 6, 2); network.Hidden.Neurons[0].Weights[0] = 0.00461421; network.Hidden.Neurons[0].Weights[1] = 0.04337112; network.Hidden.Neurons[0].Weights[2] = -0.10839599; network.Hidden.Neurons[0].Weights[3] = -0.06234004; network.Hidden.Neurons[0].Weights[4] = -0.03017057; network.Hidden.Neurons[0].Weights[5] = 0.09520391; network.Hidden.Neurons[0].Threshold = 0; network.Hidden.Neurons[1].Weights[0] = 0.08263872; network.Hidden.Neurons[1].Weights[1] = -0.118437; network.Hidden.Neurons[1].Weights[2] = -0.21710971; network.Hidden.Neurons[1].Weights[3] = 0.02332903; network.Hidden.Neurons[1].Weights[4] = 0.00953116; network.Hidden.Neurons[1].Weights[5] = 0.09870652; network.Hidden.Neurons[1].Threshold = 0; network.Visible.Neurons[0].Threshold = 0; network.Visible.Neurons[1].Threshold = 0; network.Visible.Neurons[2].Threshold = 0; network.Visible.Neurons[3].Threshold = 0; network.Visible.Neurons[4].Threshold = 0; network.Visible.Neurons[5].Threshold = 0; network.Visible.CopyReversedWeightsFrom(network.Hidden); ContrastiveDivergenceLearning target = new ContrastiveDivergenceLearning(network); target.Momentum = 0; target.LearningRate = 0.1; target.Decay = 0; int iterations = 5000; double[] errors = new double[iterations]; for (int i = 0; i < iterations; i++) errors[i] = target.RunEpoch(inputs); double startError = errors[0]; double lastError = errors[iterations - 1]; Assert.IsTrue(startError > lastError); Assert.AreEqual(9.5400234262580224, startError); Assert.AreEqual(1.3364496250348414, lastError, 1e-10); { double[] output = network.GenerateOutput(new double[] { 0, 0, 0, 1, 1, 0 }); Assert.AreEqual(2, output.Length); Assert.AreEqual(0, output[0]); Assert.AreEqual(1, output[1]); } { double[] output = network.GenerateOutput(new double[] { 1, 1, 1, 0, 0, 0 }); Assert.AreEqual(2, output.Length); Assert.AreEqual(1, output[0]); Assert.AreEqual(0, output[1]); } }