/// <summary> /// Data of a single function for which KMeans will be calculated. /// </summary> /// <param name="data"></param> /// <param name="ctx"></param> /// <returns></returns> public IScore Run(double[][] data, IContext ctx) { /* * if (this.Score.NomOfTrainedFunctions == 1) * { * this.Settings.InitialCentroids = new double[this.Settings.NumberOfClusters][]; * for (int i = 0; i < this.Settings.NumberOfClusters; i++) * { * this.Settings.InitialCentroids[i] = this.Score.Centroids[i]; * } * }*/ this.Settings.InitialCentroids = null; KMeansAlgorithm kmeans = new KMeansAlgorithm(this.Settings.Clone()); KMeansScore res = kmeans.Train(data, ctx) as KMeansScore; this.Score.NomOfTrainedFunctions += 1; if (this.Settings.FuncRecogMethod == 1) { double[][] oldCentroids = this.Score.Centroids; for (int clusterIndx = 0; clusterIndx < res.Model.Clusters.Length; clusterIndx++) { if (this.Score.NomOfTrainedFunctions == 1) { this.Score.Centroids[clusterIndx] = res.Model.Clusters[clusterIndx].Centroid; //this.Score.InClusterMaxDistance[clusterIndx] = res.Model.Clusters[clusterIndx].InClusterMaxDistance; } else { for (int d = 0; d < this.Settings.NumOfDimensions; d++) { this.Score.Centroids[clusterIndx][d] = (res.Model.Clusters[clusterIndx].Centroid[d] + oldCentroids[clusterIndx][d] * (this.Score.NomOfTrainedFunctions - 1)) / this.Score.NomOfTrainedFunctions; } adjustInClusterMaxDistance(clusterIndx, res, oldCentroids); } } } else { //Debug.WriteLine($"C0: {res.Model.Clusters[0].Centroid[0]},{res.Model.Clusters[0].Centroid[1]}"); //Debug.WriteLine($"C1: {res.Model.Clusters[1].Centroid[0]},{res.Model.Clusters[0].Centroid[1]}"); //Debug.WriteLine($"C2: {res.Model.Clusters[2].Centroid[0]},{res.Model.Clusters[0].Centroid[1]}"); //Debug.WriteLine($"C3: {res.Model.Clusters[3].Centroid[0]},{res.Model.Clusters[0].Centroid[1]}"); for (int clusterIndx = 0; clusterIndx < res.Model.Clusters.Length; clusterIndx++) { for (int dim = 0; dim < this.Settings.NumOfDimensions; dim++) { if (res.Model.Clusters[clusterIndx].Centroid[dim] > this.Score.MaxCentroid[clusterIndx][dim]) { this.Score.MaxCentroid[clusterIndx][dim] = res.Model.Clusters[clusterIndx].Centroid[dim]; } if (res.Model.Clusters[clusterIndx].Centroid[dim] < this.Score.MinCentroid[clusterIndx][dim]) { this.Score.MinCentroid[clusterIndx][dim] = res.Model.Clusters[clusterIndx].Centroid[dim]; } } } for (int clusterIndex = 0; clusterIndex < res.Model.Clusters.Length; clusterIndex++) { this.Score.Centroids[clusterIndex] = new double[Settings.NumOfDimensions]; for (int dim = 0; dim < Settings.NumOfDimensions; dim++) { if (this.Score.MinCentroid[clusterIndex][dim] >= 0) { this.Score.Centroids[clusterIndex][dim] = (this.Score.MaxCentroid[clusterIndex][dim] + this.Score.MinCentroid[clusterIndex][dim]) / 2; } else { this.Score.Centroids[clusterIndex][dim] = ((this.Score.MaxCentroid[clusterIndex][dim] - this.Score.MinCentroid[clusterIndex][dim]) / 2) + this.Score.MinCentroid[clusterIndex][dim]; } } } } return(Score); }
/// <summary> /// Predicts if the specified function fits in the trainined MIN-MAX cluster interval. /// All calculated clusters must fit in trained cluster MIN-MAX intervals. /// </summary> /// <param name="funcData"></param> /// <param name="ctx"></param> /// <returns></returns> public IResult Predict(double[][] funcData, IContext ctx) { /* * for (int i = 0; i < this.Settings.NumberOfClusters; i++) * { * this.Settings.InitialCentroids[i] = this.Score.Centroids[i]; * }*/ this.Settings.InitialCentroids = null; KMeansAlgorithm kmeans = new KMeansAlgorithm(this.Settings.Clone()); kmeans.Instance = null; KMeansScore res = kmeans.Train(funcData, ctx) as KMeansScore; int scores = 0; KMeansFunctionRecognitionResult predRes = new KMeansFunctionRecognitionResult(); predRes.ResultsPerCluster = new bool[Settings.NumberOfClusters]; double[][] results = new double[Settings.NumberOfClusters][]; if (this.Settings.FuncRecogMethod == 1) { //double[] currDistance = new double[results.Length]; double currDistance; for (int i = 0; i < results.Length; i++) { currDistance = KMeansAlgorithm.calculateDistance(Score.Centroids[i], res.Model.Clusters[i].Centroid); if (currDistance <= Score.InClusterMaxDistance[i] * (1.0 + this.Settings.Tolerance / 100.0)) { predRes.ResultsPerCluster[i] = true; scores++; } else { predRes.ResultsPerCluster[i] = false; } } predRes.Result = (scores == Settings.NumberOfClusters); predRes.Loss = ((float)scores) / (Settings.NumberOfClusters); } else { for (int i = 0; i < results.Length; i++) { results[i] = new double[Settings.NumOfDimensions]; for (int dim = 0; dim < Settings.NumOfDimensions; dim++) { if (res.Model.Clusters[i].Centroid[dim] >= Score.MinCentroid[i][dim] && res.Model.Clusters[i].Centroid[dim] <= Score.MaxCentroid[i][dim]) { results[i][dim] = 1; scores++; } else { results[i][dim] = 0; } // // We calculate here the result of cluster over all dimensions. If all dimensions fits then cluster result is true. if (results[i].Count(r => r == 1) == Settings.NumOfDimensions) { predRes.ResultsPerCluster[i] = true; } else { predRes.ResultsPerCluster[i] = false; } } } predRes.Result = (scores == Settings.NumberOfClusters * Settings.NumOfDimensions); predRes.Loss = ((float)scores) / (Settings.NumberOfClusters * Settings.NumOfDimensions); } return(predRes); }