Exemple #1
0
    def evaluate(self):
        data = Dataset('datasets/textures/')
        max_dist = -32
        timer = genetics.speed_fitness(threshold=60, maximum=2 * 60)
        sensor = htm.EyeSensor(self.eye)
        sp = htm.SpatialPooler(self.sp,
                               input_sdr=sensor.optic_sdr,
                               column_sdr=SDR(self.columns),
                               radii=self.radii,
                               multisegment_experiment=None)
        classifier = htm.SDR_Classifier(self.sdrc,
                                        sp.columns, (len(data.names), ),
                                        output_type='pdf')
        baseline = htm.RandomOutputClassifier((len(data.names), ))

        time_per_image = int(round(self.time_per_image))
        num_images = int(round(self.image_cycles))
        if self.debug:
            sampler = htm.EyeSensorSampler(sensor, num_images, 30)
            memory_perf = 0  # Debug takes extra memory, this is disabled during debug.
        sp_score = 0
        baseline_score = 0
        # Outer loop through images.
        for img_num in range(num_images):
            # Setup for a new image
            data.random_image()
            sensor.new_image(data.current_image)
            # Determine where the eye will look on the image.
            positions = data.points_near_label(max_dist=max_dist,
                                               number=time_per_image)

            # Inner loop through samples from each image.
            for sample_point in positions:
                # Classify the image.
                sensor.randomize_view()  # Get a new orientation and scale.
                sensor.position = sample_point
                sp.compute(input_sdr=sensor.view())
                sp_prediction = classifier.predict(sp.columns)
                baseline_prediction = baseline.predict()

                # Compare results to labels.
                label_sample_points = sensor.input_space_sample_points(20)
                labels = data.sample_labels(label_sample_points)
                sp_score += data.compare_label_samples(sp_prediction, labels)
                baseline_score += data.compare_label_samples(
                    baseline_prediction, labels)
                # Learn.
                sp.learn()
                classifier.train(sp.columns.index, labels)
                baseline.train(labels)

            # Sample memory usage.
            if img_num == min(10, num_images - 1) and not self.debug:
                # I want each process to take no more than 20% of my RAM or 2.5
                # GB.  This should let me run 4 processes + linux + firefox.
                memory_perf = genetics.memory_fitness(2e9, 4e9)

        sp_score /= sp.age
        baseline_score /= sp.age
        time_perf = timer.done(
        )  # Stop the timer before debug opens windows and returns control to user.
        if self.debug:
            print(sp.statistics())
            sampler.view_samples()

        return {
            'baseline': baseline_score,
            'score': sp_score,
            'time': time_perf,
            'memory': memory_perf,
        }
