Ejemplo n.º 1
0
 def testAdaptShouldRemoveSegments(self):
   """
   Test that connections are generated on predefined segments.
   """
   random = Random(1981)
   active_cells = np.array(random.sample(np.arange(0, NUM_CELLS, 1, dtype="uint32"), 40), dtype="uint32")
   active_cells.sort()
   
   presynaptic_input = list(range(0, 10))
   inputSDR = SDR(1024)
   inputSDR.sparse = presynaptic_input
   
   connections = Connections(NUM_CELLS, 0.51) 
   for i in range(NUM_CELLS):
     seg = connections.createSegment(i, 2)
     seg = connections.createSegment(i, 2) #create 2 segments on each cell
   
   for cell in active_cells:
       segments = connections.segmentsForCell(cell)
       self.assertEqual(len(segments), 2, "Segments were prematurely destroyed.")
       segment = segments[0]
       numSynapsesOnSegment = len(segments)
       connections.adaptSegment(segment, inputSDR, 0.1, 0.001, pruneZeroSynapses=True, segmentThreshold=1) #set to =1 so that segments get always deleted in this test
       segments = connections.segmentsForCell(cell)
       self.assertEqual(len(segments), 1, "Segments were not destroyed.")
Ejemplo n.º 2
0
    def testAdaptShouldRemoveSegments(self):
        """
    Test that connections are generated on predefined segments.
    """
        random = Random(1981)
        active_cells = np.array(random.sample(
            np.arange(0, NUM_CELLS, 1, dtype="uint32"), 40),
                                dtype="uint32")
        active_cells.sort()

        presynaptic_input = list(range(0, 10))
        inputSDR = SDR(1024)
        inputSDR.sparse = presynaptic_input

        connections = Connections(NUM_CELLS, 0.51)
        for i in range(NUM_CELLS):
            seg = connections.createSegment(i, 1)

        for cell in active_cells:
            segments = connections.segmentsForCell(cell)
            self.assertEqual(len(segments), 1,
                             "Segments were prematurely destroyed.")
            segment = segments[0]
            connections.adaptSegment(segment, inputSDR, 0.1, 0.001, True)
            segments = connections.segmentsForCell(cell)
            self.assertEqual(len(segments), 0, "Segments were not destroyed.")
Ejemplo n.º 3
0
    def testAdaptShouldIncrementSynapses(self):
        """
    Test that connections are generated on predefined segments.
    """
        random = Random(1981)
        active_cells = np.array(random.sample(
            np.arange(0, NUM_CELLS, 1, dtype="uint32"), 40),
                                dtype="uint32")
        active_cells.sort()

        presynaptic_input = list(range(0, 10))
        presynaptic_input_set = set(presynaptic_input)
        inputSDR = SDR(1024)
        inputSDR.sparse = presynaptic_input

        connections = Connections(NUM_CELLS, 0.51)
        for i in range(NUM_CELLS):
            seg = connections.createSegment(i, 1)

        for cell in active_cells:
            segments = connections.segmentsForCell(cell)
            segment = segments[0]
            for c in presynaptic_input:
                connections.createSynapse(segment, c, 0.1)
            connections.adaptSegment(segment, inputSDR, 0.1, 0.001, True)

            presynamptic_cells = self._getPresynapticCells(
                connections, segment, 0.2)
            self.assertEqual(presynamptic_cells, presynaptic_input_set,
                             "Missing synapses")

            presynamptic_cells = self._getPresynapticCells(
                connections, segment, 0.3)
            self.assertEqual(presynamptic_cells, set(), "Too many synapses")
Ejemplo n.º 4
0
    def testNumSynapses(self):
        """
    Test that connections are generated on predefined segments.
    """
        random = Random(1981)
        active_cells = np.array(random.sample(
            np.arange(0, NUM_CELLS, 1, dtype="uint32"), 40),
                                dtype="uint32")
        active_cells.sort()

        presynaptic_input = list(range(0, 10))
        presynaptic_input_set = set(presynaptic_input)
        inputSDR = SDR(1024)
        inputSDR.sparse = presynaptic_input

        connections = Connections(NUM_CELLS, 0.3)
        for i in range(NUM_CELLS):
            seg = connections.createSegment(i, 1)

        for cell in active_cells:
            segments = connections.segmentsForCell(cell)
            segment = segments[0]
            for c in presynaptic_input:
                connections.createSynapse(segment, c, 0.1)

            connections.adaptSegment(segment, inputSDR, 0.1, 0.0, False)

            num_synapses = connections.numSynapses(segment)
            self.assertEqual(num_synapses, len(presynaptic_input),
                             "Missing synapses")

        self.assertEqual(connections.numSynapses(),
                         len(presynaptic_input) * 40, "Missing synapses")
Ejemplo n.º 5
0
    def testShuffleEmpty(self):
        r = Random(42)
        arr = numpy.zeros([0], dtype="uint32")

        r.shuffle(arr)

        self.assertEqual(arr.size, 0)
Ejemplo n.º 6
0
    def testSampleNone(self):
        r = Random(42)
        population = numpy.array([1, 2, 3, 4], dtype="uint32")

        # Just make sure there is no exception thrown.
        choices = r.sample(population, 0)

        self.assertEqual(len(choices), 0)
Ejemplo n.º 7
0
    def testSample(self):
        r = Random(42)
        population = numpy.array([1, 2, 3, 4], dtype="uint32")

        choices = r.sample(population, 2)

        self.assertEqual(choices[0], 2)
        self.assertEqual(choices[1], 1)
Ejemplo n.º 8
0
    def testShuffle(self):
        r = Random(42)
        arr = numpy.array([1, 2, 3, 4], dtype="uint32")

        r.shuffle(arr)

        self.assertEqual(arr[0], 2)
        self.assertEqual(arr[1], 1)
        self.assertEqual(arr[2], 4)
        self.assertEqual(arr[3], 3)
Ejemplo n.º 9
0
    def _orderForCoordinate(cls, coordinate):
        """
        Returns the order for a coordinate.

        @param coordinate (np.array) Coordinate
        @return (float) A value in the interval [0, 1), representing the order of the coordinate
        """
        seed = cls._hashCoordinate(coordinate)
        rng = Random(seed)
        return rng.getReal64()
Ejemplo n.º 10
0
    def __init__(self, dataWidth, randomSeed):
        if dataWidth <= 0:
            raise ValueError("Parameter dataWidth must be > 0")

        # Arbitrary value that's compatible with UInt32 in the proto schema
        # for testing serialization of python-native property
        self._dataWidth = dataWidth

        # For testing serialization of object implemented in the extension
        self._rand = Random(randomSeed)
Ejemplo n.º 11
0
    def _bitForCoordinate(cls, coordinate, n):
        """
        Maps the coordinate to a bit in the SDR.

        @param coordinate (np.array) Coordinate
        @param n (int) The number of available bits in the SDR
        @return (int) The index to a bit in the SDR
        """
        seed = cls._hashCoordinate(coordinate)
        rng = Random(seed)
        return rng.getUInt32(n)
