Beispiel #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ProximalSynapse"/> class and 
        /// sets its input source and initial permanance values.
        /// </summary>
        /// <param name="proximalSeg">
        /// </param>
        /// <param name="inputSource">
        /// An <see cref="InputCell"/> providing source of the input to this synapse.
        /// </param>
        /// <param name="permanence">Initial permanence value.</param>
        internal ProximalSynapse(ProximalSegment proximalSeg, InputCell inputSource, float permanence)
        {
            // Set fields
            this.ProximalSegment = proximalSeg;
            this.InputSource = inputSource;
            this.Permanence = permanence;

            SelectablelType = SelectableObjectType.ProximalSynapse;
        }
Beispiel #2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ProximalSynapse"/> class and
        /// sets its input source and initial permanance values.
        /// </summary>
        /// <param name="proximalSeg">
        /// </param>
        /// <param name="inputSource">
        /// An <see cref="InputCell"/> providing source of the input to this synapse.
        /// </param>
        /// <param name="permanence">Initial permanence value.</param>
        internal ProximalSynapse(ProximalSegment proximalSeg, InputCell inputSource, float permanence)
        {
            // Set fields
            this.ProximalSegment = proximalSeg;
            this.InputSource     = inputSource;
            this.Permanence      = permanence;

            SelectablelType = SelectableObjectType.ProximalSynapse;
        }
