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++;
                        }
                    }
                }
            }
Example #2
0
        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);
        }