Ejemplo n.º 12
0
    def testComputeActivity(self):
        """
    Test that connections are generated on predefined segments.
    """
        random = Random(1981)
        active_cells = np.array(random.sample(
            np.arange(0, NUM_CELLS, 1, dtype="uint32"), 40),
                                dtype="uint32")
        active_cells.sort()

        presynaptic_input = list(range(0, 10))
        presynaptic_input_set = set(presynaptic_input)
        inputSDR = SDR(1024)
        inputSDR.sparse = presynaptic_input
        l = len(presynaptic_input)

        connections = Connections(NUM_CELLS, 0.51, False)
        for i in range(NUM_CELLS):
            seg = connections.createSegment(i, 1)

        numActiveConnectedSynapsesForSegment = connections.computeActivity(
            inputSDR, False)
        for count in numActiveConnectedSynapsesForSegment:
            self.assertEqual(count, 0, "Segment should not be active")

        for cell in active_cells:
            segments = connections.segmentsForCell(cell)
            segment = segments[0]
            for c in presynaptic_input:
                connections.createSynapse(segment, c, 0.1)

        numActiveConnectedSynapsesForSegment = connections.computeActivity(
            inputSDR, False)
        for count in numActiveConnectedSynapsesForSegment:
            self.assertEqual(count, 0, "Segment should not be active")

        for cell in active_cells:
            segments = connections.segmentsForCell(cell)
            segment = segments[0]
            connections.adaptSegment(segment, inputSDR, 0.5, 0.0, False)

        active_cells_set = set(active_cells)
        numActiveConnectedSynapsesForSegment = connections.computeActivity(
            inputSDR, False)
        for cell, count in enumerate(numActiveConnectedSynapsesForSegment):
            if cell in active_cells_set:
                self.assertEqual(count, l, "Segment should be active")
            else:
                self.assertEqual(count, 0, "Segment should not be active")
Ejemplo n.º 13
0
    def testSamplePopulationTooSmall(self):
        r = Random(42)
        population = numpy.array([1, 2, 3, 4], dtype="uint32")

        #RuntimeError and not ValueError because it goes to Cpp code and there is
        #just NTA_CHECK that raises runtime_error
        self.assertRaises(RuntimeError, r.sample, population, 999)
Ejemplo n.º 14
0
    def testSampleBadDtype(self):
        r = Random(42)
        population = numpy.array([1, 2, 3, 4], dtype="int64")

        # throws std::invalid_argument("Invalid numpy array precision used.");
        # in py_utils.hpp
        # so thats why it is ValueError and not TypeError
        self.assertRaises(ValueError, r.sample, population, 2)
Ejemplo n.º 15
0
    def __init__(self, n, w, num=100, seed=42):
        """
        @param n     (int)            Number of available bits in pattern
        @param w     (int/list) Number of on bits in pattern
                                                    If list, each pattern will have a `w` randomly
                                                    selected from the list.
        @param num (int)            Number of available patterns
        """
        # Save member variables
        self._n = n
        self._w = w
        self._num = num

        # Initialize member variables
        self._random = Random(seed)
        self._patterns = dict()

        self._generate()
Ejemplo n.º 16
0
    def testSampleSequenceRaisesTypeError(self):
        """Check that passing lists throws a TypeError.

    This behavior may change if sample is extended to understand sequences.
    """
        r = Random(42)
        population = [1, 2, 3, 4]

        self.assertRaises(TypeError, r.sample, population, 2)
Ejemplo n.º 17
0
    def testEquals(self):
        r1 = Random(42)
        v1 = r1.getReal64()
        i1 = r1.getUInt32()

        r2 = Random(42)
        v2 = r2.getReal64()
        i2 = r2.getUInt32()

        r3 = Random(66)

        self.assertEqual(v1, v2)
        self.assertEqual(i1, i2)
        self.assertEqual(r1, r2)
        self.assertNotEqual(r1, r3)
Ejemplo n.º 18
0
    def testComputeActivityUnion(self):
        """
    Test that connections are generated on predefined segments.
    """
        random = Random(1981)
        active_cells = np.array(random.sample(
            np.arange(0, NUM_CELLS, 1, dtype="uint32"), 40),
                                dtype="uint32")
        active_cells.sort()

        presynaptic_input1 = list(range(0, 10))
        presynaptic_input1_set = set(presynaptic_input1)
        presynaptic_input2 = list(range(10, 20))
        presynaptic_input2_set = set(presynaptic_input1)

        connections = Connections(NUM_CELLS, 0.51, False)
        for i in range(NUM_CELLS):
            seg = connections.createSegment(i, 1)

        self._learn(connections, active_cells, presynaptic_input1)
        self._learn(connections, active_cells, presynaptic_input2)

        numSynapses = connections.numSynapses()
        self.assertNotEqual(
            numSynapses, 40,
            "There should be a synapse for each presynaptic cell")

        active_cells_set = set(active_cells)
        inputSDR = SDR(1024)
        inputSDR.sparse = presynaptic_input1

        numActiveConnectedSynapsesForSegment = connections.computeActivity(
            inputSDR, False)
        for cell, count in enumerate(numActiveConnectedSynapsesForSegment):
            if cell in active_cells_set:
                self.assertNotEqual(count, 0, "Segment should be active")

        inputSDR.sparse = presynaptic_input2
        numActiveConnectedSynapsesForSegment = connections.computeActivity(
            inputSDR, False)
        for cell, count in enumerate(numActiveConnectedSynapsesForSegment):
            if cell in active_cells_set:
                self.assertNotEqual(count, 0, "Segment should be active")
Ejemplo n.º 19
0
 def testNoTopology(self):
     rng = Random(42)
     presyn = SDR([5, 6, 7, 8])
     postsyn = SDR([6, 5, 4, 3, 2, 1])
     postsyn.randomize(1. / postsyn.size)
     for sparsity in (0., 1., 1. / presyn.size):
         function = NoTopology(sparsity)
         pp = function(postsyn, presyn.dimensions, rng)
         assert (pp.dimensions == presyn.dimensions)
         assert (abs(pp.getSparsity() - sparsity) < (.25 / presyn.size))
Ejemplo n.º 20
0
def main():
  """Measure serialization performance of Random
  """
  r = Random(42)

  # Measure serialization
  startSerializationTime = time.time()

  for i in range(_SERIALIZATION_LOOPS):
    r.saveToFile("RandonSerialization.stream")

  elapsedSerializationTime = time.time() - startSerializationTime

  # Measure deserialization
  startDeserializationTime = time.time()

  for _ in range(_DESERIALIZATION_LOOPS):
    r.loadFromFile("RandonSerialization.stream")

  elapsedDeserializationTime = time.time() - startDeserializationTime

  # Print report
  print(_SERIALIZATION_LOOPS, "Serialization loops in", \
        elapsedSerializationTime, "seconds.")
  print("\t", elapsedSerializationTime/_SERIALIZATION_LOOPS, "seconds per loop.")

  print(deserializationCount, "Deserialization loops in", \
        elapsedDeserializationTime, "seconds.")
  print("\t", elapsedDeserializationTime/deserializationCount, "seconds per loop.")