Beispiel #3
0
        /// <summary>
        /// For each (position in inputSpaceRandomPositions): 
        ///  1. Create a new InputCell with input bit = position
        ///  2. Attach a new ProximalSynapse
        ///  3. Add the synapse to the synapse update list.
        /// </summary>
        /// <remarks>
        /// Prior to receiving any inputs, the region is initialized by computing a list of 
        /// initial potential synapses for each column. This consists of a random set of inputs
        /// selected from the input space. Each input is represented by a synapse and assigned
        /// a random permanence value. The random permanence values are chosen with two 
        /// criteria. First, the values are chosen to be in a small range around connectedPerm
        /// (the minimum permanence value at which a synapse is considered "connected"). This 
        /// enables potential synapses to become connected (or disconnected) after a small 
        /// number of training iterations. Second, each column has a natural center over the 
        /// input region, and the permanence values have a bias towards this center (they 
        /// have higher values near the center).
        /// 
        /// The concept of Locality Radius is an additional parameter to control how 
        /// far away synapse connections can be made instead of allowing connections anywhere.  
        /// The reason for this is that in the case of video images I wanted to experiment 
        /// with forcing each Column to only learn on a small section of the total input to 
        /// more effectively learn lines or corners in a small section.
        /// </remarks>
        internal void CreateProximalSegments()
        {
            // Calculates inputRadius for Columns from localityRadius
            //var inputRadius = (int)Math.Round ( this.Region.LocalityRadius * this.Region.InputProportionX );
            // JS
            // JS - should there be 2 inputRadiae, for X and Y, to allow for non-square input fields?
            //(1)
            var inputRadius = (int) Math.Max( 1, Math.Round(this.Region.LocalityRadius * this.Region.InputProportionX));
            //inputRadius = (int)Math.Max ( 1, Math.Round ( this.Region.PercentageInputPerColumn * this.Region.InputSize.Height * this.Region.InputSize.Width ) / 2 );
            //var inputRadius = (int)Math.Max ( 1, Math.Round ( this.Region.LocalityRadius * Math.Max ( this.Region.InputProportionX, this.Region.InputProportionY ) ) );

            // The coordinates of the input space for the Column
            // Think of input space like a 'imaginary' square below the column center.
            int minY, maxY, minX, maxX;
            //(2)
            if (this.Region.LocalityRadius > 0)
            {
                // Compute values of input square and cut radius on edges
                minX = Math.Max ( 0, this.CentralPositionInInput.X - inputRadius);
                maxX = Math.Min(this.Region.InputSize.Width - 1,
                                this.CentralPositionInInput.X + inputRadius);
                minY = Math.Max ( 0, this.CentralPositionInInput.Y - inputRadius);
                maxY = Math.Min(this.Region.InputSize.Height - 1,
                                this.CentralPositionInInput.Y + inputRadius);
            }
            else
            {
                minX = 0;
                minY = 0;
                maxX = this.Region.InputSize.Width - 1;
                maxY = this.Region.InputSize.Height - 1;
            }

            // Compute input area
            // (3)
            int inputArea = (maxX - minX + 1) * (maxY - minY + 1);

            // Proximal synapses per Column (input segment)
            // TODO: give user some control over the number of synapses per segment
            //var synapsesPerSegment =

            //debug js
            //	(int) (inputArea * this.Region.PercentageInputPerColumn);
            // (4)
            var synapsesPerSegment = Math.Max(1, (int)(inputArea * this.Region.PercentageInputPerColumn));

            // JS
            //synapsesPerSegment = Math.Max ( 1, (int)(inputArea * this.Region.InputProportionX) );

            // Updates minimum overlap value, i.e. the minimum number of inputs that must
            // be active for a column to be considered during the inhibition step.
            //debug js
            //this.MinOverlap =
            //	(int) Math.Round(synapsesPerSegment * this.Region.PercentageMinOverlap);
            // (5)
            this.MinOverlap = Math.Max(1,
                (int)Math.Round ( synapsesPerSegment * this.Region.PercentageMinOverlap ));

            // Create all possible x,y positions for this column input space
            // (6)
            var inputPositions = new List<Point>();
            for (int y = minY; y <= maxY; y++)
            {
                for (int x = minX; x <= maxX; x++)
                {
                    var inputPosition = new Point(x, y);
                    inputPositions.Add(inputPosition);
                }
            }

            // Random sample of unique input positions (no duplicates).
            // Tie the random seed to this Column's position for reproducibility
            int randomSeed = (this.PositionInRegion.Y * this.Region.Size.Width) + this.PositionInRegion.X;
            // (7)
            IEnumerable<Point> inputRandomPositions =
                inputPositions.RandomSample(synapsesPerSegment, randomSeed, false);

            // Initialize the gaussian normal distribution
            // The values are chosen to be in a small range around connectedPerm
            // (the minimum permanence value at which a synapse is considered "connected")

            var gausianNormalDistribution =
                new Normal ( Synapse.InitialPermanence, Synapse.PermanenceIncrement );
            gausianNormalDistribution.RandomSource = new Random ( randomSeed );

            // Create proximal synapses to ramdom positions in input
            int longerSide = Math.Max(this.Region.InputSize.Width, this.Region.InputSize.Height);
            foreach (var position in inputRandomPositions)
            {
                var newInputCell = new InputCell(this.Region, position.X, position.Y);

                if (this.Region.FullDefaultSpatialPermanence)
                {
                    // Create new synapse and add it to segment
                    this.ProximalSegment.CreateSynapse(newInputCell, 1.0f);
                }
                else
                {
                    // Get new value for permanence from distribution
                    double permanence = gausianNormalDistribution.Sample();

                    // Distance from 'center' of this column to the current position in the input space
                    // JS - replaced with more precise code from Ultrafast
                    //var distanceInputFromColumn = new Point ();
                    //distanceInputFromColumn.X = this.CentralPositionInInput.X - position.X;
                    //distanceInputFromColumn.Y = this.CentralPositionInInput.Y - position.Y;
                    //double distanceToInput = Math.Sqrt (
                    //	(distanceInputFromColumn.X * distanceInputFromColumn.X) +
                    //	(distanceInputFromColumn.Y * distanceInputFromColumn.Y) );
                    double distanceX = this.CentralPositionInInput.X - position.X;
                    double distanceY = this.CentralPositionInInput.Y - position.Y;
                    double distanceToInput = Math.Sqrt ( distanceX * distanceX + distanceY * distanceY );

                    // Each column has a natural center over the input region, and the
                    // permanence values have a bias towards this center (they have higher values near
                    // the center)
                    int radiusBiasPeak = 2;
                    double radiusBiasStandardDeviation = 2.0; // 0.25;
                    double localityBias = radiusBiasPeak / 2.0 *
                                          Math.Exp(Math.Pow(distanceToInput /
                                            (longerSide * radiusBiasStandardDeviation), 2) / -2);

                    //StreamWriter file = new StreamWriter ( "localityBias.txt", false );

                    //for (float longSide = 1f; longSide < 10.0f; longSide += 1f)
                    //{
                    //	file.WriteLine ( "RadiusBiasPeak,distToInput,longerSide,SD,localityBias" );
                    //	for (float distToInput = 0.0f; distToInput < 2.0f; distToInput += 0.1f)
                    //	{
                    //		localityBias = radiusBiasPeak / 2.0f *
                    //						  Math.Exp ( Math.Pow ( distToInput /
                    //											(longSide * radiusBiasStandardDeviation), 2 ) / -2 );
                    //		file.WriteLine ( String.Format ( "{0:0.00},{1:0.00},{2:0.00},{3:0.00},{4:0.0000000}", radiusBiasPeak, distToInput, longSide, radiusBiasStandardDeviation, localityBias ) );
                    //	}
                    //}
                    //file.Close ();

                    double permanenceBias = Math.Min(1.0f, permanence * localityBias);
                    // Create new synapse and add it to segment
                    this.ProximalSegment.CreateSynapse(newInputCell, permanenceBias);
                }
            }
        }
