def _upper_layer_width(self, u): for v, layer_id in self.reverse_adj_list[u]: layer = self.layer_list[layer_id] if is_layer(layer, 'Conv') or is_layer(layer, 'Dense'): return layer_width(layer) elif is_layer(layer, 'Concatenate'): a = self.layer_id_to_input_node_ids[layer_id][0] b = self.layer_id_to_input_node_ids[layer_id][1] return self._upper_layer_width(a) + self._upper_layer_width(b) else: return self._upper_layer_width(v) return self.node_list[0][-1]
def _get_pooling_layers(self, start_node_id, end_node_id): layer_list = [] node_list = [start_node_id] self._depth_first_search(end_node_id, layer_list, node_list) return filter( lambda layer_id: is_layer(self.layer_list[layer_id], 'Pooling'), layer_list)
def to_deeper_graph(graph): weighted_layer_ids = graph.deep_layer_ids() target_id = weighted_layer_ids[randint(0, len(weighted_layer_ids) - 1)] if is_layer(graph.layer_list[target_id], 'Conv'): graph.to_conv_deeper_model(target_id, randint(1, 2) * 2 + 1) else: graph.to_dense_deeper_model(target_id) return graph
def _search(self, u, start_dim, total_dim, n_add): """Search the graph for widening the layers. Args: u: The starting node identifier. start_dim: The position to insert the additional dimensions. total_dim: The total number of dimensions the layer has before widening. n_add: The number of dimensions to add. """ if (u, start_dim, total_dim, n_add) in self.vis: return self.vis[(u, start_dim, total_dim, n_add)] = True for v, layer_id in self.adj_list[u]: layer = self.layer_list[layer_id] if is_layer(layer, 'Conv'): new_layer = wider_next_conv(layer, start_dim, total_dim, n_add, self.weighted) self._replace_layer(layer_id, new_layer) elif is_layer(layer, 'Dense'): new_layer = wider_next_dense(layer, start_dim, total_dim, n_add, self.weighted) self._replace_layer(layer_id, new_layer) elif is_layer(layer, 'BatchNormalization'): new_layer = wider_bn(layer, start_dim, total_dim, n_add, self.weighted) self._replace_layer(layer_id, new_layer) self._search(v, start_dim, total_dim, n_add) elif is_layer(layer, 'Concatenate'): if self.layer_id_to_input_node_ids[layer_id][1] == u: # u is on the right of the concat # next_start_dim += next_total_dim - total_dim left_dim = self._upper_layer_width( self.layer_id_to_input_node_ids[layer_id][0]) next_start_dim = start_dim + left_dim next_total_dim = total_dim + left_dim else: next_start_dim = start_dim next_total_dim = total_dim + self._upper_layer_width( self.layer_id_to_input_node_ids[layer_id][1]) self._search(v, next_start_dim, next_total_dim, n_add) else: self._search(v, start_dim, total_dim, n_add) for v, layer_id in self.reverse_adj_list[u]: layer = self.layer_list[layer_id] if is_layer(layer, 'Conv'): new_layer = wider_pre_conv(layer, n_add, self.weighted) self._replace_layer(layer_id, new_layer) elif is_layer(layer, 'Dense'): new_layer = wider_pre_dense(layer, n_add, self.weighted) self._replace_layer(layer_id, new_layer) elif is_layer(layer, 'Concatenate'): continue else: self._search(v, start_dim, total_dim, n_add)
def to_deeper_graph(graph): weighted_layer_ids = graph.deep_layer_ids() deeper_layer_ids = sample(weighted_layer_ids, 1) for layer_id in deeper_layer_ids: layer = graph.layer_list[layer_id] if is_layer(layer, 'Conv'): graph.to_conv_deeper_model(layer_id, 3) else: graph.to_dense_deeper_model(layer_id) return graph
def to_deeper_graph(graph): weighted_layer_ids = graph.deep_layer_ids() n_deeper_layer = randint(1, len(weighted_layer_ids)) deeper_layer_ids = sample(weighted_layer_ids, n_deeper_layer) for layer_id in deeper_layer_ids: layer = graph.layer_list[layer_id] if is_layer(layer, 'Conv'): graph.to_conv_deeper_model(layer_id, randint(1, 2) * 2 + 1) else: graph.to_dense_deeper_model(layer_id) return graph
def extract_descriptor(self): ret = NetworkDescriptor() topological_node_list = self.topological_order for u in topological_node_list: for v, layer_id in self.adj_list[u]: layer = self.layer_list[layer_id] if is_layer(layer, 'Conv') and layer.kernel_size not in [1, (1,), (1, 1), (1, 1, 1)]: ret.add_conv_width(layer_width(layer)) if is_layer(layer, 'Dense'): ret.add_dense_width(layer_width(layer)) # The position of each node, how many Conv and Dense layers before it. pos = [0] * len(topological_node_list) for v in topological_node_list: layer_count = 0 for u, layer_id in self.reverse_adj_list[v]: layer = self.layer_list[layer_id] weighted = 0 if (is_layer(layer, 'Conv') and layer.kernel_size not in [1, (1,), (1, 1), (1, 1, 1)]) \ or is_layer(layer, 'Dense'): weighted = 1 layer_count = max(pos[u] + weighted, layer_count) pos[v] = layer_count for u in topological_node_list: for v, layer_id in self.adj_list[u]: if pos[u] == pos[v]: continue layer = self.layer_list[layer_id] if is_layer(layer, 'Concatenate'): ret.add_skip_connection(pos[u], pos[v], NetworkDescriptor.CONCAT_CONNECT) if is_layer(layer, 'Add'): ret.add_skip_connection(pos[u], pos[v], NetworkDescriptor.ADD_CONNECT) return ret
def _search(self, u, start_dim, total_dim, n_add): """Search the graph for widening the layers. Args: u: The starting node identifier. start_dim: The position to insert the additional dimensions. total_dim: The total number of dimensions the layer has before widening. n_add: The number of dimensions to add. """ if (u, start_dim, total_dim, n_add) in self.vis: return self.vis[(u, start_dim, total_dim, n_add)] = True for v, layer_id in self.adj_list[u]: layer = self.layer_list[layer_id] if is_layer(layer, 'Conv'): new_layer = wider_next_conv(layer, start_dim, total_dim, n_add, self.weighted) self._replace_layer(layer_id, new_layer) elif is_layer(layer, 'Dense'): new_layer = wider_next_dense(layer, start_dim, total_dim, n_add, self.weighted) self._replace_layer(layer_id, new_layer) elif is_layer(layer, 'BatchNormalization'): new_layer = wider_bn(layer, start_dim, total_dim, n_add, self.weighted) self._replace_layer(layer_id, new_layer) self._search(v, start_dim, total_dim, n_add) elif is_layer(layer, 'Concatenate'): if self.layer_id_to_input_node_ids[layer_id][1] == u: # u is on the right of the concat # next_start_dim += next_total_dim - total_dim left_dim = self._upper_layer_width(self.layer_id_to_input_node_ids[layer_id][0]) next_start_dim = start_dim + left_dim next_total_dim = total_dim + left_dim else: next_start_dim = start_dim next_total_dim = total_dim + self._upper_layer_width(self.layer_id_to_input_node_ids[layer_id][1]) self._search(v, next_start_dim, next_total_dim, n_add) else: self._search(v, start_dim, total_dim, n_add) for v, layer_id in self.reverse_adj_list[u]: layer = self.layer_list[layer_id] if is_layer(layer, 'Conv'): new_layer = wider_pre_conv(layer, n_add, self.weighted) self._replace_layer(layer_id, new_layer) elif is_layer(layer, 'Dense'): new_layer = wider_pre_dense(layer, n_add, self.weighted) self._replace_layer(layer_id, new_layer) elif is_layer(layer, 'Concatenate'): continue else: self._search(v, start_dim, total_dim, n_add)
def to_wider_graph(graph): weighted_layer_ids = graph.wide_layer_ids() wider_layers = sample(weighted_layer_ids, 1) for layer_id in wider_layers: layer = graph.layer_list[layer_id] if is_layer(layer, 'Conv'): n_add = layer.filters else: n_add = layer.units graph.to_wider_model(layer_id, n_add) return graph
def to_wider_graph(graph): weighted_layer_ids = graph.wide_layer_ids() if len(weighted_layer_ids) <= 1: target_id = weighted_layer_ids[0] else: target_id = weighted_layer_ids[randint(0, len(weighted_layer_ids) - 1)] if is_layer(graph.layer_list[target_id], 'Conv'): n_add = graph.layer_list[target_id].filters else: n_add = graph.layer_list[target_id].units graph.to_wider_model(target_id, n_add) return graph
def to_deeper_graph(graph): weighted_layer_ids = graph.deep_layer_ids() if len(weighted_layer_ids) >= Constant.MAX_MODEL_DEPTH: return None deeper_layer_ids = sample(weighted_layer_ids, 1) # n_deeper_layer = randint(1, len(weighted_layer_ids)) # deeper_layer_ids = sample(weighted_layer_ids, n_deeper_layer) for layer_id in deeper_layer_ids: layer = graph.layer_list[layer_id] if is_layer(layer, 'Conv'): graph.to_conv_deeper_model(layer_id, 3) else: graph.to_dense_deeper_model(layer_id) return graph
def to_wider_graph(graph): weighted_layer_ids = graph.wide_layer_ids() weighted_layer_ids = list( filter( lambda x: layer_width(graph.layer_list[x]) * 2 <= Constant. MAX_MODEL_WIDTH, weighted_layer_ids)) if len(weighted_layer_ids) == 0: return None # n_wider_layer = randint(1, len(weighted_layer_ids)) # wider_layers = sample(weighted_layer_ids, n_wider_layer) wider_layers = sample(weighted_layer_ids, 1) for layer_id in wider_layers: layer = graph.layer_list[layer_id] if is_layer(layer, 'Conv'): n_add = layer.filters else: n_add = layer.units graph.to_wider_model(layer_id, n_add) return graph
def _layer_ids_by_type(self, type_str): return list( filter( lambda layer_id: is_layer(self.layer_list[layer_id], type_str), range(self.n_layers)))
def _get_pooling_layers(self, start_node_id, end_node_id): layer_list = [] node_list = [start_node_id] self._depth_first_search(end_node_id, layer_list, node_list) return filter(lambda layer_id: is_layer(self.layer_list[layer_id], 'Pooling'), layer_list)
def _layer_ids_by_type(self, type_str): return list(filter(lambda layer_id: is_layer(self.layer_list[layer_id], type_str), range(self.n_layers)))