Пример #1
0
        public void Analyze(IForecastingDataSets datasets)
        {
            if (ModelStartRunning != null)
            {
                ModelStartRunning(this, new ComponentRunEventArgs(datasets));
            }
            int learningRadius = Math.Max(mSOMParameter.LayerWidth, mSOMParameter.LayerHeight) / 2;

            KohonenLayer inputLayer  = new KohonenLayer(datasets.InputData[0].Length);
            KohonenLayer outputLayer = new KohonenLayer(new Size(mSOMParameter.LayerWidth, mSOMParameter.LayerHeight),
                                                        mSOMParameter.NeighborhoodFunction, mSOMParameter.Topology);
            KohonenConnector connector = new KohonenConnector(inputLayer, outputLayer);

            connector.Initializer = new RandomFunction(0, 100);
            outputLayer.SetLearningRate(mSOMParameter.LearningRate, mSOMParameter.FinalLearningRate);
            outputLayer.IsRowCircular    = mSOMParameter.IsRowCircular;
            outputLayer.IsColumnCircular = mSOMParameter.IsColumnCircular;
            mNetwork = new KohonenNetwork(inputLayer, outputLayer);

            mNetwork.EndEpochEvent += new TrainingEpochEventHandler(
                delegate(object senderNetwork, TrainingEpochEventArgs args)
            {
                if (ModelRunningEpoch != null)
                {
                    ModelRunningEpoch(this, new ComponentRunEpochEventArgs(args.TrainingIteration));
                }
            });
            mTrainingSet = ForecastingDataSets.ConvertToUnSupervisedTrainingSet(datasets);
            mNetwork.Learn(mTrainingSet, mSOMParameter.Iterations);

            if (ModelFinishRunning != null)
            {
                ModelFinishRunning(this, new ComponentRunEventArgs(datasets));
            }
        }
Пример #2
0
        /// <summary>
        /// Creates new positon neuron
        /// </summary>
        /// <param name="coordinate">
        /// Neuron Position
        /// </param>
        /// <param name="parent">
        /// Parent neuron containing this neuron
        /// </param>
        /// <value>
        /// If <c>parent</c> is <c>null</c>
        /// </value>
        public PositionNeuron(Point coordinate, KohonenLayer parent)
        {
            Helper.ValidateNotNull(parent, "parent");

            this.coordinate = coordinate;
            this.parent = parent;
            this.value = 0d;
        }
Пример #3
0
        /// <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(KohonenLayer layer, int currentIteration, int trainingEpochs)
        {
            Helper.ValidateNotNull(layer, "layer");
            Helper.ValidatePositive(trainingEpochs, "trainingEpochs");
            Helper.ValidateWithinRange(currentIteration, 0, trainingEpochs - 1, "currentIteration");

            // Winner co-ordinates
            int winnerX = layer.Winner.Coordinate.X;
            int winnerY = layer.Winner.Coordinate.Y;

            // Layer width and height
            int layerWidth  = layer.Size.Width;
            int layerHeight = layer.Size.Height;

            // 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
            foreach (PositionNeuron neuron in layer.Neurons)
            {
                int dx = System.Math.Abs(winnerX - neuron.Coordinate.X);
                int dy = System.Math.Abs(winnerY - neuron.Coordinate.Y);

                if (layer.IsRowCircular)
                {
                    dx = System.Math.Min(dx, layerWidth - dx);
                }
                if (layer.IsColumnCircular)
                {
                    dy = System.Math.Min(dy, layerHeight - dy);
                }

                double dxSquare = dx * dx;
                double dySquare = dy * dy;
                if (layer.Topology == LatticeTopology.Hexagonal)
                {
                    if (dy % 2 == 1)
                    {
                        dxSquare += 0.25 + (((neuron.Coordinate.X > winnerX) == (winnerY % 2 == 0))? dx: -dx);
                    }
                    dySquare *= 0.75;
                }
                neuron.neighborhoodValue = System.Math.Exp(-(dxSquare + dySquare) / twoSigmaSquare);
            }
        }