Ejemplo n.º 21
0
    def testNupicRandomPickling(self):
        """Test pickling / unpickling of NuPIC randomness."""

        # Simple test: make sure that dumping / loading works...
        r = Random(42)
        pickledR = pickle.dumps(r)

        test1 = [r.getUInt32() for _ in range(10)]
        r = pickle.loads(pickledR)
        test2 = [r.getUInt32() for _ in range(10)]

        self.assertEqual(test1, test2,
                         "Simple NuPIC random pickle/unpickle failed.")

        # A little tricker: dump / load _after_ some numbers have been generated
        # (in the first test).  Things should still work...
        # ...the idea of this test is to make sure that the pickle code isn't just
        # saving the initial seed...
        pickledR = pickle.dumps(r)

        test3 = [r.getUInt32() for _ in range(10)]
        r = pickle.loads(pickledR)
        test4 = [r.getUInt32() for _ in range(10)]

        self.assertEqual(
            test3, test4,
            "NuPIC random pickle/unpickle didn't work for saving later state.")

        self.assertNotEqual(test1, test3,
                            "NuPIC random gave the same result twice.")
        self.assertNotEqual(test2, test4,
                            "NuPIC random gave the same result twice.")
Ejemplo n.º 22
0
    def __init__(
        self,
        size,
        sparsity,
        periods,
        seed=0,
    ):
        """
        Argument size is the total number of bits in the encoded output SDR.

        Argument sparsity is fraction of bits which this encoder activates in
        the output SDR.

        Argument periods is a list of distances.  The period of a module is the
        distance between the centers of a grid cells receptive fields.  The
        length of this list defines the number of distinct modules.

        Argument seed controls the pseudo-random-number-generator which this
        encoder uses.  This encoder produces deterministic output.  The seed
        zero is special, seed zero is replaced with a truly random seed.
        """
        self.size = size
        self.dimensions = (size, )
        self.sparsity = sparsity
        self.periods = tuple(sorted(float(p) for p in periods))
        assert (len(self.periods) > 0)
        assert (min(self.periods) >= 4)
        assert (self.sparsity >= 0)
        assert (self.sparsity <= 1)

        # Assign each module a range of cells in the output SDR.
        partitions = np.linspace(0, self.size, num=len(self.periods) + 1)
        partitions = list(zip(partitions, partitions[1:]))
        self.partitions_ = [(int(round(start)), int(round(stop)))
                            for start, stop in partitions]

        # Assign each module a random offset and orientation.
        rng = np.random.RandomState(seed=Random(seed).getUInt32())
        self.offsets_ = rng.uniform(0,
                                    max(self.periods) * 9,
                                    size=(self.size, 2))
        self.angles_ = []
        self.rot_mats_ = []
        for period in self.periods:
            angle = rng.uniform() * 2 * math.pi
            self.angles_.append(angle)
            c, s = math.cos(angle), math.sin(angle)
            R = np.array(((c, -s), (s, c)))
            self.rot_mats_.append(R)
Ejemplo n.º 23
0
    def testDefaultTopology(self):
        rng = Random(42)
        presyn = SDR([10, 10])
        postsyn = SDR([10, 10])
        postsyn.dense[0, 4] = 1
        postsyn.dense = postsyn.dense
        noWrap = DefaultTopology(1.0, 1.1, False)
        noWrapPP = noWrap(postsyn, presyn.dimensions, rng)
        assert (noWrapPP.dimensions == presyn.dimensions)
        assert (set(noWrapPP.sparse) == set([3, 4, 5, 13, 14, 15]))

        wrap = DefaultTopology(1.0, 1.1, True)
        wrapPP = wrap(postsyn, presyn.dimensions, rng)
        assert (set(wrapPP.sparse) == set([3, 4, 5, 13, 14, 15, 93, 94, 95]))

        potentialPct = DefaultTopology(0.5, 1.1, False)
        assert (potentialPct(postsyn, presyn.dimensions, rng).getSum() == 3)
Ejemplo n.º 24
0
    def __init__(self,
                 cellsPerAxis,
                 scale,
                 orientation,
                 anchorInputSize,
                 activationThreshold=10,
                 initialPermanence=0.21,
                 connectedPermanence=0.50,
                 learningThreshold=10,
                 sampleSize=20,
                 permanenceIncrement=0.1,
                 permanenceDecrement=0.0,
                 maxSynapsesPerSegment=-1,
                 maxSegmentsPerCell=255,
                 seed=42):

        self.cellsPerAxis = cellsPerAxis
        self.anchorInputSize = anchorInputSize
        self.scale = scale
        self.orientation = orientation

        self.activeCells = np.empty(0, dtype="int")

        # The cells that were activated by sensory input in an inference timestep,
        # or cells that were associated with sensory input in a learning timestep.
        self.sensoryAssociatedCells = np.empty(0, dtype="int")

        self.activeSegments = np.empty(0, dtype="uint32")

        self.connections = None

        self.initialPermanence = initialPermanence
        self.connectedPermanence = connectedPermanence
        self.learningThreshold = learningThreshold
        self.sampleSize = sampleSize
        self.permanenceIncrement = permanenceIncrement
        self.permanenceDecrement = permanenceDecrement
        self.activationThreshold = activationThreshold
        self.maxSynapsesPerSegment = maxSynapsesPerSegment
        self.maxSegmentsPerCell = maxSegmentsPerCell

        self.rng = Random(seed)
Ejemplo n.º 25
0
class PatternMachine(object):
    """
    Base pattern machine class.
    """
    def __init__(self, n, w, num=100, seed=42):
        """
        @param n     (int)            Number of available bits in pattern
        @param w     (int/list) Number of on bits in pattern
                                                    If list, each pattern will have a `w` randomly
                                                    selected from the list.
        @param num (int)            Number of available patterns
        """
        # Save member variables
        self._n = n
        self._w = w
        self._num = num

        # Initialize member variables
        self._random = Random(seed)
        self._patterns = dict()

        self._generate()

    def get(self, number):
        """
        Return a pattern for a number.

        @param number (int) Number of pattern

        @return (set) Indices of on bits
        """
        if not number in self._patterns:
            raise IndexError("Invalid number")

        return self._patterns[number]

    def addNoise(self, bits, amount):
        """
        Add noise to pattern.

        @param bits     (set)     Indices of on bits
        @param amount (float) Probability of switching an on bit with a random bit

        @return (set) Indices of on bits in noisy pattern
        """
        newBits = set()

        for bit in bits:
            if self._random.getReal64() < amount:
                newBits.add(self._random.getUInt32(self._n))
            else:
                newBits.add(bit)

        return newBits

    def numbersForBit(self, bit):
        """
        Return the set of pattern numbers that match a bit.

        @param bit (int) Index of bit

        @return (set) Indices of numbers
        """
        if bit >= self._n:
            raise IndexError("Invalid bit")

        numbers = set()

        for index, pattern in self._patterns.items():
            if bit in pattern:
                numbers.add(index)

        return numbers

    def numberMapForBits(self, bits):
        """
        Return a map from number to matching on bits,
        for all numbers that match a set of bits.

        @param bits (set) Indices of bits

        @return (dict) Mapping from number => on bits.
        """
        numberMap = dict()

        for bit in bits:
            numbers = self.numbersForBit(bit)

            for number in numbers:
                if not number in numberMap:
                    numberMap[number] = set()

                numberMap[number].add(bit)

        return numberMap

    def prettyPrintPattern(self, bits, verbosity=1):
        """
        Pretty print a pattern.

        @param bits            (set) Indices of on bits
        @param verbosity (int) Verbosity level

        @return (string) Pretty-printed text
        """
        numberMap = self.numberMapForBits(bits)
        text = ""

        numberList = []
        numberItems = sorted(iter(numberMap.items()),
                             key=lambda number_bits: len(number_bits[1]),
                             reverse=True)

        for number, bits in numberItems:

            if verbosity > 2:
                strBits = [str(n) for n in bits]
                numberText = "{0} (bits: {1})".format(number,
                                                      ",".join(strBits))
            elif verbosity > 1:
                numberText = "{0} ({1} bits)".format(number, len(bits))
            else:
                numberText = str(number)

            numberList.append(numberText)

        text += "[{0}]".format(", ".join(numberList))

        return text

    def _generate(self):
        """
        Generates set of random patterns.
        """
        candidates = np.array(list(range(self._n)), np.uint32)
        for i in range(self._num):
            self._random.shuffle(candidates)
            pattern = candidates[0:self._getW()]
            self._patterns[i] = set(pattern)

    def _getW(self):
        """
        Gets a value of `w` for use in generating a pattern.
        """
        w = self._w

        if type(w) is list:
            return w[self._random.getUInt32(len(w))]
        else:
            return w
