def calculate_min_activity(columns, active, distances, inhibition_area, activity, min_activity_threshold): """ Calculates the minActivity matrix from the paper (p. 4). :param columns: the 4-dimensional array of HTM columns: a 4-dimensional array of shape *shape* that represents the HTM columns and their synapses; each element columns[a, b, c, d] contains the permanence value of the synapse connecting the column with coordinates (a, b) to input with coordinates (c, d). :param active: array of shape (columns.shape[0], columns.shape[0]); each element active[a, b] is True if the column [a, b] is active this iteration and False otherwise. :param distances: a 4-dimensional array of the same shape as *columns*; each element distances[a, b, c, d] contains the euclidean distance from (a, b) to (c, d). :param inhibition_area: the BSP's inhibitionArea parameter (p. 3, 4). :param activity: the BSP's activity matrix (p. 4). This parameter is modified and returned. It is a dictionary with tuples (y, x) of HTM column coordinates as keys and deque (a queue implementation) instances as values. The queue for key [a, b] stores a 1 each iteration the the column [a, b] is active during the last 1000 iterations. :param min_activity_threshold: the BSP's minActivityThreshold parameter (p. 4). :return: the BSP's minActivity matrix (p. 4); an array min_activity of shape (columns.shape[0], columns.shape[1]), where each min_activity[a b] represents the calculated minActivity for the column [a, b]: minActivity([a, b]) = max(activity[u, v]) * minActivityThreshold where the column [u, v] is a neighbour of [y, x] (within inhibitionArea) """ # Initialize the min_activity array. min_activity = np.zeros(shape=columns.shape[:2]) # For each active column [y, x], ... for y, x, _ in iter_columns(columns, active_matrix=active): c = (y, x) max_activity = 0 # get the neighbours of [y, x] ... neighbours = iter_neighbours(columns, y, x, distances, inhibition_area) # and for each neighbour [u, v] of [y, x], ... for u, v, _ in neighbours: n = (u, v) # calculate the how many times [u, v] was active during the # last 1000 iterations, ... activity_count = activity[n].sum() # and choose the maximum count among all the neighbours of # [y, x]. if activity_count > max_activity: max_activity = activity_count # Finally, scale the maximum activity count among the neighbours of # [y, x] by min_activity_threshold. min_activity[c] = max_activity * min_activity_threshold return min_activity
def compute_heatmap_expanded(weight): heatmap = np.zeros((2 * GRID_HEIGHT - 1, 2 * GRID_WIDTH - 1)) for (neuron_x, neuron_y), neighbours in iter_neighbours(weight): for (neigbour_x, neigbour_y) in neighbours: neuron_vec = weight[:, neuron_x, neuron_y] neigbour_vec = weight[:, neigbour_x, neigbour_y] distance = np.linalg.norm(neuron_vec - neigbour_vec) if neuron_x == neigbour_x and (neigbour_y - neuron_y) == 1: heatmap[2 * neuron_x, 2 * neuron_y + 1] = distance elif (neigbour_x - neuron_x) == 1 and neigbour_y == neuron_y: heatmap[2 * neuron_x + 1, 2 * neuron_y] = distance return heatmap
def compute_heatmap(weight): heatmap = np.zeros((GRID_HEIGHT, GRID_WIDTH)) for (neuron_x, neuron_y), neighbours in iter_neighbours(weight): total_distance = 0 for (neigbour_x, neigbour_y) in neighbours: neuron_vec = weight[:, neuron_x, neuron_y] neigbour_vec = weight[:, neigbour_x, neigbour_y] distance = np.linalg.norm(neuron_vec - neigbour_vec) total_distance += distance avg_distance = total_distance / len(neighbours) heatmap[neuron_x, neuron_y] = avg_distance return heatmap
def inhibit_columns(columns, distances, inhibition_area, overlap, activity, desired_activity): """ Implements the inhibitColums function from the paper (pp. 3, 4) :param columns: the 4-dimensional array of HTM columns: a 4-dimensional array of shape *shape* that represents the HTM columns and their synapses; each element columns[a, b, c, d] contains the permanence value of the synapse connecting the column with coordinates (a, b) to input with coordinates (c, d). :param distances: a 4-dimensional array of the same shape as *columns*; each element distances[a, b, c, d] contains the euclidean distance from (a, b) to (c, d). :param inhibition_area: the BSP's inhibitionArea parameter (p. 3, 4). :param overlap: an array of shape (columns.shape[0], columns.shape[0]); each element overlap[a, b] contains the overlap of the column [a, b] with the image. :param activity: the BSP's activity matrix (p. 4). This parameter is modified and returned. It is a dictionary with tuples (y, x) of HTM column coordinates as keys and deque (a queue implementation) instances as values. The queue for key [a, b] stores a 1 each iteration the the column [a, b] is active during the last 1000 iterations. :param desired_activity: the BSP's desiredActivity parameter (p. 4). :return: a tuple (active, activity). *active* is an array of shape (columns.shape[0], columns.shape[0]); each element active[a, b] is True if the column [a, b] is active this iteration and False otherwise. *activity* is the parameter of the same name; the queue in activity[a, b] will have a 1 pushed into it if the the column [a, b] was active this iteration. """ # Initialize the active array filling it with False. active = np.zeros(shape=columns.shape[:2], dtype=np.bool) # For each column [y, x]... for y, x, _ in iter_columns(columns): # if [y, x] reacted to the input at all, ... # (NOTE: This test is not present in the ASP paper, but it is present # in the original HTM paper. However it does make sense that a column # should be active only if some synapses were exited by the input.) if overlap[y, x] > 0: # initialize the activity counter, ... activity_sum = 0 # obtain the list of neighbours of the column [y, x], ... neighbours = iter_neighbours(columns, y, x, distances, inhibition_area) # for each neighbour [u, v] of [y, x] ... for u, v, _ in neighbours: # if the neighbour's overlap is over this column's overlap, ... if overlap[u, v] > overlap[y, x]: # count it towards the activity, ... activity_sum += 1 # and if the neighbours of [y, x] are not too active, ... if activity_sum < desired_activity: # set [y, x] as active, ... active[y, x] = True # and then update the activity array, indicating that # the column [y, x] was active in this iteration. activity[y, x].append(1) else: # and then update the activity array, indicating that # the column [y, x] was inactive in this iteration. activity[y, x].append(0) else: # update the activity array, indicating that # the column [y, x] was inactive in this iteration. activity[y, x].append(0) return active, activity