Пример #4
0
        /// <summary>
        /// 使用高斯函数确定给定的Kohonen层中相对于获胜者神经元的每个神经元的邻域
        /// </summary>
        /// <param name="layer">
        /// 含有神经元的Kohonen层
        /// </param>
        /// <param name="currentIteration">
        /// 当前训练迭代
        /// </param>
        /// <param name="trainingEpochs">
        /// 训练时期的总数
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// 如果<c> layer </ c>为<c> null </ c>
        /// </exception>
        /// <exception cref="ArgumentException">
        /// 如果<c> trainingEpochs </ c>为零或负值
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        /// 如果<c> currentIteration </ c>为负,或者如果它不小于<c> trainingEpochs </ c>
        /// </exception>
        public void EvaluateNeighborhood(KohonenLayer layer, int currentIteration, int trainingEpochs)
        {
            Helper.ValidateNotNull(layer, "layer");
            Helper.ValidatePositive(trainingEpochs, "trainingEpochs");
            Helper.ValidateWithinRange(currentIteration, 0, trainingEpochs - 1, "currentIteration");

            // 优胜者坐标
            int winnerX = layer.Winner.Coordinate.X;
            int winnerY = layer.Winner.Coordinate.Y;

            // 图层宽度和高度
            int layerWidth  = layer.Size.Width;
            int layerHeight = layer.Size.Height;

            // 随着训练的进行,Sigma值均匀地减小到零
            double currentSigma = sigma - ((sigma * currentIteration) / trainingEpochs);

            // 优化措施:预计算的2-Sigma-Square
            double twoSigmaSquare = 2 * currentSigma * currentSigma;

            // 评估和更新每个神经元的邻域值
            foreach (PositionNeuron neuron in layer.Neurons)
            {
                int dx = Math.Abs(winnerX - neuron.Coordinate.X);
                int dy = Math.Abs(winnerY - neuron.Coordinate.Y);

                if (layer.IsRowCircular)
                {
                    dx = Math.Min(dx, layerWidth - dx);
                }
                if (layer.IsColumnCircular)
                {
                    dy = Math.Min(dy, layerHeight - dy);
                }

                double dxSquare = dx * dx;
                double dySquare = dy * dy;
                if (layer.Topology == LatticeTopology.Hexagonal)
                {
                    if (dy % 2 == 1)
                    {
                        dxSquare += 0.25 + (((neuron.Coordinate.X > winnerX) == (winnerY % 2 == 0)) ? dx : -dx);
                    }
                    dySquare *= 0.75;
                }
                neuron.neighborhoodValue = Math.Exp(-(dxSquare + dySquare) / twoSigmaSquare);
            }
        }
Пример #5
0
        /// <summary>
        /// Determines the neighborhood of every neuron in the given Kohonen layer with respect to
        /// winner neuron using Mexican Hat 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(KohonenLayer layer, int currentIteration, int trainingEpochs)
        {
            Helper.ValidateNotNull(layer, "layer");
            Helper.ValidatePositive(trainingEpochs, "trainingEpochs");
            Helper.ValidateWithinRange(currentIteration, 0, trainingEpochs - 1, "currentIteration");

            // Winner co-ordinates
            int winnerX = layer.Winner.Coordinate.X;
            int winnerY = layer.Winner.Coordinate.Y;

            // Layer width and height
            int layerWidth  = layer.Size.Width;
            int layerHeight = layer.Size.Height;

            // 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 dx = System.Math.Abs(winnerX - neuron.Coordinate.X);
                int dy = System.Math.Abs(winnerY - neuron.Coordinate.Y);

                if (layer.IsRowCircular)
                {
                    dx = System.Math.Min(dx, layerWidth - dx);
                }
                if (layer.IsColumnCircular)
                {
                    dy = System.Math.Min(dy, layerHeight - dy);
                }

                double dxSquare = dx * dx;
                double dySquare = dy * dy;
                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 distanceBySigmaSquare = (dxSquare + dySquare) / sigmaSquare;
                neuron.neighborhoodValue = (1 - distanceBySigmaSquare) * System.Math.Exp(-distanceBySigmaSquare / 2);
            }
        }
Пример #6
0
 /// <summary>
 /// Creates new position neuron
 /// </summary>
 /// <param name="x">
 /// X-Coordinate of the neuron positon
 /// </param>
 /// <param name="y">
 /// Y-Coordinate of the neuron position
 /// </param>
 /// <param name="parent">
 /// Parent layer containing this neuron
 /// </param>
 /// <exception cref="ArgumentNullException">
 /// If <c>parent</c> is <c>null</c>
 /// </exception>
 public PositionNeuron(int x, int y, KohonenLayer parent)
     : this(new Point(x, y), parent)
 {
 }