Exemple #2
0
    def evaluate(self, debug):
        # SETUP
        inputs, objects = object_dataset()
        enc = EnumEncoder(self.enc_size, self.enc_sparsity, diag=False)
        enc.output_sdr = SDR(enc.output_sdr, average_overlap_alpha=self.alpha)
        sp = SpatialPooler(
            SpatialPoolerParameters(
                permanence_inc=self.inc,
                permanence_dec=self.dec,
                permanence_thresh=self.thresh,
                potential_pool=self.pp,
                sparsity=self.col_sparsity,
                boosting_alpha=self.alpha,
            ),
            input_sdr=SDR(enc.output_sdr,
                          activation_frequency_alpha=self.alpha),
            column_sdr=SDR((self.cols, )),
            multisegment_experiment=self.prox_segs,
            init_dist=self.init_dist,
        )
        sdrc = SDR_Classifier(SDRC_Parameters(alpha=0.001),
                              input_sdr=sp.columns,
                              output_shape=(num_objects, ),
                              output_type='index')

        def measure():
            # Compute every sensation for every object.
            objects_columns = []
            for obj in objects:
                objects_columns.append([])
                for sensation in obj:
                    enc.encode(sensation)
                    sp.compute(input_sdr=enc.output_sdr)
                    objects_columns[-1].append(SDR(sp.columns))

            # Measure classification accuracy.
            score = 0
            max_score = 0
            for object_id, obj_cols in enumerate(objects_columns):
                for sp_cols in obj_cols:
                    prediction = np.argmax(sdrc.predict(sp_cols))
                    if prediction == object_id:
                        score += 1
                    max_score += 1
            score = score / max_score

            # Measure column overlap within objects.
            overlap_stability = 0
            comparisions = 0
            for obj_cols in objects_columns:
                for c1, c2 in itertools.combinations(obj_cols, 2):
                    overlap_stability += c1.overlap(c2)
                    comparisions += 1
            stability = overlap_stability / comparisions

            # Measure column overlap between objects.
            overlap_between_objects = 0
            comparisions = 0
            skip_compare = itertools.cycle([False] + [True] * 24)
            for obj1_cols, obj2_cols in itertools.combinations(
                    objects_columns, 2):
                for c1 in obj1_cols:
                    for c2 in obj2_cols:
                        if next(skip_compare):
                            continue
                        overlap_between_objects += c1.overlap(c2)
                        comparisions += 1
            distinctiveness = overlap_between_objects / comparisions
            return stability, distinctiveness, score

        if debug:
            untrained_stability, untrained_distinctiveness, untrained_score = measure(
            )
            print('NUM-OBJ ', num_objects)
            print("OBJ-SIZE", object_size)
            print(sp.statistics())
            print('UNTRAINED INTER OBJECT OVERLAP', untrained_distinctiveness)
            print('UNTRAINED INTRA OBJECT OVERLAP', untrained_stability)
            print('UNTRAINED SCORE', untrained_score)
            print('Training ...')

        # RUN ONLINE
        prev_cols = SDR(sp.columns)
        prev_cols.zero()
        for step in range(num_objects * (object_size**2) * 10):
            if step % 2 * object_size == 0:
                object_id = random.choice(range(len(objects)))
            sensation = random.choice(objects[object_id])
            enc.encode(sensation)
            sp.compute(input_sdr=enc.output_sdr)
            sp.stabilize(prev_cols, self.min_stab)
            prev_cols = SDR(sp.columns)
            sp.learn()
            sdrc.train(sp.columns, (object_id, ))

        trained_stability, trained_distinctiveness, trained_score = measure()

        if debug:
            print('TRAINED FOR CYCLES', step + 1)
            print('TRAINED INTER OBJECT OVERLAP', trained_distinctiveness)
            print('TRAINED INTRA OBJECT OVERLAP', trained_stability)
            print('TRAINED SCORE', trained_score)
            print()
            print('Encoder Output', enc.output_sdr.statistics())
            print(sp.statistics())

        return {
            'score': trained_score,
            'ovlp': trained_stability / trained_distinctiveness,
            'memory': genetics.memory_fitness(4e9, 5e9),
        }