Ejemplo n.º 26
0
class ColumnPooler(object):
    """
    This class constitutes a temporary implementation for a cross-column pooler.
    The implementation goal of this class is to prove basic properties before
    creating a cleaner implementation.
    """
    def __init__(
            self,
            inputWidth,
            lateralInputWidths=(),
            cellCount=4096,
            sdrSize=40,
            onlineLearning=False,
            maxSdrSize=None,
            minSdrSize=None,

            # Proximal
            synPermProximalInc=0.1,
            synPermProximalDec=0.001,
            initialProximalPermanence=0.6,
            sampleSizeProximal=20,
            minThresholdProximal=10,
            connectedPermanenceProximal=0.50,
            predictedInhibitionThreshold=20,

            # Distal
            synPermDistalInc=0.1,
            synPermDistalDec=0.001,
            initialDistalPermanence=0.6,
            sampleSizeDistal=20,
            activationThresholdDistal=13,
            connectedPermanenceDistal=0.50,
            inertiaFactor=1.,
            seed=42):
        """
        Parameters:
        ----------------------------
        @param  inputWidth (int)
                The number of bits in the feedforward input
    
        @param  lateralInputWidths (list of ints)
                The number of bits in each lateral input
    
        @param  sdrSize (int)
                The number of active cells in an object SDR
    
        @param  onlineLearning (Bool)
                Whether or not the column pooler should learn in online mode.
    
        @param  maxSdrSize (int)
                The maximum SDR size for learning.  If the column pooler has more
                than this many cells active, it will refuse to learn.  This serves
                to stop the pooler from learning when it is uncertain of what object
                it is sensing.
    
        @param  minSdrSize (int)
                The minimum SDR size for learning.  If the column pooler has fewer
                than this many active cells, it will create a new representation
                and learn that instead.  This serves to create separate
                representations for different objects and sequences.
    
                If online learning is enabled, this parameter should be at least
                inertiaFactor*sdrSize.  Otherwise, two different objects may be
                incorrectly inferred to be the same, as SDRs may still be active
                enough to learn even after inertial decay.
    
        @param  synPermProximalInc (float)
                Permanence increment for proximal synapses
    
        @param  synPermProximalDec (float)
                Permanence decrement for proximal synapses
    
        @param  initialProximalPermanence (float)
                Initial permanence value for proximal synapses
    
        @param  sampleSizeProximal (int)
                Number of proximal synapses a cell should grow to each feedforward
                pattern, or -1 to connect to every active bit
    
        @param  minThresholdProximal (int)
                Number of active synapses required for a cell to have feedforward
                support
    
        @param  connectedPermanenceProximal (float)
                Permanence required for a proximal synapse to be connected
    
        @param  predictedInhibitionThreshold (int)
                How much predicted input must be present for inhibitory behavior
                to be triggered.  Only has effects if onlineLearning is true.
    
        @param  synPermDistalInc (float)
                Permanence increment for distal synapses
    
        @param  synPermDistalDec (float)
                Permanence decrement for distal synapses
    
        @param  sampleSizeDistal (int)
                Number of distal synapses a cell should grow to each lateral
                pattern, or -1 to connect to every active bit
    
        @param  initialDistalPermanence (float)
                Initial permanence value for distal synapses
    
        @param  activationThresholdDistal (int)
                Number of active synapses required to activate a distal segment
    
        @param  connectedPermanenceDistal (float)
                Permanence required for a distal synapse to be connected
    
        @param  inertiaFactor (float)
                The proportion of previously active cells that remain
                active in the next timestep due to inertia (in the absence of
                inhibition).  If onlineLearning is enabled, should be at most
                1 - learningTolerance, or representations may incorrectly become
                mixed.
    
        @param  seed (int)
                Random number generator seed
        """

        assert maxSdrSize is None or maxSdrSize >= sdrSize
        assert minSdrSize is None or minSdrSize <= sdrSize

        self.inputWidth = inputWidth
        self.cellCount = cellCount
        self.sdrSize = sdrSize
        self.onlineLearning = onlineLearning
        if maxSdrSize is None:
            self.maxSdrSize = sdrSize
        else:
            self.maxSdrSize = maxSdrSize
        if minSdrSize is None:
            self.minSdrSize = sdrSize
        else:
            self.minSdrSize = minSdrSize
        self.synPermProximalInc = synPermProximalInc
        self.synPermProximalDec = synPermProximalDec
        self.initialProximalPermanence = initialProximalPermanence
        self.connectedPermanenceProximal = connectedPermanenceProximal
        self.sampleSizeProximal = sampleSizeProximal
        self.minThresholdProximal = minThresholdProximal
        self.predictedInhibitionThreshold = predictedInhibitionThreshold
        self.synPermDistalInc = synPermDistalInc
        self.synPermDistalDec = synPermDistalDec
        self.initialDistalPermanence = initialDistalPermanence
        self.connectedPermanenceDistal = connectedPermanenceDistal
        self.sampleSizeDistal = sampleSizeDistal
        self.activationThresholdDistal = activationThresholdDistal
        self.inertiaFactor = inertiaFactor
        self.lateralInputWidths = lateralInputWidths

        self.activeCells = np.empty(0, dtype="uint32")
        self._random = Random(seed)

        # Each cell potentially has
        # 1 proximal segment and 1+len(lateralInputWidths) distal segments.
        self.proximalPermanences = Connections(cellCount,
                                               connectedPermanenceProximal,
                                               False)  #inputWidth max synapses
        self.internalDistalPermanences = Connections(
            cellCount, connectedPermanenceDistal,
            False)  #cellCount max synapses
        self.distalPermanences = [
            Connections(cellCount, connectedPermanenceDistal, False)
            for _ in lateralInputWidths
        ]  #lateralInputWidths max synapses

        self.useInertia = True

    def compute(self,
                feedforwardInput=(),
                lateralInputs=(),
                feedforwardGrowthCandidates=None,
                learn=True,
                predictedInput=None):
        """
        Runs one time step of the column pooler algorithm.
    
        @param  feedforwardInput (sequence)
                Sorted indices of active feedforward input bits
    
        @param  lateralInputs (list of sequences)
                For each lateral layer, a list of sorted indices of active lateral
                input bits
    
        @param  feedforwardGrowthCandidates (sequence or None)
                Sorted indices of feedforward input bits that active cells may grow
                new synapses to. If None, the entire feedforwardInput is used.
    
        @param  learn (bool)
                If True, we are learning a new object
    
        @param predictedInput (sequence)
               Sorted indices of predicted cells in the TM layer.
        """

        if feedforwardGrowthCandidates is None:
            feedforwardGrowthCandidates = feedforwardInput

        # inference step
        if not learn:
            self._computeInferenceMode(feedforwardInput, lateralInputs)

        # learning step
        elif not self.onlineLearning:
            self._computeLearningMode(feedforwardInput, lateralInputs,
                                      feedforwardGrowthCandidates)
        # online learning step
        else:
            if (predictedInput is not None and
                    len(predictedInput) > self.predictedInhibitionThreshold):
                predictedActiveInput = np.intersect1d(feedforwardInput,
                                                      predictedInput)
                #                 predictedGrowthCandidates = np.intersect1d(feedforwardGrowthCandidates, predictedInput)
                self._computeInferenceMode(predictedActiveInput, lateralInputs)
                self._computeLearningMode(predictedActiveInput, lateralInputs,
                                          feedforwardGrowthCandidates)
            elif not self.minSdrSize <= len(
                    self.activeCells) <= self.maxSdrSize:
                # If the pooler doesn't have a single representation, try to infer one,
                # before actually attempting to learn.
                self._computeInferenceMode(feedforwardInput, lateralInputs)
                self._computeLearningMode(feedforwardInput, lateralInputs,
                                          feedforwardGrowthCandidates)
            else:
                # If there isn't predicted input and we have a single SDR,
                # we are extending that representation and should just learn.
                self._computeLearningMode(feedforwardInput, lateralInputs,
                                          feedforwardGrowthCandidates)

    def _computeLearningMode(self, feedforwardInput, lateralInputs,
                             feedforwardGrowthCandidates):
        """
        Learning mode: we are learning a new object in an online fashion. If there
        is no prior activity, we randomly activate 'sdrSize' cells and create
        connections to incoming input. If there was prior activity, we maintain it.
        If we have a union, we simply do not learn at all.
    
        These cells will represent the object and learn distal connections to each
        other and to lateral cortical columns.
    
        Parameters:
        ----------------------------
        @param  feedforwardInput (sequence)
                Sorted indices of active feedforward input bits
    
        @param  lateralInputs (list of sequences)
                For each lateral layer, a list of sorted indices of active lateral
                input bits
    
        @param  feedforwardGrowthCandidates (sequence or None)
                Sorted indices of feedforward input bits that the active cells may
                grow new synapses to.  This is assumed to be the predicted active
                cells of the input layer.
        """
        prevActiveCells = self.activeCells

        # If there are not enough previously active cells, then we are no longer on
        # a familiar object.    Either our representation decayed due to the passage
        # of time (i.e. we moved somewhere else) or we were mistaken.    Either way,
        # create a new SDR and learn on it.
        # This case is the only way different object representations are created.
        # enforce the active cells in the output layer
        if len(self.activeCells) < self.minSdrSize:
            self.activeCells = self._sampleRange(0,
                                                 self.numberOfCells(),
                                                 step=1,
                                                 k=self.sdrSize)
            self.activeCells.sort()

        # If we have a union of cells active, don't learn.    This primarily affects
        # online learning.
        if len(self.activeCells) > self.maxSdrSize:
            return

        # Finally, now that we have decided which cells we should be learning on, do
        # the actual learning.
        if len(feedforwardInput) > 0:
            feedforwardInputSDR = SDR(self.inputWidth)
            feedforwardInputSDR.sparse = feedforwardInput
            self._learn(self.proximalPermanences, feedforwardInputSDR,
                        feedforwardGrowthCandidates, self.sampleSizeProximal,
                        self.initialProximalPermanence,
                        self.synPermProximalInc, self.synPermProximalDec,
                        self.connectedPermanenceProximal)

            # External distal learning
            for i, lateralInput in enumerate(lateralInputs):
                if len(lateralInput) > 0:
                    lateralInputSDR = SDR(self.lateralInputWidths[i])
                    lateralInputSDR.sparse = lateralInput
                    self._learn(self.distalPermanences[i], lateralInputSDR,
                                lateralInput, self.sampleSizeDistal,
                                self.initialDistalPermanence,
                                self.synPermDistalInc, self.synPermDistalDec,
                                self.connectedPermanenceDistal)

            # Internal distal learning
            if len(prevActiveCells):
                prevActiveCellsSDR = SDR(self.cellCount)
                prevActiveCellsSDR.sparse = prevActiveCells
                self._learn(self.internalDistalPermanences, prevActiveCellsSDR,
                            prevActiveCells, self.sampleSizeDistal,
                            self.initialDistalPermanence,
                            self.synPermDistalInc, self.synPermDistalDec,
                            self.connectedPermanenceDistal)

    def _computeInferenceMode(self, feedforwardInput, lateralInputs):
        """
        Inference mode: if there is some feedforward activity, perform
        spatial pooling on it to recognize previously known objects, then use
        lateral activity to activate a subset of the cells with feedforward
        support. If there is no feedforward activity, use lateral activity to
        activate a subset of the previous active cells.
    
        Parameters:
        ----------------------------
        @param  feedforwardInput (sequence)
                Sorted indices of active feedforward input bits
    
        @param  lateralInputs (list of sequences)
                For each lateral layer, a list of sorted indices of active lateral
                input bits
        """
        prevActiveCells = self.activeCells

        # Calculate the feedforward supported cells
        feedforwardInputSDR = SDR(self.inputWidth)
        feedforwardInputSDR.sparse = feedforwardInput
        activeSegments = self.proximalPermanences.computeActiveSegments(
            feedforwardInputSDR, self.minThresholdProximal)
        feedforwardSupportedCells = self.proximalPermanences.mapSegmentsToCells(
            activeSegments)

        # Calculate the number of active segments on each cell
        numActiveSegmentsByCell = np.zeros(self.cellCount, dtype="int")

        prevActiveCellsSDR = SDR(self.cellCount)
        prevActiveCellsSDR.sparse = prevActiveCells
        activeSegments = self.internalDistalPermanences.computeActiveSegments(
            prevActiveCellsSDR, self.activationThresholdDistal)
        for cell in self.proximalPermanences.mapSegmentsToCells(
                activeSegments):
            numActiveSegmentsByCell[cell] += 1

        for i, lateralInput in enumerate(lateralInputs):
            lateralInputSDR = SDR(self.lateralInputWidths[i])
            lateralInputSDR.sparse = lateralInput
            activeSegments = self.distalPermanences[i].computeActiveSegments(
                lateralInputSDR, self.activationThresholdDistal)
            for cell in self.proximalPermanences.mapSegmentsToCells(
                    activeSegments):
                numActiveSegmentsByCell[cell] += 1

        chosenCells = []

        # First, activate the FF-supported cells that have the highest number of
        # lateral active segments (as long as it's not 0)
        if len(feedforwardSupportedCells) == 0:
            pass
        else:
            numActiveSegsForFFSuppCells = numActiveSegmentsByCell[
                feedforwardSupportedCells]

            # This loop will select the FF-supported AND laterally-active cells, in
            # order of descending lateral activation, until we exceed the sdrSize
            # quorum - but will exclude cells with 0 lateral active segments.
            ttop = np.max(numActiveSegsForFFSuppCells)
            while ttop > 0 and len(chosenCells) < self.sdrSize:
                supportedCells = [
                    feedforwardSupportedCells[i]
                    for i in range(len(feedforwardSupportedCells))
                    if numActiveSegsForFFSuppCells[i] >= ttop
                ]
                chosenCells = np.union1d(chosenCells, supportedCells)
                ttop -= 1

        # If we haven't filled the sdrSize quorum, add in inertial cells.
        if len(chosenCells) < self.sdrSize:
            if self.useInertia:
                prevCells = np.setdiff1d(prevActiveCells, chosenCells)
                inertialCap = int(len(prevCells) * self.inertiaFactor)
                if inertialCap > 0:
                    numActiveSegsForPrevCells = numActiveSegmentsByCell[
                        prevCells]
                    # We sort the previously-active cells by number of active lateral
                    # segments (this really helps).    We then activate them in order of
                    # descending lateral activation.
                    sortIndices = np.argsort(numActiveSegsForPrevCells)[::-1]
                    prevCells = prevCells[sortIndices]
                    numActiveSegsForPrevCells = numActiveSegsForPrevCells[
                        sortIndices]

                    # We use inertiaFactor to limit the number of previously-active cells
                    # which can become active, forcing decay even if we are below quota.
                    prevCells = prevCells[:inertialCap]
                    numActiveSegsForPrevCells = numActiveSegsForPrevCells[:
                                                                          inertialCap]

                    # Activate groups of previously active cells by order of their lateral
                    # support until we either meet quota or run out of cells.
                    ttop = np.max(numActiveSegsForPrevCells)
                    while ttop >= 0 and len(chosenCells) < self.sdrSize:
                        chosenCells = np.union1d(
                            chosenCells,
                            prevCells[numActiveSegsForPrevCells >= ttop])
                        ttop -= 1

        # If we haven't filled the sdrSize quorum, add cells that have feedforward
        # support and no lateral support.
        discrepancy = self.sdrSize - len(chosenCells)
        if discrepancy > 0:
            remainingFFcells = np.setdiff1d(feedforwardSupportedCells,
                                            chosenCells)

            # Inhibit cells proportionally to the number of cells that have already
            # been chosen. If ~0 have been chosen activate ~all of the feedforward
            # supported cells. If ~sdrSize have been chosen, activate very few of
            # the feedforward supported cells.

            # Use the discrepancy:sdrSize ratio to determine the number of cells to
            # activate.
            n = (len(remainingFFcells) * discrepancy) // self.sdrSize
            # Activate at least 'discrepancy' cells.
            n = max(n, discrepancy)
            # If there aren't 'n' available, activate all of the available cells.
            n = min(n, len(remainingFFcells))

            if len(remainingFFcells) > n:
                selected = self._random.sample(remainingFFcells, n)
                chosenCells = np.append(chosenCells, selected)
            else:
                chosenCells = np.append(chosenCells, remainingFFcells)

        chosenCells.sort()
        self.activeCells = np.asarray(chosenCells, dtype="uint32")

    def numberOfInputs(self):
        """
        Returns the number of inputs into this layer
        """
        return self.inputWidth

    def numberOfCells(self):
        """
        Returns the number of cells in this layer.
        @return (int) Number of cells
        """
        return self.cellCount

    def getActiveCells(self):
        """
        Returns the indices of the active cells.
        @return (list) Indices of active cells.
        """
        return self.activeCells

    def numberOfConnectedProximalSynapses(self, cells=None):
        """
        Returns the number of proximal connected synapses on these cells.
    
        Parameters:
        ----------------------------
        @param  cells (iterable)
                Indices of the cells. If None return count for all cells.
        """
        if cells is None:
            cells = list(range(self.numberOfCells()))

        return self.proximalPermanences.numConnectedSynapsesForCells(cells)

    def numberOfProximalSynapses(self, cells=None):
        """
        Returns the number of proximal synapses with permanence>0 on these cells.
    
        Parameters:
        ----------------------------
        @param  cells (iterable)
                Indices of the cells. If None return count for all cells.
        """
        if cells is None:
            return self.proximalPermanences.numSynapses()

        return self.proximalPermanences.numSynapsesForCells(cells)

    def numberOfDistalSegments(self, cells=None):
        """
        Returns the total number of distal segments for these cells.
    
        A segment "exists" if its row in the matrix has any permanence values > 0.
    
        Parameters:
        ----------------------------
        @param  cells (iterable)
                Indices of the cells
        """
        if cells is None:
            cells = list(range(self.numberOfCells()))

        n = self.internalDistalPermanences.numSegmentsWithSynapses(cells)

        for permanences in self.distalPermanences:
            n += permanences.numSegmentsWithSynapses(cells)

        return n

    def numberOfConnectedDistalSynapses(self, cells=None):
        """
        Returns the number of connected distal synapses on these cells.
    
        Parameters:
        ----------------------------
        @param  cells (iterable)
                Indices of the cells. If None return count for all cells.
        """
        if cells is None:
            cells = list(range(self.numberOfCells()))

        n = self.internalDistalPermanences.numConnectedSynapsesForCells(cells)

        for permanences in self.distalPermanences:
            n += permanences.numConnectedSynapsesForCells(cells)

        return n

    def numberOfDistalSynapses(self, cells=None):
        """
        Returns the total number of distal synapses for these cells.
    
        Parameters:
        ----------------------------
        @param  cells (iterable)
                Indices of the cells
        """
        if cells is None:
            cells = list(range(self.numberOfCells()))

        n = self.internalDistalPermanences.numSynapsesForCells(cells)

        for permanences in self.distalPermanences:
            n += permanences.numSynapsesForCells(cells)

        return n

    def reset(self):
        """
        Reset internal states. When learning this signifies we are to learn a
        unique new object.
        """
        self.activeCells = np.empty(0, dtype="uint32")

    def getUseInertia(self):
        """
        Get whether we actually use inertia    (i.e. a fraction of the
        previously active cells remain active at the next time step unless
        inhibited by cells with both feedforward and lateral support).
        @return (Bool) Whether inertia is used.
        """
        return self.useInertia

    def setUseInertia(self, useInertia):
        """
        Sets whether we actually use inertia (i.e. a fraction of the
        previously active cells remain active at the next time step unless
        inhibited by cells with both feedforward and lateral support).
        @param useInertia (Bool) Whether inertia is used.
        """
        self.useInertia = useInertia

    def _learn(
            self,
            permanences,

            # activity
            activeInput,
            growthCandidateInput,

            # configuration
            sampleSize,
            initialPermanence,
            permanenceIncrement,
            permanenceDecrement,
            connectedPermanence):
        """
        For each active cell, reinforce active synapses, punish inactive synapses,
        and grow new synapses to a subset of the active input bits that the cell
        isn't already connected to.
    
        Parameters:
        ----------------------------
        @param  permanences (Connections)
                Matrix of permanences, with cells as rows and inputs as columns
    
        @param  activeInput (SDR)
                Active bits in the input
    
        @param  growthCandidateInput (sorted sequence)
                Sorted list of active bits in the input that the activeCells may
                grow new synapses to
    
        For remaining parameters, see the __init__ docstring.
        """

        active_input_array = activeInput.sparse
        growthCandidateInput = np.uint32(growthCandidateInput)

        for cell in self.activeCells:
            segments = permanences.segmentsForCell(cell)
            if not segments:
                segment = permanences.createSegment(cell, 1)
            else:
                segment = segments[0]  # Should only have one segment per cell

            permanences.adaptSegment(segment, activeInput, permanenceIncrement,
                                     permanenceDecrement, False)
            presynamptic_cells = np.array([
                permanences.presynapticCellForSynapse(synapse)
                for synapse in permanences.synapsesForSegment(segment)
            ])

            if sampleSize == -1:
                active_cells_without_synapses = np.setdiff1d(
                    growthCandidateInput,
                    presynamptic_cells,
                    assume_unique=True)

            else:
                active_cells_without_synapses = []

                existingSynapseCounts = len(
                    np.intersect1d(presynamptic_cells,
                                   active_input_array,
                                   assume_unique=True))
                effective_sample_size = sampleSize - existingSynapseCounts

                if effective_sample_size > 0:
                    active_cells_without_synapses = np.setdiff1d(
                        growthCandidateInput,
                        presynamptic_cells,
                        assume_unique=True)
                    if effective_sample_size < len(
                            active_cells_without_synapses):
                        active_cells_without_synapses = self._random.sample(
                            active_cells_without_synapses,
                            effective_sample_size)

            for c in active_cells_without_synapses:
                permanences.createSynapse(segment, c, initialPermanence)

    #
    # Functionality that could be added to the C code or bindings
    #
    def _sampleRange(self, start, end, step, k):
        """
        Equivalent to:
    
        random.sample(xrange(start, end, step), k)
    
        except it uses our random number generator.
        """
        return np.array(self._random.sample(
            np.arange(start, end, step, dtype="uint32"), k),
                        dtype="uint32")
