예제 #1
0
  def setUp(self):
    print ("\n"
           "======================================================\n"
           "Test: {0} \n"
           "{1}\n"
           "======================================================\n"
    ).format(self.id(), self.shortDescription())

    self.patternMachine = PatternMachine(1024, 20, num=100)
    self.sequenceMachine = SequenceMachine(self.patternMachine)

    self.tm = MonitoredTemporalMemory(
      mmName="TM",
      columnDimensions=[1024],
      cellsPerColumn=16,
      initialPermanence=0.5,
      connectedPermanence=0.7,
      minThreshold=20,
      maxNewSynapseCount=30,
      permanenceIncrement=0.1,
      permanenceDecrement=0.02,
      activationThreshold=20)

    self.tp = MonitoredTemporalPooler(
      inputDimensions=[1024, 16],
      columnDimensions=[1024],
      mmName="TP")

    self._showInternalStatePlots(appendTitle=" (initial)")
예제 #2
0
def generateSequences(patternDimensionality, patternCardinality,
                      sequenceLength, sequenceCount):
    patternAlphabetSize = sequenceLength * sequenceCount
    patternMachine = PatternMachine(patternDimensionality, patternCardinality,
                                    patternAlphabetSize)
    sequenceMachine = SequenceMachine(patternMachine)
    numbers = sequenceMachine.generateNumbers(sequenceCount, sequenceLength)
    generatedSequences = sequenceMachine.generateFromNumbers(numbers)

    return generatedSequences
예제 #3
0
    def testAddNoise(self):
        patternMachine = PatternMachine(10000, 1000, num=1)
        pattern = patternMachine.get(0)

        noisy = patternMachine.addNoise(pattern, 0.0)
        self.assertEqual(len(pattern & noisy), 1000)

        noisy = patternMachine.addNoise(pattern, 0.5)
        self.assertTrue(400 < len(pattern & noisy) < 600)

        noisy = patternMachine.addNoise(pattern, 1.0)
        self.assertTrue(50 < len(pattern & noisy) < 150)
예제 #4
0
    def testWList(self):
        w = [4, 7, 11]
        patternMachine = PatternMachine(100, w, num=50)
        widths = dict((el, 0) for el in w)

        for i in range(50):
            pattern = patternMachine.get(i)
            width = len(pattern)
            self.assertTrue(width in w)
            widths[len(pattern)] += 1

        for i in w:
            self.assertTrue(widths[i] > 0)
예제 #5
0
  def testWrite(self):
    tm1 = TemporalMemory(
      columnDimensions=[100],
      cellsPerColumn=4,
      activationThreshold=7,
      initialPermanence=0.37,
      connectedPermanence=0.58,
      minThreshold=4,
      maxNewSynapseCount=18,
      permanenceIncrement=0.23,
      permanenceDecrement=0.08,
      seed=91
    )

    # Run some data through before serializing
    self.patternMachine = PatternMachine(100, 4)
    self.sequenceMachine = SequenceMachine(self.patternMachine)
    sequence = self.sequenceMachine.generateFromNumbers(range(5))
    for _ in range(3):
      for pattern in sequence:
        tm1.compute(pattern)

    proto1 = TemporalMemoryProto_capnp.TemporalMemoryProto.new_message()
    tm1.write(proto1)

    # Write the proto to a temp file and read it back into a new proto
    with tempfile.TemporaryFile() as f:
      proto1.write(f)
      f.seek(0)
      proto2 = TemporalMemoryProto_capnp.TemporalMemoryProto.read(f)

    # Load the deserialized proto
    tm2 = TemporalMemory.read(proto2)

    # Check that the two temporal memory objects have the same attributes
    self.assertEqual(tm1, tm2)

    # Run a couple records through after deserializing and check results match
    tm1.compute(self.patternMachine.get(0))
    tm2.compute(self.patternMachine.get(0))
    self.assertEqual(tm1.activeCells, tm2.activeCells)
    self.assertEqual(tm1.predictiveCells, tm2.predictiveCells)
    self.assertEqual(tm1.winnerCells, tm2.winnerCells)
    self.assertEqual(tm1.connections, tm2.connections)

    tm1.compute(self.patternMachine.get(3))
    tm2.compute(self.patternMachine.get(3))
    self.assertEqual(tm1.activeCells, tm2.activeCells)
    self.assertEqual(tm1.predictiveCells, tm2.predictiveCells)
    self.assertEqual(tm1.winnerCells, tm2.winnerCells)
    self.assertEqual(tm1.connections, tm2.connections)
예제 #6
0
    def setUp(self):
        self.tmPy = TemporalMemoryPy(columnDimensions=[2048],
                                     cellsPerColumn=32,
                                     initialPermanence=0.5,
                                     connectedPermanence=0.8,
                                     minThreshold=10,
                                     maxNewSynapseCount=12,
                                     permanenceIncrement=0.1,
                                     permanenceDecrement=0.05,
                                     activationThreshold=15)

        self.tmCPP = TemporalMemoryCPP(columnDimensions=[2048],
                                       cellsPerColumn=32,
                                       initialPermanence=0.5,
                                       connectedPermanence=0.8,
                                       minThreshold=10,
                                       maxNewSynapseCount=12,
                                       permanenceIncrement=0.1,
                                       permanenceDecrement=0.05,
                                       activationThreshold=15)

        self.tp = TP(numberOfCols=2048,
                     cellsPerColumn=32,
                     initialPerm=0.5,
                     connectedPerm=0.8,
                     minThreshold=10,
                     newSynapseCount=12,
                     permanenceInc=0.1,
                     permanenceDec=0.05,
                     activationThreshold=15,
                     globalDecay=0,
                     burnIn=1,
                     checkSynapseConsistency=False,
                     pamLength=1)

        self.tp10x2 = TP10X2(numberOfCols=2048,
                             cellsPerColumn=32,
                             initialPerm=0.5,
                             connectedPerm=0.8,
                             minThreshold=10,
                             newSynapseCount=12,
                             permanenceInc=0.1,
                             permanenceDec=0.05,
                             activationThreshold=15,
                             globalDecay=0,
                             burnIn=1,
                             checkSynapseConsistency=False,
                             pamLength=1)

        self.patternMachine = PatternMachine(2048, 40, num=100)
        self.sequenceMachine = SequenceMachine(self.patternMachine)
