public DrinksSelfOrganizingMap(Node[] neuralNet, int neuralMapWidth, int neuralMapHeight, float distanceBetweenNeurons, double vectorQuantizationError, double vectorQuantizationErrorStandardDeviation) { NeuralNet = neuralNet; NeuralMapWidth = neuralMapWidth; NeuralMapHeight = neuralMapHeight; DistanceBetweenNeurons = distanceBetweenNeurons; VectorQuantizationError = vectorQuantizationError; VectorQuantizationErrorStandardDeviation = vectorQuantizationErrorStandardDeviation; nodesByDrinkIdDictionary = ComputeNodesByDrinkIdDictionary(neuralNet); nodesByCoordinatesDictionary = ComputeNodesByCoordinatesDictionary(neuralNet); }
private Node[] ComputeNearestDrinks(Node[] neuralNet) { int counter = 0; foreach (Node node in neuralNet) { int nearestDrinkID = GetNearestDrink(node.Weights); if (nearestDrinkID != node.DrinkID) { node.DrinkID = nearestDrinkID; counter++; } } return neuralNet; }
private Dictionary<PointF, int> ComputeNodesByCoordinatesDictionary(Node[] nodesArray) { Dictionary<PointF, int> result = new Dictionary<PointF, int>(); foreach (Node node in nodesArray) { result.Add(new PointF(node.X, node.Y), node.DrinkID); } return result; }
private Dictionary<int, List<PointF>> ComputeNodesByDrinkIdDictionary(Node[] nodesArray) { Dictionary<int, List<PointF>> result = new Dictionary<int, List<PointF>>(); foreach (Node node in nodesArray) { if (!result.ContainsKey(node.DrinkID)) result.Add(node.DrinkID, new List<PointF>()); result[node.DrinkID].Add(new PointF(node.X, node.Y)); } return result; }
private Node[] Epoch(int t, Drink inputDrink, Node[] nodesArray) { BestMatchingNodeMultiThreadedSearcher bestMatchingNodeMultiThreadedSearcher = new BestMatchingNodeMultiThreadedSearcher(nodesArray, processorsCount, inputDrink.FeaturesArray); int winningNodeIndex = bestMatchingNodeMultiThreadedSearcher.GetBestMatchingNodeIndex(); double neighbourhoodRadius = Radius(t); double learningRate = LearningRate(t); potentialsArray[winningNodeIndex] -= (_minNeuronPotential + maxNeuronRestTimeInv); UpdatePotentialsArray(maxNeuronRestTimeInv); System.Threading.Tasks.Parallel.ForEach(nodesArray, node => { double theta = Theta(t, nodesArray[winningNodeIndex], node, neighbourhoodRadius); if (theta > 0) { node.AdjustWeights(theta, learningRate, inputDrink.FeaturesArray); node.DrinkID = inputDrink.ID; } }); return nodesArray; }
private void FindBestMatchingNodes(Node[] neuralNet, double[] inputVector) { List<Thread> list_threads = new List<Thread>(); int chunkFactor = processorsCount; int chunkLength = ((neuralNet.Length % chunkFactor) == 0) ? neuralNet.Length / chunkFactor : ((int)((neuralNet.Length) / ((float)chunkFactor)) + 1); int remaining = neuralNet.Length; int currentRow = 0; int threadIndex = 0; while (remaining > 0) { if (remaining < chunkLength) chunkLength = remaining; remaining -= chunkLength; int t_currentRow = currentRow, t_chunkLength = chunkLength, t_boundaryRow = t_currentRow + t_chunkLength, t_threadIndex = threadIndex; Thread thread = new Thread(() => FindBestMatchingNodeThread(neuralNet, t_currentRow, t_boundaryRow, t_threadIndex, inputVector)); list_threads.Add(thread); thread.Start(); currentRow += chunkLength; threadIndex ++; } list_threads.ForEach(t => t.Join()); }
private void FindBestMatchingNodeThread(Node[] neuralNet, int startIndex, int endIndex, int threadIndex, double[] inputVector) { int bestMatchingNodeIndex = 0; double bestDistance = double.MaxValue; for(int i = startIndex; i < endIndex; i++) { double distance = neuralNet[i].Weights.GetDistance(inputVector); if (distance < bestDistance && potentialsArray[i] > _minNeuronPotential) { bestDistance = distance; bestMatchingNodeIndex = i; } } bestMatchingNodes[threadIndex] = new Tuple<int, double>(bestMatchingNodeIndex, bestDistance); }
public BestMatchingNodeMultiThreadedSearcher(Node[] neuralNet, int processorsCount, double[] inputVector) { this.processorsCount = processorsCount; bestMatchingNodes = new Tuple<int,double>[processorsCount]; FindBestMatchingNodes(neuralNet, inputVector); }
private double Theta(int t, Node BestMatchingNode, Node node, double radius) { double distSqr = (BestMatchingNode.X - node.X) * (BestMatchingNode.X - node.X) + (BestMatchingNode.Y - node.Y) * (BestMatchingNode.Y - node.Y); if (distSqr > radius * radius) return 0; return Math.Exp(-distSqr / (2 * radius * radius)); }
private Node[] InitializeNodes(int weightsCount) { int nodesNumber = neuralMapWidth * neuralMapHeight; Node[] nodesArray = new Node[nodesNumber]; for (int i = 0; i < nodesNumber; i++) { nodesArray[i] = new Node(GetRandomWeights(weightsCount), (i % neuralMapWidth) * distanceBetweenNeurons, (i / neuralMapWidth) * distanceBetweenNeurons, -1); } return nodesArray; }
private Node[] InitializeNodes(Drink[] trainingDataBaseArray) { List<Drink> trainingData = trainingDataBaseArray.ToList(); int nodesNumber = neuralMapWidth * neuralMapHeight; Node[] nodesArray = new Node[nodesNumber]; for (int i = 0; i < nodesNumber; i++) { if( trainingData.Count == 0) trainingData = trainingDataBaseArray.ToList(); int index = randomizer.Next(trainingData.Count); Drink drink = trainingData[index]; nodesArray[i] = new Node(trainingData[index].FeaturesArray,(i % neuralMapWidth) * distanceBetweenNeurons, (i / neuralMapWidth) * distanceBetweenNeurons, drink.ID); trainingData.RemoveAt(index); } return nodesArray; }
// item1 - error average, item 2 - stddev private Tuple<double, double> GetVectorQuantizationError(Node[] neuralNet) { double[] nodeErrorArray = new double[neuralNet.Length]; for (int i = 0; i < nodeErrorArray.Length; i++) { nodeErrorArray[i] = neuralNet[i].Weights.GetSquareDistance(drinksDictionary[neuralNet[i].DrinkID].FeaturesArray); } return new Tuple<double,double>(nodeErrorArray.Average(), nodeErrorArray.StandardDeviation()); }