Esempio n. 1
0
    def __init__(self, inputs, outputs, debug=False):

        if not inputs:
            raise ValueError("Inputs can't be empty")
        if not outputs:
            raise ValueError("Ouputs can't be empty")

        # FIXME: check we have the same number of inputs and output
        # and they have the same shape because we are using the ouputs as
        # the next inputs

        # set debug
        self.debug = debug

        # graph underlying structure
        self.graph = nx.DiGraph()

        # tracking structures
        self.idx2op = {}  # op object
        self.idx2results = {}  # op computation result
        self.idx2input_idx = defaultdict(set)  # ops used as inputs
        self.idx2ouput_ops = defaultdict(set)  # ops used as outputs

        self.inputs_idx = []  # track which op idx are inputs
        self.outputs_idx = []  # track what op idx are outputs

        self.fitness = None
        self.compiled = False
        self._results = None
        self.callback_collection = None

        # storing inputs tensors
        self.inputs = box(inputs)
        for ipt in self.inputs:
            self.inputs_idx.append(ipt.idx)

        # output
        self.outputs = box(outputs)
        for output in self.outputs:
            self.outputs_idx.append(output.idx)

        # build forward graph
        for output in self.outputs:
            self._add_op_to_graph(output, None, self.debug)

        # FIXME: check that the graph is fully connected from input to output

        # coerce exec_path as a list to allow reuse accros batches.
        self.execution_path = list(nx.topological_sort(self.graph))
Esempio n. 2
0
    def compile(self, selection_strategy, fitness_functions):
        """Configure evoluationary model for training

        """
        # FIXME: check args validity
        self.selection_strategy = selection_strategy
        self.fitness_functions = box(fitness_functions)
        self.compiled = True

        self._results = Results(debug=self.debug)
Esempio n. 3
0
    def __call__(self, ops):

        # boxing inputs if needed
        ops = box(ops)

        # graph computation or eager?
        if self.debug:
            input_types = [type(op) for op in ops]
            self.print_debug('inputs type:%s' % (input_types))

        if issubclass(type(ops[0]), OP):
            # graph mode
            self.print_debug('graph mode')

            input_shapes = []
            for op in ops:
                assert issubclass(type(op), OP)
                self.input_ops.append(op)
                input_shapes.append(op.get_output_shapes())

            self.compute_output_shape(input_shapes)

            return self
        else:
            # eager mode
            self.print_debug('eager mode')

            # check inputs are valis
            for op in ops:
                if not B.is_tensor(op):
                    raise ValueError("Expecting list(tensors) or a tensor")

            # input shapes
            input_shapes = []
            for op in ops:
                input_shapes.append(op.shape)
            self.compute_output_shape(input_shapes)

            # compute concrete results - dispatch iterate through populations.
            return unbox(self.dispatch(ops, self.EAGER))
Esempio n. 4
0
 def dispatch(self, populations, mode):
     return box(self.call(populations))
Esempio n. 5
0
 def _call_from_graph(self, populations):
     "Function called during graph executions"
     populations = box(populations)
     # dispatch take care of iterating through populations
     return unbox(self.dispatch(populations, self.GRAPH))
Esempio n. 6
0
    def evolve(self, populations, generations=1, callbacks=None, verbose=1):

        if not self.compiled:
            raise ValueError("compile() must be run before using the graph")
            return

        self.callback_collection = CallbackCollection(callbacks)

        populations = box(populations)
        self.print_debug("Initial Populations", populations)

        if not len(populations) == len(self.inputs):
            raise ValueError('The numbers of population must be equal\
                 to number of inputs')

        # assign initial value to inputs
        current_populations = []
        for pop_idx, ipt in enumerate(self.inputs):
            self.inputs[pop_idx].assign(populations[pop_idx])
            pop = self.inputs[pop_idx].get()
            current_populations.append(pop)
        num_populations = len(current_populations)
        self.print_debug('Initial current_populations', current_populations)

        # callbacks
        self.callback_collection.on_evolution_begin(current_populations)

        # progress bar
        if verbose:
            pb = tqdm(total=generations, unit='generation')

        # evolve loop
        for generation_idx in range(generations):

            # callbacks
            self.callback_collection.on_generation_begin(generation_idx)

            # perform evolution
            evolved_populations = self.perform_evolution()

            # assign evolved populations
            self.print_debug(generation_idx, 'evolved pop',
                             evolved_populations)

            fitness_scores_list = []  # keep track of fitness scores
            metrics_list = []  # keep track of the metrics scores
            for pop_idx in range(num_populations):
                # find current informaiton
                current_pop = current_populations[pop_idx]
                evolved_pop = evolved_populations[pop_idx]
                fitness_function = self.fitness_functions[pop_idx]

                self.print_debug('current_population', pop_idx, current_pop)
                self.print_debug('evolved_population', pop_idx, evolved_pop)
                # select population
                new_population, fitness_scores, metrics = self.selection_strategy(  # noqa
                    fitness_function, current_pop, evolved_pop)

                # tracks metrics
                metrics_list.append(metrics)
                fitness_scores_list.append(fitness_scores)

                # update population tensor
                self.inputs[pop_idx].assign(new_population)

                # track current population
                current_populations[pop_idx] = new_population
                # record fitness scores

            self._results.record_fitness(fitness_scores_list)

            latest_metrics = self._results.get_latest_metrics(flatten=True)

            # callbacks
            self.callback_collection.on_generation_end(generation_idx,
                                                       latest_metrics,
                                                       fitness_scores_list,
                                                       populations)

            # progress bar
            if verbose:
                formatted_metrics = {}
                for name, value in latest_metrics.items():
                    name = name.lower().replace(' ', '_')
                    formatted_metrics[name] = value
                pb.set_postfix(formatted_metrics)
                pb.update()

        if verbose:
            pb.close()

        # final callback
        self.callback_collection.on_evolution_end(current_populations)

        # record last population
        self._results.set_population(current_populations)

        # return last evolution
        return self._results
Esempio n. 7
0
def test_box_unbox_tensor():
    val = tensor([1, 2, 3])

    assert tensor_equal(unbox(box(val)), val)
Esempio n. 8
0
def test_box_unbox():
    vals = ['a', [1, 2, 3]]

    for val in vals:
        assert unbox(box(val)) == val