Пример #7
0
 /// <summary>
 /// Creates a new Kohonen SOM, with the specified input and output layers. (You are required
 /// to connect all layers using appropriate synapses, before using the constructor. Any changes
 /// made to the structure of the network here-after, may lead to complete malfunctioning of the
 /// network)
 /// </summary>
 /// <param name="inputLayer">
 /// The input layer
 /// </param>
 /// <param name="outputLayer">
 /// The output layer
 /// </param>
 /// <exception cref="ArgumentNullException">
 /// If <c>inputLayer</c> or <c>outputLayer</c> is <c>null</c>
 /// </exception>
 public KohonenNetwork(ILayer inputLayer, KohonenLayer outputLayer)
     : base(inputLayer, outputLayer, TrainingMethod.Unsupervised)
 {
 }
Пример #8
0
        /// <summary>
        /// Determines the neighborhood of every neuron in the given Kohonen layer with respect to
        /// winner neuron using Mexican Hat 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(KohonenLayer layer, int currentIteration, int trainingEpochs)
        {
            Helper.ValidateNotNull(layer, "layer");
            Helper.ValidatePositive(trainingEpochs, "trainingEpochs");
            Helper.ValidateWithinRange(currentIteration, 0, trainingEpochs - 1, "currentIteration");

            // Winner co-ordinates
            int winnerX = layer.Winner.Coordinate.X;
            int winnerY = layer.Winner.Coordinate.Y;

            // Layer width and height
            int layerWidth = layer.Size.Width;
            int layerHeight = layer.Size.Height;

            // 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 dx = Math.Abs(winnerX - neuron.Coordinate.X);
                int dy = Math.Abs(winnerY - neuron.Coordinate.Y);

                if (layer.IsRowCircular)
                {
                    dx = Math.Min(dx, layerWidth - dx);
                }
                if (layer.IsColumnCircular)
                {
                    dy = Math.Min(dy, layerHeight - dy);
                }

                double dxSquare = dx * dx;
                double dySquare = dy * dy;
                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 distanceBySigmaSquare = (dxSquare + dySquare) / sigmaSquare;
                neuron.neighborhoodValue = (1 - distanceBySigmaSquare) * Math.Exp(-distanceBySigmaSquare / 2);
            }
        }
Пример #9
0
        /// <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(KohonenLayer layer, int currentIteration, int trainingEpochs)
        {
            Helper.ValidateNotNull(layer, "layer");
            Helper.ValidatePositive(trainingEpochs, "trainingEpochs");
            Helper.ValidateWithinRange(currentIteration, 0, trainingEpochs - 1, "currentIteration");

            // Winner co-ordinates
            int winnerX = layer.Winner.Coordinate.X;
            int winnerY = layer.Winner.Coordinate.Y;

            // Layer width and height
            int layerWidth = layer.Size.Width;
            int layerHeight = layer.Size.Height;

            // 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
            foreach (PositionNeuron neuron in layer.Neurons)
            {
                int dx = Math.Abs(winnerX - neuron.Coordinate.X);
                int dy = Math.Abs(winnerY - neuron.Coordinate.Y);

                if (layer.IsRowCircular)
                {
                    dx = Math.Min(dx, layerWidth - dx);
                }
                if (layer.IsColumnCircular)
                {
                    dy = Math.Min(dy, layerHeight - dy);
                }

                double dxSquare = dx * dx;
                double dySquare = dy * dy;
                if (layer.Topology == LatticeTopology.Hexagonal)
                {
                    if (dy % 2 == 1)
                    {
                        dxSquare += 0.25 + (((neuron.Coordinate.X > winnerX )== (winnerY % 2 ==0))? dx: -dx);
                    }
                    dySquare *= 0.75;
                }
                neuron.neighborhoodValue = Math.Exp(-(dxSquare + dySquare) / twoSigmaSquare);
            }
        }
Пример #10
0
        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);
        }
