예제 #1
0
        /// <summary>
        ///     Intended for use with data augmentation
        /// </summary>
        /// <param name="volume">Input volume</param>
        /// <param name="crop">Size of output</param>
        /// <param name="dx">Offset wrt incoming volume, of the shift</param>
        /// <param name="dy">Offset wrt incoming volume, of the shift</param>
        /// <param name="flipLeftRight">flip left/right</param>
        /// <returns></returns>
        public static Volume Augment(this Volume volume, int crop, int dx = -1, int dy = -1, bool flipLeftRight = false)
        {
            if (dx == -1)
            {
                dx = Random.Next(volume.Width - crop);
            }

            if (dy == -1)
            {
                dy = Random.Next(volume.Height - crop);
            }

            // randomly sample a crop in the input volume
            Volume w;

            if (crop != volume.Width || dx != 0 || dy != 0)
            {
                w = new Volume(crop, crop, volume.Depth, 0.0);
                for (var x = 0; x < crop; x++)
                {
                    for (var y = 0; y < crop; y++)
                    {
                        if (x + dx < 0 || x + dx >= volume.Width || y + dy < 0 || y + dy >= volume.Width)
                        {
                            continue; // oob
                        }

                        for (var depth = 0; depth < volume.Depth; depth++)
                        {
                            w.Set(x, y, depth, volume.Get(x + dx, y + dy, depth)); // copy data over
                        }
                    }
                }
            }
            else
            {
                w = volume;
            }

            if (flipLeftRight)
            {
                // flip volume horziontally
                var w2 = w.CloneAndZero();
                for (var x = 0; x < w.Width; x++)
                {
                    for (var y = 0; y < w.Height; y++)
                    {
                        for (var depth = 0; depth < w.Depth; depth++)
                        {
                            w2.Set(x, y, depth, w.Get(w.Width - x - 1, y, depth)); // copy data over
                        }
                    }
                }
                w = w2; //swap
            }

            return(w);
        }
예제 #2
0
        /// <summary>
        ///     Intended for use with data augmentation
        /// </summary>
        /// <param name="volume">Input volume</param>
        /// <param name="crop">Size of output</param>
        /// <param name="dx">Offset wrt incoming volume, of the shift</param>
        /// <param name="dy">Offset wrt incoming volume, of the shift</param>
        /// <param name="flipLeftRight">flip left/right</param>
        /// <returns></returns>
        public static Volume Augment(this Volume volume, int crop, int dx = -1, int dy = -1, bool flipLeftRight = false)
        {
            if (dx == -1)
            {
                dx = Random.Next(volume.Width - crop);
            }

            if (dy == -1)
            {
                dy = Random.Next(volume.Height - crop);
            }

            // randomly sample a crop in the input volume
            Volume w;
            if (crop != volume.Width || dx != 0 || dy != 0)
            {
                w = new Volume(crop, crop, volume.Depth, 0.0);
                for (var x = 0; x < crop; x++)
                {
                    for (var y = 0; y < crop; y++)
                    {
                        if (x + dx < 0 || x + dx >= volume.Width || y + dy < 0 || y + dy >= volume.Width)
                        {
                            continue; // oob
                        }

                        for (var depth = 0; depth < volume.Depth; depth++)
                        {
                            w.Set(x, y, depth, volume.Get(x + dx, y + dy, depth)); // copy data over
                        }
                    }
                }
            }
            else
            {
                w = volume;
            }

            if (flipLeftRight)
            {
                // flip volume horziontally
                var w2 = w.CloneAndZero();
                for (var x = 0; x < w.Width; x++)
                {
                    for (var y = 0; y < w.Height; y++)
                    {
                        for (var depth = 0; depth < w.Depth; depth++)
                        {
                            w2.Set(x, y, depth, w.Get(w.Width - x - 1, y, depth)); // copy data over
                        }
                    }
                }
                w = w2; //swap
            }

            return w;
        }