Exemple #3
0
    def evaluate(self):
        cell_death_experiment = None
        reward_adjustment_experiment = False
        adversarial_dataset_experiment = False

        if adversarial_dataset_experiment:
            datastream = AdversarialDataset()
        else:
            datastream = Dataset(num_sequences=self.num_seq)

        # SETUP AI.
        start_time = time.time()
        enc = htm.EnumEncoder(self.enc_bits, self.enc_spar, diag=False)
        sp = htm.SpatialPooler(
            self.sp,
            input_sdr=enc.output_sdr,
            column_sdr=SDR((self.cols, )),
        )
        sp_sdrc = htm.SDR_Classifier(htm.SDRC_Parameters(alpha=0.001),
                                     sp.columns, datastream.class_shape,
                                     'index')
        tm = htm.TemporalMemory(self.tm, sp.columns)
        tm_sdrc = htm.SDR_Classifier(htm.SDRC_Parameters(alpha=0.001),
                                     tm.active, datastream.class_shape,
                                     'index')
        bg = basal_ganglia.BasalGanglia(self.bg,
                                        tm.active,
                                        future_discount=.95)
        d1_sdrc = htm.SDR_Classifier(htm.SDRC_Parameters(alpha=0.001),
                                     bg.d1.active, datastream.class_shape,
                                     'index')
        d2_sdrc = htm.SDR_Classifier(htm.SDRC_Parameters(alpha=0.001),
                                     bg.d2.active, datastream.class_shape,
                                     'index')
        memory_score = genetics.memory_fitness(2e9, 3e9)

        # SETUP ACCUMULATORS.
        anom_rand = 0
        anom_rand_total = 0
        anom_pred = 0
        anom_pred_total = 0
        sp_seq_score = 0
        tm_seq_score = 0
        d1_seq_score = 0
        d2_seq_score = 0
        sequence_total = 0
        td_error = 0
        td_error_total = 0  # RMS of TD-Error
        baseline = 0  # RMS(reward). If EV === 0 then this is also the RMS TD-Error.
        event_step = None  # A vertical line is drawn on the TD-Error graph at this step.
        if self.debug:
            input_history = []
            reward_history = []
            anomalous_input_history = []
            ev_history = []
            td_error_history = []
            anomaly_history = []

        def plot_striatum_performance_vs_reward():
            # Measure classification accuracy of each sequence.
            d1_seq_scores = []
            d2_seq_scores = []
            for seq_idx, seq in enumerate(datastream.sequences):
                reward = datastream.rewards[seq_idx]
                d1_seq_scores.append(0)
                d2_seq_scores.append(0)
                seqence_classification_samples = 0
                for measurement in range(3):
                    # Add random inputs at the start of the seqence.
                    reset_steps = random.randrange(
                        min(datastream.filler_length),
                        max(datastream.filler_length) + 1)
                    reset_noise = [
                        random.choice(datastream.inputs)
                        for step in range(reset_steps)
                    ]
                    seq = seq + reset_noise
                    for step, inp in enumerate(seq):
                        enc.encode(inp)
                        sp.compute()
                        tm.compute()
                        bg.compute(tm.active, reward=None)  # No learning.
                        # Filter out the random noise at the start of the sequence.
                        if step not in range(reset_steps):
                            d1_seq_cls = d1_sdrc.predict(bg.d1.active)
                            d2_seq_cls = d2_sdrc.predict(bg.d2.active)
                            d1_seq_scores[seq_idx] += d1_seq_cls[
                                seq_idx] / np.sum(d1_seq_cls)
                            d2_seq_scores[seq_idx] += d2_seq_cls[
                                seq_idx] / np.sum(d2_seq_cls)
                            seqence_classification_samples += 1
                d1_seq_scores[seq_idx] /= seqence_classification_samples
                d2_seq_scores[seq_idx] /= seqence_classification_samples
            # Plot the relationship between sequence value and which striatum
            # populations learned to recognise the sequence.
            plt.figure('Reward versus Striatum')
            plt.subplot(1, 2, 1)
            plt.title('D1')
            plt.plot(datastream.rewards, d1_seq_scores, 'ro')
            plt.xlabel('Sequence Reward')
            plt.ylabel('Classification Accuracy')

            plt.subplot(1, 2, 2)
            plt.title('D2')
            plt.plot(datastream.rewards, d2_seq_scores, 'bo')
            plt.xlabel('Sequence Reward')
            plt.ylabel('Classification Accuracy')

        # RUN ONLINE.
        print("Num Cycles", self.cycles)
        for step in range(self.cycles):
            inp, reward = next(datastream)
            enc.encode(inp)
            sp.compute()
            tm.compute()
            bg.compute(tm.active, reward)
            sp.learn()
            tm.learn()

            if cell_death_experiment is not None and step == self.cycles // 2:
                tm.active.kill_cells(cell_death_experiment)
                bg.d1.active.kill_cells(cell_death_experiment)
                bg.d2.active.kill_cells(cell_death_experiment)
                bg.gpe.active.kill_cells(cell_death_experiment)
                bg.gpi.active.kill_cells(cell_death_experiment)
                print("KILLED %g %% OF CELLS" % (cell_death_experiment * 100))
                event_step = step

            # Measure performance.
            if bg.td_error is not None:
                baseline += reward**2
                td_error += bg.td_error**2
                td_error_total += 1

            if datastream.anomallous:
                anom_rand += tm.anomaly
                anom_rand_total += 1
            else:
                anom_pred += tm.anomaly
                anom_pred_total += 1

            # Train and test sequence classifiers for every part of the system.
            if datastream.state[0] == 'sequence':
                sp_seq_cls = sp_sdrc.predict(sp.columns)
                tm_seq_cls = tm_sdrc.predict(tm.active)
                d1_seq_cls = d1_sdrc.predict(bg.d1.active)
                d2_seq_cls = d2_sdrc.predict(bg.d2.active)
                sequence_total += 1
                seq_idx = datastream.state[1]
                # SDR Classifier outputs a PDF.  At creation, PDF may be beneath
                # the minumum representable floating point value.
                sp_seq_score += np.nan_to_num(sp_seq_cls[seq_idx] /
                                              np.sum(sp_seq_cls))
                tm_seq_score += np.nan_to_num(tm_seq_cls[seq_idx] /
                                              np.sum(tm_seq_cls))
                d1_seq_score += np.nan_to_num(d1_seq_cls[seq_idx] /
                                              np.sum(d1_seq_cls))
                d2_seq_score += np.nan_to_num(d2_seq_cls[seq_idx] /
                                              np.sum(d2_seq_cls))
                sp_sdrc.train(sp.columns, (seq_idx, ))
                tm_sdrc.train(tm.active, (seq_idx, ))
                d1_sdrc.train(bg.d1.active, (seq_idx, ))
                d2_sdrc.train(bg.d2.active, (seq_idx, ))

            if self.debug:
                # Record everything for debugging.
                input_history.append(inp)
                reward_history.append(reward)
                anomalous_input_history.append(datastream.anomallous)
                ev_history.append(bg.expected_value)
                td_error_history.append(
                    bg.td_error if bg.td_error is not None else 0)
                anomaly_history.append(tm.anomaly)

                if reward_adjustment_experiment and step == self.cycles // 2:
                    plot_striatum_performance_vs_reward()
                    plt.show()
                    print('ADJUSTING ALL REWARDS!')
                    datastream.adjust_rewards()
                    event_step = step

        # REPORT.
        sp_seq_score = sp_seq_score / sequence_total
        tm_seq_score = tm_seq_score / sequence_total
        d1_seq_score = d1_seq_score / sequence_total
        d2_seq_score = d2_seq_score / sequence_total
        anom_pred = anom_pred / anom_pred_total
        anom_rand = anom_rand / anom_rand_total
        baseline = (baseline / td_error_total)**.5
        td_error = (td_error / td_error_total)**.5
        fitness = {
            'anom_pred': anom_pred,
            'anom_rand': anom_rand,
            'seq_sp': sp_seq_score,
            'seq_tm': tm_seq_score,
            'seq_d1': d1_seq_score,
            'seq_d2': d2_seq_score,
            'td_error': td_error / baseline,
            'time': (time.time() - start_time) / 60,
            'memory': memory_score,
        }
        if self.debug:
            print(sp.statistics())
            print(tm.statistics())
            print(bg.statistics())
            print("TD-Error Baseline", baseline, "Measured", td_error)
            print(fitness)

            plot_striatum_performance_vs_reward()

            # Plot the Reward, Expected Value, and TD-Error.
            steps = np.arange(len(input_history))
            plt.figure('Reinforcement Learning Graph')
            plt.title(
                'Reward is Red, Expected Value is Green, TD-Error is Blue.')
            plt.xlabel('Step Number')
            plt.plot(steps, reward_history, 'r', steps, ev_history, 'g', steps,
                     td_error_history, 'b')

            # Plot the Anomaly.
            plt.figure('Anomaly Graph')
            plt.title('Anomaly is Green, Unpredictable input is Red.')
            plt.plot(steps, anomaly_history, 'g', steps,
                     anomalous_input_history, 'r')
            plt.xlabel('Step Number')

            # Smooth and plot the TD error alone.
            alpha = .005
            td_err_cleaned = []
            avg = 0
            for td_err in td_error_history:
                avg = avg * (1 - alpha) + abs(td_err) * alpha
                td_err_cleaned.append(avg)
            plt.figure('TD Error')
            plt.title('Exponential Rolling average of |TD Error|, alpha = %g' %
                      alpha)
            plt.plot(steps, td_err_cleaned, 'b')
            plt.xlabel('Step Number')
            if event_step is not None:
                plt.axvline(event_step)

            plt.show()
        return fitness
    def evaluate(self, debug):
        # Setup test and train datasets and perform lexical analysis.  First get
        # full text of training dataset into a string.
        if self.dataset == 'gutenberg':
            text_stream = read_corpus(debug=debug)
        elif self.dataset == 'states':
            text_stream = state_name_reader(debug=debug)
        train_dataset = []
        for i in range(self.train_time):
            char = next(text_stream)
            train_dataset.append(char)
        train_dataset = ''.join(train_dataset)
        # Search for words in the dataset.  Store the words as keys in a
        # histogram of word occurances.
        word_regex = r"\w(\w|')*"
        word_iter = re.finditer(word_regex, train_dataset)
        word_hist = {}
        # train_word_spans stores where each word is located, list of pairs of
        # (start, end) index into train_dataset.
        train_word_spans = []
        for match in word_iter:
            span = match.span()  # Returns pair of (start-index, end-index)
            word = train_dataset[span[0]:span[1]]
            if word not in word_hist:
                word_hist[word] = 0
            word_hist[word] += 1
            train_word_spans.append(span)
        # Sort words by the number of times the occur in the train_dataset.
        # Break ties randomly.
        word_list = list(word_hist.keys())
        word_freq = [
            -(word_hist[word] + random.random()) for word in word_list
        ]
        word_rank = np.take(word_list, np.argsort(word_freq))
        # Get word_list and word_freq out of memory, from here on use word_rank & word_hist.
        word_list = None
        word_freq = None
        # Select some common words to test vocabulary with.
        test_words = word_rank[:self.test_words].tolist()
        # Assign each vocabulary word an integer identifier.  A test words
        # identifier doubles as its index into the test_words list.
        if False:
            test_words.sort()  # Make the index easier for humans to use.
        # The first entry is special B/C when the SDRC can't identify the word
        # at all, it outputs all zeros.  Then np.argmax() outputs as index 0 as
        # the best prediction.
        test_words.insert(0, "WORD_UNKNOWN")
        word_hist[test_words[0]] = 0
        test_word_id_lookup = {
            word: index
            for index, word in enumerate(test_words)
        }
        # Search for examples of the vocabulary words used in sentances.  First
        # read a large amount of sample text.  Only relevant sections of the
        # test_dataset are used, the ranges of text are stored in variable
        # test_sentance_spans.
        test_dataset = []
        for i in range(int(self.test_time)):
            char = next(text_stream)
            test_dataset.append(char)
        test_dataset = ''.join(test_dataset)
        word_iter = re.finditer(word_regex, test_dataset)
        # The following two lists hold pairs of (start, end) slice indexes into
        # test_dataset.  They are NOT the same length because overlapping
        # test_sentance_spans are merged into a single example containing
        # several of the vocabulary words.
        test_word_spans = []  # Spans of just the test vocabulary words.
        test_sentance_spans = [
        ]  # Spans of test words with preceding context included.
        test_hist = {word: 0 for word in test_words}
        for match in word_iter:
            span = match.span()  # Returns pair of (start-index, end-index)
            start, end = span
            word = test_dataset[start:end]
            if word not in test_word_id_lookup.keys():
                continue
            # Ignore test vocabulary words after they've been seen many times.
            if test_hist[word] >= self.test_sample:
                continue
            test_hist[word] += 1
            test_word_spans.append(span)
            context_start = max(0, start - self.min_context)
            if test_sentance_spans and test_sentance_spans[-1][
                    1] >= context_start:
                # Extend the last test sentance and test this additional word using it.
                context_start = test_sentance_spans[-1][0]
                test_sentance_spans[-1] = (context_start, end)
            else:
                # Add a new test sentance.
                test_sentance_spans.append((context_start, end))
        len_test_dataset = sum(e - s for s, e in test_sentance_spans)
        if debug:
            print('Training dataset size:', self.train_time, 'characters,',
                  len(train_word_spans), 'words,', len(word_hist),
                  'unique words.')
            print('Test vocabulary size:', len(test_words), 'words.')
            min_freq = min(word_hist[word] for word in test_words[1:])
            max_freq = max(word_hist[word] for word in test_words[1:])
            print('Test vocabulary samples:',
                  ', '.join(random.sample(test_words[1:], 6)) + '.')
            print(
                'Test vocabulary min & max occurances in training dataset: %d - %d.'
                % (min_freq, max_freq))
            test_hist_values = list(test_hist[word] for word in test_words[1:])
            min_freq = min(test_hist_values)
            avg_freq = np.mean(test_hist_values)
            max_freq = max(test_hist_values)
            print(
                'Test vocabulary min/mean/max occurances in testing dataset: %d / %.1f / %d.'
                % (min_freq, avg_freq, max_freq))
            print('Test dataset size:', len_test_dataset, 'characters,',
                  len(test_word_spans), 'vocabulary words.')
            print('Test sentance average length: %.1f characters.' %
                  (len_test_dataset / len(test_sentance_spans)))
            if self.list_test_words:
                print('Index) Word, Train samples, Test samples.')
                if False:
                    # Sort by number of samples in dataset.
                    # TODO: This would be more useful if it sorted the actual test_words list.
                    test_freq = [-test_hist[word] for word in test_words]
                    test_rank = np.take(test_words, np.argsort(test_freq))
                    ordered_words = test_rank
                else:
                    # Sort by index.
                    ordered_words = test_words
                # Print index of test words.
                for word in ordered_words:
                    index = test_word_id_lookup[word]
                    train_samples = word_hist[word]
                    test_samples = test_hist[word]
                    fmt_str = '%3d) %-15s\t%2d, %2d'
                    print(fmt_str % (index, word, train_samples, test_samples))
                if True:
                    # Look at some test sentances
                    sample_spans = random.sample(
                        test_sentance_spans, min(10, len(test_sentance_spans)))
                    sample_sentances = [
                        test_dataset[s[0]:s[1]] for s in sample_spans
                    ]
                    print('Sample test sentances:\n\t',
                          '\n\n\t'.join(sample_sentances))
            print()
        # After seeing all of the words in either dataset, wait forever for the
        # next word, or until the dataset is finished playing.  This case is
        # needed when the dataset ends with white space.
        train_word_spans.append((float('inf'), float('inf')))
        test_word_spans.append((float('inf'), float('inf')))
        # if len(test_words) != self.test_words + 1:
        #     raise ValueError('Could not find %d test words'%self.test_words)

        # Setup AI.
        timer = genetics.speed_fitness(self.time_limit / 3, self.time_limit)
        enc = encoders.EnumEncoder(self.enc_bits,
                                   self.enc_sparsity,
                                   diag=False)

        # Make the context SDR which both L4 and L23 use to predict the future.
        context_size = self.l4.cells + self.l23.cells
        context = SDR((context_size, ))
        l4 = unified.Unified(
            self.l4,
            input_sdr=enc.output_sdr,
            context_sdr=context,
            macro_columns=(1, ),
            radii=self.l4_radii,
        )
        l23 = unified.Unified(
            self.l23,
            input_sdr=l4.active,
            context_sdr=context,
            macro_columns=(1, ),
            radii=self.l23_radii,
        )

        l4_sdrc = classifiers.SDR_Classifier(self.sdrc, l4.active,
                                             (len(test_words), ), 'index')
        l23_sdrc = classifiers.SDR_Classifier(self.sdrc, l23.active,
                                              (len(test_words), ), 'index')

        def reset():
            l4.reset()
            l23.reset()

        def compute(learn=True):
            context.assign_flat_concatenate([l4.active, l23.active])
            if self.l4_only:
                # Test L4 in isolation, Disable feedback from L2/3 to L4.
                zeros_like_l23 = SDR(l23.active)
                zeros_like_l23.zero()
                context.assign_flat_concatenate([l4.active, zeros_like_l23])
            l4.compute()
            l23.compute()
            if learn:
                l4.learn()
                l23.learn()

        if debug:
            print('SDR DEBUG:', sdr.debug)
            if self.l4_only:
                print("L4 Isolated, Disabled L2/3 -> L4 Feedback.")
            if False:
                print('L4', l4.statistics())
                print('L23', l23.statistics())

        # Train by reading books.
        if self.train_no_stability:
            self.l23.min_stability = 0
            assert (debug)
            print('L23 min stability set to', self.l23.min_stability)
        if debug:
            print('Training ...')
        word = None  # Current word or None, AI trains to predict this variable.
        word_index = None  # Index of current word in test_data, or None if its not a test word.
        word_span_index = 0  # Index of current word in train_dataset
        reset()
        for step in range(self.train_time):
            # Determine the current word.
            start, end = train_word_spans[word_span_index]
            if step == start:
                word = train_dataset[start:end]
                try:
                    word_index = (test_word_id_lookup[word], )
                except KeyError:  # Word is not in vocabulary test words, SDRC should ignore it.
                    word_index = None
            if step == end:
                word = None
                word_index = None
                word_span_index += 1
            # Process the next letter of the book.
            char = train_dataset[step]
            enc.encode(char)
            compute(learn=True)
            if word_index is not None and step == end - 1:
                l4_sdrc.train(input_sdr=None, out=word_index)
                l23_sdrc.train(input_sdr=None, out=word_index)

        # Test.  Measure:
        # 1) Stability,
        # 2) Anomaly,
        # 3) Word recognition accuracy and cross-catagory confusion.
        real_min_stab = l23.args.min_stability
        if self.test_no_stability:
            l23.args.min_stability = 0
        if debug:
            print('Testing ...')
            if l23.args.min_stability != real_min_stab:
                print('L23 min stability changed to', l23.args.min_stability)
            else:
                print('L23 min stability remains at', l23.args.min_stability)
        l23_stability = 0.  # Accumulates the L2/3 stability.
        l4_anomaly = 0.  # Accumulates the L4 anomaly.
        l23_anomaly = 0.  # Accumulates the L2/3 anomaly.
        l4_accuracy = 0.  # Accumulates the L4 word classificatioon accuracy.
        l23_accuracy = 0.  # Accumulates the L2/3 word classificatioon accuracy.
        max_accuracy = 0.  # Number of samples accumulated in variable 'l23_accuracy'.
        l4_end_accuracy = 0.  # Like 'l4_accuracy' but only measured on the final letter of the word.
        l23_end_accuracy = 0.  # Like 'l23_accuracy' but only measured on the final letter of the word.
        max_end_accuracy = 0.  # Number of samples accumulated in variable 'l23_end_accuracy'.
        l23_confusion = np.zeros((len(test_words), len(test_words)))
        l4_confusion = np.zeros((len(test_words), len(test_words)))
        next_span_index = 0  # Index of current word in test_word_spans (or next word if not currently on a word).
        for sentance_start, sentance_end in test_sentance_spans:
            reset()
            word_index = None  # Index of current word, or None.
            for index in range(sentance_start, sentance_end):
                # Determine the current word.  Allow words to immediately follow
                # each other, they in case they're seperated by a reset and zero
                # characters of context.
                word_start, word_end = test_word_spans[next_span_index]
                if index >= word_end:
                    word_index = None
                    next_span_index += 1
                word_start, word_end = test_word_spans[next_span_index]
                if index >= word_start:
                    word = test_dataset[word_start:word_end]
                    word_index = test_word_id_lookup[word]
                # Process the current character.
                char = test_dataset[index]
                enc.encode(char)
                compute(learn=False)
                # Measure.
                if real_min_stab > 0:
                    l23_stability += min(l23.stability,
                                         real_min_stab) / real_min_stab
                else:
                    l23_stability += 1
                l4_anomaly += l4.anomaly
                l23_anomaly += l23.anomaly
                if word_index is not None:
                    l4_prediction = l4_sdrc.predict()
                    l23_prediction = l23_sdrc.predict()
                    l4_best_guess = np.argmax(l4_prediction)
                    l23_best_guess = np.argmax(l23_prediction)
                    if l23_best_guess == word_index:
                        l23_accuracy += 1
                        if index == word_end - 1:
                            l23_end_accuracy += 1
                    if l4_best_guess == word_index:
                        l4_accuracy += 1
                        if index == word_end - 1:
                            l4_end_accuracy += 1
                    max_accuracy += 1
                    if index == word_end - 1:
                        max_end_accuracy += 1
                    # Update confusion matixes.  Prediction is a PDF, sum must equal 1.
                    if True:
                        l23_confusion[word_index, l23_best_guess] += 1
                        if index == word_end - 1:
                            l4_confusion[word_index, l4_best_guess] += 1
                    else:
                        l23_prediction_sum = np.sum(l23_prediction)
                        if l23_prediction_sum != 0.:
                            l23_prediction /= l23_prediction_sum
                            l23_confusion[word_index, :] += l23_prediction
                        l4_prediction_sum = np.sum(l4_prediction)
                        if l4_prediction_sum != 0.:
                            l4_prediction /= l4_prediction_sum
                            l4_confusion[word_index, :] += l4_prediction
        # Divide all accumulators by the number of samples added to them.
        l23_stability /= len_test_dataset
        l23_accuracy /= max_accuracy
        l23_end_accuracy /= max_end_accuracy
        l23_anomaly /= len_test_dataset
        l4_accuracy /= max_accuracy
        l4_end_accuracy /= max_end_accuracy
        l4_anomaly /= len_test_dataset
        for label_idx, label in enumerate(test_words):
            # Divide by the number of PDF's which have accumulated at each
            # label, each PDF has sum of 1.
            l23_num_samples = np.sum(l23_confusion[label_idx, :])
            if l23_num_samples != 0:
                l23_confusion[label_idx, :] /= l23_num_samples
            l4_num_samples = np.sum(l4_confusion[label_idx, :])
            if l4_num_samples != 0:
                l4_confusion[label_idx, :] /= l4_num_samples

        def plot_sentance_stability(string):
            plt.figure('Stability')
            plt.ylim(-0.01, 1.01)
            plt.xlim(-0.5, len(string) - 0.5)
            plt.xlabel('Time')
            plt.ylabel('L2/3 Overlap')
            plt.axhline(real_min_stab)
            stability = []
            confidence = []
            anomaly = []
            reset()
            for step, char in enumerate(string):
                enc.encode(char)
                compute(learn=False)
                stability.append(l23.stability)
                anomaly.append(l23.anomaly)
                prediction = l23_sdrc.predict()
                best_guess = test_words[np.argmax(prediction)]
                confidence.append(np.max(prediction) / np.sum(prediction))
                #
                plt.axvline(step + .5, color='grey', alpha=0.25)
                plt.text(step - 0.25, .98, char)
                if char.isalpha():
                    plt.text(step - 0.25,
                             0.95,
                             best_guess,
                             rotation='vertical')
                # TODO: Determine which steps it learns on by looking at the dataset.
                elif step - 1 >= 0 and string[step - 1].isalpha():
                    plt.axvspan(step - 1.5,
                                step - .5,
                                color='yellow',
                                alpha=0.5)
            plt.axvspan(step - .5, step + .5, color='yellow', alpha=0.5)
            plt.plot(
                np.arange(len(string)),
                stability,
                'r-',
            )
            # np.arange(len(string)), confidence,   'b-',)
            # np.arange(len(string)), anomaly,   'b-',)
            # plt.title('L2/3 Overlap is Red,  Confidence is Blue')
            # plt.title('L2/3 Overlap is Red,  Anomaly is Blue')
            plt.title((
                'Top: Input Letter, Middle: Best Guess,\n' +
                'Bottom Graph: Red Line L2/3 Stability, Blue Line: Target Stability, Learning Enabled on Yellow Steps.'
            ))

        # Report.
        fitness = {
            'L23_stability': l23_stability,
            'L23_accuracy': l23_accuracy,
            'L23_end_accuracy': l23_end_accuracy,
            'L23_anomaly': l23_anomaly,
            'L4_accuracy': l4_accuracy,
            'L4_end_accuracy': l4_end_accuracy,
            'L4_anomaly': l4_anomaly,
            'speed': timer.done(),
            'memory': genetics.memory_fitness(2e9, 3e9),
        }
        if debug:
            print()
            print('L4', l4.statistics())
            print('L23', l23.statistics())

            span = random.choice(test_sentance_spans)
            sentance = test_dataset[span[0]:span[1]]
            sentance = sentance[
                -100:]  # Don't show too much text in one figure.
            if self.show_typos:
                sentance = ' '.join(
                    [mutate_word(w) for w in sentance.split(' ')])
            plot_sentance_stability(sentance)

            plt.figure('L23 Confusion Matrix')
            plt.imshow(l23_confusion, interpolation='nearest')
            plt.xlabel('Prediction')
            plt.ylabel('Label')
            plt.figure('L4 Confusion Matrix')
            plt.imshow(l4_confusion, interpolation='nearest')
            plt.xlabel('Prediction')
            plt.ylabel('Label')

            plt.show()
        return fitness