Ejemplo n.º 27
0
class SerializationTestPyRegion(PyRegion):
    """Custom python region for testing serialization/deserialization of network
  containing a python region that contains a nupic.bindings-based Random
  instance.
  """
    def __init__(self, dataWidth, randomSeed):
        if dataWidth <= 0:
            raise ValueError("Parameter dataWidth must be > 0")

        # Arbitrary value that's compatible with UInt32 in the proto schema
        # for testing serialization of python-native property
        self._dataWidth = dataWidth

        # For testing serialization of object implemented in the extension
        self._rand = Random(randomSeed)

    @property
    def dataWidth(self):
        return self._dataWidth

    @property
    def randomSeed(self):
        return self._rand.getSeed()

    def initialize(self, dims=None, splitterMaps=None):
        pass

    def compute(self, inputs, outputs):
        """
    Run one iteration of SerializationTestPyRegion's compute
    """
        outputs["out"][:] = inputs["in"]

    @classmethod
    def getSpec(cls):
        """Return the Spec for SerializationTestPyRegion.
    """
        spec = {
            "description": SerializationTestPyRegion.__doc__,
            "singleNodeOnly": True,
            "inputs": {
                "in": {
                    "description": "The input vector.",
                    "dataType": "Real32",
                    "count": 0,
                    "required": True,
                    "regionLevel": False,
                    "isDefaultInput": True,
                    "requireSplitterMap": False
                },
            },
            "outputs": {
                "out": {
                    "description": "A copy of the input vector.",
                    "dataType": "Real32",
                    "count": 0,
                    "regionLevel": True,
                    "isDefaultOutput": True
                },
            },
            "parameters": {
                "dataWidth": {
                    "description": "Size of inputs",
                    "accessMode": "Create",
                    "dataType": "UInt32",
                    "count": 1,
                    "constraints": ""
                },
                "randomSeed": {
                    "description": "Seed for constructing the Random instance",
                    "accessMode": "Create",
                    "dataType": "UInt32",
                    "count": 1,
                    "constraints": ""
                },
            },
        }

        return spec

    def getOutputElementCount(self, name):
        if name == "out":
            return self._dataWidth
        else:
            raise Exception("Unrecognized output: " + name)