예제 #3
0
        public override Volume Forward(Volume input, bool isTraining = false)
        {
            this.InputActivation = input;

            var outputActivation = new Volume(this.OutputWidth, this.OutputHeight, this.OutputDepth, 0.0);

#if PARALLEL
            Parallel.For(0, this.OutputDepth, depth =>
#else
            for (var depth = 0; depth < this.OutputDepth; depth++)
#endif
            {
                var n = depth * this.OutputWidth * this.OutputHeight; // a counter for switches

                var x = -this.Pad;
                var y = -this.Pad;
                for (var ax = 0; ax < this.OutputWidth; x += this.Stride, ax++)
                {
                    y = -this.Pad;
                    for (var ay = 0; ay < this.OutputHeight; y += this.Stride, ay++)
                    {
                        // convolve centered at this particular location
                        var a = double.MinValue;
                        int winx = -1, winy = -1;

                        for (var fx = 0; fx < this.Width; fx++)
                        {
                            for (var fy = 0; fy < this.Height; fy++)
                            {
                                var oy = y + fy;
                                var ox = x + fx;
                                if (oy >= 0 && oy < input.Height && ox >= 0 && ox < input.Width)
                                {
                                    var v = input.Get(ox, oy, depth);
                                    // perform max pooling and store pointers to where
                                    // the max came from. This will speed up backprop 
                                    // and can help make nice visualizations in future
                                    if (v > a)
                                    {
                                        a = v;
                                        winx = ox;
                                        winy = oy;
                                    }
                                }
                            }
                        }

                        this.switchx[n] = winx;
                        this.switchy[n] = winy;
                        n++;
                        outputActivation.Set(ax, ay, depth, a);
                    }
                }
            }
예제 #4
0
        public override Volume Forward(Volume input, bool isTraining = false)
        {
            // optimized code by @mdda that achieves 2x speedup over previous version

            this.InputActivation = input;
            var outputActivation = new Volume(this.OutputWidth, this.OutputHeight, this.OutputDepth, 0.0);

            var volumeWidth = input.Width;
            var volumeHeight = input.Height;
            var xyStride = this.Stride;

#if PARALLEL
            Parallel.For(0, this.OutputDepth, depth =>
#else
            for (var depth = 0; depth < this.OutputDepth; depth++)
#endif
            {
                var filter = this.Filters[depth];
                var y = -this.Pad;

                for (var ay = 0; ay < this.OutputHeight; y += xyStride, ay++)
                {
                    // xyStride
                    var x = -this.Pad;
                    for (var ax = 0; ax < this.OutputWidth; x += xyStride, ax++)
                    {
                        // xyStride

                        // convolve centered at this particular location
                        var a = 0.0;
                        for (var fy = 0; fy < filter.Height; fy++)
                        {
                            var oy = y + fy; // coordinates in the original input array coordinates
                            for (var fx = 0; fx < filter.Width; fx++)
                            {
                                var ox = x + fx;
                                if (oy >= 0 && oy < volumeHeight && ox >= 0 && ox < volumeWidth)
                                {
                                    for (var fd = 0; fd < filter.Depth; fd++)
                                    {
                                        // avoid function call overhead (x2) for efficiency, compromise modularity :(
                                        a += filter.Weights[((filter.Width * fy) + fx) * filter.Depth + fd] *
                                             input.Weights[((volumeWidth * oy) + ox) * input.Depth + fd];
                                    }
                                }
                            }
                        }

                        a += this.Biases.Weights[depth];
                        outputActivation.Set(ax, ay, depth, a);
                    }
                }
            }
        /// <summary>
        ///     Intended for use with data augmentation
        /// </summary>
        /// <param name="volume">Input volume</param>
        /// <param name="crop">Size of output</param>
        /// <param name="dx">Offset wrt incoming volume, of the shift</param>
        /// <param name="dy">Offset wrt incoming volume, of the shift</param>
        /// <param name="flipLeftRight">flip left/right</param>
        /// <returns></returns>
        public static IVolume Augment(this Volume volume, int crop, int dx = -1, int dy = -1, bool flipLeftRight = false)
        {
            if (dx == -1)
            {
                dx = Random.Next(volume.Width - crop);
            }

            if (dy == -1)
            {
                dy = Random.Next(volume.Height - crop);
            }

            // randomly sample a crop in the input volume
            Volume w;

            if (crop != volume.Width || dx != 0 || dy != 0)
            {
                w = new Volume(crop, crop, volume.Depth, 0.0);
                for (var x = 0; x < crop; x++)
                {
                    for (var y = 0; y < crop; y++)
                    {
                        if (x + dx < 0 || x + dx >= volume.Width || y + dy < 0 || y + dy >= volume.Width)
                        {
                            continue; // oob
                        }

                        for (var depth = 0; depth < volume.Depth; depth++)
                        {
                            w.Set(x, y, depth, volume.Get(x + dx, y + dy, depth)); // copy data over
                        }
                    }
                }
            }
            else
            {
                w = volume;
            }

            IVolume result = w;

            if (flipLeftRight)
            {
                result = w.Flip(FlipMode.LeftRight);
            }

            return(result);
        }
예제 #6
0
        public override Volume Forward(Volume input, bool isTraining = false)
        {
            this.InputActivation = input;

            var outputActivation = new Volume(this.OutputWidth, this.OutputHeight, this.OutputDepth, 0.0);

#if PARALLEL
            Parallel.For(0, this.OutputDepth, depth =>
#else
            for (var depth = 0; depth < this.OutputDepth; depth++)
#endif
            {
                var n = depth * this.OutputWidth * this.OutputHeight; // a counter for switches

                var x = -this.Pad;
                var y = -this.Pad;
                for (var ax = 0; ax < this.OutputWidth; x += this.Stride, ax++)
                {
                    y = -this.Pad;
                    for (var ay = 0; ay < this.OutputHeight; y += this.Stride, ay++)
                    {
                        // convolve centered at this particular location
                        var a = double.MinValue;
                        int winx = -1, winy = -1;

                        for (var fx = 0; fx < this.Width; fx++)
                        {
                            for (var fy = 0; fy < this.Height; fy++)
                            {
                                var oy = y + fy;
                                var ox = x + fx;
                                if (oy >= 0 && oy < input.Height && ox >= 0 && ox < input.Width)
                                {
                                    var v = input.Get(ox, oy, depth);
                                    // perform max pooling and store pointers to where
                                    // the max came from. This will speed up backprop 
                                    // and can help make nice visualizations in future
                                    if (v > a)
                                    {
                                        a = v;
                                        winx = ox;
                                        winy = oy;
                                    }
                                }
                            }
                        }

                        this.switchx[n] = winx;
                        this.switchy[n] = winy;
                        n++;
                        outputActivation.Set(ax, ay, depth, a);
                    }
                }
            }
#if PARALLEL
);
#endif

            this.OutputActivation = outputActivation;
            return this.OutputActivation;
        }
예제 #7
0
        public override Volume Forward(Volume input, bool isTraining = false)
        {
            this.InputActivation = input;
            var depth            = this.OutputDepth;
            var outputActivation = new Volume(this.OutputWidth, this.OutputHeight, this.OutputDepth, 0.0);

            // optimization branch. If we're operating on 1D arrays we dont have
            // to worry about keeping track of x,y,d coordinates inside
            // input volumes. In convnets we do :(
            if (this.OutputWidth == 1 && this.OutputHeight == 1)
            {
                for (var i = 0; i < depth; i++)
                {
                    var ix = i * this.GroupSize; // base index offset
                    var a  = input.Weights[ix];
                    var ai = 0;

                    for (var j = 1; j < this.GroupSize; j++)
                    {
                        var a2 = input.Weights[ix + j];
                        if (a2 > a)
                        {
                            a  = a2;
                            ai = j;
                        }
                    }

                    outputActivation.Weights[i] = a;
                    this.switches[i]            = ix + ai;
                }
            }
            else
            {
                var n = 0; // counter for switches
                for (var x = 0; x < input.Width; x++)
                {
                    for (var y = 0; y < input.Height; y++)
                    {
                        for (var i = 0; i < depth; i++)
                        {
                            var ix = i * this.GroupSize;
                            var a  = input.Get(x, y, ix);
                            var ai = 0;

                            for (var j = 1; j < this.GroupSize; j++)
                            {
                                var a2 = input.Get(x, y, ix + j);
                                if (a2 > a)
                                {
                                    a  = a2;
                                    ai = j;
                                }
                            }

                            outputActivation.Set(x, y, i, a);
                            this.switches[n] = ix + ai;
                            n++;
                        }
                    }
                }
            }

            this.OutputActivation = outputActivation;
            return(this.OutputActivation);
        }
예제 #8
0
        public override Volume Forward(Volume input, bool isTraining = false)
        {
            // optimized code by @mdda that achieves 2x speedup over previous version

            this.InputActivation = input;
            var outputActivation = new Volume(this.OutputWidth, this.OutputHeight, this.OutputDepth, 0.0);

            var volumeWidth = input.Width;
            var volumeHeight = input.Height;
            var xyStride = this.Stride;

#if PARALLEL
            Parallel.For(0, this.OutputDepth, depth =>
#else
            for (var depth = 0; depth < this.OutputDepth; depth++)
#endif
            {
                var filter = this.Filters[depth];
                var y = -this.Pad;

                for (var ay = 0; ay < this.OutputHeight; y += xyStride, ay++)
                {
                    // xyStride
                    var x = -this.Pad;
                    for (var ax = 0; ax < this.OutputWidth; x += xyStride, ax++)
                    {
                        // xyStride

                        // convolve centered at this particular location
                        var a = 0.0;
                        for (var fy = 0; fy < filter.Height; fy++)
                        {
                            var oy = y + fy; // coordinates in the original input array coordinates
                            for (var fx = 0; fx < filter.Width; fx++)
                            {
                                var ox = x + fx;
                                if (oy >= 0 && oy < volumeHeight && ox >= 0 && ox < volumeWidth)
                                {
                                    for (var fd = 0; fd < filter.Depth; fd++)
                                    {
                                        // avoid function call overhead (x2) for efficiency, compromise modularity :(
                                        a += filter.Weights[((filter.Width * fy) + fx) * filter.Depth + fd] *
                                             input.Weights[((volumeWidth * oy) + ox) * input.Depth + fd];
                                    }
                                }
                            }
                        }

                        a += this.Biases.Weights[depth];
                        outputActivation.Set(ax, ay, depth, a);
                    }
                }
            }
#if PARALLEL
);
#endif

            this.OutputActivation = outputActivation;
            return this.OutputActivation;
        }
예제 #9
0
        public override Volume Forward(Volume input, bool isTraining = false)
        {
            this.InputActivation = input;
            var depth = this.OutputDepth;
            var outputActivation = new Volume(this.OutputWidth, this.OutputHeight, this.OutputDepth, 0.0);

            // optimization branch. If we're operating on 1D arrays we dont have
            // to worry about keeping track of x,y,d coordinates inside
            // input volumes. In convnets we do :(
            if (this.OutputWidth == 1 && this.OutputHeight == 1)
            {
                for (var i = 0; i < depth; i++)
                {
                    var ix = i * this.GroupSize; // base index offset
                    var a = input.Weights[ix];
                    var ai = 0;

                    for (var j = 1; j < this.GroupSize; j++)
                    {
                        var a2 = input.Weights[ix + j];
                        if (a2 > a)
                        {
                            a = a2;
                            ai = j;
                        }
                    }

                    outputActivation.Weights[i] = a;
                    this.switches[i] = ix + ai;
                }
            }
            else
            {
                var n = 0; // counter for switches
                for (var x = 0; x < input.Width; x++)
                {
                    for (var y = 0; y < input.Height; y++)
                    {
                        for (var i = 0; i < depth; i++)
                        {
                            var ix = i * this.GroupSize;
                            var a = input.Get(x, y, ix);
                            var ai = 0;

                            for (var j = 1; j < this.GroupSize; j++)
                            {
                                var a2 = input.Get(x, y, ix + j);
                                if (a2 > a)
                                {
                                    a = a2;
                                    ai = j;
                                }
                            }

                            outputActivation.Set(x, y, i, a);
                            this.switches[n] = ix + ai;
                            n++;
                        }
                    }
                }
            }

            this.OutputActivation = outputActivation;
            return this.OutputActivation;
        }