def test_fuzz_feed_forward_layers(): for _ in range(1000): n_hidden = random.randint(10, 100) n_in = random.randint(1, 10) n_out = random.randint(1, 10) nodes = list( set( random.randint(0, 1000) for _ in range(n_in + n_out + n_hidden))) random.shuffle(nodes) inputs = nodes[:n_in] outputs = nodes[n_in:n_in + n_out] connections = [] for _ in range(n_hidden * 2): a = random.choice(nodes) b = random.choice(nodes) if a == b: continue if a in inputs and b in inputs: continue if a in outputs and b in outputs: continue connections.append((a, b)) feed_forward_layers(inputs, outputs, connections)
def test_feed_forward_layers(): inputs = [0, 1] outputs = [2] connections = [(0, 2), (1, 2)] layers = feed_forward_layers(inputs, outputs, connections) assert [{2}] == layers inputs = [0, 1] outputs = [3] connections = [(0, 2), (1, 2), (2, 3)] layers = feed_forward_layers(inputs, outputs, connections) assert [{2}, {3}] == layers inputs = [0, 1] outputs = [4] connections = [(0, 2), (1, 2), (1, 3), (2, 3), (2, 4), (3, 4)] layers = feed_forward_layers(inputs, outputs, connections) assert [{2}, {3}, {4}] == layers inputs = [0, 1, 2, 3] outputs = [11, 12, 13] connections = [(0, 4), (1, 4), (1, 5), (2, 5), (2, 6), (3, 6), (3, 7), (4, 8), (5, 8), (5, 9), (5, 10), (6, 10), (6, 7), (8, 11), (8, 12), (8, 9), (9, 10), (7, 10), (10, 12), (10, 13)] layers = feed_forward_layers(inputs, outputs, connections) assert [{4, 5, 6}, {8, 7}, {9, 11}, {10}, {12, 13}] == layers inputs = [0, 1, 2, 3] outputs = [11, 12, 13] connections = [(0, 4), (1, 4), (1, 5), (2, 5), (2, 6), (3, 6), (3, 7), (4, 8), (5, 8), (5, 9), (5, 10), (6, 10), (6, 7), (8, 11), (8, 12), (8, 9), (9, 10), (7, 10), (10, 12), (10, 13), (3, 14), (14, 15), (5, 16), (10, 16)] layers = feed_forward_layers(inputs, outputs, connections) assert [{4, 5, 6}, {8, 7}, {9, 11}, {10}, {12, 13}] == layers
def create(genome, config): """ Receives a genome and returns its phenotype (a FeedForwardNetwork). """ # Gather expressed connections. connections = [cg.key for cg in genome.connections.values() if cg.enabled] layers = feed_forward_layers(config.genome_config.input_keys, config.genome_config.output_keys, connections) node_evals = [] for layer in layers: for node in layer: inputs = [] node_expr = [] # currently unused for conn_key in connections: inode, onode = conn_key if onode == node: cg = genome.connections[conn_key] inputs.append((inode, cg.weight)) node_expr.append("v[{}] * {:.7e}".format(inode, cg.weight)) ng = genome.nodes[node] aggregation_function = config.genome_config.aggregation_function_defs.get(ng.aggregation) activation_function = config.genome_config.activation_defs.get(ng.activation) node_evals.append((node, activation_function, aggregation_function, ng.bias, ng.response, inputs)) return FeedForwardNetwork(config.genome_config.input_keys, config.genome_config.output_keys, node_evals)
def create(genome, config): # Gather expressed connections. connections = [ cg.key for cg in itervalues(genome.connections) if cg.enabled ] layers = feed_forward_layers(config.genome_config.input_keys, config.genome_config.output_keys, connections) # print(layers) node_evals = [] for layer in layers: for node in layer: inputs = [] for conn_key in connections: inode, onode = conn_key if onode == node: cg = genome.connections[conn_key] inputs.append((inode, cg)) ng = genome.nodes[node] node_evals.append((node, inputs)) return FormNetwork(config.genome_config.input_keys, config.genome_config.output_keys, node_evals)
def create(genome, config): """ Receives a genome and returns its phenotype (a MLRecurrentNetwork). """ genome_config = config.genome_config connections = [ cg.key for cg in itervalues(genome.connections) if cg.enabled ] layers = \ feed_forward_layers(config.genome_config.input_keys, config.genome_config.output_keys, connections, True) node_evals = [] for layer in layers: for node in layer: inputs = [] for conn_key in connections: inode, onode = conn_key if onode == node: cg = genome.connections[conn_key] inputs.append((inode, cg.weight)) ng = genome.nodes[node] aggregation_function = config.genome_config.aggregation_function_defs.get( ng.aggregation) activation_function = config.genome_config.activation_defs.get( ng.activation) node_evals.append( (node, activation_function, aggregation_function, ng.bias, ng.response, inputs)) return MLRecurrentNetwork(genome_config.input_keys, genome_config.output_keys, node_evals)
def create(genome, config): """ Receives a genome and returns its phenotype (a FeedForwardNetwork). """ # Gather expressed connections. connections = [ cg.key for cg in itervalues(genome.connections) if cg.enabled ] layers = feed_forward_layers(config.genome_config.input_keys, config.genome_config.output_keys, connections) node_evals = [] for layer in layers: for node in layer: inputs = [] node_expr = [] # TODO: This could be more efficient. for cg in itervalues(genome.connections): inode, onode = cg.key if onode == node and cg.enabled: inputs.append((inode, cg.weight)) node_expr.append("v[{}] * {:.7e}".format( inode, cg.weight)) ng = genome.nodes[node] aggregation_function = config.genome_config.aggregation_function_defs[ ng.aggregation] activation_function = config.genome_config.activation_defs.get( ng.activation) node_evals.append( (node, activation_function, aggregation_function, ng.bias, ng.response, inputs)) return FeedForwardNetwork(config.genome_config.input_keys, config.genome_config.output_keys, node_evals)
def _create(self, genome, config): connections = [ cg.key for cg in itervalues(genome.connections) if cg.enabled ] struct = feed_forward_layers(config.genome_config.input_keys, config.genome_config.output_keys, connections) for layer in struct: prev_size = self.layers[-1].num_nodes nn_layer = Layer(genes=[genome.nodes[key] for key in layer], prev_size=prev_size) self.layers.append(nn_layer)
def create(genome, config): """ Receives a genome and returns its phenotype (a FeedForwardNetwork). """ # Gather expressed connections. connections = [ cg.key for cg in genome.connections.values() if cg.enabled ] smart_connections = {} for cg_in, cg_out in connections: if cg_out in smart_connections: smart_connections[cg_out].append(cg_in) else: smart_connections[cg_out] = [cg_in] layers = feed_forward_layers(config.genome_config.input_keys, config.genome_config.output_keys, connections) node_to_layer = {} for node in config.genome_config.input_keys: node_to_layer[node] = 0 for i, layer in enumerate(layers): for node in layer: node_to_layer[node] = i + 1 layers_conn = [] layers_node = [] for i, layer in enumerate(layers): layer_conn = [] # (layer in, node in, node out, weight) layer_node = [] # (node, activation, aggregation, bias) for node in layer: for inode in smart_connections[node]: cg = genome.connections[(inode, node)] layer_conn.append( (node_to_layer[inode], inode, node, cg.weight)) ng = genome.nodes[node] aggregation_function = config.genome_config.aggregation_function_defs.get( ng.aggregation) activation_function = config.genome_config.activation_defs.get( ng.activation) layer_node.append( (node, activation_function, aggregation_function, ng.bias)) layers_conn.append(layer_conn) layers_node.append(layer_node) return FeedForwardNetwork(config.genome_config.input_keys, config.genome_config.output_keys, layers_conn, layer_node)
def my_create_net_layer(self, genome, config): self.connections = [ cg.key for cg in itervalues(genome.connections) if cg.enabled ] self.layers = feed_forward_layers(config.genome_config.input_keys, config.genome_config.output_keys, self.connections) for layer in self.layers: inputVectorThisLayer = [] outputVectorThisLayer = [] key_weight_dict = dict() act_funcThislayer = [] biasThislayer = [] responseThislayer = [] for cg in itervalues(genome.connections): inode, onode = cg.key if onode in layer and cg.enabled: if inode not in inputVectorThisLayer: inputVectorThisLayer.append(inode) if onode not in outputVectorThisLayer: outputVectorThisLayer.append(onode) indx_i = inputVectorThisLayer.index(inode) indx_o = outputVectorThisLayer.index(onode) key_weight_dict.update({(indx_i, indx_o): cg.weight}) ng = genome.nodes[onode] act_funcThislayer.append( config.genome_config.activation_defs.get( ng.activation)) biasThislayer.append(ng.bias) responseThislayer.append(ng.response) weight_matrix = np.zeros( (len(inputVectorThisLayer), len(outputVectorThisLayer))) for key, val in key_weight_dict.items(): indx_i, indx_o = key weight_matrix[indx_i][indx_o] = float(val) self.inputVectorKeyMap.append(inputVectorThisLayer) self.outputVectorKeyMap.append(outputVectorThisLayer) self.layerWeightMatrices.append(weight_matrix) self.act_funcMap.append(act_funcThislayer) self.biasMap.append(biasThislayer) self.responseMap.append(responseThislayer)
def create(genome, config): """ Receives a genome and returns its phenotype (a FeedForwardNetwork). """ # Gather expressed connections. connections = [ cg.key for cg in genome.connections.values() if cg.enabled ] layers = feed_forward_layers(config.genome_config.input_keys, config.genome_config.output_keys, connections) node_evals = [] for layer in layers: for node in layer: inputs = [] for conn_key in connections: inode, onode = conn_key if onode == node: cg = genome.connections[conn_key] # TODO: check tensor assert isinstance( cg.weight, torch.Tensor) and cg.weight.requires_grad inputs.append((inode, cg.weight)) ng = genome.nodes[node] aggregation_function = config.genome_config.aggregation_function_defs.get( ng.aggregation) activation_function = config.genome_config.activation_defs.get( ng.activation) # TODO: check tensor assert isinstance(ng.bias, torch.Tensor) and ng.bias.requires_grad node_evals.append( (node, activation_function, aggregation_function, ng.bias, torch.tensor(1.), inputs)) return FeedForwardNetwork(config.genome_config.input_keys, config.genome_config.output_keys, node_evals)
def create(genome: DefaultGenome, config: Config): """ Receives a genome and returns its phenotype (a FeedForwardNetwork). """ # Gather expressed connections. connections: List[Tuple[int, int]] = [ cg.key for cg in genome.connections.values() if cg.enabled ] layers: List[Set[int]] = feed_forward_layers( config.genome_config.input_keys, config.genome_config.output_keys, connections) node_evals: List[Tuple[int, Callable, Callable, float, float, List[Tuple[int, float], Tuple[int, float]]]] = [] for layer in layers: for node in layer: inputs: List[Tuple[int, float]] = [] node_expr: List[str] = [] # currently unused for conn_key in connections: inode, onode = conn_key if onode == node: cg: DefaultConnectionGene = genome.connections[ conn_key] inputs.append((inode, cg.weight)) node_expr.append("v[{}] * {:.7e}".format( inode, cg.weight)) ng: DefaultNodeGene = genome.nodes[node] aggregation_function: Callable = config.genome_config.aggregation_function_defs.get( ng.aggregation) activation_function: Callable = config.genome_config.activation_defs.get( ng.activation) node_evals.append( (node, activation_function, aggregation_function, ng.bias, ng.response, inputs)) return FeedForwardNetwork(config.genome_config.input_keys, config.genome_config.output_keys, node_evals)
def create(genome, config): """ Receives a genome and returns its phenotype (a FeedForwardNetwork). """ # Ideas for optimization # - profiling the code # - memoization # - use contiguous array in memory # Gather expressed connections. connections = [ cg.key for cg in genome.connections.values() if cg.enabled ] # TODO: remove this call to feed_forward_layers # Because some work done in this function is done again here computational_layers = feed_forward_layers( config.genome_config.input_keys, config.genome_config.output_keys, connections) # Insert the input layer as the first layer # It matters that the input layer is inserted as a list and not a set, otherwise ordering'd be messed up computational_layers.insert(0, config.genome_config.input_keys) # TODO: visited_nodes can be a set instead of a list, might speed-up # OrderedSet ? visited_nodes = copy.copy(config.genome_config.input_keys) # Each entry of the dict stores the global id of a node global_ids = {} global_count = 0 global_OUT_keys = np.zeros(config.genome_config.num_outputs, dtype=int) for i, l in enumerate(computational_layers): for n in l: global_ids[n] = global_count # If the node is one the output of the NN, keep memory if n in config.genome_config.output_keys: global_OUT_keys[n] = global_count global_count += 1 build_layers = [] # Start with the first hidden "layer" for l in computational_layers[1:]: input_global_keys = [] output_global_keys = [] weight_matrix = [] bias_vector = [] # Go over the nodes in the computational layer for no, okey in enumerate(l): output_global_keys.append(global_ids[okey]) bias_vector.append(genome.nodes[okey].bias) # Fill in the weight matrix for ikey in visited_nodes: if (ikey, okey) in connections: # If we created already this row in the weight matrix if global_ids[ikey] in input_global_keys: row_index = input_global_keys.index( global_ids[ikey]) weight_matrix[row_index][no] = genome.connections[( ikey, okey)].weight else: input_global_keys.append(global_ids[ikey]) weight_matrix.append(np.zeros(len(l))) weight_matrix[-1][no] = genome.connections[( ikey, okey)].weight connections.remove((ikey, okey)) visited_nodes += list(l) ng = genome.nodes[0] if ng.activation == 'sigmoid': act_function = sigmoid # Conversion input_global_keys = np.array(input_global_keys) output_global_keys = np.array(output_global_keys) # The factor 5 is here to match the definition of sigmoid in neat-python library weight_matrix = 5 * np.matrix(weight_matrix).transpose() bias_vector = 5 * np.array(bias_vector) else: act_function = config.genome_config.activation_defs.get( ng.activation) input_global_keys = np.array(input_global_keys) output_global_keys = np.array(output_global_keys) weight_matrix = np.matrix(weight_matrix).transpose() bias_vector = np.array(bias_vector) build_layers.append( Layer(input_global_keys, output_global_keys, weight_matrix, bias_vector, act_function)) return SimpleFeedForwardNetwork(build_layers, global_OUT_keys, global_count)
def create(genome, config, quantize=8): """ Receives a genome and returns its phenotype (a FeedForwardNetwork). """ idx = 0 valueIDMap_neat2fpga = dict() valueIDMap_fpga2neat = dict() for o_id in config.genome_config.input_keys + config.genome_config.output_keys: valueIDMap_neat2fpga[o_id] = idx valueIDMap_fpga2neat[idx] = o_id idx += 1 # Gather expressed connections. connections = [ cg.key for cg in itervalues(genome.connections) if cg.enabled ] layers = feed_forward_layers(config.genome_config.input_keys, config.genome_config.output_keys, connections) layer = [] for c in connections: for i in range(2): if c[i] not in valueIDMap_neat2fpga: o_id = c[i] valueIDMap_neat2fpga[o_id] = idx valueIDMap_fpga2neat[idx] = o_id idx += 1 total_nodes = idx command_layer = len(layers) + 1 command_init_total_node = len(valueIDMap_neat2fpga) command_init_in_nodes = len(config.genome_config.input_keys) command_s = [ command_layer, command_init_total_node, command_init_in_nodes ] resp_s = [0] * total_nodes bias_s = [0] * total_nodes for idx in range(command_init_in_nodes, total_nodes, 1): o_id = valueIDMap_fpga2neat[idx] ng = genome.nodes[o_id] resp_s[idx] = int(ng.response * 2**quantize) bias_s[idx] = int(ng.bias * 2**(quantize + quantize + quantize)) serial_in_pre = command_s serial_in_post = [] for idx, layer in enumerate(layers): inputVectorThisLayer = [] i_id = [] outputVectorThisLayer = [] o_id = [] key_weight_dict = dict() for node in layer: for conn_key in connections: inode, onode = conn_key if onode == node: if inode not in inputVectorThisLayer: inputVectorThisLayer.append(inode) i_id.append(valueIDMap_neat2fpga[inode]) if onode not in outputVectorThisLayer: outputVectorThisLayer.append(onode) o_id.append(valueIDMap_neat2fpga[onode]) indx_i = inputVectorThisLayer.index(inode) indx_o = outputVectorThisLayer.index(onode) cg = genome.connections[conn_key] key_weight_dict.update({(indx_i, indx_o): cg.weight}) weight_matrix = np.zeros( (len(outputVectorThisLayer), len(inputVectorThisLayer))) for key, val in key_weight_dict.items(): indx_i, indx_o = key weight_matrix[indx_o][indx_i] = int(val * 2**quantize) # if idx ==0: # print("init_in_total: ", command_init_in_nodes, "in_first :", len(inputVectorThisLayer)) serial_in_pre.append(len(inputVectorThisLayer)) serial_in_pre.append(len(outputVectorThisLayer)) serial_in_post = serial_in_post + o_id + i_id + list( np.ravel(weight_matrix)) serial_in_pre = serial_in_pre + resp_s + bias_s return FeedForwardNetworkFPGA(serial_in_pre, serial_in_post, command_init_in_nodes, len(layer), quantize)