using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Core; using System.IO; namespace TimTester { class Program { //========================================= //Random //========================================= static Random rand = new Random(40); static Random trainTestrand = new Random(40); //========================================= //Network //========================================= static Network network; //========================================= //Gabor Parameters //========================================= static float scale = 0.5f; static float[] orientations = new float[] { 22.5f, 67.5f, 112.5f, 157.5f }; static float[] percents = new float[] { 0.15f, 0.12f, 0.10f, 0.07f, 0.05f }; static float gaborDiv = 4; static int gaborRF = 5; static int gaborCRF = 7; //========================================= //Kernel Parameters //========================================= static float ap = 0.05f; static float an = 0.025f; static float antiAp = ap; static float antiAn = 0.005f; static float[] thresholds; static int numberOfFeatures = 10; static int SRF = 17; static int threshold = 42; static float pr_interval = 0.8f; static float pr_min = 0.2f; static float dropOutProbability = 0.3f; //========================================= //Classification task //========================================= static int numberOfClasses = 2; //NOTE: //Those the network should remain silent for, must be added after main classes static string[] allImages = new string[] { @"..\..\dataset\caltech\Face", @"..\..\dataset\caltech\Motorbike", }; static int[] startIndices; static int numberOfTrainingSamples = 50; static string[] classNames = { "Face", "Motorbike", }; static List labels; static int[] neuronAssociations = new int[numberOfFeatures]; static GaborLayer gaborLayer; static Performance bestTrainPerformance; static Performance bestTestPerformance; static Kernel bestTrainKernel = null; static Kernel bestTestKernel = null; static void Main(string[] args) { string taskName = "CaltechFaceMotorbike"; int epochs = 200; //Network network = new Network(rand); gaborLayer = new GaborLayer(allImages, scale, orientations, gaborRF, gaborDiv, gaborCRF, percents); //Labels labels = new List(); startIndices = new int[allImages.Length + 1]; for(int i = 0; i < allImages.Length; i++) { string folder = allImages[i]; int cnt = Directory.EnumerateFiles(folder, "*.png").Count(); startIndices[i + 1] = startIndices[i] + cnt; int lbl = i; if (i >= numberOfClasses) lbl = -1; //for silence labels.AddRange(Enumerable.Repeat(lbl, cnt)); } //Associations int d = numberOfFeatures / numberOfClasses; for(int i = 0; i < numberOfFeatures; i++) { neuronAssociations[i] = i / d; } //Thresholds thresholds = Enumerable.Repeat((float)threshold, numberOfFeatures).ToArray(); int c = 1; string tempTaskName = Path.Combine(taskName, c.ToString()); Directory.CreateDirectory(tempTaskName); MyModel(tempTaskName, c, epochs); } static void MyModel(string taskName, int c, int epoch) { if(!Directory.Exists(taskName)) Directory.CreateDirectory(taskName); SaveModelConfig(taskName); StreamWriter trainPerfWriter = new StreamWriter(Path.Combine(taskName, "trainHistory.txt")); StreamWriter testPerfWriter = new StreamWriter(Path.Combine(taskName, "testHistory.txt")); StreamWriter bestPerfWriter = new StreamWriter(Path.Combine(taskName, "bestPerformance.txt")); trainPerfWriter.WriteLine("# Corrects Wrongs Silences"); testPerfWriter.WriteLine("# Corrects Wrongs Silences"); //Dividing Test/Train List> testOrderedData = new List>(); List> testData = new List>(); List testNames = new List(); List testLabels = new List(); List> trainOrderedData = new List>(); List> trainData = new List>(); List trainNames = new List(); List trainLabels = new List(); bool[] visit = new bool[gaborLayer.OrderedData.Count]; int[] trainCnt = Enumerable.Repeat(numberOfTrainingSamples, allImages.Length).ToArray(); for (int i = 0; i < allImages.Length; i++) { while (trainCnt[i] > 0) { int idx = trainTestrand.Next(startIndices[i], startIndices[i + 1]); if (visit[idx] == false) { visit[idx] = true; --trainCnt[i]; } } } for (int j = 0; j < gaborLayer.OrderedData.Count; j++) { if (!visit[j]) { testOrderedData.Add(gaborLayer.OrderedData[j]); testData.Add(gaborLayer.SpikeData2D[j]); testNames.Add(gaborLayer.FileNames[j]); testLabels.Add(labels[j]); } else { trainOrderedData.Add(gaborLayer.OrderedData[j]); trainData.Add(gaborLayer.SpikeData2D[j]); trainNames.Add(gaborLayer.FileNames[j]); trainLabels.Add(labels[j]); } } //TODO: Loading kernel Kernel kernel = new Kernel("S2RL", numberOfFeatures, orientations.Length, SRF, thresholds, 1, ap, an, antiAp, antiAn, 0.8f, 0.05f, rand); kernel.Ap = ((1f - 1.0f / numberOfClasses) * pr_interval + pr_min) * ap; kernel.An = ((1f - 1.0f / numberOfClasses) * pr_interval + pr_min) * an; kernel.AntiAp = ((1.0f / numberOfClasses) * pr_interval + pr_min) * antiAp; kernel.AntiAn = ((1.0f / numberOfClasses) * pr_interval + pr_min) * antiAn; int maxIteration = epoch; for (int iter = 1; iter <= maxIteration; iter++) { Console.WriteLine(iter); //Train bool[] active = Enumerable.Repeat(true, numberOfFeatures).Select(a => rand.NextDouble() >= dropOutProbability).ToArray(); network.TrainKernelRL(trainOrderedData, trainData, kernel, 1, 1, trainLabels, neuronAssociations, active); //Compute Train/Test Performance List> trainResponses = null; List> testResponses = null; trainResponses = network.GetKernelFirstSpikes(trainOrderedData, trainData, kernel); testResponses = network.GetKernelFirstSpikes(testOrderedData, testData, kernel); Console.WriteLine(); int correct = 0, wrong = 0, silence = 0; for (int i = 0; i < trainOrderedData.Count; ++i) { int idx = trainResponses[i].FindIndex(tr => tr == 1); if (idx == -1) { if (trainLabels[i] != -1) ++silence; else ++correct; } else if (neuronAssociations[idx] == trainLabels[i]) ++correct; else ++wrong; } Performance tempTrainPerf = new Performance(iter, correct, wrong, silence); if (bestTrainPerformance == null || bestTrainPerformance.Corrects <= tempTrainPerf.Corrects) { bestTrainPerformance = tempTrainPerf; bestTrainKernel = Kernel.GetCopy(kernel, kernel.Name + "Train" + iter); } trainPerfWriter.WriteLine($"{tempTrainPerf.Corrects} {tempTrainPerf.Wrongs} {tempTrainPerf.Silences}"); Console.WriteLine("Best Train: " + bestTrainPerformance); kernel.Ap = (tempTrainPerf.Wrongs * pr_interval + pr_min) * ap; kernel.An = (tempTrainPerf.Wrongs * pr_interval + pr_min) * an; kernel.AntiAp = (tempTrainPerf.Corrects * pr_interval + pr_min) * antiAp; kernel.AntiAn = (tempTrainPerf.Corrects * pr_interval + pr_min) * antiAn; correct = 0; wrong = 0; silence = 0; for (int i = 0; i < testOrderedData.Count; ++i) { int idx = testResponses[i].FindIndex(tr => tr == 1); if (idx == -1) { if (testLabels[i] != -1) ++silence; else ++correct; } else if (neuronAssociations[idx] == testLabels[i]) ++correct; else ++wrong; } Performance tempTestPerf = new Performance(iter, correct, wrong, silence); if (bestTestPerformance == null || bestTestPerformance.Corrects <= tempTestPerf.Corrects) { bestTestPerformance = tempTestPerf; bestTestKernel = Kernel.GetCopy(kernel, kernel.Name + "Test" + iter); if (wrong == 0 && silence == 0) { break; } } testPerfWriter.WriteLine($"{tempTestPerf.Corrects} {tempTestPerf.Wrongs} {tempTestPerf.Silences}"); Console.WriteLine("Best Test: " + bestTestPerformance); Console.WriteLine($"Params: ap: {kernel.Ap}, an: {kernel.An}, antiap: {kernel.AntiAp}, antian: {kernel.AntiAn}"); Console.WriteLine(); if (iter % 25 == 0) { trainPerfWriter.Flush(); testPerfWriter.Flush(); } if (iter % 250 == 0) { bestPerfWriter.WriteLine($"#Iteration {iter}"); bestPerfWriter.WriteLine("#Train"); bestPerfWriter.WriteLine(bestTrainPerformance); bestPerfWriter.WriteLine("#Test"); bestPerfWriter.WriteLine(bestTestPerformance); bestPerfWriter.Flush(); } } trainPerfWriter.Close(); testPerfWriter.Close(); bestPerfWriter.WriteLine("#Train"); bestPerfWriter.WriteLine(bestTrainPerformance); bestPerfWriter.WriteLine("#Test"); bestPerfWriter.WriteLine(bestTestPerformance); bestPerfWriter.Close(); network.SaveKernel(taskName, bestTrainKernel, gaborLayer.gabor.gaborFeatures); network.SaveKernel(taskName, bestTestKernel, gaborLayer.gabor.gaborFeatures); MyModelTest(Path.Combine(taskName, "testOnTest"), bestTestKernel, testOrderedData, testData, testLabels, testNames.Select(s => Path.GetFileNameWithoutExtension(s)).ToArray()); MyModelTest(Path.Combine(taskName, "testOnTrain"), bestTestKernel, trainOrderedData, trainData, trainLabels, trainNames.Select(s => Path.GetFileNameWithoutExtension(s)).ToArray()); } static void SaveModelConfig(string taskName) { StreamWriter configWriter = new StreamWriter(Path.Combine(taskName, "config.txt")); configWriter.WriteLine($"gabor.scales {scale}"); configWriter.WriteLine($"gabor.orientations {string.Join(",", orientations)}"); configWriter.WriteLine($"gabor.inhibition {string.Join(",", percents)}"); configWriter.WriteLine($"gabor.div {gaborDiv}"); configWriter.WriteLine($"gabor.rf {gaborRF}"); configWriter.WriteLine($"gabor.crf {gaborCRF}"); configWriter.WriteLine($"kernel.ap {ap}"); configWriter.WriteLine($"kernel.an {an}"); configWriter.WriteLine($"kernel.antiap {antiAp}"); configWriter.WriteLine($"kernel.antian {antiAn}"); configWriter.WriteLine($"kernel.thresholds {string.Join(",", thresholds)}"); configWriter.WriteLine($"kernel.numberoffeatures {numberOfFeatures}"); configWriter.WriteLine($"kernel.srf {SRF}"); configWriter.WriteLine($"printerval {pr_interval}"); configWriter.WriteLine($"prmin {pr_min}"); configWriter.Close(); } static void MyModelTest(string taskName, Kernel kernel, List> orderedSpikes, List> spikeData, List labels, string[] inputNames) { if (!Directory.Exists(taskName)) Directory.CreateDirectory(taskName); //Finding greatest dim values int maxHeight = 0; int maxWidth = 0; foreach (var level2 in spikeData) { foreach (var level3 in level2) { if (level3.GetLength(0) > maxHeight) maxHeight = level3.GetLength(0); if (level3.GetLength(1) > maxWidth) maxWidth = level3.GetLength(1); } } int[] correctResponsCnt = new int[numberOfFeatures]; int[] averages = new int[numberOfClasses]; int[] wrongResponsCnt = new int[numberOfFeatures]; int[,] confusionMatrix = new int[numberOfClasses, numberOfClasses + 1]; int maxInConfusion = 0; StreamWriter missWriter = new StreamWriter(Path.Combine(taskName, "misses.txt")); List> output = network.GetKernelFirstSpikes(orderedSpikes, spikeData, kernel); int corrects = 0, wrongs = 0, silences = 0; for (int i = 0; i < output.Count; i++) { if (labels[i] == -1) continue; int winner = output[i].IndexOf(1); if (winner == -1) { ++confusionMatrix[labels[i], numberOfClasses]; if (confusionMatrix[labels[i], numberOfClasses] > maxInConfusion) maxInConfusion = confusionMatrix[labels[i], numberOfClasses]; ++silences; } else if (neuronAssociations[winner] != labels[i]) { ++confusionMatrix[labels[i], neuronAssociations[winner]]; if (confusionMatrix[labels[i], neuronAssociations[winner]] > maxInConfusion) maxInConfusion = confusionMatrix[labels[i], neuronAssociations[winner]]; missWriter.WriteLine($"{inputNames[i]}({labels[i]}) -> Neuron:{winner} Class:{neuronAssociations[winner]}"); ++wrongResponsCnt[winner]; ++averages[neuronAssociations[winner]]; ++wrongs; } else { ++confusionMatrix[labels[i], neuronAssociations[winner]]; if (confusionMatrix[labels[i], neuronAssociations[winner]] > maxInConfusion) maxInConfusion = confusionMatrix[labels[i], neuronAssociations[winner]]; ++correctResponsCnt[winner]; ++averages[neuronAssociations[winner]]; ++corrects; } } missWriter.Close(); Performance testPerformance = new Performance(0, corrects, wrongs, silences); Console.WriteLine(testPerformance); //Involvements StreamWriter[] statWriter = new StreamWriter[numberOfClasses]; for (int c = 0; c < numberOfClasses; c++) { statWriter[c] = new StreamWriter(Path.Combine(taskName, $"CWStat_c{c}.txt")); List neuronsForClass = Enumerable.Range(0, numberOfFeatures). Where(i => neuronAssociations[i] == c).ToList(); averages[c] /= neuronsForClass.Count; for (int i = 0; i < neuronsForClass.Count; i++) { statWriter[c].WriteLine($"{neuronsForClass[i]} {correctResponsCnt[neuronsForClass[i]]} {wrongResponsCnt[neuronsForClass[i]]}"); } } foreach (StreamWriter writer in statWriter) writer.Close(); StreamWriter gnuScript = new StreamWriter(Path.Combine(taskName,"involvement.plt")); gnuScript.WriteLine($"set xrange[0:*]; set yrange[0:*]"); gnuScript.WriteLine($"set terminal pdf"); gnuScript.WriteLine($"set xlabel 'Neuron number'"); gnuScript.WriteLine($"set ylabel 'Response count over all test images'"); gnuScript.WriteLine($"set xtics rotate"); gnuScript.WriteLine($"set grid ytics"); gnuScript.WriteLine("set boxwidth 0.25 absolute"); gnuScript.WriteLine("set style fill solid 0.25 border"); gnuScript.WriteLine("set offsets 0.5, 0.5, 0, 0"); for (int i = 0; i < numberOfClasses; i++) { gnuScript.WriteLine($" t = sprintf('Class{i}: {classNames[i]}')"); gnuScript.WriteLine($" set title t"); gnuScript.WriteLine($" outfile = sprintf('invovlement_{i}.pdf')"); gnuScript.WriteLine($" set output outfile"); gnuScript.WriteLine($" infile = sprintf('CWStat_c{i}.txt')"); gnuScript.WriteLine($" plot infile u 0:2:(0.75):xticlabels(1) with boxes linecolor rgb '#00a148' title 'Corrects', infile u 0:3:(0.25) with boxes linecolor rgb '#ff0000' title 'Wrongs', {averages[i]} title ''"); gnuScript.WriteLine(); } gnuScript.Close(); //Confusion Matrix int maxLength = 0; while(maxInConfusion > 0) { maxInConfusion /= 10; maxLength++; } maxLength = Math.Max(maxLength, classNames.Max(s => s.Length)); maxLength = Math.Max(maxLength, "Silence".Length); StreamWriter confusionWriter = new StreamWriter(Path.Combine(taskName, "confusionMatrix.txt")); confusionWriter.Write("{0," + maxLength + "}|", " "); for (int i = 0; i < classNames.Length; i++) { confusionWriter.Write("{0," + maxLength + "}|", classNames[i]); } confusionWriter.WriteLine("{0," + maxLength + "}", "Silence"); for (int c = 0; c < classNames.Length; c++) { confusionWriter.Write("{0," + maxLength + "}|", classNames[c]); for (int i = 0; i < classNames.Length; i++) { confusionWriter.Write("{0," + maxLength + "}|", confusionMatrix[c, i]); } confusionWriter.WriteLine("{0," + maxLength + "}", confusionMatrix[c, classNames.Length]); } confusionWriter.Close(); } } }