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)); } }
/// <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; }
/// <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); } }
/// <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); } }
/// <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); } }
/// <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) { }
/// <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) { }
/// <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); } }
/// <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); } }
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); }
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); }