def test_grayscale_node(self, squeeze_channel, tensor_data): device = 'cpu' dtype = torch.float32 input_tensor = torch.tensor( [[1, 1, 1], [0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1]], device=device, dtype=dtype) expected_tensor = torch.tensor(tensor_data, device=device, dtype=dtype) mb0 = MemoryBlock() mb0.tensor = input_tensor gn = GrayscaleNode(squeeze_channel=squeeze_channel) Connector.connect(mb0, gn.inputs.input) gn.allocate_memory_blocks(AllocatingCreator(device)) gn._step() assert same(gn.outputs.output.tensor, expected_tensor, 0.000001) # allow small epsilon differences
def test_compute_output_projection_per_sequence(self, device, seqs, expected_output_projection): seqs_tensor = torch.tensor(seqs, device=device, dtype=torch.int64) expected_output_projection_tensor = torch.tensor(expected_output_projection, device=device, dtype=get_float(device)) flock_size, n_frequent_seqs, seq_length = seqs_tensor.shape n_cluster_centers = 4 seq_lookahead = 1 output_projection = TPOutputProjection(flock_size, n_frequent_seqs, n_cluster_centers, seq_length, seq_lookahead, device) projection_outputs = torch.zeros((flock_size, n_frequent_seqs, n_cluster_centers), device=device, dtype=get_float(device)) output_projection.compute_output_projection_per_sequence( seqs_tensor, projection_outputs ) assert same(expected_output_projection_tensor, projection_outputs)
def test_sequence_transition(sequences, trans_probs, iters, device): """For ease of use, sequences should be in ascending order.""" float_dtype = get_float(device) seq_params = DatasetSequenceMNISTNodeParams(sequences, transition_probs=trans_probs) seq_params.use_custom_probs = True node = DatasetSequenceMNISTNode(params=DatasetMNISTParams(one_hot_labels=False), seq_params=seq_params) node.allocate_memory_blocks(AllocatingCreator(device=device)) actual_sequence = [] for x in range(iters): node.step() actual_sequence.append(node.outputs.label.tensor.clone()) actual_sequence = torch.cat(actual_sequence, dim=0) proportions = torch.bincount(actual_sequence).type(float_dtype) / iters real_proportions = proportions[proportions > 0] expected_proportions = normalize_probs(torch.tensor(trans_probs, dtype=float_dtype, device=device ).sum(0), dim=0) assert same(expected_proportions, real_proportions, eps=1e-2)
def test_graph_save_load(): graph = create_graph() graph2 = create_graph() graph.step() graph2.step() graph2.nodes[0].outputs.output.tensor.random_() graph2.nodes[1].outputs.output.tensor.random_() graph2.nodes[2].outputs.output.tensor.random_() with TemporaryDirectory() as folder: saver = Saver(folder) graph.save(saver) saver.save() loader = Loader(folder) graph2.load(loader) for i in range(2): assert same(graph.nodes[i].outputs.output.tensor, graph2.nodes[i].outputs.output.tensor)
def test_join_node_inverse_0(): # TODO (Test): Make a dim = 1 variant # TODO (Test): Then, refactor tests here, maybe something to match the test class above, but for the backward projection. creator = AllocatingCreator(device='cpu') dtype = creator.float32 dim = 0 # The result of the inverse projection should only be one tensor. expected_results = [ creator.tensor([[1, 2, 3, 4], [5, 6, 7, 8]], dtype=dtype, device=creator.device), creator.tensor([[9, 10, 11, 12], [13, 14, 15, 16]], dtype=dtype, device=creator.device) ] input_memory_blocks = [MemoryBlock(), MemoryBlock()] input_memory_blocks[0].tensor = creator.zeros((2, 4)) input_memory_blocks[1].tensor = creator.zeros((2, 4)) output_tensor = creator.tensor( [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]], dtype=dtype, device=creator.device) join_node = JoinNode(dim, n_inputs=2) Connector.connect(input_memory_blocks[0], join_node.inputs[0]) Connector.connect(input_memory_blocks[1], join_node.inputs[1]) output_inverse_packet = InversePassOutputPacket(output_tensor, join_node.outputs.output) join_node.allocate_memory_blocks(creator) results = join_node.recursive_inverse_projection_from_output( output_inverse_packet) for expected, result in zip(expected_results, results): assert same(expected, result.tensor)
def test_coefficients(learning_coefficients): """Test that the data with learning_coefficients equal zero will not be sampled.""" params = NeuralNetworkFlockParams() params.flock_size = len(learning_coefficients) params.mini_batch_size = 57 device = 'cuda' params.input_size, params.output_size, batch_size, flock_inputs, flock_targets = \ prepare_inputs_and_targets(params.flock_size, device) neural_nets = MultilayerPerceptronFlock(params, device) batch_learning_coefficients = torch.tensor(learning_coefficients, device=device, dtype=get_float(device)) batch_learning_coefficients = batch_learning_coefficients.unsqueeze(2) data_loaders, should_learn = neural_nets.make_data_loaders( flock_inputs, flock_targets, batch_learning_coefficients, params.mini_batch_size, params.coefficients_minimum_max) # Compute frequency of each datapoint for flock_idx, loader in enumerate(data_loaders): for input_batch, target_batch in loader: occurrences = [] for point_idx, point in enumerate(flock_inputs[flock_idx]): seen = 0 for sampled_point in input_batch: if same(sampled_point, point): seen += 1 occurrences.append(seen) # Data-points with 0 coefficients should not be present if learning_coefficients[flock_idx][point_idx] == 0: assert seen == 0 else: assert seen > 0
def test_buffer_mask_creation(): buffer = create_buffer(flock_size=3, buffer_size=10, last_dim=3) buffer.current_ptr = torch.tensor([1, 3, 6], dtype=torch.int64, device=DEVICE) buffer.t1.stored_data[0][1] = torch.tensor([0.1, 0.1, 0.1], dtype=buffer._float_dtype, device=DEVICE) buffer.t1.stored_data[1][3] = torch.tensor([0.2, 0.2, 0.2], dtype=buffer._float_dtype, device=DEVICE) inp = torch.tensor([[0.1, 0.1, 0.1], [0.2, 0.2, 0.2], [0.3, 0.3, 0.3]], dtype=buffer._float_dtype, device=DEVICE) ground_truth = torch.tensor([0, 0, 1], dtype=torch.uint8, device=DEVICE) eq_data = buffer.t1.compare_with_last_data(inp, SPFlock._detect_any_difference) assert same(eq_data, ground_truth)
def test_context_creation(seq_lookahead): device = 'cuda' float_dtype = get_float(device) seq_length = 3 seq_lookbehind = seq_length - seq_lookahead flock = prepare_flock_for_context(device=device, seq_length=seq_length, seq_lookahead=seq_lookahead, n_cluster_centers=3) nan = float("nan") # Randomise our important tensors flock.sp_flock.forward_clusters.uniform_() flock.tp_flock.passive_predicted_clusters_outputs.uniform_() flock.tp_flock.action_rewards.uniform_() flock.tp_flock.action_punishments.uniform_() flock._assemble_output_context() padding = torch.full((flock.params.flock_size, flock.n_cluster_centers), fill_value=nan, dtype=float_dtype, device=device) expected_output_context = torch.cat([ flock.sp_flock.forward_clusters, flock.tp_flock.action_rewards, flock.tp_flock.action_punishments, flock.tp_flock.passive_predicted_clusters_outputs[:, seq_lookbehind, :], padding, padding ], dim=1).view(flock.params.flock_size, 2, NUMBER_OF_CONTEXT_TYPES, flock.n_cluster_centers) assert same(expected_output_context, flock.output_context)
def test_one_hot(device: str): """Test whether the one-hot representation works correctly as well.""" # request one-hot representation of landmarks one_hot_divisor = SpaceDivisor(horizontal_segments=3, vertical_segments=4, device=device) positions, results = get_data(device) no_positions = positions.shape[0] _, one_hot_landmarks = one_hot_divisor.get_landmarks(positions) for position in range(0, no_positions): coordinates = get_pos(position, positions) _, one_hot_l = one_hot_divisor.get_landmark(*coordinates) assert same(one_hot_l, one_hot_landmarks[position]) val, index = one_hot_l.max(-1) assert index == results[position].long()
def test_lambda_node(): device = 'cpu' dtype = torch.float32 input_tensor_0 = torch.tensor([0, 1, -1], device=device, dtype=dtype) input_tensor_1 = torch.tensor([1, 1, -1], device=device, dtype=dtype) expected_tensor = input_tensor_0 + input_tensor_1 mb0, mb1 = MemoryBlock(), MemoryBlock() mb0.tensor, mb1.tensor = input_tensor_0, input_tensor_1 def add_f(inputs, outputs): outputs[0][:] = 0 outputs[0].add_(inputs[0]) outputs[0].add_(inputs[1]) ln = LambdaNode(add_f, 2, [input_tensor_0.shape]) ln.allocate_memory_blocks(AllocatingCreator(device=device)) Connector.connect(mb0, ln.inputs[0]) Connector.connect(mb1, ln.inputs[1]) ln._step() assert same(ln.outputs[0].tensor, expected_tensor)
def test_action_monitor_node(action_in, override, override_action, device): float_dtype = get_float(device) action_in = action_in.type(float_dtype).to(device) node = ActionMonitorNode(descriptor) node.allocate_memory_blocks(AllocatingCreator(device=device)) block = MemoryBlock() block.tensor = action_in Connector.connect(block, node.inputs.action_in) node._override_checked = override node._actions_values = override_action node.step() output = node.outputs.action_out.tensor expected_output = torch.tensor(override_action, dtype=float_dtype, device=device) if override else action_in assert same(expected_output, output)
def test_integrate(): flock_size = 10 # Those indices which are subflocked and those that are not indices = torch.tensor([0, 1, 3, 6, 9], dtype=torch.int64) non_indices = torch.tensor([2, 4, 5, 7, 8], dtype=torch.int64) # Define tensors for the process read1 = torch.full((flock_size, 10), fill_value=2) read2 = torch.full((flock_size, 10), fill_value=3) rw1 = torch.full((flock_size, 10), fill_value=4) rw2 = torch.full((flock_size, 10), fill_value=5) # Subflock via the process proc = init_process(indices) sub_read1 = proc._read(read1) sub_read2 = proc._read(read2) sub_read_write1 = proc._read_write(rw1) sub_read_write2 = proc._read_write(rw2) # Modify the subtensored lot sub_read1.fill_(22) sub_read2.fill_(100) sub_read_write1.fill_(15) sub_read_write2.fill_(8) # Integrate proc.integrate() # Test that we have the same read_only values assert same(torch.full((flock_size, 10), fill_value=2), read1) assert same(torch.full((flock_size, 10), fill_value=3), read2) # Test that the rw tensors have changed and nont changed in the relevant places assert same(torch.full((5, 10), fill_value=4), rw1[non_indices]) assert same(torch.full((5, 10), fill_value=15), rw1[indices]) assert same(torch.full((5, 10), fill_value=5), rw2[non_indices]) assert same(torch.full((5, 10), fill_value=8), rw2[indices])
def test_update_knowledge_new_seqs(): """ Unlike the non-conv TP, there is only one sets of new sequences, and one set of all encountered sequences irrespective of the number of experts that are learning in this process. """ flock_size = 2 n_providers = 1 max_encountered_seqs = 7 n_frequent_seqs = 3 seq_length = 3 n_cluster_centers = 3 batch_size = 3 forgetting_limit = 3 context_size = 4 seq_lookahead = 1 max_new_seqs = 3 device = 'cpu' dtype = get_float(device) learning_proc = create_tp_flock_learn_process( flock_size=flock_size, max_encountered_seqs=max_encountered_seqs, n_frequent_seqs=n_frequent_seqs, seq_length=seq_length, n_cluster_centers=n_cluster_centers, batch_size=batch_size, forgetting_limit=forgetting_limit, context_size=context_size, device=device, seq_lookahead=seq_lookahead, n_providers=n_providers) learning_proc._all_encountered_seqs[0, 0] = torch.tensor([1, 2, 3], device=device, dtype=torch.int64) learning_proc._all_encountered_seq_occurrences[0, 0] = 3 learning_proc._all_encountered_seqs[0, 1] = torch.tensor([2, 1, 0], device=device, dtype=torch.int64) learning_proc._all_encountered_seq_occurrences[0, 1] = 0.4 all_enc_seqs = learning_proc._all_encountered_seqs all_enc_seq_occ = learning_proc._all_encountered_seq_occurrences all_enc_cont_occ = torch.full( (1, max_encountered_seqs, seq_length, n_providers, context_size), fill_value=-1, dtype=dtype, device=device) all_enc_exp_att = torch.full( (flock_size, max_encountered_seqs, seq_lookahead, n_cluster_centers), fill_value=-1., dtype=dtype, device=device) all_enc_exp_suc_rates = torch.full( (flock_size, max_encountered_seqs, seq_lookahead, n_cluster_centers), fill_value=-1., dtype=dtype, device=device) all_enc_rew_pun = torch.full( (flock_size, max_encountered_seqs, seq_lookahead, 2), fill_value=-1, dtype=dtype, device=device) most_probable_batch_seqs = torch.tensor( [[[0, 1, 3], [2, 1, 3], [-1, -1, -1], [3, 1, 3]]], device=device, dtype=torch.int64) newly_enc_seq_counts = torch.tensor([[2, 3, 0, 1]], device=device, dtype=dtype) learning_proc._update_knowledge_new_seqs(all_enc_seqs, all_enc_seq_occ, all_enc_cont_occ, all_enc_rew_pun, all_enc_exp_att, all_enc_exp_suc_rates, most_probable_batch_seqs, newly_enc_seq_counts) expected_all_enc_seqs = all_enc_seqs.clone() expected_all_enc_seqs[0, -max_new_seqs:] = torch.tensor( [[2, 1, 3], [0, 1, 3], [3, 1, 3]], dtype=torch.int64) expected_all_enc_seq_occ = all_enc_seq_occ.clone() expected_all_enc_seq_occ[0, -max_new_seqs:] = torch.tensor([3, 2, 1], dtype=dtype) new_context_counts = expected_all_enc_seq_occ[:, -max_new_seqs:].view( 1, max_new_seqs, 1, 1, 1).expand(1, max_new_seqs, seq_length, n_providers, context_size) / 2 expected_all_enc_cont_occ = all_enc_cont_occ.clone() expected_all_enc_cont_occ[:, -max_new_seqs:, :, :, :] = new_context_counts expected_all_enc_exp_att = all_enc_exp_att.clone() expected_all_enc_exp_att[:, -max_new_seqs:, :, :] = learning_proc._exploration_attempts_prior expected_all_enc_exp_suc_rates = all_enc_exp_suc_rates.clone() expected_all_enc_exp_suc_rates[:, -max_new_seqs:, :, :] = 0 expected_all_enc_rew_pun = all_enc_rew_pun.clone() expected_all_enc_rew_pun[:-max_new_seqs:, :, :] = 0 assert same(expected_all_enc_seqs, all_enc_seqs) assert same(expected_all_enc_seq_occ, all_enc_seq_occ) assert same(expected_all_enc_cont_occ, all_enc_cont_occ) assert same(expected_all_enc_exp_att, all_enc_exp_att) assert same(expected_all_enc_exp_suc_rates, all_enc_exp_suc_rates) assert same(expected_all_enc_rew_pun, all_enc_rew_pun)
def test_boost_clusters(self, cluster_boosting_durations, variance_batch, cluster_batch, expected_boosting_targets): """Testing if it correctly computes the boosting targets.""" flock_size = 2 n_cluster_centers = 4 input_size = 3 batch_size = 4 do_subflocking = True learning_period = 10 device = 'cpu' float_dtype = get_float(device) cluster_boost_threshold = 370 all_indices = torch.arange(flock_size, dtype=torch.int64, device=device).unsqueeze(dim=1) cluster_boosting_durations = torch.tensor(cluster_boosting_durations, dtype=torch.int64, device=device) variance_batch = torch.tensor(variance_batch, dtype=float_dtype, device=device) cluster_batch = torch.tensor(cluster_batch, dtype=float_dtype, device=device) prev_boosted_clusters = torch.zeros_like(cluster_boosting_durations, dtype=torch.uint8, device=device) boosting_targets = torch.zeros((2, 4), dtype=torch.int64, device=device) cluster_centers = torch.rand(flock_size, n_cluster_centers, input_size, dtype=float_dtype, device=device) cluster_center_targets = torch.zeros( (flock_size, n_cluster_centers, input_size), dtype=float_dtype, device=device) cluster_center_deltas = torch.zeros( (flock_size, n_cluster_centers, input_size), dtype=float_dtype, device=device) # Not used, but required by SPFlockLearning buffer = SPFlockBuffer(AllocatingCreator(device), buffer_size=20, n_cluster_centers=n_cluster_centers, flock_size=flock_size, input_size=input_size) process = SPFlockLearning( all_indices, do_subflocking, buffer, cluster_centers, cluster_center_targets, cluster_boosting_durations, boosting_targets, cluster_center_deltas, prev_boosted_clusters, n_cluster_centers=n_cluster_centers, input_size=input_size, cluster_boost_threshold=cluster_boost_threshold, max_boost_time=200, learning_rate=0.01, learning_period=learning_period, batch_size=batch_size, execution_counter=create_execution_counter(flock_size, device), device=device, boost=False) process._boost_clusters(cluster_batch, variance_batch, cluster_boosting_durations, boosting_targets, prev_boosted_clusters, process.tmp_boosting_targets, process._expert_row_indices, process._cluster_index_matrix) expected_boosting_targets = torch.tensor(expected_boosting_targets, dtype=torch.int64, device=device) assert same(expected_boosting_targets, boosting_targets)
def __eq__(self, other: Any): return isinstance(other, ComparableTensor) and same( self._tensor, other._tensor)
def test_rgb_transform(self, t_input, p_min, p_max, expected_result): result = TensorViewProjection._rgb_transform(t_input, p_min, p_max) assert same(expected_result, result, eps=0.001)
def test_learning_with_boosting(self): flock_size = 7 n_cluster_centers = 5 input_size = 3 batch_size = 10 do_subflocking = True learning_rate = 0.1 learning_period = 10 device = 'cuda' float_dtype = get_float(device) all_indices = torch.arange(flock_size, dtype=torch.int64, device=device).unsqueeze(dim=1) buffer = SPFlockBuffer(AllocatingCreator(device), buffer_size=20, n_cluster_centers=n_cluster_centers, flock_size=flock_size, input_size=input_size) buffer.inputs.stored_data = torch.randn( buffer.inputs.stored_data.size(), dtype=float_dtype, device=device) cluster_centers = torch.rand( (flock_size, n_cluster_centers, input_size), dtype=float_dtype, device=device) cluster_center_targets = torch.zeros( (flock_size, n_cluster_centers, input_size), dtype=float_dtype, device=device) cluster_center_deltas = torch.zeros( (flock_size, n_cluster_centers, input_size), dtype=float_dtype, device=device) cluster_boosting_durations = torch.full( (flock_size, n_cluster_centers), fill_value=995, device=device, dtype=torch.int64) boosting_targets = torch.zeros((flock_size, n_cluster_centers), dtype=torch.int64, device=device) prev_boosted_clusters = torch.zeros((flock_size, n_cluster_centers), dtype=torch.uint8, device=device) buffer.current_ptr = torch.full((flock_size, ), fill_value=9, dtype=torch.int64, device=device) buffer_data = torch.zeros((flock_size, batch_size, input_size), dtype=float_dtype, device=device) buffer.inputs.sample_contiguous_batch(batch_size, buffer_data) perm_data = buffer_data process = SPFlockLearning(all_indices, do_subflocking, buffer, cluster_centers, cluster_center_targets, cluster_boosting_durations, boosting_targets, cluster_center_deltas, prev_boosted_clusters, n_cluster_centers=n_cluster_centers, input_size=input_size, cluster_boost_threshold=1000, max_boost_time=200, learning_rate=learning_rate, learning_period=learning_period, batch_size=batch_size, execution_counter=create_execution_counter( flock_size, device), device=device, boost=True) buffer_clusters, _ = process.compute_closest_cluster_centers( cluster_centers, buffer_data) perm_clusters = buffer_clusters all_sum_data = [] # Go through each flock and compute the means of points belonging to each cluster center for exp_data, exp_clust in zip(perm_data, perm_clusters): sum_data = [] for c in range(process._n_cluster_centers): indices = exp_clust.type(torch.ByteTensor)[:, c] individual_data_points = exp_data[indices, :] if sum(indices) == 0: mean_data_points = torch.full((process._input_size, ), fill_value=FLOAT_NAN, dtype=float_dtype, device=device) else: mean_data_points = torch.mean(individual_data_points, dim=0) sum_data.append(mean_data_points) all_sum_data.append(torch.stack(sum_data)) ground_truth = torch.stack(all_sum_data) previous_cluster_centers = cluster_centers.clone() process.run() process.integrate() # cluster center targets correctly computed assert same(ground_truth, cluster_center_targets, eps=1e-6) # cluster centers correctly moved deltas = cluster_centers[ prev_boosted_clusters] - previous_cluster_centers[ prev_boosted_clusters] boosting_targets_indexes = boosting_targets.unsqueeze(dim=2).expand( flock_size, n_cluster_centers, input_size) boosting_cluster_centers = torch.gather(previous_cluster_centers, dim=1, index=boosting_targets_indexes) expected_deltas = boosting_cluster_centers[ prev_boosted_clusters] - previous_cluster_centers[ prev_boosted_clusters] expected_deltas *= learning_rate assert same(expected_deltas, deltas, eps=1e-2) # check that cluster boosting durations was increased correctly assert ( cluster_boosting_durations[prev_boosted_clusters == 0] == 0).all() assert ( cluster_boosting_durations[prev_boosted_clusters] == 1005).all()
def test_batch_sampling(): buffer = create_buffer(flock_size=7, buffer_size=1000, last_dim=5) buffer.t1.stored_data = torch.randn(buffer.t1.stored_data.size(), dtype=buffer._float_dtype, device=DEVICE) batch_size = 100 sample = torch.zeros((7, 100, 5), dtype=buffer._float_dtype, device=DEVICE) # Test 1: Past is contiguous in the buffer, pointers equal buffer.current_ptr = torch.full((7, ), fill_value=990, dtype=torch.int64, device=DEVICE) buffer.t1._sample_batch(batch_size, sample) # Permute for batch-major format ground_truth_sample = buffer.t1.stored_data[:, 891:991] assert same(sample, ground_truth_sample) # Test2: Past is non-contiguous in the buffer, pointers equal buffer.current_ptr = torch.full((7, ), fill_value=50, dtype=torch.int64, device=DEVICE) buffer.t1._sample_batch(batch_size, sample) # Permute for batch-major format ground_truth_sample = torch.cat( [buffer.t1.stored_data[:, -49:], buffer.t1.stored_data[:, :51]], dim=1) assert same(sample, ground_truth_sample) # Test3: Past is uneven in the buffer, pointers unequal buffer.current_ptr = torch.tensor([50, 200, 10, 500, 70, 95, 33], dtype=torch.int64, device=DEVICE) ground_truth_sample = [ torch.cat([ buffer.t1.stored_data[0, -49:], buffer.t1.stored_data[0, :51] ]), buffer.t1.stored_data[1, 101:201], torch.cat( [buffer.t1.stored_data[2, -89:], buffer.t1.stored_data[2, :11]]), buffer.t1.stored_data[3, 401:501], torch.cat( [buffer.t1.stored_data[4, -29:], buffer.t1.stored_data[4, :71]]), torch.cat( [buffer.t1.stored_data[5, -4:], buffer.t1.stored_data[5, :96]]), torch.cat( [buffer.t1.stored_data[6, -66:], buffer.t1.stored_data[6, :34]]) ] # After stacking, convert to batch-major via permute ground_truth_sample = torch.stack(ground_truth_sample) buffer.t1._sample_batch(batch_size, sample) assert same(sample, ground_truth_sample) # Test4: Test different batch-sizes - smaller batch_size = 1 sample = torch.zeros((7, 1, 5), dtype=buffer._float_dtype, device=DEVICE) buffer.current_ptr = torch.full((7, ), fill_value=500, dtype=torch.int64, device=DEVICE) buffer.t1._sample_batch(batch_size, sample) ground_truth_sample = buffer.t1.stored_data[:, (501 - batch_size):501] assert same(sample, ground_truth_sample) # Test5: Test different batch-sizes - bigger batch_size = 423 sample = torch.zeros((7, 423, 5), dtype=buffer._float_dtype, device=DEVICE) buffer.current_ptr = torch.full((7, ), fill_value=500, dtype=torch.int64, device=DEVICE) buffer.t1._sample_batch(batch_size, sample) ground_truth_sample = buffer.t1.stored_data[:, (501 - batch_size):501] assert same(sample, ground_truth_sample)
def test_forward_learn_disambiguating_context(): """Tests if context helps to disambiguate situations. Two experts, both seeing the same data and contexts """ device = 'cuda' float_dtype = get_float(device) batch_size = 5 params = ExpertParams() params.flock_size = 2 params.n_cluster_centers = 3 tp_params = params.temporal tp_params.n_providers = 1 tp_params.incoming_context_size = 2 tp_params.seq_length = 2 tp_params.buffer_size = 1000 tp_params.batch_size = batch_size tp_params.seq_lookahead = 1 tp_params.n_frequent_seqs = 50 tp_params.max_encountered_seqs = 300 tp_params.forgetting_limit = 1 tp_params.learning_period = 1 tp_params.context_prior = SMALL_CONSTANT tp_params.exploration_probability = 0 tp_params.follow_goals = False tp_params.enable_learning = True tp_params.max_new_seqs = 4 tp_params.compute_backward_pass = True flock = ConvTPFlock(params, creator=AllocatingCreator(device)) # experts: # both receive a cycling sequence and useful context seqs = torch.tensor([[[1, 0, 0], [1, 0, 0]], [[0, 1, 0], [0, 1, 0]], [[0, 0, 1], [0, 0, 1]], [[0, 1, 0], [0, 1, 0]]], dtype=float_dtype, device=device) contexts = torch.tensor( [[[[[1, 0], [0, 0], [0, 0]]], [[[1, 0], [0, 0], [0, 0]]]], [[[[1, 0], [0, 0], [0, 0]]], [[[1, 0], [0, 0], [0, 0]]]], [[[[1, 0], [0, 0], [0, 0]]], [[[1, 0], [0, 0], [0, 0]]]], [[[[0, 1], [0, 0], [0, 0]]], [[[0, 1], [0, 0], [0, 0]]]]], dtype=float_dtype, device=device) expected_actions = torch.tensor( [[[0, 1, 0], [0, 1, 0]], [[0, 0, 1], [0, 0, 1]], [[0, 1, 0], [0, 1, 0]], [[1, 0, 0], [1, 0, 0]]], dtype=float_dtype, device=device) expected_projections = torch.tensor( [[[0.6666, 0.3333, 0.], [0.6666, 0.3333, 0.]], [[0., 0.6666, 0.3333], [0., 0.6666, 0.3333]], [[0., 0.3333, 0.6666], [0., 0.3333, 0.6666]], [[0.3333, 0.6666, 0.], [0.3333, 0.6666, 0.]]], dtype=float_dtype, device=device) # need to learn at least 2 times because contexts are not extracted when sequence is new. And they are regarded # as uniform context so we need even more to get to a sharp probability iterations = batch_size * 4 for k in range(iterations): cluster_data = seqs[k % 4] context_data = contexts[k % 4] flock.forward_learn(cluster_data, context_data, input_rewards=None) # Run through the sequences yet again and no grab the outputs each time for flock 2 for k in range(4): flock._forward(seqs[k], contexts[k], input_rewards=None, sp_mask=None) # Check that the predicted outputs are what we expect assert same(expected_actions[k], flock.action_outputs, eps=1e-1) # Check that the output projection is what we expect assert same(expected_projections[k], flock.projection_outputs, eps=3e-2)
def test_compute_similarity(self, device, item, sequences, expected_result): def t(data): return torch.tensor(data, device=device, dtype=get_float(device)) result = TPOutputProjection.compute_similarity(t(item), t(sequences)) assert same(t(expected_result), result, eps=1e-3)
def test_convolutional_aspect(): """Tests whether the convTP is actually convolutional, The convolutional TP should allow any expert to recognise and predict the next element in a sequence when one expert does. This test shows two experts two separate sequences and, then tests them using the sequence which the other expert trained. Because lookbehind is 2, before testing, the experts need to be 'primed' with the cluster immediately preceeding the sequence they are to be tested on. """ device = 'cuda' float_dtype = get_float(device) batch_size = 10 params = ExpertParams() params.flock_size = 2 params.n_cluster_centers = 6 tp_params = params.temporal tp_params.incoming_context_size = 2 tp_params.seq_length = 3 tp_params.buffer_size = 1000 tp_params.batch_size = batch_size tp_params.seq_lookahead = 1 tp_params.n_frequent_seqs = 50 tp_params.max_encountered_seqs = 300 tp_params.forgetting_limit = 1 tp_params.learning_period = 1 tp_params.context_prior = SMALL_CONSTANT tp_params.exploration_probability = 0 tp_params.follow_goals = False tp_params.enable_learning = True tp_params.max_new_seqs = 4 tp_params.compute_backward_pass = True flock = ConvTPFlock(params, creator=AllocatingCreator(device)) training_seqs = torch.tensor([[[1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1]], [[0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0]], [[0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0]]], dtype=float_dtype, device=device) training_contexts = torch.tensor( [[[[[1, 0], [0, 0], [0, 0]]], [[[0, 1], [0, 0], [0, 0]]]], [[[[1, 0], [0, 0], [0, 0]]], [[[0, 1], [0, 0], [0, 0]]]], [[[[1, 0], [0, 0], [0, 0]]], [[[0, 1], [0, 0], [0, 0]]]], [[[[1, 0], [0, 0], [0, 0]]], [[[0, 1], [0, 0], [0, 0]]]]], dtype=float_dtype, device=device) expected_actions_1 = torch.tensor( [[[0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 1, 0]], [[0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0]], [[1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1]]], dtype=float_dtype, device=device) # Train the models iterations = batch_size + 10 for k in range(iterations): for cluster_data, context_data in zip(training_seqs, training_contexts): flock.forward_learn(cluster_data, context_data, input_rewards=None) # Test that each expert can recall the sequences that it had learned for cluster_data, context_data, expected_action in zip( training_seqs, training_contexts, expected_actions_1): flock._forward(cluster_data, context_data, input_rewards=None, sp_mask=None) # Check that the predicted outputs are what we expect assert same(expected_action, flock.action_outputs, eps=1e-1) # There is a probably a cool way to reshuffle the innermost values of the tensor, but for now, # just define what we want to test with manually. testing_seqs = torch.tensor([[[0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 0]], [[0, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 0]]], dtype=float_dtype, device=device) testing_contexts = torch.tensor( [[[[[0, 1], [0, 0], [0, 0]]], [[[1, 0], [0, 0], [0, 0]]]], [[[[0, 1], [0, 0], [0, 0]]], [[[1, 0], [0, 0], [0, 0]]]], [[[[0, 1], [0, 0], [0, 0]]], [[[1, 0], [0, 0], [0, 0]]]], [[[[0, 1], [0, 0], [0, 0]]], [[[1, 0], [0, 0], [0, 0]]]]], dtype=float_dtype, device=device) expected_actions = torch.tensor([[[0, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 0]], [[0, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 0]], [[0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0]]], dtype=float_dtype, device=device) # Because each expert maintains its own buffer, we need to "prime" them with a single example from the sequence we # want them to now recognise. This is the last part of testing seqs, so it lines up with the first example next time flock._forward(testing_seqs[2], testing_contexts[2], input_rewards=None, sp_mask=None) # Test that each expert can recall the sequences that *the other expert* had learned for cluster_data, context_data, expected_action in zip( testing_seqs, testing_contexts, expected_actions): flock._forward(cluster_data, context_data, input_rewards=None, sp_mask=None) # Check that the predicted outputs are what we expect assert same(expected_action, flock.action_outputs, eps=1e-1)
def test_same(): """Another test is together with same_list in test_list_utils.""" assert same(torch.ones(10), torch.ones(10), 1e-5) assert not same(torch.ones(10), torch.zeros(10), 1e-5)
def _same(expected, result) -> bool: return expected.shape == result.shape and \ same(result[0], result[1])
def test_combine_flocks(flock_size, batch_size, overlap): """Test the mechanism for combining all the batches from each flock into 4 tensors with padding in between. """ max_encountered_seqs = 7 n_frequent_seqs = 3 seq_length = 3 n_cluster_centers = 3 forgetting_limit = 3 context_size = 4 seq_lookahead = 1 device = 'cpu' dtype = get_float(device) learning_proc = create_tp_flock_learn_process( flock_size=flock_size, max_encountered_seqs=max_encountered_seqs, n_frequent_seqs=n_frequent_seqs, seq_length=seq_length, n_cluster_centers=n_cluster_centers, batch_size=batch_size, forgetting_limit=forgetting_limit, context_size=context_size, device=device, seq_lookahead=seq_lookahead) cluster_batch = torch.rand((flock_size, batch_size, n_cluster_centers), dtype=dtype, device=device) context_batch = torch.rand((flock_size, batch_size, context_size), dtype=dtype, device=device) exploring_batch = torch.rand((flock_size, batch_size, 1), dtype=dtype, device=device) actions_batch = torch.rand((flock_size, batch_size, n_cluster_centers), dtype=dtype, device=device) rewards_batch = torch.rand((flock_size, batch_size, 2), dtype=dtype, device=device) learning_proc._subbatch_overlap = overlap comb_clusters, comb_contexts, comb_rewards, comb_exploring, comb_actions = learning_proc._combine_flocks( cluster_batch, context_batch, rewards_batch, exploring_batch, actions_batch) expected_comb_clusters = torch.cat( [cluster_batch, torch.zeros(flock_size, overlap, n_cluster_centers)], dim=1).view(1, -1, n_cluster_centers) expected_comb_contexts = torch.cat( [context_batch, torch.zeros(flock_size, overlap, context_size)], dim=1).view(1, -1, context_size) expected_comb_exploring = torch.cat( [exploring_batch, torch.zeros(flock_size, overlap, 1)], dim=1).view(1, -1, 1) expected_comb_actions = torch.cat( [actions_batch, torch.zeros(flock_size, overlap, n_cluster_centers)], dim=1).view(1, -1, n_cluster_centers) expected_comb_rewards = torch.cat( [rewards_batch, torch.zeros(flock_size, overlap, 2)], dim=1).view(1, -1, 2) expected_valid_seqs_indicator = torch.cat( [ torch.ones((flock_size, batch_size - overlap), dtype=torch.int64), torch.zeros((flock_size, overlap * 2), dtype=torch.int64) ], dim=1).view(1, -1)[:, :learning_proc._max_seqs_in_batch] assert same(expected_comb_clusters, comb_clusters, eps=1e-3) assert same(expected_comb_contexts, comb_contexts, eps=1e-3) assert same(expected_comb_exploring, comb_exploring, eps=1e-3) assert same(expected_comb_actions, comb_actions, eps=1e-3) assert same(expected_comb_rewards, comb_rewards, eps=1e-3) assert same(expected_valid_seqs_indicator, learning_proc._combined_valid_seqs)
def test_forward_passive(): device = 'cuda' float_dtype = get_float(device) flock_size = 2 buffer_size = 6 context_size = 2 n_cluster_centers = 3 n_frequent_seqs = 3 n_providers = 1 buffer = create_tp_buffer(flock_size=flock_size, buffer_size=buffer_size, n_cluster_centers=n_cluster_centers, n_frequent_seqs=n_frequent_seqs, context_size=context_size, n_providers=n_providers, device=device) # region setup tensors nan = FLOAT_NAN small_const = SMALL_CONSTANT buffer.clusters.stored_data = torch.tensor( [ [ [0, 1, 0], [1, 0, 0], # current_ptr [0, 1, 0], [1, 0, 0], [0, 0, 1], [1, 0, 0] ], [ [0, 1, 0], [0, 0, 1], [1, 0, 0], [0, 0, 1], # current_ptr [nan, nan, nan], [nan, nan, nan] ] ], dtype=float_dtype, device=device) normalize_probs_(buffer.clusters.stored_data, dim=2, add_constant=True) buffer.contexts.stored_data = torch.tensor( [ [ [[1, 1]], [[0.1, 0.1]], # current_ptr [[0, 1]], [[1, 0.5]], [[1, 0]], [[0, 0]] ], [ [[1, 1]], [[1, 1]], [[0.9, 0]], [[1, 0]], # current_ptr [[nan, nan]], [[nan, nan]] ] ], dtype=float_dtype, device=device) move_probs_towards_50_(buffer.contexts.stored_data) # 2 is used just for checking that nothing else changed. buffer.seq_probs.stored_data.fill_(2) buffer.outputs.stored_data.fill_(2) buffer.current_ptr = torch.tensor([1, 3], dtype=torch.int64, device=device) buffer.total_data_written = torch.tensor([8, 3], dtype=torch.int64, device=device) frequent_context_likelihoods = torch.tensor( [[[[4.5, 2.5], [1, 2.5], [3, 2.5]], [[4, 2], [0.1, 2], [3, 2]], [[0, 0], [0, 0], [0, 0]]], [[[0, 1.5], [1, 1.5], [2.9, 1.5]], [[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]]], dtype=float_dtype, device=device) add_small_constant_(frequent_context_likelihoods, small_const) cluster_data = torch.tensor([[0, 0, 1], [0.5, 0.5, 0]], dtype=float_dtype, device=device) # sequences: # [1, 0, 2], # [0, 2, 0 or 1] context_data = torch.tensor( [[[[0, 1], [0, 0], [0, 0]]], [[[1, 0.5], [0, 0], [0, 0]]]], dtype=float_dtype, device=device) # contexts: # [[1.0, 1.0], [0.1, 0.1], [0.0, 1.0]], # [[0.9, 0.0], [1.0, 0.0], [1.0, 0.5]] # Pre-fill the output tensors so that we can check that they were written into projection_output = torch.full((flock_size, n_cluster_centers), fill_value=-2, dtype=float_dtype, device=device) action_output = torch.full((flock_size, n_cluster_centers), fill_value=-2, dtype=float_dtype, device=device) # endregion process = create_tp_flock_untrained_forward_process( flock_size=flock_size, n_frequent_seqs=n_frequent_seqs, n_cluster_centers=n_cluster_centers, context_size=context_size, buffer=buffer, cluster_data=cluster_data, context_data=context_data, projection_outputs=projection_output, action_outputs=action_output, do_subflocking=True, device=device) process.run_and_integrate() # temporary process expected values # region expected_values expected_buffer_current_ptr = torch.tensor([2, 4], dtype=torch.int64, device=device) expected_buffer_total_data_written = torch.tensor([9, 4], dtype=torch.int64, device=device) expected_buffer_clusters = torch.tensor( [ [ [0, 1, 0], [1, 0, 0], [0, 0, 1], # current_ptr [1, 0, 0], [0, 0, 1], [1, 0, 0] ], [ [0, 1, 0], [0, 0, 1], [1, 0, 0], [0, 0, 1], [0.5, 0.5, 0], # current_ptr [nan, nan, nan] ] ], dtype=float_dtype, device=device) normalize_probs_(expected_buffer_clusters, dim=2, add_constant=True) expected_buffer_contexts = torch.tensor( [ [ [[1, 1]], [[0.1, 0.1]], [[0, 1]], # current_ptr [[1, 0.5]], [[1, 0]], [[0, 0]] ], [ [[1, 1]], [[1, 1]], [[0.9, 0]], [[1, 0]], [[1, 0.5]], # current_ptr [[nan, nan]] ] ], dtype=float_dtype, device=device) move_probs_towards_50_(expected_buffer_contexts) # There are 3 frequent sequences, so current pointer says that the first one is 100% probable. expected_buffer_seq_probs = torch.tensor( [ [ [2, 2, 2], [2, 2, 2], [0, 0, 0], # current_ptr [2, 2, 2], [2, 2, 2], [2, 2, 2] ], [ [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [0, 0, 0], # current_ptr [2, 2, 2] ] ], dtype=float_dtype, device=device) fill_value = (1.0 / n_cluster_centers) # There are 3 cluster centers. expected_buffer_outputs = torch.tensor( [ [ [2, 2, 2], [2, 2, 2], [fill_value, fill_value, fill_value], # current_ptr [2, 2, 2], [2, 2, 2], [2, 2, 2] ], [ [2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2], [fill_value, fill_value, fill_value], # current_ptr [2, 2, 2] ] ], dtype=float_dtype, device=device) expected_projection_output = torch.full((2, 3), fill_value=fill_value, dtype=float_dtype, device=device) expected_action_output = torch.full((2, 3), fill_value=fill_value, dtype=float_dtype, device=device) # endregion assert same(expected_projection_output, projection_output, eps=1e-4) assert same(expected_action_output, action_output, eps=1e-4) # test also storing into buffer assert same(expected_buffer_current_ptr, buffer.current_ptr) assert same(expected_buffer_total_data_written, buffer.total_data_written) assert same(expected_buffer_outputs, buffer.outputs.stored_data, eps=1e-4) assert same(expected_buffer_seq_probs, buffer.seq_probs.stored_data, eps=1e-4) assert same(expected_buffer_clusters, buffer.clusters.stored_data, eps=1e-4) assert same(expected_buffer_contexts, buffer.contexts.stored_data, eps=1e-4)
def test_forward_and_learning(self): def manually_calc_cc_targets(): buffer = flock.buffer buffer_data = torch.full( (flock.flock_size, flock.batch_size, flock.n_cluster_centers), dtype=float_dtype, fill_value=FLOAT_NAN, device=device) buffer.inputs._sample_batch(flock.batch_size, buffer_data) perm_data = buffer_data all_indices = torch.arange(flock.flock_size, dtype=torch.int64, device=flock._device) learn_process = flock._create_learning_process(all_indices) buffer_clusters, _ = learn_process.compute_closest_cluster_centers( flock.cluster_centers, buffer_data) perm_clusters = buffer_clusters all_sum_data = [] # compute for each flock independently for exp_data, exp_clust in zip(perm_data, perm_clusters): sum_data = [] for c in range(flock.n_cluster_centers): indices = exp_clust.type(torch.ByteTensor)[:, c] individual_data_points = exp_data[indices, :] if sum(indices) == 0: mean_data_points = torch.full((flock.input_size, ), dtype=float_dtype, fill_value=FLOAT_NAN, device=device) else: mean_data_points = torch.mean(individual_data_points, dim=0) sum_data.append(mean_data_points) all_sum_data.append(torch.stack(sum_data)) ground_truth = torch.stack(all_sum_data) return ground_truth def run_forward(data): forward_process = flock._create_forward_process(data, all_indices) forward_process.run_and_integrate() def run_learning(): learn_process = flock._create_learning_process(all_indices) learn_process.run_and_integrate() n_cluster_centers = 2 f_size = 3 i_size = 2 buff_size = 10 ba_size = 1 device = 'cuda' float_dtype = get_float(device) params = ExpertParams() params.flock_size = f_size params.n_cluster_centers = n_cluster_centers params.spatial.input_size = i_size params.spatial.buffer_size = buff_size params.spatial.batch_size = ba_size params.spatial.sampling_method = SamplingMethod.LAST_N flock = SPFlock(params, AllocatingCreator(device)) flock.cluster_boosting_durations.fill_(0) all_indices = torch.arange(f_size, dtype=torch.int64, device=device).unsqueeze(dim=1) flock.cluster_centers = torch.tensor( [[[0.25, 1.1], [-0.3, 0.2]], [[1.2, 1.3], [-1, -2]], [[0.6, 0.2], [-1.2, -0.8]]], dtype=float_dtype, device=device) # First pass - no learning happens data1 = torch.tensor([[0.2, 1], [1.1, 1.1], [-1.2, -0.7]], dtype=float_dtype, device=device) cc1 = torch.tensor([[1., 0], [1., 0], [0, 1]], dtype=float_dtype, device=device) run_forward(data1) cc_res1 = flock.forward_clusters run_learning() assert same(cc1, cc_res1) # Second pass - learning happens for experts 1 and 2 data2 = torch.tensor([[0.2, 1], [-1, -0.4], [0.2, 0.3]], dtype=float_dtype, device=device) cc2 = torch.tensor([[1., 0], [0, 1.], [1, 0]], dtype=float_dtype, device=device) run_forward(data2) cc_res2 = flock.forward_clusters cc_targets2 = manually_calc_cc_targets() cc_deltas2 = (cc_targets2 - flock.cluster_centers) cc_deltas2[torch.isnan(cc_deltas2)] = 0 run_learning() assert same(cc2, cc_res2) assert same(cc_targets2, flock.cluster_center_targets) assert same(cc_deltas2, flock.cluster_center_deltas) # Third pass, all inputs are valid, but only expert 0 learns data3 = torch.tensor([[0.1, 1], [-1.1, -0.4], [0.3, 0.3]], dtype=float_dtype, device=device) cc3 = torch.tensor([[1., 0], [0, 1.], [1, 0]], dtype=float_dtype, device=device) run_forward(data3) cc_res3 = flock.forward_clusters cc_targets3 = manually_calc_cc_targets() cc_deltas3 = (cc_targets3 - flock.cluster_centers) cc_deltas3[torch.isnan(cc_deltas3)] = 0 run_learning() assert same(cc3, cc_res3) assert same(cc_targets3, flock.cluster_center_targets) assert same(cc_deltas3, flock.cluster_center_deltas) # Test with NaN input... copy_of_buffer = flock.buffer.inputs.stored_data.clone() data4 = torch.tensor([[0.1, 1], [-1.1, FLOAT_NAN], [0.3, 0.3]], dtype=float_dtype, device=device) cc4 = cc3 run_forward(data4) cc_res4 = flock.forward_clusters run_learning() assert same( cc4, cc_res4), "Classification should still work with NaN in the input" data5 = torch.tensor([[FLOAT_NAN, 1], [-1, -0.4], [0.2, 0.3]], dtype=float_dtype, device=device) cc5 = cc2 run_forward(data5) cc_res5 = flock.forward_clusters run_learning() assert same( cc5, cc_res5), "Classification should still work with NaN in the input"
def test_buffer_force_cpu(flock_indices): device = 'cuda' flock_size = 3 buffer_size = 10 last_dim = 4 # Create the buffer buffer = Buffer(AllocatingCreator(device), flock_size=flock_size, buffer_size=buffer_size) buffer.t1 = buffer._create_storage("t1", (flock_size, buffer_size, last_dim), force_cpu=True) # Assemble the flock indices if flock_indices is not None: flock_indices = torch.tensor(flock_indices, dtype=torch.int64) buffer.set_flock_indices(flock_indices) flock_ind_len = flock_indices.numel() else: flock_ind_len = flock_size storing_data = torch.ones((flock_ind_len, last_dim), dtype=FLOAT_TYPE_CUDA, device=device) expected_stored_data = storing_data.to('cpu').type(FLOAT_TYPE_CPU) buffer.t1.store(storing_data) if flock_indices is not None: actual_stored_data = buffer.t1.stored_data[flock_indices, -1] else: actual_stored_data = buffer.t1.stored_data[:, -1] # Test some storing! assert same(expected_stored_data, actual_stored_data) # Test comparison expected_comparison = torch.zeros(flock_size, dtype=torch.uint8, device=device) data = buffer.t1.stored_data[:, -1].type(FLOAT_TYPE_CUDA).to(device) actual_comparison = buffer.t1.compare_with_last_data( data, SPFlock._detect_any_difference) assert same(expected_comparison, actual_comparison) # Test_sampling out_tensor = torch.zeros(flock_ind_len, 3, last_dim, dtype=FLOAT_TYPE_CUDA, device=device) buffer.t1.sample_contiguous_batch(3, out_tensor) expected_out_tensor = torch.full((flock_ind_len, 3, last_dim), fill_value=FLOAT_NAN, dtype=FLOAT_TYPE_CUDA, device=device) expected_out_tensor[:, -1] = 1 assert same(expected_out_tensor, out_tensor)
def test_forward_learn_subflocking(self, sampling_method): params = ExpertParams() params.flock_size = 2 params.n_cluster_centers = 4 params.spatial.input_size = 2 params.spatial.cluster_boost_threshold = 2 params.spatial.learning_rate = 0.1 params.spatial.learning_period = 1 params.spatial.batch_size = 8 params.spatial.buffer_size = 10 params.spatial.max_boost_time = 10 params.spatial.sampling_method = sampling_method device = 'cuda' float_dtype = get_float(device) flock = ConvSPFlock(params, AllocatingCreator(device)) # Flock1 sequence is [0, 0], [1, 0], [0, 1], [1, 1], [0, 1] # Flock2 sequence is [0, 0], [1, 0], [0, 1], [1, 1], [1, 1] data = torch.tensor( [[[0., 0], [0., 0]], [[1., 0], [1., 0]], [[0., 1], [0., 1]], [[1, 1], [1, 1]], [[0, 1], [1, 1]]], dtype=float_dtype, device=device) iters = 15 for itr in range(iters): for k in data: flock.forward_learn(k) expected_forward_executions = torch.tensor([[iters * 5], [iters * 4]], dtype=torch.int64, device=device) expected_learning_executions = torch.tensor( [[iters * 5]], dtype=torch.int64, device=device) - 3 expected_learning_executions = expected_learning_executions.expand( params.flock_size, 1) assert same(expected_forward_executions, flock.execution_counter_forward) assert same(expected_learning_executions, flock.execution_counter_learning) cluster_centers1 = flock.cluster_centers.to('cpu').data[0].numpy() cluster_centers2 = flock.cluster_centers.to('cpu').data[1].numpy() data = data.to('cpu').data.numpy() expected_cluster_centers1 = data[:4, 0] expected_cluster_centers2 = data[:4, 1] # Cluster centers have no guarantee of order - so we have to order them manually rounded_cluster_centers1 = np.around(cluster_centers1, decimals=2) rounded_cluster_centers2 = np.around(cluster_centers2, decimals=2) cc_indices1 = [] cc_indices2 = [] for cc1, cc2 in zip(rounded_cluster_centers1, rounded_cluster_centers2): cc_indices1.append(cc1[0] * 2 + cc1[1] * 4) cc_indices2.append(cc2[0] * 2 + cc2[1] * 4) sorted_indices1 = np.argsort(cc_indices1) sorted_ccs1 = cluster_centers1[sorted_indices1] sorted_indices2 = np.argsort(cc_indices2) sorted_ccs2 = cluster_centers2[sorted_indices2] np.testing.assert_almost_equal(expected_cluster_centers1, sorted_ccs1, decimal=1) np.testing.assert_almost_equal(expected_cluster_centers2, sorted_ccs2, decimal=1)
def test_replace_cluster_ids_with_projections(self, source, projections, expected_result, device): t_source = torch.Tensor(source).long().to(device) t_projections = torch.Tensor(projections).float().to(device) t_expected = torch.Tensor(expected_result).to(device) t_result = replace_cluster_ids_with_projections(t_source, t_projections) assert same(t_expected, t_result)
def test_colorize(self, t_input, minimum, maximum, expected_result): result = self.instance._colorize(t_input, minimum, maximum) assert same(expected_result, result, eps=0.001)