/// <summary> /// Determines the neighborhood of every neuron in the given Kohonen layer with respect to /// winner neuron using Gaussian function /// </summary> /// <param name="layer"> /// The Kohonen Layer containing neurons /// </param> /// <param name="currentIteration"> /// Current training iteration /// </param> /// <param name="trainingEpochs"> /// Total number of training epochs /// </param> /// <exception cref="ArgumentNullException"> /// If <c>layer</c> is <c>null</c> /// </exception> /// <exception cref="ArgumentException"> /// If <c>trainingEpochs</c> is zero or negative /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// If <c>currentIteration</c> is negative or, if it is not less than <c>trainingEpochs</c> /// </exception> public void EvaluateNeighborhood(KohonenLayerND layer, int currentIteration, int trainingEpochs) { Helper.ValidateNotNull(layer, "layer"); Helper.ValidatePositive(trainingEpochs, "trainingEpochs"); Helper.ValidateWithinRange(currentIteration, 0, trainingEpochs - 1, "currentIteration"); // Winner co-ordinates int[] winner = layer.WinnerND.CoordinateND; // Layer width and height int[] size = layer.Size; // Sigma value uniformly decreases to zero as training progresses double currentSigma = sigma - ((sigma * currentIteration) / trainingEpochs); // Optimization measure: Pre-calculated 2-Sigma-Square double twoSigmaSquare = 2 * currentSigma * currentSigma; //// Evaluate and update neighborhood value of each neuron if (!layer.ParallelComputation) { foreach (PositionNeuron neuron in layer.Neurons) { int[] dD = new int[winner.Length]; for (int i = 0; i < winner.Length; i++) { dD[i] = Math.Abs(winner[i] - neuron.CoordinateND[i]); } // TO DO!!! /* * if (layer.IsRowCircular) * { * dx = Math.Min(dx, layerWidth - dx); * } * if (layer.IsColumnCircular) * { * dy = Math.Min(dy, layerHeight - dy); * } * */ double[] dDSquares = new double[winner.Length]; for (int i = 0; i < dD.Length; i++) { dDSquares[i] = dD[i] * dD[i]; } /*if (layer.Topology == LatticeTopology.Hexagonal) * * { * if (dy % 2 == 1) * { * dxSquare += 0.25 + (((neuron.Coordinate.X > winnerX) == (winnerY % 2 == 0)) ? dx : -dx); * } * dySquare *= 0.75; * }*/ double dSum = 0.0; for (int i = 0; i < dDSquares.Length; i++) { if (euclideanNeighborDistance) { dSum += dDSquares[i]; } else { dSum += dD[i]; } } if (!euclideanNeighborDistance) { dSum *= dSum; } neuron.neighborhoodValue = Math.Exp(-(dSum) / twoSigmaSquare); } } else { var neurons = layer.Neurons.ToList(); ParallelOptions opt = new ParallelOptions(); opt.MaxDegreeOfParallelism = System.Environment.ProcessorCount; Parallel.For(0, layer.NeuronCount, opt, index => { int[] dD = new int[winner.Length]; for (int i = 0; i < winner.Length; i++) { dD[i] = Math.Abs(winner[i] - neurons[index].CoordinateND[i]); } // TO DO!!! /* * if (layer.IsRowCircular) * { * dx = Math.Min(dx, layerWidth - dx); * } * if (layer.IsColumnCircular) * { * dy = Math.Min(dy, layerHeight - dy); * } */ double[] dDSquares = new double[winner.Length]; for (int i = 0; i < dD.Length; i++) { dDSquares[i] = dD[i] * dD[i]; } /*if (layer.Topology == LatticeTopology.Hexagonal) * * { * if (dy % 2 == 1) * { * dxSquare += 0.25 + (((neuron.Coordinate.X > winnerX) == (winnerY % 2 == 0)) ? dx : -dx); * } * dySquare *= 0.75; * }*/ double dSum = 0.0; for (int i = 0; i < dDSquares.Length; i++) { if (euclideanNeighborDistance) { dSum += dDSquares[i]; } else { dSum += dD[i]; } } if (!euclideanNeighborDistance) { dSum *= dSum; } neurons[index].neighborhoodValue = Math.Exp(-(dSum) / twoSigmaSquare); }); } }
void Solve() { #region prepare and assign trainingSet.Clear(); for (int i = 0; i < trainVectorCount; i++) { List <double> dl = new List <double>(); for (int j = 0; j < trainVectorDimension; j++) { dl.Add(trainVectors[i][j]); } trainingSet.Add(new TrainingSample(dl.ToArray())); } /// process /// start learning /// get learning radius for neighborhood function int learningRadius = 0; for (int i = 0; i < dimension; i++) { if (size[i] > learningRadius) { learningRadius = size[i]; } } learningRadius /= 2; INeighborhoodFunction neighborhoodFunction = new GaussianFunction(learningRadius, netUP.neighborDistance) as INeighborhoodFunction; if (neighborhood) { neighborhoodFunction = new MexicanHatFunction(learningRadius) as INeighborhoodFunction; } LatticeTopology topology = LatticeTopology.Rectangular; if (latticeTopology) { topology = LatticeTopology.Hexagonal; } /// instantiate relevant network layers KohonenLayer inputLayer = new KohonenLayer(trainVectorDimension); KohonenLayerND outputLayer = new KohonenLayerND(size, neighborhoodFunction, topology); KohonenConnectorND connector = new KohonenConnectorND(inputLayer, outputLayer, netUP.initialNodes); if (netUP.initialNodes.Length != 0) { connector.Initializer = new GivenInput(netUP.initialNodes); } else { connector.Initializer = new RandomFunction(0.0, 1.0); } outputLayer.SetLearningRate(learningRate, 0.05d); outputLayer.IsDimensionCircular = isDimensionCircular; network = new KohonenNetworkND(inputLayer, outputLayer); network.useRandomTrainingOrder = randomTrainingOrder; inputLayer.ParallelComputation = false; outputLayer.ParallelComputation = parallelComputing; #endregion #region delegates network.BeginEpochEvent += new TrainingEpochEventHandler( delegate(object senderNetwork, TrainingEpochEventArgs args) { #region trainingCylce if (network == null || !GO) { return; } trainedVectors = new double[outputLayer.neuronCount, trainVectorDimension]; for (int i = 0; i < outputLayer.neuronCount; i++) { IList <ISynapse> synapses = (network.OutputLayer as KohonenLayerND)[outputLayer.adressBook[i]].SourceSynapses; for (int j = 0; j < trainVectorDimension; j++) { trainedVectors[i, j] = synapses[j].Weight; } } //make new net here netP = new CrowNetSOMNDP(size, isDimensionCircular, latticeTopology, neighborhood, trainedVectors, outputLayer.adressBook); counter++; #endregion }); network.EndSampleEvent += new TrainingSampleEventHandler( delegate(object senderNetwork, TrainingSampleEventArgs args) { netP.winner = outputLayer.WinnerND.CoordinateND; }); #endregion network.Learn(trainingSet, cycles); }
public void EvaluateNeighborhood(KohonenLayerND layer, int currentIteration, int trainingEpochs) { Helper.ValidateNotNull(layer, "layer"); Helper.ValidatePositive(trainingEpochs, "trainingEpochs"); Helper.ValidateWithinRange(currentIteration, 0, trainingEpochs - 1, "currentIteration"); // Winner co-ordinates int[] winner = layer.WinnerND.CoordinateND; // Layer width and height int[] size = layer.Size; // Optimization: Pre-calculated 2-Sigma-Square (1e-9 to make sure it is non-zero) double sigmaSquare = sigma * sigma + 1e-9; // Evaluate and update neighborhood value of each neuron foreach (PositionNeuron neuron in layer.Neurons) { int[] dD = new int[winner.Length]; for (int i = 0; i < winner.Length; i++) { dD[i] = Math.Abs(winner[i] - neuron.CoordinateND[i]); } /// TO DO!!! /*if (layer.IsDimensionCircular[0]) * { * dx = Math.Min(dx, layerWidth - dx); * } * if (layer.IsDimensionCircular[1]) * { * dy = Math.Min(dy, layerHeight - dy); * }*/ double[] dDSquares = new double[winner.Length]; for (int i = 0; i < dD.Length; i++) { dDSquares[i] = dD[i] * dD[i]; } /* * if (layer.Topology == LatticeTopology.Hexagonal) * { * if (dy % 2 == 1) * { * dxSquare += 0.25 + (((neuron.Coordinate.X > winnerX) == (winnerY % 2 == 0)) ? dx : -dx); * } * dySquare *= 0.75; * }*/ double dSum = 0.0; for (int i = 0; i < dDSquares.Length; i++) { dSum += dDSquares[i]; } double distanceBySigmaSquare = dSum / sigmaSquare; // double distanceBySigmaSquare = (dxSquare + dySquare) / sigmaSquare; neuron.neighborhoodValue = (1 - distanceBySigmaSquare) * Math.Exp(-distanceBySigmaSquare / 2); } }