public void Populate(int size, AbstractInputFunction inputFunction = null, AbstractActivationFunction activationFunction = null) { for (int toFill = size - Neurons.Count(); toFill > 0; toFill--) { Neurons.Add(new Neuron(inputFunction, activationFunction)); } Size = Neurons.Count(); }
/// <summary> /// Mutates a random link whithin the neural network. /// </summary> public void MutateLink() { int from; int to; Stopwatch sw = new Stopwatch(); sw.Start(); do { rand = new Random(Guid.NewGuid().GetHashCode()); do { rand = new Random(Guid.NewGuid().GetHashCode()); from = rand.Next(Neurons.Count()); } while (from > NumInputs - 1 && from < NumInputs + NumOutputs); do { rand = new Random(Guid.NewGuid().GetHashCode()); to = rand.Next(NumInputs, Neurons.Count()); } while (to == from || to < NumInputs || (to < from && to >= NumInputs + NumOutputs)); if (sw.ElapsedMilliseconds > 10) { return; } } while (Connections.Contains(new Tuple <int, int>(from, to))); if (Neurons.TryGetValue(to, out Neuron toNeuron)) { if (Neurons.TryGetValue(from, out Neuron fromNeuron)) { Tuple <int, int> fromToPair = new Tuple <int, int>(from, to); Connection conn; if (InnovationNumbers.ContainsKey(fromToPair)) { lock (InnovationNumbers) { InnovationNumbers.TryGetValue(fromToPair, out int innoNumber); conn = new Connection(innoNumber, fromNeuron, rand.NextDouble() * 4 - 2); } } else { lock (InnovationNumbers) { conn = new Connection(InnovationNumbers.Count(), fromNeuron, rand.NextDouble() * 4 - 2); InnovationNumbers.Add(new Tuple <int, int>(from, to), InnovationNumbers.Count()); } } Connections.Add(fromToPair); toNeuron.AddConnection(conn.ID, conn); } } }
/// <summary> /// Returns a string in DOT language that can be used to visualize the neural network. /// </summary> /// <returns>A string in DOT language that can be used to visualize the neural network.</returns> public string GenerateDOT() { StringBuilder sb = new StringBuilder("digraph NeuralNetwork{\n"); sb.Append("subgraph cluster_level1{\nlabel = \"Inputs\";\n"); for (int i = 1; i < NumInputs; i++) { Neuron neur = Neurons.Values.ElementAt(i); sb.Append(neur.ID + ";\n"); } sb.Append("}\nsubgraph cluster_level3{\nlabel = \"Outputs\";\n"); for (int i = NumInputs; i < NumInputs + NumOutputs; i++) { Neuron neur = Neurons.Values.ElementAt(i); sb.Append(neur.ID + "[label=\"" + outputNames.ElementAt(i - NumInputs) + "\"];\n"); } sb.Append("}\nsubgraph cluster_level2{\nlabel = \"Hidden Layers\";\nrankdir=LR;\n"); for (int i = NumInputs + NumOutputs; i < Neurons.Count(); i++) { Neuron neur = Neurons.Values.ElementAt(i); sb.Append(neur.ID + ";\n"); } sb.Append("}\n"); foreach (Neuron neuron in Neurons.Values) { foreach (Connection conn in neuron.Connections.Values) { if (conn.Enabled) { sb.Append(conn.From.ID + " -> " + neuron.ID + "[label=\"" + Math.Round(conn.Weight, 3) + "\"];\n"); } else { sb.Append(conn.From.ID + " -> " + neuron.ID + "[label=\"" + Math.Round(conn.Weight, 3) + "\", style=dotted];\n"); } } } sb.Append("}"); return(sb.ToString()); }
/// <summary> /// Returns the count of all Neurons and all connections. /// </summary> /// <returns>The count of all neurons and all connections</returns> public int Size() { return(Connections.Count() + Neurons.Count()); }