public ConvolutionalPoolingLayer(ConvolutionalPoolingLayer layer) : base(layer) { var activationMapWidth = layer.imageWidth - layer.filterWidth + 1; var activationMapHeight = layer.imageHeight - layer.filterHeight + 1; var length = layer.filters * layer.channels * layer.filterWidth * layer.filterHeight; this.weights = new double[length]; this.biases = new double[layer.filters * activationMapWidth * activationMapHeight]; this.imageWidth = layer.imageWidth; this.imageHeight = layer.imageHeight; this.channels = layer.channels; this.filters = layer.filters; this.filterWidth = layer.filterWidth; this.filterHeight = layer.filterHeight; this.poolWidth = layer.poolWidth; this.poolHeight = layer.poolHeight; this.convolvedInputs = new double[layer.filters, activationMapHeight, activationMapWidth]; this.activationMaps = new double[layer.filters, activationMapHeight, activationMapWidth]; this.activationFunction = layer.activationFunction; for (int i = 0; i < length; i++) { this.weights[i] = layer.weights[i]; } for (int i = 0, j = 0; i < this.filters; i++) { for (int k = 0; k < activationMapHeight; k++) { for (int l = 0; l < activationMapWidth; l++) { this.biases[j] = layer.biases[j]; this.convolvedInputs[i, k, l] = layer.convolvedInputs[i, k, l]; this.activationMaps[i, k, l] = layer.activationMaps[i, k, l]; j++; } } } }
static void Main(string[] args) { Console.WriteLine("MNIST Test"); int seed; using (var rng = new RNGCryptoServiceProvider()) { var buffer = new byte[sizeof(int)]; rng.GetBytes(buffer); seed = BitConverter.ToInt32(buffer, 0); } RandomProvider.SetSeed(seed); var assembly = Assembly.GetExecutingAssembly(); var random = RandomProvider.GetRandom(); var trainingList = new List <Tuple <double[], double[]> >(); var testList = new List <Tuple <double[], double[]> >(); var accuracyList = new List <double>(); var lossList = new List <double>(); var logDictionary = new Dictionary <string, IEnumerable <double> >(); var logPath = "Log.csv"; var channels = 1; var imageWidth = 28; var imageHeight = 28; var filters = 30; var filterWidth = 5; var filterHeight = 5; var poolWidth = 2; var poolHeight = 2; using (Stream imagesStream = assembly.GetManifestResourceStream("MNISTTest.train-images.idx3-ubyte"), labelsStream = assembly.GetManifestResourceStream("MNISTTest.train-labels.idx1-ubyte")) { foreach (var image in MnistImage.Load(imagesStream, labelsStream).Take(1000)) { var t = new double[10]; for (int i = 0; i < 10; i++) { if (i == image.Label) { t[i] = 1.0; } else { t[i] = 0.0; } } trainingList.Add(Tuple.Create <double[], double[]>(image.Normalize(), t)); } } using (Stream imagesStream = assembly.GetManifestResourceStream("MNISTTest.t10k-images.idx3-ubyte"), labelsStream = assembly.GetManifestResourceStream("MNISTTest.t10k-labels.idx1-ubyte")) { foreach (var image in MnistImage.Load(imagesStream, labelsStream).Take(1000)) { var t = new double[10]; for (int i = 0; i < 10; i++) { if (i == image.Label) { t[i] = 1.0; } else { t[i] = 0.0; } } testList.Add(Tuple.Create <double[], double[]>(image.Normalize(), t)); } } var inputLayer = new ConvolutionalPoolingLayer(channels, imageWidth, imageHeight, filters, filterWidth, filterHeight, poolWidth, poolHeight, new ReLU(), (index, fanIn, fanOut) => Initializers.HeNormal(fanIn)); var hiddenLayer = new FullyConnectedLayer(inputLayer, 100, new ReLU(), (index, fanIn, fanOut) => Initializers.HeNormal(fanIn)); var outputLayer = new SoftmaxLayer(hiddenLayer, 10, (index, fanIn, fanOut) => Initializers.GlorotNormal(fanIn, fanOut)); var network = new Network(inputLayer, outputLayer, new Adam(), new SoftmaxCrossEntropy()); int epochs = 50; int iterations = 1; network.Stepped += (sender, e) => { double tptn = 0; trainingList.ForEach(x => { var vector = network.Predicate(x.Item1); var i = ArgMax(vector); var j = ArgMax(x.Item2); if (i == j && Math.Round(vector[i]) == x.Item2[j]) { tptn += 1.0; } }); var accuracy = tptn / trainingList.Count; accuracyList.Add(accuracy); lossList.Add(network.Loss); Console.WriteLine("Epoch {0}/{1}", iterations, epochs); Console.WriteLine("Accuracy: {0}, Loss: {1}", accuracy, network.Loss); iterations++; }; Console.WriteLine("Training..."); var stopwatch = Stopwatch.StartNew(); network.Train(trainingList, epochs, 100); stopwatch.Stop(); Console.WriteLine("Done ({0}).", stopwatch.Elapsed.ToString()); double testTptn = 0; testList.ForEach(x => { var vector = network.Predicate(x.Item1); var i = ArgMax(vector); var j = ArgMax(x.Item2); if (i == j && Math.Round(vector[i]) == x.Item2[j]) { testTptn += 1.0; } }); Console.WriteLine("Accuracy: {0}", testTptn / testList.Count); logDictionary.Add("Accuracy", accuracyList); logDictionary.Add("Loss", lossList); ToCsv(logPath, logDictionary); Console.Write("Saved log to {0}...", logPath); }