Exemple #5
0
def evaluate_recognition(parameters, debug=False):
    data = Dataset('datasets/textures/')
    train_data, test_data = data.split_dataset(75, 25, verbosity=0)
    max_dist = -32

    timer       = genetics.speed_fitness(threshold = 30, maximum = 2*60)
    eye_params  = parameters.eye
    sp_params   = parameters.sp
    sdrc_params = parameters.sdrc
    sensor      = htm.EyeSensor(eye_params)
    sp          = htm.SpatialPooler(sp_params, sensor.view_shape)
    classifier  = htm.SDR_Classifier(sdrc_params, sp.column_dimensions, (len(data.names),), output_type='pdf')
    baseline_classifier = htm.RandomOutputClassifier((len(data.names),))

    time_per_image = 10
    training_time  = int(round(time_per_image * parameters.image_cycles))
    if debug:
        training_time = time_per_image * 2
    for i in range(training_time):
        # Setup for a new image
        if i % time_per_image == 0:
            train_data.random_image()
            sensor.new_image(train_data.current_image)
            eye_positions = train_data.points_near_label(
                                    max_dist = max_dist,
                                    number=time_per_image)
        # Setup and compute for this cycle
        sensor.randomize_view()     # Random scale and orientation
        sensor.position = eye_positions.pop()
        labels_pdf = train_data.sample_labels(sensor.input_space_sample_points())
        view       = sensor.view()
        columns    = sp.compute(view)
        classifier.train(columns, labels_pdf)
        baseline_classifier.train(labels_pdf)
        # Sample the memory usage.
        if i == time_per_image-1:
            memory_performance = genetics.memory_fitness([sensor, sp, classifier],  0.5e9, 2e9)

    testing_time     = min(1000, time_per_image * 100)
    if debug:
        testing_time = time_per_image * 2
    score            = 0    # Regular accuracy, summed results of dataset.compare_label_samples
    baseline_score   = 0
    for i in range(testing_time):
        # Setup for a new image
        if i % time_per_image == 0:
            test_data.random_image()
            sensor.new_image(test_data.current_image)
            eye_positions = test_data.points_near_label(
                                    max_dist = max_dist,
                                    number   = time_per_image)
        # Setup and compute for this cycle
        sensor.randomize_view()
        sensor.position = eye_positions.pop()
        view            = sensor.view()
        columns         = sp.compute(view, learn=False)
        prediction      = classifier.predict(columns)
        baseline        = baseline_classifier.predict()
        # Compare results to labels
        labels         = test_data.sample_labels(sensor.input_space_sample_points())
        score          += test_data.compare_label_samples(prediction, labels)
        baseline_score += test_data.compare_label_samples(baseline, labels)
    score           /= testing_time
    baseline_score  /= testing_time

    return {
        'recognition':  score,
        'baseline':     baseline_score,
        'time':         timer.done(),
        'memory':       memory_performance,
    }