예제 #7
0
def generateSequences(n=2048, w=40, sequenceLength=5, sequenceCount=2,
                      sharedRange=None, seed=42):
  """
  Generate high order sequences using SequenceMachine
  """
  # Lots of room for noise sdrs
  patternAlphabetSize = 10*(sequenceLength * sequenceCount)
  patternMachine = PatternMachine(n, w, patternAlphabetSize, seed)
  sequenceMachine = SequenceMachine(patternMachine, seed)
  numbers = sequenceMachine.generateNumbers(sequenceCount, sequenceLength,
                                            sharedRange=sharedRange )
  generatedSequences = sequenceMachine.generateFromNumbers(numbers)

  return sequenceMachine, generatedSequences, numbers
예제 #8
0
    def testAddSpatialNoise(self):
        patternMachine = PatternMachine(10000, 1000, num=100)
        sequenceMachine = SequenceMachine(patternMachine)
        numbers = range(0, 100)
        numbers.append(None)

        sequence = sequenceMachine.generateFromNumbers(numbers)
        noisy = sequenceMachine.addSpatialNoise(sequence, 0.5)

        overlap = len(noisy[0] & patternMachine.get(0))
        self.assertTrue(400 < overlap < 600)

        sequence = sequenceMachine.generateFromNumbers(numbers)
        noisy = sequenceMachine.addSpatialNoise(sequence, 0.0)

        overlap = len(noisy[0] & patternMachine.get(0))
        self.assertEqual(overlap, 1000)
예제 #9
0
    def setUp(self):
        """
    Sets up the test.
    """
        # single column case
        self.pooler = None

        # multi column case
        self.poolers = []

        # create pattern machine
        self.proximalPatternMachine = PatternMachine(
            n=self.inputWidth,
            w=self.numOutputActiveBits,
            num=200,
            seed=self.seed)

        self.patternId = 0
        np.random.seed(self.seed)
예제 #10
0
def generateSequences(patternDimensionality, patternCardinality, sequenceLength,
                      sequenceCount):
  # Generate a sequence list and an associated labeled list
  # (both containing a set of sequences separated by None)
  print "Generating sequences..."
  patternAlphabetSize = sequenceLength * sequenceCount
  patternMachine = PatternMachine(patternDimensionality, patternCardinality,
                                  patternAlphabetSize)
  sequenceMachine = SequenceMachine(patternMachine)
  numbers = sequenceMachine.generateNumbers(sequenceCount, sequenceLength)
  generatedSequences = sequenceMachine.generateFromNumbers(numbers)
  sequenceLabels = [
    str(numbers[i + i * sequenceLength: i + (i + 1) * sequenceLength])
    for i in xrange(sequenceCount)]
  labeledSequences = []
  for label in sequenceLabels:
    for _ in xrange(sequenceLength):
      labeledSequences.append(label)
    labeledSequences.append(None)

  return generatedSequences, labeledSequences
def generateSequences(patternCardinality, patternDimensionality,
                      numberOfSequences, sequenceLength, consoleVerbosity):
    patternAlphabetSize = sequenceLength * numberOfSequences
    patternMachine = PatternMachine(patternDimensionality, patternCardinality,
                                    patternAlphabetSize)
    sequenceMachine = SequenceMachine(patternMachine)
    numbers = sequenceMachine.generateNumbers(numberOfSequences,
                                              sequenceLength)
    inputSequences = sequenceMachine.generateFromNumbers(numbers)
    inputCategories = []
    for i in xrange(numberOfSequences):
        for _ in xrange(sequenceLength):
            inputCategories.append(i)
        inputCategories.append(None)
    if consoleVerbosity > 1:
        for i in xrange(len(inputSequences)):
            if inputSequences[i] is None:
                print
            else:
                print "{0} {1}".format(inputSequences[i], inputCategories[i])

    return inputSequences, inputCategories
