def to_resource_graph(self, space: SearchSpace, *args, **kwargs): return space.to_resource_graph(self.arch, self.input_shape, self.num_classes, *args, **kwargs)
def __init__(self, wrapped_arch: Architecture, space: SearchSpace, input_shape, num_classes): self.arch = wrapped_arch self.input_shape = input_shape self.num_classes = num_classes self.val_error = None # Filled out by the experiment caller self.test_error = None rg = space.to_resource_graph(self.arch, input_shape, num_classes) self.resource_features = self.compute_resource_features(rg) # Here we convert the architecture into a representation compatible with Dragonfly's kernel, # which is: # - `layer_labels`: a string describing the kind of a layer ("ip" and "op" for input and # output layers, or e.g. "DWConv2D-3" for a 3x3 DW convolution); # - `edge_list`: a list of tuples representing connections between layers (indices are # determined by the position of the latter in the `layer_labels` list); # - `units`: number of units in a layer, which Dragonfly uses to compute "layer mass". # The conversion can be done for any `Architecture` from its resource graph representation layer_labels = [] edge_list = [] units = [] mass = [ ] # -1 marks non-processing layers, mass will be filled out later layers = [t for t in rg.tensors.values() if not t.is_constant] # input and layer output tensors tensor_name_to_id = {t.name: i for i, t in enumerate(layers)} # Add input tensors as "input layers" for tensor in rg.inputs: layer_labels.append("ip") units.append(tensor.shape[-1]) mass.append(-1) # Add each operator as its own layer and connect its input layers to itself for op in rg.operators.values(): layer_labels.append(op_to_label(op)) units.append(op.output.shape[-1]) inputs = [i for i in op.inputs if i.name in tensor_name_to_id] edge_list.extend( (tensor_name_to_id[i.name], tensor_name_to_id[op.output.name]) for i in inputs) mass.append(macs(op)) # Invent a dummy layer for each output tensor for tensor in rg.outputs: i = len(layer_labels) layer_labels.append("op") units.append(tensor.shape[-1]) edge_list.append((tensor_name_to_id[tensor.name], i)) mass.append(-1) num_layers = len(layer_labels) conn_mat = dok_matrix((num_layers, num_layers)) for (a, b) in edge_list: conn_mat[a, b] = 1 non_proc_layer_mass = max(0.1 * sum(f for f in mass if f != -1), 100) # according to Dragonfly self.layer_masses = np.array([(non_proc_layer_mass if f == -1 else f) for f in mass], dtype=np.float) / 1000 super().__init__("unas-net", layer_labels, conn_mat, num_units_in_each_layer=units, all_layer_label_classes=all_possible_labels(), layer_label_similarities=None)