Ejemplo n.º 28
0
    def __init__(
            self,
            inputWidth,
            lateralInputWidths=(),
            cellCount=4096,
            sdrSize=40,
            onlineLearning=False,
            maxSdrSize=None,
            minSdrSize=None,

            # Proximal
            synPermProximalInc=0.1,
            synPermProximalDec=0.001,
            initialProximalPermanence=0.6,
            sampleSizeProximal=20,
            minThresholdProximal=10,
            connectedPermanenceProximal=0.50,
            predictedInhibitionThreshold=20,

            # Distal
            synPermDistalInc=0.1,
            synPermDistalDec=0.001,
            initialDistalPermanence=0.6,
            sampleSizeDistal=20,
            activationThresholdDistal=13,
            connectedPermanenceDistal=0.50,
            inertiaFactor=1.,
            seed=42):
        """
        Parameters:
        ----------------------------
        @param  inputWidth (int)
                The number of bits in the feedforward input
    
        @param  lateralInputWidths (list of ints)
                The number of bits in each lateral input
    
        @param  sdrSize (int)
                The number of active cells in an object SDR
    
        @param  onlineLearning (Bool)
                Whether or not the column pooler should learn in online mode.
    
        @param  maxSdrSize (int)
                The maximum SDR size for learning.  If the column pooler has more
                than this many cells active, it will refuse to learn.  This serves
                to stop the pooler from learning when it is uncertain of what object
                it is sensing.
    
        @param  minSdrSize (int)
                The minimum SDR size for learning.  If the column pooler has fewer
                than this many active cells, it will create a new representation
                and learn that instead.  This serves to create separate
                representations for different objects and sequences.
    
                If online learning is enabled, this parameter should be at least
                inertiaFactor*sdrSize.  Otherwise, two different objects may be
                incorrectly inferred to be the same, as SDRs may still be active
                enough to learn even after inertial decay.
    
        @param  synPermProximalInc (float)
                Permanence increment for proximal synapses
    
        @param  synPermProximalDec (float)
                Permanence decrement for proximal synapses
    
        @param  initialProximalPermanence (float)
                Initial permanence value for proximal synapses
    
        @param  sampleSizeProximal (int)
                Number of proximal synapses a cell should grow to each feedforward
                pattern, or -1 to connect to every active bit
    
        @param  minThresholdProximal (int)
                Number of active synapses required for a cell to have feedforward
                support
    
        @param  connectedPermanenceProximal (float)
                Permanence required for a proximal synapse to be connected
    
        @param  predictedInhibitionThreshold (int)
                How much predicted input must be present for inhibitory behavior
                to be triggered.  Only has effects if onlineLearning is true.
    
        @param  synPermDistalInc (float)
                Permanence increment for distal synapses
    
        @param  synPermDistalDec (float)
                Permanence decrement for distal synapses
    
        @param  sampleSizeDistal (int)
                Number of distal synapses a cell should grow to each lateral
                pattern, or -1 to connect to every active bit
    
        @param  initialDistalPermanence (float)
                Initial permanence value for distal synapses
    
        @param  activationThresholdDistal (int)
                Number of active synapses required to activate a distal segment
    
        @param  connectedPermanenceDistal (float)
                Permanence required for a distal synapse to be connected
    
        @param  inertiaFactor (float)
                The proportion of previously active cells that remain
                active in the next timestep due to inertia (in the absence of
                inhibition).  If onlineLearning is enabled, should be at most
                1 - learningTolerance, or representations may incorrectly become
                mixed.
    
        @param  seed (int)
                Random number generator seed
        """

        assert maxSdrSize is None or maxSdrSize >= sdrSize
        assert minSdrSize is None or minSdrSize <= sdrSize

        self.inputWidth = inputWidth
        self.cellCount = cellCount
        self.sdrSize = sdrSize
        self.onlineLearning = onlineLearning
        if maxSdrSize is None:
            self.maxSdrSize = sdrSize
        else:
            self.maxSdrSize = maxSdrSize
        if minSdrSize is None:
            self.minSdrSize = sdrSize
        else:
            self.minSdrSize = minSdrSize
        self.synPermProximalInc = synPermProximalInc
        self.synPermProximalDec = synPermProximalDec
        self.initialProximalPermanence = initialProximalPermanence
        self.connectedPermanenceProximal = connectedPermanenceProximal
        self.sampleSizeProximal = sampleSizeProximal
        self.minThresholdProximal = minThresholdProximal
        self.predictedInhibitionThreshold = predictedInhibitionThreshold
        self.synPermDistalInc = synPermDistalInc
        self.synPermDistalDec = synPermDistalDec
        self.initialDistalPermanence = initialDistalPermanence
        self.connectedPermanenceDistal = connectedPermanenceDistal
        self.sampleSizeDistal = sampleSizeDistal
        self.activationThresholdDistal = activationThresholdDistal
        self.inertiaFactor = inertiaFactor
        self.lateralInputWidths = lateralInputWidths

        self.activeCells = np.empty(0, dtype="uint32")
        self._random = Random(seed)

        # Each cell potentially has
        # 1 proximal segment and 1+len(lateralInputWidths) distal segments.
        self.proximalPermanences = Connections(cellCount,
                                               connectedPermanenceProximal,
                                               False)  #inputWidth max synapses
        self.internalDistalPermanences = Connections(
            cellCount, connectedPermanenceDistal,
            False)  #cellCount max synapses
        self.distalPermanences = [
            Connections(cellCount, connectedPermanenceDistal, False)
            for _ in lateralInputWidths
        ]  #lateralInputWidths max synapses

        self.useInertia = True