def run(params, paramDir, outputDir, plotVerbosity=0, consoleVerbosity=0):
  """
  Runs the union overlap experiment.

  :param params: A dict of experiment parameters
  :param paramDir: Path of parameter file
  :param outputDir: Output will be written to this path
  :param plotVerbosity: Plotting verbosity
  :param consoleVerbosity: Console output verbosity
  """
  print "Running SDR overlap experiment...\n"
  print "Params dir: {0}".format(paramDir)
  print "Output dir: {0}\n".format(outputDir)

  # Dimensionality of sequence patterns
  patternDimensionality = params["patternDimensionality"]

  # Cardinality (ON / true bits) of sequence patterns
  patternCardinality = params["patternCardinality"]

  # TODO If this parameter is to be supported, the sequence generation code
  # below must change
  # Number of unique patterns from which sequences are built
  # patternAlphabetSize = params["patternAlphabetSize"]

  # Length of sequences shown to network
  sequenceLength = params["sequenceLength"]

  # Number of sequences used. Sequences may share common elements.
  numberOfSequences = params["numberOfSequences"]

  # Number of sequence passes for training the TM. Zero => no training.
  trainingPasses = params["trainingPasses"]

  tmParamOverrides = params["temporalMemoryParams"]
  upParamOverrides = params["unionPoolerParams"]

  # Generate a sequence list and an associated labeled list (both containing a
  # set of sequences separated by None)
  start = time.time()
  print "\nGenerating sequences..."
  patternAlphabetSize = sequenceLength * numberOfSequences
  patternMachine = PatternMachine(patternDimensionality, patternCardinality,
                                  patternAlphabetSize)
  sequenceMachine = SequenceMachine(patternMachine)

  numbers = sequenceMachine.generateNumbers(numberOfSequences, sequenceLength)
  generatedSequences = sequenceMachine.generateFromNumbers(numbers)
  sequenceLabels = [str(numbers[i + i*sequenceLength: i + (i+1)*sequenceLength])
                    for i in xrange(numberOfSequences)]
  labeledSequences = []
  for label in sequenceLabels:
    for _ in xrange(sequenceLength):
      labeledSequences.append(label)
    labeledSequences.append(None)

  # Set up the Temporal Memory and Union Pooler network
  print "\nCreating network..."
  experiment = UnionTemporalPoolerExperiment(tmParamOverrides, upParamOverrides)

  # Train only the Temporal Memory on the generated sequences
  if trainingPasses > 0:

    print "\nTraining Temporal Memory..."
    if consoleVerbosity > 0:
      print "\nPass\tBursting Columns Mean\tStdDev\tMax"

    for i in xrange(trainingPasses):
      experiment.runNetworkOnSequences(generatedSequences,
                                       labeledSequences,
                                       tmLearn=True,
                                       upLearn=None,
                                       verbosity=consoleVerbosity,
                                       progressInterval=_SHOW_PROGRESS_INTERVAL)

      if consoleVerbosity > 0:
        stats = experiment.getBurstingColumnsStats()
        print "{0}\t{1}\t{2}\t{3}".format(i, stats[0], stats[1], stats[2])

      # Reset the TM monitor mixin's records accrued during this training pass
      experiment.tm.mmClearHistory()

    print
    print MonitorMixinBase.mmPrettyPrintMetrics(
      experiment.tm.mmGetDefaultMetrics())
    print
    if plotVerbosity >= 2:
      plotNetworkState(experiment, plotVerbosity, trainingPasses,
                       phase="Training")

  print "\nRunning test phase..."
  experiment.runNetworkOnSequences(generatedSequences,
                                   labeledSequences,
                                   tmLearn=False,
                                   upLearn=False,
                                   verbosity=consoleVerbosity,
                                   progressInterval=_SHOW_PROGRESS_INTERVAL)

  print "\nPass\tBursting Columns Mean\tStdDev\tMax"
  stats = experiment.getBurstingColumnsStats()
  print "{0}\t{1}\t{2}\t{3}".format(0, stats[0], stats[1], stats[2])
  if trainingPasses > 0 and stats[0] > 0:
    print "***WARNING! MEAN BURSTING COLUMNS IN TEST PHASE IS GREATER THAN 0***"

  print
  print MonitorMixinBase.mmPrettyPrintMetrics(
      experiment.tm.mmGetDefaultMetrics() + experiment.up.mmGetDefaultMetrics())
  print
  plotNetworkState(experiment, plotVerbosity, trainingPasses, phase="Testing")

  elapsed = int(time.time() - start)
  print "Total time: {0:2} seconds.".format(elapsed)

  # Write Union SDR trace
  metricName = "activeCells"
  outputFileName = "unionSdrTrace_{0}learningPasses.csv".format(trainingPasses)
  writeMetricTrace(experiment, metricName, outputDir, outputFileName)

  if plotVerbosity >= 1:
    raw_input("Press any key to exit...")
예제 #13
0
patternCardinality = params["patternCardinality"]

# Length of sequences shown to network
sequenceLength = params["sequenceLength"]

# Number of sequences used. Sequences may share common elements.
numberOfSequences = params["numberOfSequences"]

# Number of sequence passes for training the TM. Zero => no training.
trainingPasses = params["trainingPasses"]

# Generate a sequence list and an associated labeled list (both containing a
# set of sequences separated by None)
print "\nGenerating sequences..."
patternAlphabetSize = sequenceLength * numberOfSequences
patternMachine = PatternMachine(patternDimensionality, patternCardinality,
                                patternAlphabetSize)
sequenceMachine = SequenceMachine(patternMachine)

numbers = sequenceMachine.generateNumbers(numberOfSequences, sequenceLength)
generatedSequences = sequenceMachine.generateFromNumbers(numbers)
sequenceLabels = [
    str(numbers[i + i * sequenceLength:i + (i + 1) * sequenceLength])
    for i in xrange(numberOfSequences)
]
labeledSequences = []
for label in sequenceLabels:
    for _ in xrange(sequenceLength):
        labeledSequences.append(label)
    labeledSequences.append(None)

예제 #14
0
 def getPatternMachine(self):
     return PatternMachine(self.n, self.w, num=300)
예제 #15
0
 def setUp(self):
     self.patternMachine = PatternMachine(10000, 5, num=50)
