class ConvExpertTopology(Topology): sp_params: ExpertParams mnist_params: DatasetMNISTParams def __init__(self): super().__init__(device='cuda') self.sp_params = ExpertParams() self.sp_params.n_cluster_centers = 4 self.sp_params.spatial.input_size = 28 * 28 self.sp_params.flock_size = 4 self.sp_params.spatial.buffer_size = 100 self.sp_params.spatial.batch_size = 45 mnist_params0 = DatasetMNISTParams(class_filter=[0], one_hot_labels=False) mnist_params1 = DatasetMNISTParams(class_filter=[1], one_hot_labels=False) mnist_params2 = DatasetMNISTParams(class_filter=[2], one_hot_labels=False) mnist_params3 = DatasetMNISTParams(class_filter=[3], one_hot_labels=False) expert = ConvExpertFlockNode(self.sp_params.clone()) mnist0 = DatasetMNISTNode(params=mnist_params0) mnist1 = DatasetMNISTNode(params=mnist_params1) mnist2 = DatasetMNISTNode(params=mnist_params2) mnist3 = DatasetMNISTNode(params=mnist_params3) expand0 = ExpandNode(dim=0, desired_size=1) expand1 = ExpandNode(dim=0, desired_size=1) expand2 = ExpandNode(dim=0, desired_size=1) expand3 = ExpandNode(dim=0, desired_size=1) join = JoinNode(dim=0, n_inputs=4) self.add_node(mnist0) self.add_node(mnist1) self.add_node(mnist2) self.add_node(mnist3) self.add_node(expand0) self.add_node(expand1) self.add_node(expand2) self.add_node(expand3) self.add_node(expert) self.add_node(join) Connector.connect(mnist0.outputs.data, expand0.inputs.input) Connector.connect(mnist1.outputs.data, expand1.inputs.input) Connector.connect(mnist2.outputs.data, expand2.inputs.input) Connector.connect(mnist3.outputs.data, expand3.inputs.input) Connector.connect(expand0.outputs.output, join.inputs[0]) Connector.connect(expand1.outputs.output, join.inputs[1]) Connector.connect(expand2.outputs.output, join.inputs[2]) Connector.connect(expand3.outputs.output, join.inputs[3]) Connector.connect(join.outputs.output, expert.inputs.sp.data_input)
def __init__(self, c_n_ccs, c_buffer_size, c_seq_length, c_seq_lookahead, p_seq_length, p_seq_lookahead, p_n_ccs, flock_size): super().__init__("Two Experts") expert_params1 = ExpertParams() expert_params1.flock_size = flock_size expert_params1.n_cluster_centers = c_n_ccs expert_params1.produce_actions = True expert_params1.temporal.seq_length = c_seq_length expert_params1.temporal.seq_lookahead = c_seq_lookahead expert_params1.temporal.n_frequent_seqs = 700 expert_params1.temporal.max_encountered_seqs = 1000 expert_params1.temporal.exploration_probability = 0.05 expert_params1.temporal.batch_size = 200 expert_params1.temporal.compute_backward_pass = True expert_params1.temporal.frustration_threshold = 2 expert_params2 = expert_params1.clone() expert_params1.spatial.buffer_size = c_buffer_size expert_params1.compute_reconstruction = True expert_params2.temporal.seq_length = p_seq_length expert_params2.temporal.seq_lookahead = p_seq_lookahead expert_params2.n_cluster_centers = p_n_ccs expert_params2.produce_actions = False expert_params2.temporal.frustration_threshold = 10 expert_node1 = ExpertFlockNode(expert_params1) expert_node2 = ExpertFlockNode(expert_params2) self.add_node(expert_node1) self.add_node(expert_node2) Connector.connect(self.inputs.data.output, expert_node1.inputs.sp.data_input) Connector.connect(self.inputs.reward.output, expert_node1.inputs.tp.reward_input) Connector.connect(self.inputs.reward.output, expert_node2.inputs.tp.reward_input) # Connect the experts to each other. Connector.connect(expert_node1.outputs.tp.projection_outputs, expert_node2.inputs.sp.data_input) Connector.connect(expert_node2.outputs.output_context, expert_node1.inputs.tp.context_input, is_backward=True) # Connect the group output. Connector.connect(expert_node1.outputs.sp.predicted_reconstructed_input, self.outputs.predicted_reconstructed_input.input)
class LrfTopology(Topology): def __init__(self, expert_width: int = 1, input_square_side: int = 28, n_cluster_centers: int = 8, stride: int = None, is_convolutional: bool = False, training_phase_steps: int = 200, testing_phase_steps: int = 800, seed: int = 0): super().__init__(device='cuda') if stride is None: stride = expert_width self.training_phase_steps = training_phase_steps self.testing_phase_steps = testing_phase_steps self.testing_phase = True self.n_testing_phase = -1 self.training_step = -1 self._step_counter = 0 assert (input_square_side - (expert_width - stride)) % stride == 0, \ f'(input_square_side - (expert_width - stride)) ' \ f'({(input_square_side - (expert_width - stride))}) must be divisible' \ f' by stride ({stride})' self.n_experts_width = (input_square_side - (expert_width - stride)) // stride self.input_square_side = input_square_side self.one_expert_lrf_width = expert_width self.sp_params = ExpertParams() self.sp_params.n_cluster_centers = n_cluster_centers self.sp_params.spatial.input_size = self.one_expert_lrf_width * self.one_expert_lrf_width self.sp_params.flock_size = int(self.n_experts_width**2) self.sp_params.spatial.buffer_size = 800 self.sp_params.spatial.batch_size = 500 self.sp_params.compute_reconstruction = True self.mnist_params = DatasetMNISTParams(one_hot_labels=False, examples_per_class=100) self.mnist_test_params = DatasetMNISTParams(one_hot_labels=False, examples_per_class=1000) self.reconstructed_data = torch.zeros( (self.input_square_side, self.input_square_side), dtype=self.float_dtype, device=self.device) self.image_difference = torch.zeros( (self.input_square_side, self.input_square_side), dtype=self.float_dtype, device=self.device) # init nodes random_noise_params = RandomNoiseParams(amplitude=0.0001) self._node_mnist = DatasetMNISTNode(self.mnist_params, seed=0) self._node_mnist_test = DatasetMNISTNode(self.mnist_test_params, seed=1) parent_rf_dims = Size2D(self.one_expert_lrf_width, self.one_expert_lrf_width) self._node_lrf = ReceptiveFieldNode( (input_square_side, input_square_side, 1), parent_rf_dims, Stride(stride, stride)) sp_class = ConvSpatialPoolerFlockNode if is_convolutional else SpatialPoolerFlockNode # necessary to clone the params, because the GUI changes them during the simulation (restart needed) self._node_spatial_pooler = sp_class(self.sp_params.clone(), seed=seed) self._node_spatial_pooler_backup = sp_class(self.sp_params.clone(), seed=seed) self._noise_node = RandomNoiseNode(random_noise_params) self.add_node(self._node_mnist) self.add_node(self._node_mnist_test) self.add_node(self._noise_node) self.add_node(self._node_lrf) self.add_node(self._node_spatial_pooler) self.add_node(self._node_spatial_pooler_backup) Connector.connect(self._node_mnist.outputs.data, self._noise_node.inputs[0]) Connector.connect(self._noise_node.outputs[0], self._node_lrf.inputs[0]) Connector.connect(self._node_lrf.outputs[0], self._node_spatial_pooler.inputs.sp.data_input) Connector.connect( self._node_lrf.outputs[0], self._node_spatial_pooler_backup.inputs.sp.data_input) self.mnist_node = self._node_mnist def step(self): if not self._is_initialized: self._assign_ids_to_nodes(self._id_generator) self.order_nodes() self._update_memory_blocks() if not self.testing_phase and self._step_counter % self.training_phase_steps == 0: self.testing_phase = True self.n_testing_phase += 1 self.set_testing_model() self._step_counter = 0 elif self.testing_phase and self._step_counter % self.testing_phase_steps == 0: self.testing_phase = False self.set_training_model() self._step_counter = 0 self._step_counter += 1 if not self.testing_phase: self.training_step += 1 super().step() flock_reconstruction = self._node_spatial_pooler.outputs.sp.current_reconstructed_input # noinspection PyProtectedMember self.reconstructed_data.copy_( self._node_lrf.inverse_projection(flock_reconstruction.tensor)) self.image_difference.copy_(self.reconstructed_data - self._node_mnist.outputs.data.tensor) def set_training_model(self): # noinspection PyProtectedMember self._node_spatial_pooler_backup._unit.copy_to( self._node_spatial_pooler._unit) self._node_spatial_pooler.switch_learning(True) self._node_mnist_test.skip_execution = True self._node_mnist.skip_execution = False self.mnist_node = self._node_mnist Connector.disconnect_input(self._noise_node.inputs[0]) Connector.connect(self._node_mnist.outputs.data, self._noise_node.inputs[0]) def set_testing_model(self): # noinspection PyProtectedMember self._node_spatial_pooler._unit.copy_to( self._node_spatial_pooler_backup._unit) self._node_spatial_pooler.switch_learning(False) self._node_mnist.skip_execution = True self._node_mnist_test.skip_execution = False Connector.disconnect_input(self._noise_node.inputs[0]) Connector.connect(self._node_mnist_test.outputs.data, self._noise_node.inputs[0])
def __init__(self, params: ExpertParams, creator: TensorCreator = torch): """Initialises the flock. Args: params: parameters of the flock, see ExpertParams form default values. creator: """ super_params = params.clone() super_params.spatial.buffer_size = 1 # these are just internal buffers local to each expert, # they do not learn from them. super().__init__(super_params, creator) super()._validate_universal_params(params) self._validate_conv_learning_params(params) float_dtype = get_float(self._device) # Common buffer where each flock stores data and from which they learn. self.common_buffer = SPFlockBuffer( creator=creator, flock_size=1, buffer_size=params.spatial.buffer_size, input_size=self.input_size, n_cluster_centers=self.n_cluster_centers) # The initial clusters are randomised self.common_cluster_centers = creator.randn( (1, self.n_cluster_centers, self.input_size), device=self._device, dtype=float_dtype) # Virtual replications of the common cluster centers, mainly for observation purposes. self.cluster_centers = self.common_cluster_centers.expand( self.flock_size, self.n_cluster_centers, self.input_size) # For keeping track of which clusters are being boosted and for how long self.cluster_boosting_durations = creator.full( (1, self.n_cluster_centers), fill_value=self.cluster_boost_threshold, device=self._device, dtype=creator.int64) self.prev_boosted_clusters = creator.zeros((1, self.n_cluster_centers), device=self._device, dtype=creator.uint8) # For holding the targets and deltas of the cluster centers self.cluster_center_targets = creator.zeros( (1, self.n_cluster_centers, self.input_size), device=self._device, dtype=float_dtype) self.cluster_center_deltas = creator.zeros( (1, self.n_cluster_centers, self.input_size), device=self._device, dtype=float_dtype) self.boosting_targets = creator.zeros((1, self.n_cluster_centers), device=self._device, dtype=creator.int64) self.tmp_boosting_targets = creator.zeros((1, self.n_cluster_centers), device=self._device, dtype=creator.int64) # There only needs to be one learning counter as only one expert learns in the convolutional case, # but we need the expanded version for cluster observer. self.common_execution_counter_learning = creator.zeros( (1, 1), device=self._device, dtype=creator.int64) self.execution_counter_learning = self.common_execution_counter_learning.expand( self.flock_size, 1)
class ExpertHierarchyTopology(Topology): def __init__(self): super().__init__('cuda') # MNIST node producing two sequences. # Receptive field looking at the input with window size = 14, 14, stride 7, 7. # 3x3 experts looking at the outputs of the RF node. # 1 expert combining the outputs. mnist_seq_params: DatasetSequenceMNISTNodeParams = DatasetSequenceMNISTNodeParams( [[0, 1, 2], [3, 1, 4]]) mnist_params = DatasetMNISTParams(class_filter=[0, 1, 2, 3, 4], one_hot_labels=False, examples_per_class=1) n_channels_1 = 1 input_dims_1 = torch.Size((28, 28, n_channels_1)) parent_rf_dims_1 = Size2D(14, 14) parent_rf_stride_dims_1 = Stride(7, 7) self.expert_params = ExpertParams() self.expert_params.flock_size = 9 self.expert_params.spatial.input_size = reduce( lambda a, x: a * x, parent_rf_dims_1 + (n_channels_1, )) self.expert_params.n_cluster_centers = 10 self.expert_params.spatial.buffer_size = 100 self.expert_params.spatial.batch_size = 50 self.expert_params.spatial.learning_period = 1 self.expert_params.spatial.cluster_boost_threshold = 100 self.expert_params.spatial.max_boost_time = 200 self.expert_params.temporal.seq_length = 3 self.expert_params.temporal.seq_lookahead = 1 self.expert_params.temporal.buffer_size = 100 self.expert_params.temporal.batch_size = 50 self.expert_params.temporal.learning_period = 50 + self.expert_params.temporal.seq_lookbehind self.expert_params.temporal.incoming_context_size = 1 self.expert_params.temporal.max_encountered_seqs = 100 self.expert_params.temporal.n_frequent_seqs = 20 self.expert_params.temporal.forgetting_limit = 1000 self.parent_expert_params = self.expert_params.clone() self.parent_expert_params.flock_size = 1 self.parent_expert_params.spatial.input_size = \ self.expert_params.flock_size * 2 * self.expert_params.n_cluster_centers # Create the nodes. mnist_node_1 = DatasetSequenceMNISTNode(params=mnist_params, seq_params=mnist_seq_params) mnist_node_2 = DatasetSequenceMNISTNode(params=mnist_params, seq_params=mnist_seq_params) receptive_field_node_1_1 = ReceptiveFieldNode(input_dims_1, parent_rf_dims_1, parent_rf_stride_dims_1) receptive_field_node_1_2 = ReceptiveFieldNode(input_dims_1, parent_rf_dims_1, parent_rf_stride_dims_1) expert_flock_node_1 = ExpertFlockNode(self.expert_params) expert_flock_node_2 = ExpertFlockNode(self.expert_params) join_node = JoinNode(dim=0, n_inputs=2) expert_parent_node = ExpertFlockNode(self.parent_expert_params) self.add_node(mnist_node_1) self.add_node(receptive_field_node_1_1) self.add_node(expert_flock_node_1) self.add_node(mnist_node_2) self.add_node(receptive_field_node_1_2) self.add_node(expert_flock_node_2) self.add_node(join_node) self.add_node(expert_parent_node) unsqueeze_node_0 = UnsqueezeNode(0) self.add_node(unsqueeze_node_0) Connector.connect(mnist_node_1.outputs.data, receptive_field_node_1_1.inputs.input) Connector.connect(receptive_field_node_1_1.outputs.output, expert_flock_node_1.inputs.sp.data_input) Connector.connect(expert_flock_node_1.outputs.tp.projection_outputs, join_node.inputs[0]) Connector.connect(mnist_node_2.outputs.data, receptive_field_node_1_2.inputs.input) Connector.connect(receptive_field_node_1_2.outputs.output, expert_flock_node_2.inputs.sp.data_input) Connector.connect(expert_flock_node_2.outputs.tp.projection_outputs, join_node.inputs[1]) Connector.connect(join_node.outputs.output, unsqueeze_node_0.inputs.input) Connector.connect(unsqueeze_node_0.outputs.output, expert_parent_node.inputs.sp.data_input)
class SeNavLrfTopology(Topology): def __init__(self, expert_width: int = 1, input_square_side: int = 64, n_cluster_centers: int = 8, stride: int = None, training_phase_steps: int = 200, testing_phase_steps: int = 800, seed: int = 0): super().__init__(device='cuda') if stride is None: stride = expert_width self.training_phase_steps = training_phase_steps self.testing_phase_steps = testing_phase_steps self.testing_phase = True self.n_testing_phase = -1 self.training_step = -1 self._step_counter = 0 assert (input_square_side - (expert_width - stride)) % stride == 0, \ f'(input_square_side - (expert_width - stride)) ' \ f'({(input_square_side - (expert_width - stride))}) must be divisible' \ f' by stride ({stride})' self.n_experts_width = (input_square_side - (expert_width - stride)) // stride self.input_square_side = input_square_side self.one_expert_lrf_width = expert_width self.sp_params = ExpertParams() self.sp_params.n_cluster_centers = n_cluster_centers self.sp_params.spatial.input_size = self.one_expert_lrf_width * self.one_expert_lrf_width * 3 self.sp_params.flock_size = int(self.n_experts_width**2) self.sp_params.spatial.buffer_size = 510 self.sp_params.spatial.batch_size = 500 self.sp_params.compute_reconstruction = True self.reconstructed_data = torch.zeros( (self.input_square_side, self.input_square_side, 3), dtype=self.float_dtype, device=self.device) self.image_difference = torch.zeros( (self.input_square_side, self.input_square_side, 3), dtype=self.float_dtype, device=self.device) se_nav_params = DatasetSENavigationParams( SeDatasetSize.SIZE_64, sampling_method=SamplingMethod.RANDOM_SAMPLING) self._node_se_nav = DatasetSeNavigationNode(se_nav_params, seed=0) parent_rf_dims = Size2D(self.one_expert_lrf_width, self.one_expert_lrf_width) self._node_lrf = ReceptiveFieldNode( (input_square_side, input_square_side, 3), parent_rf_dims, Stride(stride, stride)) # necessary to clone the params, because the GUI changes them during the simulation (restart needed) self._node_spatial_pooler = SpatialPoolerFlockNode( self.sp_params.clone(), seed=seed) self._node_spatial_pooler_backup = SpatialPoolerFlockNode( self.sp_params.clone(), seed=seed) self.add_node(self._node_se_nav) self.add_node(self._node_lrf) self.add_node(self._node_spatial_pooler) self.add_node(self._node_spatial_pooler_backup) Connector.connect(self._node_se_nav.outputs.image_output, self._node_lrf.inputs.input) Connector.connect(self._node_lrf.outputs.output, self._node_spatial_pooler.inputs.sp.data_input) Connector.connect( self._node_lrf.outputs.output, self._node_spatial_pooler_backup.inputs.sp.data_input) self.se_nav_node = self._node_se_nav def step(self): if not self._is_initialized: self._assign_ids_to_nodes(self._id_generator) self.order_nodes() self._update_memory_blocks() self.remove_node(self._node_spatial_pooler_backup) # # self.remove_node(self._node_mnist_test) if not self.testing_phase and self._step_counter % self.training_phase_steps == 0: self.testing_phase = True self.n_testing_phase += 1 self.set_testing_model() self._step_counter = 0 elif self.testing_phase and self._step_counter % self.testing_phase_steps == 0: self.testing_phase = False self.set_training_model() self._step_counter = 0 self._step_counter += 1 if not self.testing_phase: self.training_step += 1 if not self._is_initialized: self._assign_ids_to_nodes(self._id_generator) self.order_nodes() self._is_initialized = True super().step() flock_reconstruction = self._node_spatial_pooler.outputs.sp.current_reconstructed_input # noinspection PyProtectedMember self.reconstructed_data.copy_( self._node_lrf.inverse_projection(flock_reconstruction.tensor)) self.image_difference.copy_(self.reconstructed_data - self._node_se_nav.outputs[0].tensor) def set_training_model(self): # noinspection PyProtectedMember self._node_spatial_pooler_backup._unit.copy_to( self._node_spatial_pooler._unit) self._node_spatial_pooler.switch_learning(True) def set_testing_model(self): # noinspection PyProtectedMember self._node_spatial_pooler._unit.copy_to( self._node_spatial_pooler_backup._unit) self._node_spatial_pooler.switch_learning(False)
def __init__(self): super().__init__(device='cuda') actions_descriptor = GridWorldActionDescriptor() node_action_monitor = ActionMonitorNode(actions_descriptor) params = GridWorldParams(map_name='MapE') noise_params = RandomNoiseParams(amplitude=0.0001) node_grid_world = GridWorldNode(params) expert_params1 = ExpertParams() unsqueeze_node = UnsqueezeNode(dim=0) noise_node = RandomNoiseNode(noise_params) one_hot_node = ToOneHotNode() def f(inputs, outputs): probs = inputs[0] outputs[0].copy_(probs[0, -1, :4] + SMALL_CONSTANT) action_parser = LambdaNode(func=f, n_inputs=1, output_shapes=[(4, )]) expert_params1.flock_size = 1 expert_params1.n_cluster_centers = 24 expert_params1.produce_actions = True expert_params1.temporal.seq_length = 4 expert_params1.temporal.seq_lookahead = 2 expert_params1.temporal.n_frequent_seqs = 700 expert_params1.temporal.max_encountered_seqs = 1000 expert_params1.temporal.exploration_probability = 0.05 expert_params1.temporal.batch_size = 200 expert_params1.temporal.frustration_threshold = 2 # expert_params.temporal.own_rewards_weight = 20 expert_params1.compute_reconstruction = True expert_params2 = expert_params1.clone() expert_params2.temporal.seq_length = 5 expert_params2.temporal.seq_lookahead = 4 expert_params2.n_cluster_centers = 8 expert_params2.produce_actions = False expert_params2.temporal.frustration_threshold = 10 #expert_params1.temporal.incoming_context_size = 2 * expert_params2.n_cluster_centers expert_node1 = ExpertFlockNode(expert_params1) expert_node2 = ExpertFlockNode(expert_params2) self.add_node(node_grid_world) self.add_node(node_action_monitor) self.add_node(expert_node1) self.add_node(expert_node2) self.add_node(unsqueeze_node) self.add_node(action_parser) self.add_node(noise_node) self.add_node(one_hot_node) Connector.connect(node_grid_world.outputs.output_image_action, noise_node.inputs.input) Connector.connect(noise_node.outputs.output, unsqueeze_node.inputs.input) Connector.connect(unsqueeze_node.outputs.output, expert_node1.inputs.sp.data_input) Connector.connect(expert_node1.outputs.tp.projection_outputs, expert_node2.inputs.sp.data_input) Connector.connect(expert_node2.outputs.output_context, expert_node1.inputs.tp.context_input, is_backward=True) Connector.connect( expert_node1.outputs.sp.predicted_reconstructed_input, action_parser.inputs[0]) Connector.connect(node_grid_world.outputs.reward, expert_node1.inputs.tp.reward_input) Connector.connect(node_grid_world.outputs.reward, expert_node2.inputs.tp.reward_input) Connector.connect(action_parser.outputs[0], one_hot_node.inputs.input) Connector.connect(one_hot_node.outputs.output, node_action_monitor.inputs.action_in) Connector.connect(node_action_monitor.outputs.action_out, node_grid_world.inputs.agent_action, is_backward=True)
class ReceptiveFieldTopology(Topology): """ ReceptiveFieldReverseNode demonstration topology. """ def __init__(self): super().__init__('cuda') expert1_cluster_centers = 6 expert2_cluster_centers = 10 # 50 n_channels_1 = 1 rf1_input_size = (6, 8, n_channels_1) rf1_rf_size = Size2D(2, 2) rf2_input_size = (3, 4, expert1_cluster_centers) rf2_rf_size = Size2D(2, 2) rf2_stride = Stride(1, 1) self.expert_params = ExpertParams() self.expert_params.flock_size = 3 * 4 self.expert_params.n_cluster_centers = expert1_cluster_centers self.expert_params.spatial.buffer_size = 100 self.expert_params.spatial.batch_size = 50 self.expert_params.spatial.learning_period = 1 self.expert_params.spatial.cluster_boost_threshold = 100 self.expert_params.spatial.max_boost_time = 200 self.expert_params.temporal.seq_length = 3 self.expert_params.temporal.seq_lookahead = 1 self.expert_params.temporal.buffer_size = 100 # 1000 self.expert_params.temporal.batch_size = 50 # 500 self.expert_params.temporal.learning_period = 50 + self.expert_params.temporal.seq_lookbehind self.expert_params.temporal.max_encountered_seqs = 100 # 2000 self.expert_params.temporal.n_frequent_seqs = 20 self.expert_params.temporal.forgetting_limit = 1000 # 10000 self.expert_params_2 = self.expert_params.clone() self.expert_params_2.flock_size = 2 * 3 self.expert_params_2.n_cluster_centers = expert2_cluster_centers self.expert_params_2.temporal.incoming_context_size = 1 # self.expert_params_2.temporal.max_encountered_seqs = 2000 # self.expert_params_2.temporal.n_frequent_seqs = 500 # self.expert_params_2.temporal.forgetting_limit = 5000 # self.expert_params_2.temporal.context_without_rewards_size = 80 self.expert_params.temporal.n_providers = rf2_rf_size[0] * rf2_rf_size[ 1] * 2 self.expert_params.temporal.incoming_context_size = self.expert_params_2.n_cluster_centers # context_input_dims = (2, self.expert_params.temporal.context_without_rewards_size * 2) context_input_dims = (*rf2_input_size[:2], *rf2_rf_size, 2, 3, expert2_cluster_centers) # Create the nodes. receptive_field_1_node = ReceptiveFieldNode(rf1_input_size, rf1_rf_size, Stride(*rf1_rf_size)) receptive_field_2_node = ReceptiveFieldNode(rf2_input_size, rf2_rf_size, rf2_stride) receptive_field_reverse_node = ReceptiveFieldReverseNode( context_input_dims, rf2_input_size, rf2_rf_size, rf2_stride) expert_flock_1_node = ConvExpertFlockNode(self.expert_params) expert_flock_2_node = ConvExpertFlockNode(self.expert_params_2) dataset_simple_point_gravity_node = DatasetSimplePointGravityNode( DatasetSimplePointGravityParams( canvas_shape=Size2D(6, 8), point_pos=Point2D(2, 3), attractor_distance=2, move_strategy=MoveStrategy.LIMITED_TO_LEFT_DOWN_QUADRANT)) self.add_node(dataset_simple_point_gravity_node) self.add_node(receptive_field_1_node) self.add_node(expert_flock_1_node) self.add_node(receptive_field_2_node) self.add_node(expert_flock_2_node) self.add_node(receptive_field_reverse_node) Connector.connect(dataset_simple_point_gravity_node.outputs.data, receptive_field_1_node.inputs.input) Connector.connect(receptive_field_1_node.outputs.output, expert_flock_1_node.inputs.sp.data_input) Connector.connect(expert_flock_1_node.outputs.tp.projection_outputs, receptive_field_2_node.inputs.input) Connector.connect(receptive_field_2_node.outputs.output, expert_flock_2_node.inputs.sp.data_input) Connector.connect(expert_flock_2_node.outputs.output_context, receptive_field_reverse_node.inputs.input) Connector.connect(receptive_field_reverse_node.outputs.output, expert_flock_1_node.inputs.tp.context_input, is_backward=True)