Source code for wbia.algo.graph.demo

# -*- coding: utf-8 -*-
"""
TODO: separate out the tests and make this file just generate the demo data
"""
from __future__ import absolute_import, division, print_function, unicode_literals
import itertools as it
import numpy as np
import utool as ut
from wbia.algo.graph.state import POSTV, NEGTV, INCMP, UNREV
from wbia.algo.graph.state import SAME, DIFF, NULL  # NOQA

print, rrr, profile = ut.inject2(__name__)


[docs]def make_dummy_infr(annots_per_name): import wbia nids = [val for val, num in enumerate(annots_per_name, start=1) for _ in range(num)] aids = range(len(nids)) infr = wbia.AnnotInference(None, aids, nids=nids, autoinit=True, verbose=1) return infr
[docs]def demodata_mtest_infr(state='empty'): import wbia ibs = wbia.opendb(db='PZ_MTEST') annots = ibs.annots() names = list(annots.group_items(annots.nids).values()) ut.shuffle(names, rng=321) test_aids = ut.flatten(names[1::2]) infr = wbia.AnnotInference(ibs, test_aids, autoinit=True) infr.reset(state=state) return infr
[docs]def demodata_infr2(defaultdb='PZ_MTEST'): defaultdb = 'PZ_MTEST' import wbia ibs = wbia.opendb(defaultdb=defaultdb) annots = ibs.annots() names = list(annots.group_items(annots.nids).values())[0:20] def dummy_phi(c, n): x = np.arange(n) phi = c * x / (c * x + 1) phi = phi / phi.sum() phi = np.diff(phi) return phi phis = {c: dummy_phi(c, 30) for c in range(1, 4)} aids = ut.flatten(names) infr = wbia.AnnotInference(ibs, aids, autoinit=True) infr.init_termination_criteria(phis) infr.init_refresh_criteria() # Partially review n1, n2, n3, n4 = names[0:4] for name in names[4:]: for a, b in ut.itertwo(name.aids): infr.add_feedback((a, b), POSTV) for name1, name2 in it.combinations(names[4:], 2): infr.add_feedback((name1.aids[0], name2.aids[0]), NEGTV) return infr
[docs]def demo2(): """ CommandLine: python -m wbia.algo.graph.demo demo2 --viz python -m wbia.algo.graph.demo demo2 Example: >>> # DISABLE_DOCTEST >>> from wbia.algo.graph.demo import * # NOQA >>> result = demo2() >>> print(result) """ import wbia.plottool as pt from wbia.scripts.thesis import TMP_RC import matplotlib as mpl mpl.rcParams.update(TMP_RC) # ---- Synthetic data params params = { 'redun.pos': 2, 'redun.neg': 2, } # oracle_accuracy = .98 # oracle_accuracy = .90 # oracle_accuracy = (.8, 1.0) oracle_accuracy = (0.85, 1.0) # oracle_accuracy = 1.0 # --- draw params VISUALIZE = ut.get_argflag('--viz') # QUIT_OR_EMEBED = 'embed' QUIT_OR_EMEBED = 'quit' TARGET_REVIEW = ut.get_argval('--target', type_=int, default=None) START = ut.get_argval('--start', type_=int, default=None) END = ut.get_argval('--end', type_=int, default=None) # ------------------ # rng = np.random.RandomState(42) # infr = demodata_infr(num_pccs=4, size=3, size_std=1, p_incon=0) # infr = demodata_infr(num_pccs=6, size=7, size_std=1, p_incon=0) # infr = demodata_infr(num_pccs=3, size=5, size_std=.2, p_incon=0) infr = demodata_infr(pcc_sizes=[5, 2, 4]) infr.verbose = 100 # apply_dummy_viewpoints(infr) # infr.ensure_cliques() infr.ensure_cliques() infr.ensure_full() # infr.apply_edge_truth() # Dummy scoring infr.init_simulation(oracle_accuracy=oracle_accuracy, name='demo2') # infr_gt = infr.copy() dpath = ut.ensuredir(ut.truepath('~/Desktop/demo')) ut.remove_files_in_dir(dpath) fig_counter = it.count(0) def show_graph(infr, title, final=False, selected_edges=None): if not VISUALIZE: return # TODO: rich colored text? latest = '\n'.join(infr.latest_logs()) showkw = dict( # fontsize=infr.graph.graph['fontsize'], # fontname=infr.graph.graph['fontname'], show_unreviewed_edges=True, show_inferred_same=False, show_inferred_diff=False, outof=(len(infr.aids)), # show_inferred_same=True, # show_inferred_diff=True, selected_edges=selected_edges, show_labels=True, simple_labels=True, # show_recent_review=not final, show_recent_review=False, # splines=infr.graph.graph['splines'], reposition=False, # with_colorbar=True ) verbose = infr.verbose infr.verbose = 0 infr_ = infr.copy() infr_ = infr infr_.verbose = verbose infr_.show(pickable=True, verbose=0, **showkw) infr.verbose = verbose # print('status ' + ut.repr4(infr_.status())) # infr.show(**showkw) ax = pt.gca() pt.set_title(title, fontsize=20) fig = pt.gcf() fontsize = 22 if True: # postprocess xlabel lines = [] for line in latest.split('\n'): if False and line.startswith('ORACLE ERROR'): lines += ['ORACLE ERROR'] else: lines += [line] latest = '\n'.join(lines) if len(lines) > 10: fontsize = 16 if len(lines) > 12: fontsize = 14 if len(lines) > 14: fontsize = 12 if len(lines) > 18: fontsize = 10 if len(lines) > 23: fontsize = 8 if True: pt.adjust_subplots(top=0.95, left=0, right=1, bottom=0.45, fig=fig) ax.set_xlabel('\n' + latest) xlabel = ax.get_xaxis().get_label() xlabel.set_horizontalalignment('left') # xlabel.set_x(.025) xlabel.set_x(-0.6) # xlabel.set_fontname('CMU Typewriter Text') xlabel.set_fontname('Inconsolata') xlabel.set_fontsize(fontsize) ax.set_aspect('equal') # ax.xaxis.label.set_color('red') from os.path import join fpath = join(dpath, 'demo_{:04d}.png'.format(next(fig_counter))) fig.savefig( fpath, dpi=300, # transparent=True, edgecolor='none', ) # pt.save_figure(dpath=dpath, dpi=300) infr.latest_logs() if VISUALIZE: infr.update_visual_attrs(groupby='name_label') infr.set_node_attrs('pin', 'true') node_dict = ut.nx_node_dict(infr.graph) print(ut.repr4(node_dict[1])) if VISUALIZE: infr.latest_logs() # Pin Nodes into the target groundtruth position show_graph(infr, 'target-gt') print(ut.repr4(infr.status())) infr.clear_feedback() infr.clear_name_labels() infr.clear_edges() print(ut.repr4(infr.status())) infr.latest_logs() if VISUALIZE: infr.update_visual_attrs() infr.prioritize('prob_match') if VISUALIZE or TARGET_REVIEW is None or TARGET_REVIEW == 0: show_graph(infr, 'initial state') def on_new_candidate_edges(infr, edges): # hack updateing visual attrs as a callback infr.update_visual_attrs() infr.on_new_candidate_edges = on_new_candidate_edges infr.params.update(**params) infr.refresh_candidate_edges() VIZ_ALL = VISUALIZE and TARGET_REVIEW is None and START is None print('VIZ_ALL = %r' % (VIZ_ALL,)) if VIZ_ALL or TARGET_REVIEW == 0: show_graph(infr, 'find-candidates') # _iter2 = enumerate(infr.generate_reviews(**params)) # _iter2 = list(_iter2) # assert len(_iter2) > 0 # prog = ut.ProgIter(_iter2, label='demo2', bs=False, adjust=False, # enabled=False) count = 1 first = 1 for edge, priority in infr._generate_reviews(data=True): msg = 'review #%d, priority=%.3f' % (count, priority) print('\n----------') infr.print('pop edge {} with priority={:.3f}'.format(edge, priority)) # print('remaining_reviews = %r' % (infr.remaining_reviews()),) # Make the next review if START is not None: VIZ_ALL = count >= START if END is not None and count >= END: break infr.print(msg) if ut.allsame(infr.pos_graph.node_labels(*edge)) and first: # Have oracle make a mistake early feedback = infr.request_oracle_review(edge, accuracy=0) first -= 1 else: feedback = infr.request_oracle_review(edge) AT_TARGET = TARGET_REVIEW is not None and count >= TARGET_REVIEW - 1 SHOW_CANDIATE_POP = True if SHOW_CANDIATE_POP and (VIZ_ALL or AT_TARGET): # import utool # utool.embed() infr.print( ut.repr2(infr.task_probs['match_state'][edge], precision=4, si=True) ) infr.print('len(queue) = %r' % (len(infr.queue))) # Show edge selection infr.print('Oracle will predict: ' + feedback['evidence_decision']) show_graph(infr, 'pre' + msg, selected_edges=[edge]) if count == TARGET_REVIEW: infr.EMBEDME = QUIT_OR_EMEBED == 'embed' infr.add_feedback(edge, **feedback) infr.print('len(queue) = %r' % (len(infr.queue))) # infr.apply_nondynamic_update() # Show the result if VIZ_ALL or AT_TARGET: show_graph(infr, msg) # import sys # sys.exit(1) if count == TARGET_REVIEW: break count += 1 infr.print('status = ' + ut.repr4(infr.status(extended=False))) show_graph(infr, 'post-review (#reviews={})'.format(count), final=True) # ROUND 2 FIGHT # if TARGET_REVIEW is None and round2_params is not None: # # HACK TO GET NEW THINGS IN QUEUE # infr.params = round2_params # _iter2 = enumerate(infr.generate_reviews(**params)) # prog = ut.ProgIter(_iter2, label='round2', bs=False, adjust=False, # enabled=False) # for count, (aid1, aid2) in prog: # msg = 'reviewII #%d' % (count) # print('\n----------') # print(msg) # print('remaining_reviews = %r' % (infr.remaining_reviews()),) # # Make the next review evidence_decision # feedback = infr.request_oracle_review(edge) # if count == TARGET_REVIEW: # infr.EMBEDME = QUIT_OR_EMEBED == 'embed' # infr.add_feedback(edge, **feedback) # # Show the result # if PRESHOW or TARGET_REVIEW is None or count >= TARGET_REVIEW - 1: # show_graph(infr, msg) # if count == TARGET_REVIEW: # break # show_graph(infr, 'post-re-review', final=True) if not getattr(infr, 'EMBEDME', False): if ut.get_computer_name().lower() in ['hyrule', 'ooo']: pt.all_figures_tile(monitor_num=0, percent_w=0.5) else: pt.all_figures_tile() ut.show_if_requested()
valid_views = ['L', 'F', 'R', 'B'] adjacent_views = { v: [valid_views[(count + i) % len(valid_views)] for i in [-1, 0, 1]] for count, v in enumerate(valid_views) }
[docs]def get_edge_truth(infr, n1, n2): node_dict = ut.nx_node_dict(infr.graph) nid1 = node_dict[n1]['orig_name_label'] nid2 = node_dict[n2]['orig_name_label'] try: view1 = node_dict[n1]['viewpoint'] view2 = node_dict[n2]['viewpoint'] comparable = view1 in adjacent_views[view2] except KeyError: comparable = True # raise same = nid1 == nid2 if not comparable: return 2 else: return int(same)
[docs]def apply_dummy_viewpoints(infr): transition_rate = 0.5 transition_rate = 0 valid_views = ['L', 'F', 'R', 'B'] rng = np.random.RandomState(42) class MarkovView(object): def __init__(self): self.dir_ = +1 self.state = 0 def __call__(self): return self.next_state() def next_state(self): if self.dir_ == -1 and self.state <= 0: self.dir_ = +1 if self.dir_ == +1 and self.state >= len(valid_views) - 1: self.dir_ = -1 if rng.rand() < transition_rate: self.state += self.dir_ return valid_views[self.state] mkv = MarkovView() nid_to_aids = ut.group_pairs( [(n, d['name_label']) for n, d in infr.graph.nodes(data=True)] ) grouped_nodes = list(nid_to_aids.values()) node_to_view = {node: mkv() for nodes in grouped_nodes for node in nodes} infr.set_node_attrs('viewpoint', node_to_view)
[docs]def make_demo_infr(ccs, edges=[], nodes=[], infer=True): """ Depricate in favor of demodata_infr """ import wbia import networkx as nx if nx.__version__.startswith('1'): nx.add_path = nx.Graph.add_path G = wbia.AnnotInference._graph_cls() G.add_nodes_from(nodes) for cc in ccs: if len(cc) == 1: G.add_nodes_from(cc) nx.add_path(G, cc, evidence_decision=POSTV, meta_decision=NULL) # for edge in edges: # u, v, d = edge if len(edge) == 3 else tuple(edge) + ({},) G.add_edges_from(edges) infr = wbia.AnnotInference.from_netx(G, infer=infer) infr.verbose = 3 infr.relabel_using_reviews(rectify=False) infr.graph.graph['dark_background'] = False infr.graph.graph['ignore_labels'] = True infr.set_node_attrs('width', 40) infr.set_node_attrs('height', 40) # infr.set_node_attrs('fontsize', fontsize) # infr.set_node_attrs('fontname', fontname) infr.set_node_attrs('fixed_size', True) return infr
[docs]@profile def demodata_infr(**kwargs): """ kwargs = {} CommandLine: python -m wbia.algo.graph.demo demodata_infr --show python -m wbia.algo.graph.demo demodata_infr --num_pccs=25 python -m wbia.algo.graph.demo demodata_infr --profile --num_pccs=100 Ignore: >>> from wbia.algo.graph.demo import * # NOQA >>> from wbia.algo.graph import demo >>> import networkx as nx >>> kwargs = dict(num_pccs=6, p_incon=.5, size_std=2) >>> kwargs = ut.argparse_dict(kwargs) >>> infr = demo.demodata_infr(**kwargs) >>> pccs = list(infr.positive_components()) >>> assert len(pccs) == kwargs['num_pccs'] >>> nonfull_pccs = [cc for cc in pccs if len(cc) > 1 and nx.is_empty(nx.complement(infr.pos_graph.subgraph(cc)))] >>> expected_n_incon = len(nonfull_pccs) * kwargs['p_incon'] >>> n_incon = len(list(infr.inconsistent_components())) >>> # TODO can test that we our sample num incon agrees with pop mean >>> #sample_mean = n_incon / len(nonfull_pccs) >>> #pop_mean = kwargs['p_incon'] >>> print('status = ' + ut.repr4(infr.status(extended=True))) >>> ut.quit_if_noshow() >>> infr.show(pickable=True, groupby='name_label') >>> ut.show_if_requested() Ignore: kwargs = { 'ccs': [[1, 2, 3], [4, 5]] } """ import networkx as nx import vtool as vt from wbia.algo.graph import nx_utils def kwalias(*args): params = args[0:-1] default = args[-1] for key in params: if key in kwargs: return kwargs[key] return default num_pccs = kwalias('num_pccs', 16) size_mean = kwalias('pcc_size_mean', 'pcc_size', 'size', 5) size_std = kwalias('pcc_size_std', 'size_std', 0) # p_pcc_incon = kwargs.get('p_incon', .1) p_pcc_incon = kwargs.get('p_incon', 0) p_pcc_incomp = kwargs.get('p_incomp', 0) pcc_sizes = kwalias('pcc_sizes', None) pos_redun = kwalias('pos_redun', [1, 2, 3]) pos_redun = ut.ensure_iterable(pos_redun) # number of maximum inconsistent edges per pcc max_n_incon = kwargs.get('n_incon', 3) rng = np.random.RandomState(0) counter = 1 if pcc_sizes is None: pcc_sizes = [ int(randn(size_mean, size_std, rng=rng, a_min=1)) for _ in range(num_pccs) ] else: num_pccs = len(pcc_sizes) if 'ccs' in kwargs: # Overwrites other options pcc_sizes = list(map(len, kwargs['ccs'])) num_pccs = len(pcc_sizes) size_mean = None size_std = 0 new_ccs = [] pcc_iter = list(enumerate(pcc_sizes)) pcc_iter = ut.ProgIter(pcc_iter, enabled=num_pccs > 20, label='make pos-demo') for i, size in pcc_iter: p = 0.1 want_connectivity = rng.choice(pos_redun) want_connectivity = min(size - 1, want_connectivity) # Create basic graph of positive edges with desired connectivity g = nx_utils.random_k_edge_connected_graph( size, k=want_connectivity, p=p, rng=rng ) nx.set_edge_attributes(g, name='evidence_decision', values=POSTV) nx.set_edge_attributes(g, name='truth', values=POSTV) # nx.set_node_attributes(g, name='orig_name_label', values=i) assert nx.is_connected(g) # Relabel graph with non-conflicting names if 'ccs' in kwargs: g = nx.relabel_nodes(g, dict(enumerate(kwargs['ccs'][i]))) else: # Make sure nodes do not conflict with others g = nx.relabel_nodes(g, dict(enumerate(range(counter, len(g) + counter + 1)))) counter += len(g) # The probability any edge is inconsistent is `p_incon` # This is 1 - P(all edges consistent) # which means p(edge is consistent) = (1 - p_incon) / N complement_edges = ut.estarmap(nx_utils.e_, nx_utils.complement_edges(g)) if len(complement_edges) > 0: # compute probability that any particular edge is inconsistent # to achieve probability the PCC is inconsistent p_edge_inconn = 1 - (1 - p_pcc_incon) ** (1 / len(complement_edges)) p_edge_unrev = 0.1 p_edge_notcomp = 1 - (1 - p_pcc_incomp) ** (1 / len(complement_edges)) probs = np.array([p_edge_inconn, p_edge_unrev, p_edge_notcomp]) # if the total probability is greater than 1 the parameters # are invalid, so we renormalize to "fix" it. # if probs.sum() > 1: # warnings.warn('probabilities sum to more than 1') # probs = probs / probs.sum() pcumsum = probs.cumsum() # Determine which mutually exclusive state each complement edge is in # print('pcumsum = %r' % (pcumsum,)) states = np.searchsorted(pcumsum, rng.rand(len(complement_edges))) incon_idxs = np.where(states == 0)[0] if len(incon_idxs) > max_n_incon: print('max_n_incon = %r' % (max_n_incon,)) chosen = rng.choice(incon_idxs, max_n_incon, replace=False) states[np.setdiff1d(incon_idxs, chosen)] = len(probs) grouped_edges = ut.group_items(complement_edges, states) for state, edges in grouped_edges.items(): truth = POSTV if state == 0: # Add in inconsistent edges evidence_decision = NEGTV # TODO: truth could be INCMP or POSTV # new_edges.append((u, v, {'evidence_decision': NEGTV})) elif state == 1: evidence_decision = UNREV # TODO: truth could be INCMP or POSTV # new_edges.append((u, v, {'evidence_decision': UNREV})) elif state == 2: evidence_decision = INCMP truth = INCMP else: continue # Add in candidate edges attrs = {'evidence_decision': evidence_decision, 'truth': truth} for (u, v) in edges: g.add_edge(u, v, **attrs) new_ccs.append(g) # (list(g.nodes()), new_edges)) pos_g = nx.union_all(new_ccs) assert len(new_ccs) == len(list(nx.connected_components(pos_g))) assert num_pccs == len(new_ccs) # Add edges between the PCCS neg_edges = [] if not kwalias('ignore_pair', False): print('making pairs') pair_attrs_lookup = { 0: {'evidence_decision': NEGTV, 'truth': NEGTV}, 1: {'evidence_decision': INCMP, 'truth': INCMP}, 2: {'evidence_decision': UNREV, 'truth': NEGTV}, # could be incomp or neg } # These are the probabilities that one edge has this state p_pair_neg = kwalias('p_pair_neg', 0.4) p_pair_incmp = kwalias('p_pair_incmp', 0.2) p_pair_unrev = kwalias('p_pair_unrev', 0) # p_pair_neg = 1 cc_combos = ( (list(g1.nodes()), list(g2.nodes())) for (g1, g2) in it.combinations(new_ccs, 2) ) valid_cc_combos = [(cc1, cc2) for cc1, cc2 in cc_combos if len(cc1) and len(cc2)] for cc1, cc2 in ut.ProgIter(valid_cc_combos, label='make neg-demo'): possible_edges = ut.estarmap(nx_utils.e_, it.product(cc1, cc2)) # probability that any edge between these PCCs is negative n_edges = len(possible_edges) p_edge_neg = 1 - (1 - p_pair_neg) ** (1 / n_edges) p_edge_incmp = 1 - (1 - p_pair_incmp) ** (1 / n_edges) p_edge_unrev = 1 - (1 - p_pair_unrev) ** (1 / n_edges) # Create event space with sizes proportional to probabilities pcumsum = np.cumsum([p_edge_neg, p_edge_incmp, p_edge_unrev]) # Roll dice for each of the edge to see which state it lands on possible_pstate = rng.rand(len(possible_edges)) states = np.searchsorted(pcumsum, possible_pstate) flags = states < len(pcumsum) stateful_states = states.compress(flags) stateful_edges = ut.compress(possible_edges, flags) unique_states, groupxs_list = vt.group_indices(stateful_states) for state, groupxs in zip(unique_states, groupxs_list): # print('state = %r' % (state,)) # Add in candidate edges edges = ut.take(stateful_edges, groupxs) attrs = pair_attrs_lookup[state] for (u, v) in edges: neg_edges.append((u, v, attrs)) print('Made {} neg_edges between PCCS'.format(len(neg_edges))) else: print('ignoring pairs') import wbia G = wbia.AnnotInference._graph_cls() G.add_nodes_from(pos_g.nodes(data=True)) G.add_edges_from(pos_g.edges(data=True)) G.add_edges_from(neg_edges) infr = wbia.AnnotInference.from_netx(G, infer=kwargs.get('infer', True)) infr.verbose = 3 infr.relabel_using_reviews(rectify=False) # fontname = 'Ubuntu' fontsize = 12 fontname = 'sans' splines = 'spline' # splines = 'ortho' # splines = 'line' infr.set_node_attrs('shape', 'circle') infr.graph.graph['ignore_labels'] = True infr.graph.graph['dark_background'] = False infr.graph.graph['fontname'] = fontname infr.graph.graph['fontsize'] = fontsize infr.graph.graph['splines'] = splines infr.set_node_attrs('width', 29) infr.set_node_attrs('height', 29) infr.set_node_attrs('fontsize', fontsize) infr.set_node_attrs('fontname', fontname) infr.set_node_attrs('fixed_size', True) # Set synthetic ground-truth attributes for testing # infr.apply_edge_truth() infr.edge_truth = infr.get_edge_attrs('truth') # Make synthetic verif infr.dummy_verif = DummyVerif(infr) infr.verifiers = {} infr.verifiers['match_state'] = infr.dummy_verif infr.demokw = kwargs return infr
[docs]def randn(mean=0, std=1, shape=[], a_max=None, a_min=None, rng=None): a = (rng.randn(*shape) * std) + mean if a_max is not None or a_min is not None: a = np.clip(a, a_min, a_max) return a
[docs]class DummyVerif(object): """ generates dummy scores between edges (not necesarilly in the graph) CommandLine: python -m wbia.algo.graph.demo DummyVerif:1 Example: >>> # ENABLE_DOCTEST >>> from wbia.algo.graph.demo import * # NOQA >>> from wbia.algo.graph import demo >>> import networkx as nx >>> kwargs = dict(num_pccs=6, p_incon=.5, size_std=2) >>> infr = demo.demodata_infr(**kwargs) >>> infr.dummy_verif.predict_edges([(1, 2)]) >>> infr.dummy_verif.predict_edges([(1, 21)]) >>> assert len(infr.dummy_verif.infr.task_probs['match_state']) == 2 """ def __init__(verif, infr): verif.rng = np.random.RandomState(4033913) verif.dummy_params = { NEGTV: {'mean': 0.2, 'std': 0.25}, POSTV: {'mean': 0.85, 'std': 0.2}, INCMP: {'mean': 0.15, 'std': 0.1}, } verif.score_dist = randn verif.infr = infr verif.orig_nodes = set(infr.aids) verif.orig_labels = infr.get_node_attrs('orig_name_label') verif.orig_groups = ut.invert_dict(verif.orig_labels, False) verif.orig_groups = ut.map_vals(set, verif.orig_groups)
[docs] def show_score_probs(verif): """ CommandLine: python -m wbia.algo.graph.demo DummyVerif.show_score_probs --show Example: >>> # ENABLE_DOCTEST >>> from wbia.algo.graph.demo import * # NOQA >>> import wbia >>> infr = wbia.AnnotInference(None) >>> verif = DummyVerif(infr) >>> verif.show_score_probs() >>> ut.show_if_requested() """ import wbia.plottool as pt dist = verif.score_dist n = 100000 for key in verif.dummy_params.keys(): probs = dist( shape=[n], rng=verif.rng, a_max=1, a_min=0, **verif.dummy_params[key] ) color = verif.infr._get_truth_colors()[key] pt.plt.hist(probs, bins=100, label=key, alpha=0.8, color=color) pt.legend()
[docs] def dummy_ranker(verif, u, K=10): """ simulates the ranking algorithm. Order is defined using the dummy vsone scores, but tests are only applied to randomly selected gt and gf pairs. So, you usually will get a gt result, but you might not if all the scores are bad. """ infr = verif.infr nid = verif.orig_labels[u] others = verif.orig_groups[nid] others_gt = sorted(others - {u}) others_gf = sorted(verif.orig_nodes - others) # rng = np.random.RandomState(u + 4110499444 + len(others)) rng = verif.rng vs_list = [] k_gt = min(len(others_gt), max(1, K // 2)) k_gf = min(len(others_gf), max(1, K * 4)) if k_gt > 0: gt = rng.choice(others_gt, k_gt, replace=False) vs_list.append(gt) if k_gf > 0: gf = rng.choice(others_gf, k_gf, replace=False) vs_list.append(gf) u_edges = [infr.e_(u, v) for v in it.chain.from_iterable(vs_list)] u_probs = np.array(infr.dummy_verif.predict_edges(u_edges)) # infr.set_edge_attrs('prob_match', ut.dzip(u_edges, u_probs)) # Need to determenistically sort here # sortx = np.argsort(u_probs)[::-1][0:K] sortx = np.argsort(u_probs)[::-1][0:K] ranked_edges = ut.take(u_edges, sortx) # assert len(ranked_edges) == K return ranked_edges
[docs] def find_candidate_edges(verif, K=10): """ Example: >>> # ENABLE_DOCTEST >>> from wbia.algo.graph.demo import * # NOQA >>> from wbia.algo.graph import demo >>> import networkx as nx >>> kwargs = dict(num_pccs=40, size=2) >>> infr = demo.demodata_infr(**kwargs) >>> edges = list(infr.dummy_verif.find_candidate_edges(K=100)) >>> scores = np.array(infr.dummy_verif.predict_edges(edges)) """ new_edges = [] nodes = list(verif.infr.graph.nodes()) for u in nodes: new_edges.extend(verif.dummy_ranker(u, K=K)) # print('new_edges = %r' % (ut.hash_data(new_edges),)) new_edges = set(new_edges) return new_edges
def _get_truth(verif, edge): infr = verif.infr if edge in infr.edge_truth: return infr.edge_truth[edge] node_dict = ut.nx_node_dict(infr.graph) nid1 = node_dict[edge[0]]['orig_name_label'] nid2 = node_dict[edge[1]]['orig_name_label'] return POSTV if nid1 == nid2 else NEGTV
[docs] def predict_proba_df(verif, edges): """ CommandLine: python -m wbia.algo.graph.demo DummyVerif.predict_edges Example: >>> # ENABLE_DOCTEST >>> from wbia.algo.graph.demo import * # NOQA >>> from wbia.algo.graph import demo >>> import networkx as nx >>> kwargs = dict(num_pccs=40, size=2) >>> infr = demo.demodata_infr(**kwargs) >>> verif = infr.dummy_verif >>> edges = list(infr.graph.edges()) >>> probs = verif.predict_proba_df(edges) >>> #print('scores = %r' % (scores,)) >>> #hashid = ut.hash_data(scores) >>> #print('hashid = %r' % (hashid,)) >>> #assert hashid == 'cdlkytilfeqgmtsihvhqwffmhczqmpil' """ infr = verif.infr edges = list(it.starmap(verif.infr.e_, edges)) prob_cache = infr.task_probs['match_state'] is_miss = np.array([e not in prob_cache for e in edges]) # is_hit = ~is_miss if np.any(is_miss): miss_edges = ut.compress(edges, is_miss) miss_truths = [verif._get_truth(edge) for edge in miss_edges] grouped_edges = ut.group_items(miss_edges, miss_truths, sorted_=False) # Need to make this determenistic too states = [POSTV, NEGTV, INCMP] for key in sorted(grouped_edges.keys()): group = grouped_edges[key] probs0 = randn( shape=[len(group)], rng=verif.rng, a_max=1, a_min=0, **verif.dummy_params[key], ) # Just randomly assign other probs probs1 = verif.rng.rand(len(group)) * (1 - probs0) probs2 = 1 - (probs0 + probs1) for edge, probs in zip(group, zip(probs0, probs1, probs2)): prob_cache[edge] = ut.dzip(states, probs) from wbia.algo.graph import nx_utils as nxu import pandas as pd probs = pd.DataFrame( ut.take(prob_cache, edges), index=nxu.ensure_multi_index(edges, ('aid1', 'aid2')), ) return probs
[docs] def predict_edges(verif, edges): pos_scores = verif.predict_proba_df(edges)[POSTV] return pos_scores
if __name__ == '__main__': r""" CommandLine: wbia make_qt_graph_interface --show --aids=1,2,3,4,5,6,7 --graph python -m wbia.algo.graph.demo demo2 python -m wbia.algo.graph.demo python -m wbia.algo.graph.demo --allexamples python -m wbia.algo.graph.demo --allexamples --show """ import multiprocessing multiprocessing.freeze_support() # for win32 import utool as ut # NOQA ut.doctest_funcs()