class ExtensiveTemporalMemoryTest(AbstractTemporalMemoryTest):
  """
  ==============================================================================
                  Basic First Order Sequences
  ==============================================================================

  These tests ensure the most basic (first order) sequence learning mechanism is
  working.

  Parameters: Use a "fast learning mode": initPerm should be greater than
  connectedPerm and permanenceDec should be zero. With these settings sequences
  should be learned in one pass:

    minThreshold = newSynapseCount
    initialPermanence = 0.8
    connectedPermanence = 0.7
    permanenceDecrement = 0
    permanenceIncrement = 0.4

  Other Parameters:
    columnDimensions = [100]
    cellsPerColumn = 1
    newSynapseCount = 11
    activationThreshold = 11

  Note: this is not a high order sequence, so one cell per column is fine.

  Input Sequence: We train with M input sequences, each consisting of N random
  patterns. Each pattern consists of a random number of bits on. The number of
  1's in each pattern should be between 21 and 25 columns.

  Each input pattern can optionally have an amount of spatial noise represented
  by X, where X is the probability of switching an on bit with a random bit.

  Training: The TP is trained with P passes of the M sequences. There
  should be a reset between sequences. The total number of iterations during
  training is P*N*M.

  Testing: Run inference through the same set of sequences, with a reset before
  each sequence. For each sequence the system should accurately predict the
  pattern at the next time step up to and including the N-1'st pattern. The number
  of predicted inactive cells at each time step should be reasonably low.

  We can also calculate the number of synapses that should be
  learned. We raise an error if too many or too few were learned.

  B1) Basic sequence learner.  M=1, N=100, P=1.

  B2) Same as above, except P=2. Test that permanences go up and that no
  additional synapses are learned. [TODO]

  B3) N=300, M=1, P=1. (See how high we can go with N)

  B4) N=100, M=3, P=1. (See how high we can go with N*M)

  B5) Like B1 but with cellsPerColumn = 4. First order sequences should still
  work just fine.

  B6) Like B4 but with cellsPerColumn = 4. First order sequences should still
  work just fine.

  B7) Like B1 but with slower learning. Set the following parameters differently:

      initialPermanence = 0.2
      connectedPermanence = 0.7
      permanenceIncrement = 0.2

  Now we train the TP with the B1 sequence 4 times (P=4). This will increment
  the permanences to be above 0.8 and at that point the inference will be correct.
  This test will ensure the basic match function and segment activation rules are
  working correctly.

  B8) Like B7 but with 4 cells per column. Should still work.

  B9) Like B7 but present the sequence less than 4 times: the inference should be
  incorrect.

  B10) Like B2, except that cells per column = 4. Should still add zero additional
  synapses. [TODO]

  B11) Like B5, but with activationThreshold = 8 and with each pattern
  corrupted by a small amount of spatial noise (X = 0.05).


  ===============================================================================
                  High Order Sequences
  ===============================================================================

  These tests ensure that high order sequences can be learned in a multiple cells
  per column instantiation.

  Parameters: Same as Basic First Order Tests above, but with varying cells per
  column.

  Input Sequence: We train with M input sequences, each consisting of N random
  patterns. Each pattern consists of a random number of bits on. The number of
  1's in each pattern should be between 21 and 25 columns. The sequences are
  constructed to contain shared subsequences, such as:

  A B C D E F G H I J
  K L M D E F N O P Q

  The position and length of shared subsequences are parameters in the tests.

  Each input pattern can optionally have an amount of spatial noise represented
  by X, where X is the probability of switching an on bit with a random bit.

  Training: Identical to basic first order tests above.

  Testing: Identical to basic first order tests above unless noted.

  We can also calculate the number of segments and synapses that should be
  learned. We raise an error if too many or too few were learned.

  H1) Learn two sequences with a shared subsequence in the middle. Parameters
  should be the same as B1. Since cellsPerColumn == 1, it should make more
  predictions than necessary.

  H2) Same as H1, but with cellsPerColumn == 4, and train multiple times.
  It should make just the right number of predictions.

  H3) Like H2, except the shared subsequence is in the beginning (e.g.
  "ABCDEF" and "ABCGHIJ"). At the point where the shared subsequence ends, all
  possible next patterns should be predicted. As soon as you see the first unique
  pattern, the predictions should collapse to be a perfect prediction.

  H4) Shared patterns. Similar to H2 except that patterns are shared between
  sequences.  All sequences are different shufflings of the same set of N
  patterns (there is no shared subsequence).

  H5) Combination of H4) and H2). Shared patterns in different sequences, with a
  shared subsequence.

  H6) Stress test: every other pattern is shared. [TODO]

  H7) Start predicting in the middle of a sequence. [TODO]

  H8) Hub capacity. How many patterns can use that hub? [TODO]

  H9) Sensitivity to small amounts of spatial noise during inference (X = 0.05).
  Parameters the same as B11, and sequences like H2.

  H10) Higher order patterns with alternating elements.

  Create the following 4 sequences:

       A B A B A C
       A B A B D E
       A B F G H I
       A J K L M N

  After training we should verify that the expected transitions are in the
  model. Prediction accuracy should be perfect. In addition, during inference,
  after the first element is presented, the columns should not burst any more.
  Need to verify, for the first sequence, that the high order representation
  when presented with the second A and B is different from the representation
  in the first presentation. [TODO]
  """

  VERBOSITY = 1
  DEFAULT_TM_PARAMS = {
    "columnDimensions": [100],
    "cellsPerColumn": 1,
    "initialPermanence": 0.8,
    "connectedPermanence": 0.7,
    "minThreshold": 11,
    "maxNewSynapseCount": 11,
    "permanenceIncrement": 0.4,
    "permanenceDecrement": 0,
    "activationThreshold": 11
  }
  PATTERN_MACHINE = PatternMachine(100, range(21, 26), num=300)


  def testB1(self):
    """Basic sequence learner.  M=1, N=100, P=1."""
    self.init()

    numbers = self.sequenceMachine.generateNumbers(1, 100)
    sequence = self.sequenceMachine.generateFromNumbers(numbers)

    self.feedTM(sequence)

    self._testTM(sequence)
    self.assertAllActiveWerePredicted()
    self.assertAllInactiveWereUnpredicted()


  def testB3(self):
    """N=300, M=1, P=1. (See how high we can go with N)"""
    self.init()

    numbers = self.sequenceMachine.generateNumbers(1, 300)
    sequence = self.sequenceMachine.generateFromNumbers(numbers)

    self.feedTM(sequence)

    self._testTM(sequence)
    self.assertAllActiveWerePredicted()
    self.assertAllInactiveWereUnpredicted()


  def testB4(self):
    """N=100, M=3, P=1. (See how high we can go with N*M)"""
    self.init()

    numbers = self.sequenceMachine.generateNumbers(3, 100)
    sequence = self.sequenceMachine.generateFromNumbers(numbers)

    self.feedTM(sequence)

    self._testTM(sequence)
    self.assertAllActiveWerePredicted()


  def testB5(self):
    """Like B1 but with cellsPerColumn = 4.
    First order sequences should still work just fine."""
    self.init({"cellsPerColumn": 4})

    numbers = self.sequenceMachine.generateNumbers(1, 100)
    sequence = self.sequenceMachine.generateFromNumbers(numbers)

    self.feedTM(sequence)

    self._testTM(sequence)
    self.assertAllActiveWerePredicted()
    self.assertAllInactiveWereUnpredicted()


  def testB6(self):
    """Like B4 but with cellsPerColumn = 4.
    First order sequences should still work just fine."""
    self.init({"cellsPerColumn": 4})

    numbers = self.sequenceMachine.generateNumbers(3, 100)
    sequence = self.sequenceMachine.generateFromNumbers(numbers)

    self.feedTM(sequence)

    self._testTM(sequence)
    self.assertAllActiveWerePredicted()
    self.assertAllInactiveWereUnpredicted()


  def testB7(self):
    """Like B1 but with slower learning.

    Set the following parameters differently:

      initialPermanence = 0.2
      connectedPermanence = 0.7
      permanenceIncrement = 0.2

    Now we train the TP with the B1 sequence 4 times (P=4). This will increment
    the permanences to be above 0.8 and at that point the inference will be correct.
    This test will ensure the basic match function and segment activation rules are
    working correctly.
    """
    self.init({"initialPermanence": 0.2,
               "connectedPermanence": 0.7,
               "permanenceIncrement": 0.2})

    numbers = self.sequenceMachine.generateNumbers(1, 100)
    sequence = self.sequenceMachine.generateFromNumbers(numbers)

    for _ in xrange(4):
      self.feedTM(sequence)

    self._testTM(sequence)
    self.assertAllActiveWerePredicted()
    self.assertAllInactiveWereUnpredicted()


  def testB8(self):
    """Like B7 but with 4 cells per column.
    Should still work."""
    self.init({"initialPermanence": 0.2,
               "connectedPermanence": 0.7,
               "permanenceIncrement": 0.2,
               "cellsPerColumn": 4})

    numbers = self.sequenceMachine.generateNumbers(1, 100)
    sequence = self.sequenceMachine.generateFromNumbers(numbers)

    for _ in xrange(4):
      self.feedTM(sequence)

    self._testTM(sequence)
    self.assertAllActiveWerePredicted()
    self.assertAllInactiveWereUnpredicted()


  def testB9(self):
    """Like B7 but present the sequence less than 4 times.
    The inference should be incorrect."""
    self.init({"initialPermanence": 0.2,
               "connectedPermanence": 0.7,
               "permanenceIncrement": 0.2})

    numbers = self.sequenceMachine.generateNumbers(1, 100)
    sequence = self.sequenceMachine.generateFromNumbers(numbers)

    for _ in xrange(3):
      self.feedTM(sequence)

    self._testTM(sequence)
    self.assertAllActiveWereUnpredicted()


  def testB11(self):
    """Like B5, but with activationThreshold = 8 and with each pattern
    corrupted by a small amount of spatial noise (X = 0.05)."""
    self.init({"cellsPerColumn": 4,
               "activationThreshold": 8})

    numbers = self.sequenceMachine.generateNumbers(1, 100)
    sequence = self.sequenceMachine.generateFromNumbers(numbers)

    self.feedTM(sequence)

    sequence = self.sequenceMachine.addSpatialNoise(sequence, 0.05)

    self._testTM(sequence)
    unpredictedActiveColumnsMetric = self.tm.mmGetMetricFromTrace(
      self.tm.mmGetTraceUnpredictedActiveColumns())
    self.assertTrue(unpredictedActiveColumnsMetric.mean < 1)


  def testH1(self):
    """Learn two sequences with a short shared pattern.
    Parameters should be the same as B1.
    Since cellsPerColumn == 1, it should make more predictions than necessary.
    """
    self.init()

    numbers = self.sequenceMachine.generateNumbers(2, 20, (10, 15))
    sequence = self.sequenceMachine.generateFromNumbers(numbers)

    self.feedTM(sequence)

    self._testTM(sequence)
    self.assertAllActiveWerePredicted()

    predictedInactiveColumnsMetric = self.tm.mmGetMetricFromTrace(
      self.tm.mmGetTracePredictedInactiveColumns())
    self.assertTrue(predictedInactiveColumnsMetric.mean > 0)

    # At the end of both shared sequences, there should be
    # predicted but inactive columns
    self.assertTrue(
      len(self.tm.mmGetTracePredictedInactiveColumns().data[15]) > 0)
    self.assertTrue(
      len(self.tm.mmGetTracePredictedInactiveColumns().data[35]) > 0)


  def testH2(self):
    """Same as H1, but with cellsPerColumn == 4, and train multiple times.
    It should make just the right number of predictions."""
    self.init({"cellsPerColumn": 4})

    numbers = self.sequenceMachine.generateNumbers(2, 20, (10, 15))
    sequence = self.sequenceMachine.generateFromNumbers(numbers)

    for _ in xrange(10):
      self.feedTM(sequence)

    self._testTM(sequence)
    self.assertAllActiveWerePredicted()

    # Without some kind of decay, expect predicted inactive columns at the
    # end of the first shared sequence
    predictedInactiveColumnsMetric = self.tm.mmGetMetricFromTrace(
      self.tm.mmGetTracePredictedInactiveColumns())
    self.assertTrue(predictedInactiveColumnsMetric.sum < 26)

    # At the end of the second shared sequence, there should be no
    # predicted but inactive columns
    self.assertEqual(
      len(self.tm.mmGetTracePredictedInactiveColumns().data[36]), 0)


  def testH3(self):
    """Like H2, except the shared subsequence is in the beginning.
    (e.g. "ABCDEF" and "ABCGHIJ") At the point where the shared subsequence
    ends, all possible next patterns should be predicted. As soon as you see
    the first unique pattern, the predictions should collapse to be a perfect
    prediction."""
    self.init({"cellsPerColumn": 4})

    numbers = self.sequenceMachine.generateNumbers(2, 20, (0, 5))
    sequence = self.sequenceMachine.generateFromNumbers(numbers)

    self.feedTM(sequence)

    self._testTM(sequence)
    self.assertAllActiveWerePredicted()

    predictedInactiveColumnsMetric = self.tm.mmGetMetricFromTrace(
      self.tm.mmGetTracePredictedInactiveColumns())
    self.assertTrue(predictedInactiveColumnsMetric.sum < 26 * 2)

    # At the end of each shared sequence, there should be
    # predicted but inactive columns
    self.assertTrue(
      len(self.tm.mmGetTracePredictedInactiveColumns().data[5]) > 0)
    self.assertTrue(
      len(self.tm.mmGetTracePredictedInactiveColumns().data[25]) > 0)


  def testH4(self):
    """Shared patterns. Similar to H2 except that patterns are shared between
    sequences.  All sequences are different shufflings of the same set of N
    patterns (there is no shared subsequence)."""
    self.init({"cellsPerColumn": 4})

    numbers = []
    for _ in xrange(2):
      numbers += self.sequenceMachine.generateNumbers(1, 20)

    sequence = self.sequenceMachine.generateFromNumbers(numbers)

    for _ in xrange(20):
      self.feedTM(sequence)

    self._testTM(sequence)
    self.assertAllActiveWerePredicted()

    predictedInactiveColumnsMetric = self.tm.mmGetMetricFromTrace(
      self.tm.mmGetTracePredictedInactiveColumns())
    self.assertTrue(predictedInactiveColumnsMetric.mean < 3)


  def testH5(self):
    """Combination of H4) and H2).
    Shared patterns in different sequences, with a shared subsequence."""
    self.init({"cellsPerColumn": 4})

    numbers = []
    shared = self.sequenceMachine.generateNumbers(1, 5)[:-1]
    for _ in xrange(2):
      sublist = self.sequenceMachine.generateNumbers(1, 20)
      sublist = [x for x in sublist if x not in xrange(5)]
      numbers += sublist[0:10] + shared + sublist[10:]

    sequence = self.sequenceMachine.generateFromNumbers(numbers)

    for _ in xrange(20):
      self.feedTM(sequence)

    self._testTM(sequence)
    self.assertAllActiveWerePredicted()

    predictedInactiveColumnsMetric = self.tm.mmGetMetricFromTrace(
      self.tm.mmGetTracePredictedInactiveColumns())
    self.assertTrue(predictedInactiveColumnsMetric.mean < 3)


  def testH9(self):
    """Sensitivity to small amounts of spatial noise during inference
    (X = 0.05). Parameters the same as B11, and sequences like H2."""
    self.init({"cellsPerColumn": 4,
               "activationThreshold": 8})

    numbers = self.sequenceMachine.generateNumbers(2, 20, (10, 15))
    sequence = self.sequenceMachine.generateFromNumbers(numbers)

    for _ in xrange(10):
      self.feedTM(sequence)

    sequence = self.sequenceMachine.addSpatialNoise(sequence, 0.05)

    self._testTM(sequence)
    unpredictedActiveColumnsMetric = self.tm.mmGetMetricFromTrace(
      self.tm.mmGetTraceUnpredictedActiveColumns())
    self.assertTrue(unpredictedActiveColumnsMetric.mean < 3)

  def testH10(self):
    """Orphan Decay mechanism reduce predicted inactive cells (extra predictions).
    Test feeds in noisy sequences (X = 0.05) to TM with and without orphan decay.
    TM with orphan decay should has many fewer predicted inactive columns.
    Parameters the same as B11, and sequences like H9."""
    self.init({"cellsPerColumn": 4,
               "activationThreshold": 8})

    numbers = self.sequenceMachine.generateNumbers(2, 20, (10, 15))
    sequence = self.sequenceMachine.generateFromNumbers(numbers)
    sequenceNoisy = dict()
    for i in xrange(10):
      sequenceNoisy[i] = self.sequenceMachine.addSpatialNoise(sequence, 0.05)
      self.feedTM(sequenceNoisy[i])

    self._testTM(sequence)
    predictedInactiveColumnsMetric = self.tm.mmGetMetricFromTrace(
      self.tm.mmGetTracePredictedInactiveColumns())
    predictedInactiveColumnsMean1 = predictedInactiveColumnsMetric.mean

    self.init({"cellsPerColumn": 4,
               "activationThreshold": 8,
               "predictedSegmentDecrement": 0.004})

    for _ in xrange(10):
      self.feedTM(sequenceNoisy[i])

    self._testTM(sequence)
    predictedInactiveColumnsMetric = self.tm.mmGetMetricFromTrace(
      self.tm.mmGetTracePredictedInactiveColumns())
    predictedInactiveColumnsMean2 = predictedInactiveColumnsMetric.mean

    self.assertGreater(predictedInactiveColumnsMean1, 0)
    self.assertGreater(predictedInactiveColumnsMean1, predictedInactiveColumnsMean2)

  # ==============================
  # Overrides
  # ==============================

  def setUp(self):
    super(ExtensiveTemporalMemoryTest, self).setUp()

    print ("\n"
           "======================================================\n"
           "Test: {0} \n"
           "{1}\n"
           "======================================================\n"
    ).format(self.id(), self.shortDescription())


  def feedTM(self, sequence, learn=True, num=1):
    super(ExtensiveTemporalMemoryTest, self).feedTM(
      sequence, learn=learn, num=num)

    if self.VERBOSITY >= 2:
      print self.tm.mmPrettyPrintTraces(
        self.tm.mmGetDefaultTraces(verbosity=self.VERBOSITY-1))
      print

    if learn and self.VERBOSITY >= 3:
      print self.tm.mmPrettyPrintConnections()


  # ==============================
  # Helper functions
  # ==============================

  def _testTM(self, sequence):
    self.feedTM(sequence, learn=False)

    print self.tm.mmPrettyPrintMetrics(self.tm.mmGetDefaultMetrics())


  def assertAllActiveWerePredicted(self):
    unpredictedActiveColumnsMetric = self.tm.mmGetMetricFromTrace(
      self.tm.mmGetTraceUnpredictedActiveColumns())
    predictedActiveColumnsMetric = self.tm.mmGetMetricFromTrace(
      self.tm.mmGetTracePredictedActiveColumns())

    self.assertEqual(unpredictedActiveColumnsMetric.sum, 0)

    self.assertEqual(predictedActiveColumnsMetric.min, 21)
    self.assertEqual(predictedActiveColumnsMetric.max, 25)


  def assertAllInactiveWereUnpredicted(self):
    predictedInactiveColumnsMetric = self.tm.mmGetMetricFromTrace(
      self.tm.mmGetTracePredictedInactiveColumns())

    self.assertEqual(predictedInactiveColumnsMetric.sum, 0)


  def assertAllActiveWereUnpredicted(self):
    unpredictedActiveColumnsMetric = self.tm.mmGetMetricFromTrace(
      self.tm.mmGetTraceUnpredictedActiveColumns())
    predictedActiveColumnsMetric = self.tm.mmGetMetricFromTrace(
      self.tm.mmGetTracePredictedActiveColumns())

    self.assertEqual(predictedActiveColumnsMetric.sum, 0)

    self.assertEqual(unpredictedActiveColumnsMetric.min, 21)
    self.assertEqual(unpredictedActiveColumnsMetric.max, 25)
