def mutate_arch(parent_arch):
    # Choose one of the three mutations
    mutation = np.random.choice(
        ['identity', 'hidden_state_mutation', 'op_mutation'])

    adjacency_matrix, node_list = copy.deepcopy(
        parent_arch.adjacency_matrix), copy.deepcopy(parent_arch.node_list)
    if mutation == 'identity':
        return Architecture(adjacency_matrix=adjacency_matrix,
                            node_list=node_list)
    elif mutation == 'hidden_state_mutation':
        # Pick one of the intermediate nodes in the graph (neither input nor output)
        if type(search_space) == SearchSpace1:
            # Node 1 has now choice for node 2 as it always has 2 parents
            low = 3
        else:
            low = 2
        random_node = np.random.randint(low=low,
                                        high=adjacency_matrix.shape[-1])
        # Pick one of the parents of the node

        # parent_of_node_to_modify = np.random.choice(adjacency_matrix[:random_node, random_node].nonzero()[0])
        parents = adjacency_matrix[:random_node, random_node].nonzero()[0]

        #print('matrix', adjacency_matrix)
        #print('parents', parents)

        if parents.any():
            parent_of_node_to_modify = np.random.choice(parents)

            # Select a new parent for this node, (needs to be different from previous parent)
            new_parent_of_node = np.random.choice(
                np.argwhere(adjacency_matrix[:random_node,
                                             random_node] == 0).flatten())
            # Remove old parent from child
            adjacency_matrix[parent_of_node_to_modify, random_node] = 0
            # Add new parent to child
            adjacency_matrix[new_parent_of_node, random_node] = 1
            # Create new child config
            return Architecture(adjacency_matrix=adjacency_matrix,
                                node_list=node_list)

        else:
            # don't make any changes
            return Architecture(adjacency_matrix=adjacency_matrix,
                                node_list=node_list)

    else:  # op_mutation
        OPS = [CONV3X3, CONV1X1, MAXPOOL3X3]
        op_idx_to_change = np.random.randint(len(node_list))
        # Remove current op on selected idx (because we want a new op)
        OPS.remove(node_list[op_idx_to_change])
        # Select one of the remaining ops
        new_op = np.random.choice(OPS)
        node_list[op_idx_to_change] = new_op
        return Architecture(adjacency_matrix=adjacency_matrix,
                            node_list=node_list)
def get_neighborhood(arch):

    neighbors = []
    for i in range(len(arch.node_list)):
        adjacency_matrix, node_list = copy.deepcopy(
            arch.adjacency_matrix), copy.deepcopy(arch.node_list)
        OPS = [CONV3X3, CONV1X1, MAXPOOL3X3]
        OPS.remove(node_list[i])
        new_op = np.random.choice(OPS)
        node_list[i] = new_op
        neighbors.append(
            Architecture(adjacency_matrix=adjacency_matrix,
                         node_list=node_list))

    if type(search_space) == SearchSpace1:
        # Node 1 has now choice for node 2 as it always has 2 parents
        low = 3
    else:
        low = 2

    for i in range(low, arch.adjacency_matrix.shape[-1]):
        parents = arch.adjacency_matrix[:i, i].nonzero()[0]

        for parent in parents:
            for new_parent in np.argwhere(
                    arch.adjacency_matrix[:i, i] == 0).flatten():
                # Select a new parent for this node, (needs to be different from previous parent)

                adjacency_matrix = copy.deepcopy(arch.adjacency_matrix)
                node_list = copy.deepcopy(arch.node_list)

                adjacency_matrix[parent, i] = 0
                # Add new parent to child
                adjacency_matrix[new_parent, i] = 1
                # Create new child config
                neighbors.append(
                    Architecture(adjacency_matrix=adjacency_matrix,
                                 node_list=node_list))

    return neighbors
Example #3
0
    def objective_function(self, nasbench, config, budget=108):
        adjacency_matrix, node_list = super(
            SearchSpace2, self).convert_config_to_nasbench_format(config)
        # adjacency_matrix = upscale_to_nasbench_format(adjacency_matrix)
        node_list = [INPUT, *node_list, CONV1X1, OUTPUT]
        adjacency_list = adjacency_matrix.astype(np.int).tolist()
        model_spec = api.ModelSpec(matrix=adjacency_list, ops=node_list)
        nasbench_data = nasbench.query(model_spec, epochs=budget)

        # record the data to history
        architecture = Model()
        arch = Architecture(adjacency_matrix=adjacency_matrix,
                            node_list=node_list)
        architecture.update_data(arch, nasbench_data, budget)
        self.run_history.append(architecture)

        return nasbench_data['validation_accuracy'], nasbench_data[
            'training_time']
def random_architecture():
    adjacency_matrix, node_list = search_space.sample_with_loose_ends()
    architecture = Architecture(adjacency_matrix=adjacency_matrix,
                                node_list=node_list)
    return architecture