Пример #11
0
        void Solve()
        {
            CrowNetP NetP = new CrowNetP();

            if (netUP.netType == "som")
            {
                #region self organizing maps

                #region prepare and assign
                trainingSet.Clear();
                int trainVectorDimension = 3;
                if (trainDataArePoints)
                {
                    for (int i = 0; i < pointsList.Count; i++)
                    {
                        trainingSet.Add(new TrainingSample(new double[] { pointsList[i].Value.X, pointsList[i].Value.Y, pointsList[i].Value.Z }));
                    }
                }
                else
                {
                    trainVectorDimension = trainingVectorTree.Branches[0].Count;
                    trainingSet          = new TrainingSet(trainVectorDimension);
                    for (int i = 0; i < trainingVectorTree.Branches.Count; i++)
                    {
                        double[] values = new double[trainVectorDimension];

                        for (int j = 0; j < trainVectorDimension; j++)
                        {
                            values[j] = trainingVectorTree.Branches[i][j].Value;
                        }

                        trainingSet.Add(new TrainingSample(values));
                    }
                }


                ///  process
                ///  start learning

                int learningRadius = Math.Max(layerWidth, layerHeight) / 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;
                }

                KohonenLayer     inputLayer  = new KohonenLayer(trainVectorDimension);
                KohonenLayer     outputLayer = new KohonenLayer(new Size(layerWidth, layerHeight), neighborhoodFunction, topology);
                KohonenConnector connector   = new KohonenConnector(inputLayer, outputLayer);
                connector.Initializer = randomizer;

                outputLayer.SetLearningRate(learningRate, 0.05d);
                outputLayer.IsRowCircular    = isCircularRows;
                outputLayer.IsColumnCircular = isCircularColumns;
                network = new KohonenNetwork(inputLayer, outputLayer);
                network.useRandomTrainingOrder = opt.UseRandomTraining;
                #endregion

                #region delegates
                network.BeginEpochEvent += new TrainingEpochEventHandler(
                    delegate(object senderNetwork, TrainingEpochEventArgs args)
                {
                    #region TrainingCycle
                    if (network == null || !GO)
                    {
                        return;
                    }


                    int iPrev     = layerWidth - 1;
                    allValuesTree = new GH_Structure <GH_Number>();
                    for (int i = 0; i < layerWidth; i++)
                    {
                        for (int j = 0; j < layerHeight; j++)
                        {
                            IList <ISynapse> synapses = (network.OutputLayer as KohonenLayer)[i, j].SourceSynapses;
                            double x = synapses[0].Weight;
                            double y = synapses[1].Weight;
                            double z = synapses[2].Weight;

                            for (int k = 0; k < trainVectorDimension; k++)
                            {
                                allValuesTree.Append(new GH_Number(synapses[k].Weight), new GH_Path(i, j));
                            }

                            rowX[j][i]    = x;
                            rowY[j][i]    = y;
                            rowZ[j][i]    = z;
                            columnX[i][j] = x;
                            columnY[i][j] = y;
                            columnZ[i][j] = z;

                            if (j % 2 == 1)
                            {
                                hexagonalX[i][j] = x;
                                hexagonalY[i][j] = y;
                                hexagonalZ[i][j] = z;
                            }
                            else
                            {
                                hexagonalX[iPrev][j] = x;
                                hexagonalY[iPrev][j] = y;
                                hexagonalZ[iPrev][j] = z;
                            }
                        }
                        iPrev = i;
                    }

                    if (isCircularRows)
                    {
                        for (int i = 0; i < layerHeight; i++)
                        {
                            rowX[i][layerWidth] = rowX[i][0];
                            rowY[i][layerWidth] = rowY[i][0];
                            rowZ[i][layerWidth] = rowZ[i][0];
                        }
                    }

                    if (isCircularColumns)
                    {
                        for (int i = 0; i < layerWidth; i++)
                        {
                            columnX[i][layerHeight]    = columnX[i][0];
                            columnY[i][layerHeight]    = columnY[i][0];
                            columnZ[i][layerHeight]    = columnZ[i][0];
                            hexagonalX[i][layerHeight] = hexagonalX[i][0];
                            hexagonalY[i][layerHeight] = hexagonalY[i][0];
                            hexagonalZ[i][layerHeight] = hexagonalZ[i][0];
                        }
                    }

                    Array.Clear(isWinner, 0, layerHeight * layerWidth);

                    #endregion
                    NetP = new CrowNetP("som", layerWidth, layerHeight, isCircularRows, isCircularColumns, latticeTopology, neighborhood, isWinner, rowX, rowY, rowZ, columnX, columnY, columnZ, hexagonalX, hexagonalY, hexagonalZ, allValuesTree);
                    counter++;
                });

                network.EndSampleEvent += new TrainingSampleEventHandler(
                    delegate(object senderNetwork, TrainingSampleEventArgs args)
                {
                    isWinner[network.Winner.Coordinate.X, network.Winner.Coordinate.Y] = true;
                });
                #endregion

                #endregion
            }

            network.Learn(trainingSet, cycles);
        }