예제 #17
0
 def getPatternMachine(self):
     return PatternMachine(100, range(21, 26), num=300)
예제 #18
0
def experiment1():
    paramDir = 'params/1024_baseline/5_trainingPasses.yaml'
    outputDir = 'results/'
    params = yaml.safe_load(open(paramDir, 'r'))
    options = {'plotVerbosity': 2, 'consoleVerbosity': 2}
    plotVerbosity = 2
    consoleVerbosity = 1

    print "Running SDR overlap experiment...\n"
    print "Params dir: {0}".format(paramDir)
    print "Output dir: {0}\n".format(outputDir)

    # Dimensionality of sequence patterns
    patternDimensionality = params["patternDimensionality"]

    # Cardinality (ON / true bits) of sequence patterns
    patternCardinality = params["patternCardinality"]

    # TODO If this parameter is to be supported, the sequence generation code
    # below must change
    # Number of unique patterns from which sequences are built
    # patternAlphabetSize = params["patternAlphabetSize"]

    # Length of sequences shown to network
    sequenceLength = params["sequenceLength"]

    # Number of sequences used. Sequences may share common elements.
    numberOfSequences = params["numberOfSequences"]

    # Number of sequence passes for training the TM. Zero => no training.
    trainingPasses = params["trainingPasses"]

    tmParamOverrides = params["temporalMemoryParams"]
    upParamOverrides = params["unionPoolerParams"]

    # Generate a sequence list and an associated labeled list (both containing a
    # set of sequences separated by None)
    start = time.time()
    print "\nGenerating sequences..."
    patternAlphabetSize = sequenceLength * numberOfSequences
    patternMachine = PatternMachine(patternDimensionality, patternCardinality,
                                    patternAlphabetSize)
    sequenceMachine = SequenceMachine(patternMachine)

    numbers = sequenceMachine.generateNumbers(numberOfSequences,
                                              sequenceLength)
    generatedSequences = sequenceMachine.generateFromNumbers(numbers)
    sequenceLabels = [
        str(numbers[i + i * sequenceLength:i + (i + 1) * sequenceLength])
        for i in xrange(numberOfSequences)
    ]
    labeledSequences = []
    for label in sequenceLabels:
        for _ in xrange(sequenceLength):
            labeledSequences.append(label)
        labeledSequences.append(None)

    # Set up the Temporal Memory and Union Pooler network
    print "\nCreating network..."
    experiment = UnionTemporalPoolerExperiment(tmParamOverrides,
                                               upParamOverrides)

    # Train only the Temporal Memory on the generated sequences
    if trainingPasses > 0:

        print "\nTraining Temporal Memory..."
        if consoleVerbosity > 0:
            print "\nPass\tBursting Columns Mean\tStdDev\tMax"

        for i in xrange(trainingPasses):
            experiment.runNetworkOnSequences(
                generatedSequences,
                labeledSequences,
                tmLearn=True,
                upLearn=None,
                verbosity=consoleVerbosity,
                progressInterval=_SHOW_PROGRESS_INTERVAL)

            if consoleVerbosity > 0:
                stats = experiment.getBurstingColumnsStats()
                print "{0}\t{1}\t{2}\t{3}".format(i, stats[0], stats[1],
                                                  stats[2])

            # Reset the TM monitor mixin's records accrued during this training pass
            # experiment.tm.mmClearHistory()

        print
        print MonitorMixinBase.mmPrettyPrintMetrics(
            experiment.tm.mmGetDefaultMetrics())
        print

    experiment.tm.mmClearHistory()
    experiment.up.mmClearHistory()

    print "\nRunning test phase..."

    inputSequences = generatedSequences
    inputCategories = labeledSequences
    tmLearn = True
    upLearn = False
    classifierLearn = False
    currentTime = time.time()

    experiment.tm.reset()
    experiment.up.reset()

    poolingActivationTrace = numpy.zeros((experiment.up._numColumns, 1))
    activeCellsTrace = numpy.zeros((experiment.up._numColumns, 1))
    activeSPTrace = numpy.zeros((experiment.up._numColumns, 1))

    for _ in xrange(trainingPasses):
        experiment.tm.reset()
        for i in xrange(len(inputSequences)):
            sensorPattern = inputSequences[i]
            inputCategory = inputCategories[i]
            if sensorPattern is None:
                pass
            else:
                experiment.tm.compute(sensorPattern,
                                      learn=tmLearn,
                                      sequenceLabel=inputCategory)

                if upLearn is not None:
                    activeCells, predActiveCells, burstingCols, = experiment.getUnionTemporalPoolerInput(
                    )
                    experiment.up.compute(activeCells,
                                          predActiveCells,
                                          learn=upLearn,
                                          sequenceLabel=inputCategory)

                    currentPoolingActivation = experiment.up._poolingActivation

                    currentPoolingActivation = experiment.up._poolingActivation.reshape(
                        (experiment.up._numColumns, 1))
                    poolingActivationTrace = numpy.concatenate(
                        (poolingActivationTrace, currentPoolingActivation), 1)

                    currentUnionSDR = numpy.zeros(
                        (experiment.up._numColumns, 1))
                    currentUnionSDR[experiment.up._unionSDR] = 1
                    activeCellsTrace = numpy.concatenate(
                        (activeCellsTrace, currentUnionSDR), 1)

                    currentSPSDR = numpy.zeros((experiment.up._numColumns, 1))
                    currentSPSDR[experiment.up._activeCells] = 1
                    activeSPTrace = numpy.concatenate(
                        (activeSPTrace, currentSPSDR), 1)

        print "\nPass\tBursting Columns Mean\tStdDev\tMax"
        stats = experiment.getBurstingColumnsStats()
        print "{0}\t{1}\t{2}\t{3}".format(0, stats[0], stats[1], stats[2])
        print
        print MonitorMixinBase.mmPrettyPrintMetrics(\
            experiment.tm.mmGetDefaultMetrics() + experiment.up.mmGetDefaultMetrics())
        print
        experiment.tm.mmClearHistory()

    # estimate fraction of shared bits across adjacent time point
    unionSDRshared = experiment.up._mmComputeUnionSDRdiff()

    bitLifeList = experiment.up._mmComputeBitLifeStats()
    bitLife = numpy.array(bitLifeList)

    # Plot SP outputs, UP persistence and UP outputs in testing phase
    def showSequenceStartLine(ax, trainingPasses, sequenceLength):
        for i in xrange(trainingPasses):
            ax.vlines(i * sequenceLength, 0, 100, linestyles='--')

    plt.figure()
    ncolShow = 100
    f, (ax1, ax2, ax3) = plt.subplots(nrows=1, ncols=3)
    ax1.imshow(activeSPTrace[1:ncolShow, :],
               cmap=cm.Greys,
               interpolation="nearest",
               aspect='auto')
    showSequenceStartLine(ax1, trainingPasses, sequenceLength)
    ax1.set_title('SP SDR')
    ax1.set_ylabel('Columns')
    ax2.imshow(poolingActivationTrace[1:100, :],
               cmap=cm.Greys,
               interpolation="nearest",
               aspect='auto')
    showSequenceStartLine(ax2, trainingPasses, sequenceLength)
    ax2.set_title('Persistence')
    ax3.imshow(activeCellsTrace[1:ncolShow, :],
               cmap=cm.Greys,
               interpolation="nearest",
               aspect='auto')
    showSequenceStartLine(ax3, trainingPasses, sequenceLength)
    plt.title('Union SDR')

    ax2.set_xlabel('Time (steps)')

    pp = PdfPages('results/UnionPoolingOnLearnedTM_Experiment1.pdf')
    pp.savefig()
    pp.close()

    f, (ax1, ax2, ax3) = plt.subplots(nrows=3, ncols=1)
    ax1.plot((sum(activeCellsTrace)) / experiment.up._numColumns * 100)
    ax1.set_ylabel('Union SDR size (%)')
    ax1.set_xlabel('Time (steps)')
    ax1.set_ylim(0, 25)

    ax2.plot(unionSDRshared)
    ax2.set_ylabel('Shared Bits')
    ax2.set_xlabel('Time (steps)')

    ax3.hist(bitLife)
    ax3.set_xlabel('Life duration for each bit')
    pp = PdfPages('results/UnionSDRproperty_Experiment1.pdf')
    pp.savefig()
    pp.close()