Пример #1
0
        /// <summary>
        /// Runs through a single convolution layer.
        /// </summary>
        /// <param name="layerInfo">The layer info used for this layer.</param>
        /// <param name="inputImages">
        /// A matrix of all the images that will be convolved. Each row is an image.
        /// </param>
        /// <returns>A matrix of all the resulting images. Each row is an image.</returns>
        internal Matrix <double> Convolve(ConvolutionalLayerInformation layerInfo, Matrix <double> inputImages)
        {
            // Construct out return matrix that will include all layers of our images.
            Matrix <double> _outputImages = null;

            foreach (Tuple <int, Vector <double> > _imageDimensionAndIndex in inputImages.EnumerateRowsIndexed())
            {
                // Create the matrix so we can do all of the convolutions at once.
                Matrix <double> _preConvolutionMap = this.CreateMaskingMap(layerInfo.KernelSize, layerInfo.Stride, _imageDimensionAndIndex.Item2);

                Matrix <double> _filtersForThisDimension = CreateMatrix.Dense <double>(layerInfo.FlattenedFilters.Count, layerInfo.FlattenedFilters[0].ColumnCount);

                foreach (Matrix <double> _filter in layerInfo.FlattenedFilters)
                {
                    _filtersForThisDimension.InsertRow(_imageDimensionAndIndex.Item1, _filter.Row(_imageDimensionAndIndex.Item1));
                }

                // Create the result image matrix if it's not created yet
                if (_outputImages == null)
                {
                    _outputImages = CreateMatrix.Dense <double>(layerInfo.FilterCount, _preConvolutionMap.ColumnCount, 0.0);
                }

                // Store off the result of our filters multiplied by our map. This ends up being every filter passing over
                // the entire image, and returning a dimentions for each kernel in the layer. We sum all the dimensional results in one dimension.
                _outputImages = _outputImages.Add(_filtersForThisDimension.Multiply(_preConvolutionMap));
            }

            // Return all the resulting dimensions of the images after convolution
            return(_outputImages);
        }
Пример #2
0
        /// <summary>
        /// Runs through the network and makes a prediction.
        /// </summary>
        /// <param name="input">The input image to run the prediction on.</param>
        /// <returns>The values from the final layer. The largest value is the networks prediction.</returns>
        public double[] FeedForward(double[] input)
        {
            Matrix <double> _currentImages = CreateMatrix.DenseOfRowVectors(CreateVector.DenseOfArray <double>(input));

            foreach (ILayerInformation _layerInformation in this.LayerInformation)
            {
                switch (_layerInformation.LayerType)
                {
                case (LayerType.Convolutional):
                    ConvolutionalLayerInformation _convInfo = _layerInformation as ConvolutionalLayerInformation;
                    _currentImages = this.Convolve(_convInfo, _currentImages);
                    break;

                case (LayerType.Pooling):
                    PoolingLayerInformation _poolInfo = _layerInformation as PoolingLayerInformation;
                    _currentImages = this.Pool(_poolInfo, _currentImages);
                    break;

                case (LayerType.NonLinear):
                    NonLinearLayerInformation _nonLinearInfo = _layerInformation as NonLinearLayerInformation;
                    _currentImages = this.NonLinear(_nonLinearInfo, _currentImages);
                    break;
                }
            }

            double[] _fullyConnectedInput = CreateVector.DenseOfEnumerable <double>(_currentImages.EnumerateRows().SelectMany(a => a)).ToArray();

            return(this.FullyConnectedNetwork.FeedForward(_currentImages.Enumerate().ToArray()));
        }
Пример #3
0
        /// <summary>
        /// Adds a convolutional layer to the network.
        /// </summary>
        /// <param name="filterCount">The number of filters this layer should use.</param>
        /// <param name="kernelSize">
        /// A side length of each kernel (all kernels are square, so if you want a 5x5 kernel this
        /// parameter should be 5)
        /// </param>
        /// <param name="stride">The stride used for the filters.</param>
        public void AddConvolutionalLayer(int filterCount, int kernelSize, int stride)
        {
            ConvolutionalLayerInformation _previousConvolutionLayer = this.LayerInformation.LastOrDefault(p => p.LayerType == LayerType.Convolutional) as ConvolutionalLayerInformation;
            int _previousDimensions = _previousConvolutionLayer == null ? this.InputDimensions : _previousConvolutionLayer.FilterCount;
            List <Matrix <double> > _flattenedFilters = new List <Matrix <double> >(filterCount);

            for (int i = 0; i < filterCount; i++)
            {
                _flattenedFilters.Add(Matrix <double> .Build.Random(_previousDimensions, (int)Math.Pow(kernelSize, 2), new Normal(0.0, 1.0)));
            }

            this.LayerInformation.Add(new ConvolutionalLayerInformation
            {
                FilterCount      = filterCount,
                Stride           = stride,
                KernelSize       = kernelSize,
                FlattenedFilters = _flattenedFilters
            });
        }