I'm working on a neural networks project and I have 2 classes like this:
public class Net
{
// Net object is made of neurons
public List<Neuron> Neurons = new List<Neuron>();
// neurons are created in Net class constructor
public Net(int neuronCount, int neuronInputs)
{
for (int n = 0; n < neuronCount; n++)
{
Neurons.Add(new Neuron(n, neuronInputs));
}
}
}
public class Neuron
{
public int index; // neuron has index
public List<double> weights = new List<double>(); // and list of weights
// Neuron constructor is supposed to add random weights to new neuron
public Neuron(int neuronIndex, int neuronInputs)
{
Random rnd = new Random();
for (int i = 0; i < neuronInputs; i++)
{
this.index = neuronIndex;
this.weights.Add(rnd.NextDouble());
}
}
When I try to create network and display it's "contents":
Neuro.Net Network = new Neuro.Net(4, 4); // creating network with 4 neurons with 4 weights each
// dgv is a DataGridView for weights preview
dgv.Rows.Clear();
dgv.Columns.Clear();
// creating columns
foreach (Neuro.Neuron neuron in Network.Neurons)
{
dgv.Columns.Add("colN" + neuron.index, "N" + neuron.index);
}
dgv.Rows.Add(Network.Neurons[0].weights.Count());
for (int n = 0; n < Network.Neurons.Count(); n++)
{
for (int w = 0; w < Network.Neurons[n].weights.Count(); w++)
{
dgv.Rows[w].Cells[n].Value = Network.Neurons[n].weights[w];
}
}
When I run that code - I'm getting something like this (all weights are identical):
When I saw it - I tried to debug and find my mistake. However, when I put breakpoint in the neuron constructor - my network initializes as I want (weights are different):
I tried to use Debug and Release configurations - same results.
Can someone explain what is going on here?
Magic?
If a source file has changed and the source no longer matches the code you're debugging, the debugger won't set breakpoints in the code by default. Normally, this problem happens when a source file is changed, but the source code wasn't rebuilt. To fix this issue, rebuild the project.
NET Framework 2.0-based application. However, the Devenv.exe configuration files force the application to load as a . NET Framework 4.0-based application. Therefore, Visual Studio debugs the application in the wrong runtime, and this causes the breakpoints not to be hit.
Right mouse click your project. Select [Properties] Select the [Build] tab. Make sure [Define DEBUG constant] and [Define TRACE constant] are checked.
However, when I put breakpoint in neuron constructor - my network initializes as I want (neurons are diffrent):
Presumably, the breakpoint introduces enough of a delay for Random()
to be seeded with a different number. The delay can be caused by you pausing in the code (obviously) or even the non-matching evaluation of a conditional breakpoint (which slows execution slightly).
It would be better to have:
private static readonly Random _random = new Random();
And call _random.Next()
without creating a new instance, such as:
public Neuron(int neuronIndex, int neuronInputs)
{
for (int i = 0; i < neuronInputs; i++)
{
this.index = neuronIndex;
this.weights.Add(_random.NextDouble());
}
}
The parameterless constructor of Random uses Environment.TickCount
(hence the difference when a delay is introduced). You could also provide your own seed if you must create a new instance every time.
This behavior is documented here, specifically:
...because the clock has finite resolution, using the parameterless constructor to create different Random objects in close succession creates random number generators that produce identical sequences of random numbers. [...] This problem can be avoided by creating a single Random object rather than multiple ones.
Alternatively, you could use System.Security.Cryptography.RNGCryptoServiceProvider
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With