public void Epoch(KPoint p) { //get a random item SOMNeuron bmu = GetBestMatchingUnit(p); neighborhoodRadius = radius * Math.Exp(-(double)itterations / timeConstant); double neighborSqr = neighborhoodRadius * neighborhoodRadius; QuadTreePointStruct center = new QuadTreePointStruct() { Index = -1, X = bmu.position[0], Y = bmu.position[1] }; QuadTreePointStruct halfLength = new QuadTreePointStruct() { Index = -1, X = neighborhoodRadius, Y = neighborhoodRadius }; List <int> neuronsInArea = neuronQuadTree.QueryRange(new QuadTreeBoundingBox() { Center = center, HalfLength = halfLength }); //Now we need to update each neuron foreach (int i in neuronsInArea) { SOMNeuron n = neurons[i]; double distToBMU = n.position.elucideanDistance(bmu.position); if (distToBMU <= neighborhoodRadius) { influence = Math.Exp(-(distToBMU * distToBMU) / (2 * neighborSqr)); n.updateWeights(p, learningRate, influence); } } learningRate = this.initialLearningRate * Math.Exp(-(double)itterations / (double)this.totalItterations); itterations++; }
public HexagonalSelfOrganizingMap(PointSet data, int dimension, double learningRate) { _dimension = dimension; //Get initial learning rate this.initialLearningRate = learningRate; this.learningRate = learningRate; influence = 0; itterations = 1; this.data = data; rng = new Random(); int numNeurons = dimension * dimension; //Scale each attribute from [0,1] and store the conversion matrix conversionMatrix = data.GetMinMaxWeights().Max.Coordinates; foreach (KPoint d in data.PointList) { d.Normalize(conversionMatrix); } //Here We will initialize Our Neurons neurons = new List <SOMNeuron>(); KPoint zero = KPoint.Zero(data[0].Dimensions); KPoint one = KPoint.One(data[0].Dimensions); double halfNeuronDelta = 1 / Math.Sqrt(3.0); //Initialize our Quadtree for reference double centerX = (dimension - 0.5) * (2 * halfNeuronDelta) / 2.0; double centerY = (dimension - 1.0) / 2.0; QuadTreePointStruct center = new QuadTreePointStruct() { Index = -1, X = centerX, Y = centerY }; QuadTreePointStruct halfDistance = new QuadTreePointStruct() { Index = -1, X = centerX + halfNeuronDelta, Y = centerY + 0.5 }; neuronQuadTree = new QuadTree(new QuadTreeBoundingBox() { Center = center, HalfLength = halfDistance }); int neuronIndex = 0; for (int r = 0; r < dimension; r++) { double xPos = (r % 2 == 1) ? halfNeuronDelta : 0.0; for (int c = 0; c < dimension; c++) { //Generate our neurons double[] posNeuron = { xPos, (double)r }; SOMNeuron neuron = new SOMNeuron(zero, one, rng, new KPoint(posNeuron), neuronIndex); QuadTreePointStruct neuronQTPos = new QuadTreePointStruct() { Index = neuronIndex, X = posNeuron[0], Y = posNeuron[1] }; neuronQuadTree.Insert(neuronQTPos); neurons.Add(neuron); xPos += 2 * halfNeuronDelta; neuronIndex++; } } //Get the max radius SetRadius(); timeConstant = (double)totalItterations / Math.Log(radius); }