예제 #1
0
 def to_resource_graph(self, space: SearchSpace, *args, **kwargs):
     return space.to_resource_graph(self.arch, self.input_shape,
                                    self.num_classes, *args, **kwargs)
예제 #2
0
    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)