Ejemplo n.º 29
0
 def testRandomRNG(self):
     x = SDR(1000).randomize(.5, Random(77))
     y = SDR(1000).randomize(.5, Random(99))
     assert (x != y)
     z = SDR(1000).randomize(.5, Random(77))
     assert (x == z)
Ejemplo n.º 30
0
    def __init__(self,
                 columnCount=2048,
                 basalInputSize=0,
                 apicalInputSize=0,
                 cellsPerColumn=32,
                 activationThreshold=13,
                 reducedBasalThreshold=13,
                 initialPermanence=0.21,
                 connectedPermanence=0.50,
                 minThreshold=10,
                 sampleSize=20,
                 permanenceIncrement=0.1,
                 permanenceDecrement=0.1,
                 basalPredictedSegmentDecrement=0.0,
                 apicalPredictedSegmentDecrement=0.0,
                 maxSynapsesPerSegment=-1,
                 maxSegmentsPerCell=255,
                 seed=42):
        """
        @param columnCount (int)
        The number of minicolumns

        @param basalInputSize (sequence)
        The number of bits in the basal input

        @param apicalInputSize (int)
        The number of bits in the apical input

        @param cellsPerColumn (int)
        Number of cells per column

        @param activationThreshold (int)
        If the number of active connected synapses on a segment is at least this
        threshold, the segment is said to be active.

        @param reducedBasalThreshold (int)
        The activation threshold of basal (lateral) segments for cells that have
        active apical segments. If equal to activationThreshold (default),
        this parameter has no effect.

        @param initialPermanence (float)
        Initial permanence of a new synapse

        @param connectedPermanence (float)
        If the permanence value for a synapse is greater than this value, it is said
        to be connected.

        @param minThreshold (int)
        If the number of potential synapses active on a segment is at least this
        threshold, it is said to be "matching" and is eligible for learning.

        @param sampleSize (int)
        How much of the active SDR to sample with synapses.

        @param permanenceIncrement (float)
        Amount by which permanences of synapses are incremented during learning.

        @param permanenceDecrement (float)
        Amount by which permanences of synapses are decremented during learning.

        @param basalPredictedSegmentDecrement (float)
        Amount by which segments are punished for incorrect predictions.

        @param apicalPredictedSegmentDecrement (float)
        Amount by which segments are punished for incorrect predictions.

        @param maxSynapsesPerSegment
        The maximum number of synapses per segment.

        @param maxSegmentsPerCell
        The maximum number of segments per cell.
        
        @param seed (int)
        Seed for the random number generator.
        """

        self.columnCount = columnCount
        self.cellsPerColumn = cellsPerColumn
        self.initialPermanence = initialPermanence
        self.connectedPermanence = connectedPermanence
        self.reducedBasalThreshold = reducedBasalThreshold
        self.minThreshold = minThreshold
        self.sampleSize = sampleSize
        self.permanenceIncrement = permanenceIncrement
        self.permanenceDecrement = permanenceDecrement
        self.basalPredictedSegmentDecrement = basalPredictedSegmentDecrement
        self.apicalPredictedSegmentDecrement = apicalPredictedSegmentDecrement
        self.activationThreshold = activationThreshold
        self.maxSynapsesPerSegment = maxSynapsesPerSegment
        self.maxSegmentsPerCell = maxSegmentsPerCell

        self.basalConnections = Connections(columnCount*cellsPerColumn, connectedPermanence, False)
        self.apicalConnections = Connections(columnCount*cellsPerColumn, connectedPermanence, False)
        
        self.rng = Random(seed)
        self.activeCells = np.empty(0, dtype="uint32")
        self.winnerCells = np.empty(0, dtype="uint32")
        self.predictedCells = np.empty(0, dtype="uint32")
        self.predictedActiveCells = np.empty(0, dtype="uint32")
        self.activeBasalSegments = np.empty(0, dtype="uint32")
        self.activeApicalSegments = np.empty(0, dtype="uint32")
        self.matchingBasalSegments = np.empty(0, dtype="uint32")
        self.matchingApicalSegments = np.empty(0, dtype="uint32")
        self.basalPotentialOverlaps = np.empty(0, dtype="int32")
        self.apicalPotentialOverlaps = np.empty(0, dtype="int32")
        
        self.basalInputSize = basalInputSize
        self.apicalInputSize = apicalInputSize

        self.useApicalTiebreak=True
        self.useApicalModulationBasalThreshold=True