Пример #1
0
    def generate_negatives(pccs):
        generators = None
        unfinished = True
        generators = {}

        while unfinished:
            finished = set()
            if unfinished is True:
                combos = ut.random_combinations(pccs, 2)
            else:
                combos = unfinished

            for pcc1, pcc2 in combos:
                key = (pcc1, pcc2)

                if key not in generators:
                    generators[key] = ut.random_product([pcc1, pcc2])
                gen = generators[key]
                try:
                    edge = e_(next(gen))
                    yield edge
                except StopIteration:
                    finished.add(key)

            if unfinished is True:
                unfinished = set(generators.keys())

            unfinished.difference_update(finished)
Пример #2
0
def negative_sample(pccs, per_pair=None):
    import utool as ut
    rng = ut.ensure_rng(2039141610, 'python')
    neg_pcc_pairs = ut.random_combinations(pccs, 2, rng=rng)
    yield from util.roundrobin(
        ut.random_product((cc1, cc2), num=per_pair, rng=rng)
        for cc1, cc2 in neg_pcc_pairs)
Пример #3
0
 def generate_positives(pccs):
     generators = {
         i: ut.random_combinations(pcc, 2)
         for i, pcc in enumerate(pccs)
     }
     while generators:
         to_remove = set()
         for i, gen in generators.items():
             try:
                 yield e_(next(gen))
             except StopIteration:
                 to_remove.add(i)
         for i in to_remove:
             generators.pop(i)
Пример #4
0
def positive_sample(pccs, per_cc=None):
    import utool as ut
    rng = ut.ensure_rng(2039141610, 'python')
    yield from util.roundrobin(
        ut.random_combinations(cc, size=2, num=per_cc, rng=rng) for cc in pccs)
Пример #5
0
    def main_gen(infr, max_loops=None, use_refresh=True):
        """
        The main outer loop.

        This function is designed as an iterator that will execute the graph
        algorithm main loop as automatically as possible, but if user input is
        needed, it will pause and yield the decision it needs help with. Once
        feedback is given for this item, you can continue the main loop by
        calling next. StopIteration is raised once the algorithm is complete.

        Args:
            max_loops(int): maximum number of times to run the outer loop,
                i.e. ranking is run at most this many times.
            use_refresh(bool): allow the refresh criterion to stop the algo

        Notes:
            Different phases of the main loop are implemented as subiterators

        CommandLine:
            python -m wbia.algo.graph.mixin_loops main_gen

        Doctest:
            >>> # xdoctest: +REQUIRES(--slow)
            >>> from wbia.algo.graph.mixin_loops import *
            >>> from wbia.algo.graph.mixin_simulation import UserOracle
            >>> import wbia
            >>> infr = wbia.AnnotInference('testdb1', aids='all',
            >>>                             autoinit='staging', verbose=4)
            >>> infr.params['manual.n_peek'] = 10
            >>> infr.params['ranking.ntop'] = 1
            >>> infr.oracle = UserOracle(.99, rng=0)
            >>> infr.simulation_mode = False
            >>> infr.reset()
            >>> #infr.load_published()
            >>> gen = infr.main_gen()
            >>> while True:
            >>>     try:
            >>>         reviews = next(gen)
            >>>         edge, priority, data = reviews[0]
            >>>         feedback = infr.request_oracle_review(edge)
            >>>         infr.add_feedback(edge, **feedback)
            >>>     except StopIteration:
            >>>         break
        """
        infr.print('Starting main loop', 1)
        infr.print('infr.params = {}'.format(ut.repr3(infr.params)))
        if max_loops is None:
            max_loops = infr.params['algo.max_outer_loops']
            if max_loops is None:
                max_loops = np.inf

        if infr.test_mode:
            logger.info('------------------ {} -------------------'.format(infr.name))

        # Initialize a refresh criteria
        infr.init_refresh()

        infr.phase = 0
        # Phase 0.1: Ensure the user sees something immediately
        if infr.params['algo.quickstart']:
            infr.loop_phase = 'quickstart_init'
            # quick startup. Yield a bunch of random edges
            num = infr.params['manual.n_peek']
            user_request = []
            for edge in ut.random_combinations(infr.aids, 2, num=num):
                user_request += [infr._make_review_tuple(edge, None)]
                yield user_request

        if infr.params['algo.hardcase']:
            infr.loop_phase = 'hardcase_init'
            # Check previously labeled edges that where the groundtruth and the
            # verifier disagree.
            for _ in infr.hardcase_review_gen():
                yield _

        if infr.params['inference.enabled']:
            infr.loop_phase = 'incon_recover_init'
            # First, fix any inconsistencies
            for _ in infr.incon_recovery_gen():
                yield _

        # Phase 0.2: Ensure positive redundancy (this is generally quick)
        # so the user starts seeing real work after one random review is made
        # unless the graph is already positive redundant.
        if infr.params['redun.enabled'] and infr.params['redun.enforce_pos']:
            infr.loop_phase = 'pos_redun_init'
            # Fix positive redundancy of anything within the loop
            try:
                for _ in infr.pos_redun_gen():
                    yield _
            except StopIteration:
                pass

        infr.phase = 1
        if infr.params['ranking.enabled']:
            for count in it.count(0):
                infr.print('Outer loop iter %d ' % (count,))

                # Phase 1: Try to merge PCCs by searching for LNBNN candidates
                infr.loop_phase = 'ranking_{}'.format(count)
                for _ in infr.ranked_list_gen(use_refresh):
                    yield _

                terminate = infr.refresh.num_meaningful == 0
                if terminate:
                    infr.print('Triggered break criteria', 1, color='red')

                # Phase 2: Ensure positive redundancy.
                infr.phase = 2
                infr.loop_phase = 'posredun_{}'.format(count)
                if all(ut.take(infr.params, ['redun.enabled', 'redun.enforce_pos'])):
                    # Fix positive redundancy of anything within the loop
                    for _ in infr.pos_redun_gen():
                        yield _

                logger.info('prob_any_remain = %r' % (infr.refresh.prob_any_remain(),))
                logger.info(
                    'infr.refresh.num_meaningful = {!r}'.format(
                        infr.refresh.num_meaningful
                    )
                )

                if (count + 1) >= max_loops:
                    infr.print('early stop', 1, color='red')
                    break

                if terminate:
                    infr.print('break triggered')
                    break

        infr.phase = 3
        # Phase 0.3: Ensure positive redundancy (this is generally quick)
        if all(ut.take(infr.params, ['redun.enabled', 'redun.enforce_neg'])):
            # Phase 3: Try to automatically acheive negative redundancy without
            # asking the user to do anything but resolve inconsistency.
            infr.print('Entering phase 3', 1, color='red')
            infr.loop_phase = 'negredun'
            for _ in infr.neg_redun_gen():
                yield _

        infr.phase = 4
        infr.print('Terminate', 1, color='red')
        infr.print('Exiting main loop')

        if infr.params['inference.enabled']:
            infr.assert_consistency_invariant()

        return 'finished'