Beispiel #4
0
        /// <summary>
        /// For each (position in inputSpaceRandomPositions):
        ///  1. Create a new InputCell with input bit = position
        ///  2. Attach a new ProximalSynapse
        ///  3. Add the synapse to the synapse update list.
        /// </summary>
        /// <remarks>
        /// Prior to receiving any inputs, the region is initialized by computing a list of
        /// initial potential synapses for each column. This consists of a random set of inputs
        /// selected from the input space. Each input is represented by a synapse and assigned
        /// a random permanence value. The random permanence values are chosen with two
        /// criteria. First, the values are chosen to be in a small range around connectedPerm
        /// (the minimum permanence value at which a synapse is considered "connected"). This
        /// enables potential synapses to become connected (or disconnected) after a small
        /// number of training iterations. Second, each column has a natural center over the
        /// input region, and the permanence values have a bias towards this center (they
        /// have higher values near the center).
        ///
        /// The concept of Locality Radius is an additional parameter to control how
        /// far away synapse connections can be made instead of allowing connections anywhere.
        /// The reason for this is that in the case of video images I wanted to experiment
        /// with forcing each Column to only learn on a small section of the total input to
        /// more effectively learn lines or corners in a small section.
        /// </remarks>
        internal void CreateProximalSegments()
        {
            // Calculates inputRadius for Columns from localityRadius
            //var inputRadius = (int)Math.Round ( this.Region.LocalityRadius * this.Region.InputProportionX );
            // JS
            // JS - should there be 2 inputRadiae, for X and Y, to allow for non-square input fields?
            //(1)
            var inputRadius = (int)Math.Max(1, Math.Round(this.Region.LocalityRadius * this.Region.InputProportionX));
            //inputRadius = (int)Math.Max ( 1, Math.Round ( this.Region.PercentageInputPerColumn * this.Region.InputSize.Height * this.Region.InputSize.Width ) / 2 );
            //var inputRadius = (int)Math.Max ( 1, Math.Round ( this.Region.LocalityRadius * Math.Max ( this.Region.InputProportionX, this.Region.InputProportionY ) ) );

            // The coordinates of the input space for the Column
            // Think of input space like a 'imaginary' square below the column center.
            int minY, maxY, minX, maxX;

            //(2)
            if (this.Region.LocalityRadius > 0)
            {
                // Compute values of input square and cut radius on edges
                minX = Math.Max(0, this.CentralPositionInInput.X - inputRadius);
                maxX = Math.Min(this.Region.InputSize.Width - 1,
                                this.CentralPositionInInput.X + inputRadius);
                minY = Math.Max(0, this.CentralPositionInInput.Y - inputRadius);
                maxY = Math.Min(this.Region.InputSize.Height - 1,
                                this.CentralPositionInInput.Y + inputRadius);
            }
            else
            {
                minX = 0;
                minY = 0;
                maxX = this.Region.InputSize.Width - 1;
                maxY = this.Region.InputSize.Height - 1;
            }

            // Compute input area
            // (3)
            int inputArea = (maxX - minX + 1) * (maxY - minY + 1);

            // Proximal synapses per Column (input segment)
            // TODO: give user some control over the number of synapses per segment
            //var synapsesPerSegment =

            //debug js
            //	(int) (inputArea * this.Region.PercentageInputPerColumn);
            // (4)
            var synapsesPerSegment = Math.Max(1, (int)(inputArea * this.Region.PercentageInputPerColumn));

            // JS
            //synapsesPerSegment = Math.Max ( 1, (int)(inputArea * this.Region.InputProportionX) );

            // Updates minimum overlap value, i.e. the minimum number of inputs that must
            // be active for a column to be considered during the inhibition step.
            //debug js
            //this.MinOverlap =
            //	(int) Math.Round(synapsesPerSegment * this.Region.PercentageMinOverlap);
            // (5)
            this.MinOverlap = Math.Max(1,
                                       (int)Math.Round(synapsesPerSegment * this.Region.PercentageMinOverlap));

            // Create all possible x,y positions for this column input space
            // (6)
            var inputPositions = new List <Point>();

            for (int y = minY; y <= maxY; y++)
            {
                for (int x = minX; x <= maxX; x++)
                {
                    var inputPosition = new Point(x, y);
                    inputPositions.Add(inputPosition);
                }
            }

            // Random sample of unique input positions (no duplicates).
            // Tie the random seed to this Column's position for reproducibility
            int randomSeed = (this.PositionInRegion.Y * this.Region.Size.Width) + this.PositionInRegion.X;
            // (7)
            IEnumerable <Point> inputRandomPositions =
                inputPositions.RandomSample(synapsesPerSegment, randomSeed, false);

            // Initialize the gaussian normal distribution
            // The values are chosen to be in a small range around connectedPerm
            // (the minimum permanence value at which a synapse is considered "connected")

            var gausianNormalDistribution =
                new Normal(Synapse.InitialPermanence, Synapse.PermanenceIncrement);

            gausianNormalDistribution.RandomSource = new Random(randomSeed);

            // Create proximal synapses to ramdom positions in input
            int longerSide = Math.Max(this.Region.InputSize.Width, this.Region.InputSize.Height);

            foreach (var position in inputRandomPositions)
            {
                var newInputCell = new InputCell(this.Region, position.X, position.Y);

                if (this.Region.FullDefaultSpatialPermanence)
                {
                    // Create new synapse and add it to segment
                    this.ProximalSegment.CreateSynapse(newInputCell, 1.0f);
                }
                else
                {
                    // Get new value for permanence from distribution
                    double permanence = gausianNormalDistribution.Sample();

                    // Distance from 'center' of this column to the current position in the input space
                    // JS - replaced with more precise code from Ultrafast
                    //var distanceInputFromColumn = new Point ();
                    //distanceInputFromColumn.X = this.CentralPositionInInput.X - position.X;
                    //distanceInputFromColumn.Y = this.CentralPositionInInput.Y - position.Y;
                    //double distanceToInput = Math.Sqrt (
                    //	(distanceInputFromColumn.X * distanceInputFromColumn.X) +
                    //	(distanceInputFromColumn.Y * distanceInputFromColumn.Y) );
                    double distanceX       = this.CentralPositionInInput.X - position.X;
                    double distanceY       = this.CentralPositionInInput.Y - position.Y;
                    double distanceToInput = Math.Sqrt(distanceX * distanceX + distanceY * distanceY);

                    // Each column has a natural center over the input region, and the
                    // permanence values have a bias towards this center (they have higher values near
                    // the center)
                    int    radiusBiasPeak = 2;
                    double radiusBiasStandardDeviation = 2.0;                     // 0.25;
                    double localityBias = radiusBiasPeak / 2.0 *
                                          Math.Exp(Math.Pow(distanceToInput /
                                                            (longerSide * radiusBiasStandardDeviation), 2) / -2);

                    //StreamWriter file = new StreamWriter ( "localityBias.txt", false );

                    //for (float longSide = 1f; longSide < 10.0f; longSide += 1f)
                    //{
                    //	file.WriteLine ( "RadiusBiasPeak,distToInput,longerSide,SD,localityBias" );
                    //	for (float distToInput = 0.0f; distToInput < 2.0f; distToInput += 0.1f)
                    //	{
                    //		localityBias = radiusBiasPeak / 2.0f *
                    //						  Math.Exp ( Math.Pow ( distToInput /
                    //											(longSide * radiusBiasStandardDeviation), 2 ) / -2 );
                    //		file.WriteLine ( String.Format ( "{0:0.00},{1:0.00},{2:0.00},{3:0.00},{4:0.0000000}", radiusBiasPeak, distToInput, longSide, radiusBiasStandardDeviation, localityBias ) );
                    //	}
                    //}
                    //file.Close ();

                    double permanenceBias = Math.Min(1.0f, permanence * localityBias);
                    // Create new synapse and add it to segment
                    this.ProximalSegment.CreateSynapse(newInputCell, permanenceBias);
                }
            }
        }
Beispiel #5
0
 /// <summary>
 /// Create a new synapse for this segment attached to the specified input cell.
 /// </summary>
 /// <param name="inputSource">the input source of the synapse to create.</param>
 /// <param name="initialPermanence">the initial permanence of the synapse.</param>
 internal void CreateSynapse(InputCell inputSource, double initialPermanence)
 {
     var newSynapse = new ProximalSynapse(this, inputSource, (float)initialPermanence);
     this.Synapses.Add(newSynapse);
 }
Beispiel #6
0
        /// <summary>
        /// Create a new synapse for this segment attached to the specified input cell.
        /// </summary>
        /// <param name="inputSource">the input source of the synapse to create.</param>
        /// <param name="initialPermanence">the initial permanence of the synapse.</param>
        internal void CreateSynapse(InputCell inputSource, double initialPermanence)
        {
            var newSynapse = new ProximalSynapse(this, inputSource, (float)initialPermanence);

            this.Synapses.Add(newSynapse);
        }