from __future__ import absolute_import, division, print_function, unicode_literals
import six # NOQA
import utool as ut
import numpy as np
from ibeis.algo.hots.bayes import make_name_model, test_model, draw_tree_model
print, rrr, profile = ut.inject2(__name__, '[demobayes]')
[docs]def testdata_demo_cfgs():
alias_keys = {'nA': 'num_annots', 'nN': 'num_names', 'nS': 'num_scores'}
cfg_list = ut.parse_argv_cfg('--ev', alias_keys=alias_keys)
return cfg_list
[docs]def demo_bayesnet(cfg={}):
r"""
Make a model that knows who the previous annots are and tries to classify a new annot
CommandLine:
python -m ibeis --tf demo_bayesnet --diskshow --verbose --save demo4.png --dpath . --figsize=20,10 --dpi=128 --clipwhite
python -m ibeis --tf demo_bayesnet --ev :nA=3,Sab=0,Sac=0,Sbc=1
python -m ibeis --tf demo_bayesnet --ev :nA=4,Sab=0,Sac=0,Sbc=1,Sbd=1 --show
python -m ibeis --tf demo_bayesnet --ev :nA=4,Sab=0,Sac=0,Sbc=1,Scd=1 --show
python -m ibeis --tf demo_bayesnet --ev :nA=4,Sab=0,Sac=0,Sbc=1,Sbd=1,Scd=1 --show
python -m ibeis --tf demo_bayesnet --ev :nA=3,Sab=0,Sac=0,Sbc=1
python -m ibeis --tf demo_bayesnet --ev :nA=5,rand_scores=True --show
python -m ibeis --tf demo_bayesnet --ev :nA=4,nS=3,rand_scores=True --show --verbose
python -m ibeis --tf demo_bayesnet --ev :nA=5,nS=2,Na=fred,rand_scores=True --show --verbose
python -m ibeis --tf demo_bayesnet --ev :nA=5,nS=5,Na=fred,rand_scores=True --show --verbose
python -m ibeis --tf demo_bayesnet --ev :nA=4,nS=2,Na=fred,rand_scores=True --show --verbose
python -m ibeis.algo.hots.demobayes --exec-demo_bayesnet \
--ev =:nA=4,Sab=0,Sac=0,Sbc=1 \
:Sbd=1 :Scd=1 :Sbd=1,Scd=1 :Sbd=1,Scd=1,Sad=0 \
--show --present
Example:
>>> # DISABLE_DOCTEST
>>> from ibeis.algo.hots.demobayes import * # NOQA
>>> cfg_list = testdata_demo_cfgs()
>>> print('cfg_list = %r' % (cfg_list,))
>>> for cfg in cfg_list:
>>> demo_bayesnet(cfg)
>>> ut.show_if_requested()
"""
cfg = cfg.copy()
num_annots = cfg.pop('num_annots', 3)
num_names = cfg.pop('num_names', None)
num_scores = cfg.pop('num_scores', 2)
rand_scores = cfg.pop('rand_scores', False)
method = cfg.pop('method', 'bp')
other_evidence = {k: v for k, v in cfg.items() if not k.startswith('_')}
if rand_scores:
#import randomdotorg
#import sys
#r = randomdotorg.RandomDotOrg('ExampleCode')
#seed = int((1 - 2 * r.random()) * sys.maxint)
toy_data = get_toy_data_1v1(num_annots, nid_sequence=[0, 0, 1, 0, 1, 2])
print('toy_data = ' + ut.repr3(toy_data, nl=1))
diag_scores, = ut.dict_take(
toy_data, 'diag_scores'.split(', '))
discr_domain, discr_p_same = learn_prob_score(num_scores)[0:2]
def discretize_scores(scores):
# Assign continuous scores to discrete index
score_idxs = np.abs(1 - (discr_domain / scores[:, None])).argmin(axis=1)
return score_idxs
score_evidence = discretize_scores(diag_scores)
else:
score_evidence = []
discr_p_same = None
discr_domain = None
model, evidence, query_results = test_model(
num_annots=num_annots, num_names=num_names,
num_scores=num_scores,
score_evidence=score_evidence,
mode=1,
other_evidence=other_evidence,
p_score_given_same=discr_p_same,
score_basis=discr_domain,
method=method,
)
[docs]def classify_k(cfg={}):
"""
CommandLine:
python -m ibeis.algo.hots.demobayes --exec-classify_k --show --ev :nA=3
python -m ibeis.algo.hots.demobayes --exec-classify_k --show --ev :nA=3,k=1
python -m ibeis.algo.hots.demobayes --exec-classify_k --show --ev :nA=3,k=0 --method=approx
python -m ibeis.algo.hots.demobayes --exec-classify_k --show --ev :nA=10,k=1 --method=approx
Example:
>>> from ibeis.algo.hots.demobayes import * # NOQA
>>> cfg_list = testdata_demo_cfgs()
>>> classify_k(cfg_list[0])
>>> ut.show_if_requested()
"""
cfg = cfg.copy()
num_annots = cfg.pop('num_annots', 3)
num_scores = cfg.pop('num_scores', 2)
num_iter = cfg.pop('k', 0)
nid_sequence = np.array([0, 0, 1, 2, 2, 1, 1])
toy_data = get_toy_data_1v1(num_annots, nid_sequence=nid_sequence)
force_evidence = None
force_evidence = 0
diag_scores, = ut.dict_take(
toy_data, 'diag_scores'.split(', '))
#print('diag_scores = %r' % (diag_scores,))
#diag_labels = pairwise_matches.compress(is_diag)
#diag_pairs = ut.compress(pairwise_aidxs, is_diag)
discr_domain, discr_p_same = learn_prob_score(num_scores)[0:2]
def discretize_scores(scores):
# Assign continuous scores to closest discrete index
score_idxs = np.abs(1 - (discr_domain / scores[:, None])).argmin(axis=1)
return score_idxs
# Careful ordering is important here
score_evidence = discretize_scores(diag_scores)
if force_evidence is not None:
for x in range(len(score_evidence)):
score_evidence[x] = 0
model, evidence, query_results = test_model(
num_annots=num_annots, num_names=num_annots,
num_scores=num_scores,
mode=1,
score_evidence=score_evidence,
p_score_given_same=discr_p_same,
score_basis=discr_domain,
#verbose=True
)
print(query_results['top_assignments'][0])
toy_data1 = toy_data
print('toy_data1 = ' + ut.repr3(toy_data1, nl=1))
num_annots2 = num_annots + 1
score_evidence1 = [None] * len(score_evidence)
full_evidence = score_evidence.tolist()
factor_list = query_results['factor_list']
using_soft = False
if using_soft:
soft_evidence1 = [dict(zip(x.statenames[0], x.values)) for x in factor_list]
for _ in range(num_iter):
print('\n\n ---------- \n\n')
#toy_data1['all_nids'].max() + 1
num_names_gen = len(toy_data1['all_aids']) + 1
num_names_gen = toy_data1['all_nids'].max() + 2
toy_data2 = get_toy_data_1v1(
1, num_names_gen,
initial_aids=toy_data1['all_aids'],
initial_nids=toy_data1['all_nids'],
nid_sequence=nid_sequence)
diag_scores2, = ut.dict_take(
toy_data2, 'diag_scores'.split(', '))
print('toy_data2 = ' + ut.repr3(toy_data2, nl=1))
score_evidence2 = discretize_scores(diag_scores2).tolist()
if force_evidence is not None:
for x in range(len(score_evidence2)):
score_evidence2[x] = force_evidence
print('score_evidence2 = %r' % (score_evidence2,))
if using_soft:
# Demo with soft evidence
model, evidence, query_results2 = test_model(
num_annots=num_annots2, num_names=num_annots2,
num_scores=num_scores,
mode=1,
name_evidence=soft_evidence1,
#score_evidence=score_evidence1 + score_evidence2,
score_evidence=score_evidence2,
p_score_given_same=discr_p_same,
score_basis=discr_domain,
#verbose=True,
hack_score_only=len(score_evidence2),
)
if 1:
# Demo with full evidence
model, evidence, query_results2 = test_model(
num_annots=num_annots2, num_names=num_annots2,
num_scores=num_scores,
mode=1,
score_evidence=full_evidence + score_evidence2,
p_score_given_same=discr_p_same,
score_basis=discr_domain,
verbose=True
)
factor_list2 = query_results2['factor_list']
if using_soft:
soft_evidence1 = [dict(zip(x.statenames[0], x.values)) for x in factor_list2]
score_evidence1 += ([None] * len(score_evidence2))
full_evidence = full_evidence + score_evidence2
num_annots2 += 1
toy_data1 = toy_data2
[docs]def show_toy_distributions(toy_params):
import vtool as vt
import plottool as pt
pt.ensure_pylab_qt4()
xdata = np.linspace(0, 8, 1000)
tp_pdf = vt.gauss_func1d(xdata, **toy_params[True])
fp_pdf = vt.gauss_func1d(xdata, **toy_params[False])
pt.plot_probabilities(
[tp_pdf, fp_pdf], ['TP', 'TF'],
prob_colors=[pt.TRUE_BLUE, pt.FALSE_RED],
xdata=xdata,
figtitle='Toy Distributions')
[docs]def get_toy_data_1vM(num_annots, num_names=None, **kwargs):
r"""
Args:
num_annots (int):
num_names (int): (default = None)
Kwargs:
initial_aids, initial_nids, nid_sequence, seed
Returns:
tuple: (pair_list, feat_list)
CommandLine:
python -m ibeis.algo.hots.demobayes --exec-get_toy_data_1vM --show
Example:
>>> # DISABLE_DOCTEST
>>> from ibeis.algo.hots.demobayes import * # NOQA
>>> num_annots = 1000
>>> num_names = 40
>>> get_toy_data_1vM(num_annots, num_names)
>>> ut.quit_if_noshow()
>>> import plottool as pt
>>> ut.show_if_requested()
"""
import vtool as vt
tup_ = get_toy_annots(num_annots, num_names, **kwargs)
aids, nids, aids1, nids1, all_aids, all_nids = tup_
rng = vt.ensure_rng(None)
# Test a simple SVM classifier
nid2_nexemp = ut.dict_hist(nids1)
aid2_nid = dict(zip(aids, nids))
ut.fix_embed_globals()
#def add_to_globals(globals_, subdict):
# globals_.update(subdict)
unique_nids = list(nid2_nexemp.keys())
def annot_to_class_feats2(aid, aid2_nid, top=None):
pair_list = []
score_list = []
nexemplar_list = []
for nid in unique_nids:
label = (aid2_nid[aid] == nid)
num_exemplars = nid2_nexemp.get(nid, 0)
if num_exemplars == 0:
continue
params = toy_params[label]
mu, sigma = ut.dict_take(params, ['mu', 'sigma'])
score_ = rng.normal(mu, sigma, size=num_exemplars).max()
score = np.clip(score_, 0, np.inf)
pair_list.append((aid, nid))
score_list.append(score)
nexemplar_list.append(num_exemplars)
rank_list = ut.argsort(score_list, reverse=True)
feat_list = np.array([score_list, rank_list, nexemplar_list]).T
sortx = np.argsort(rank_list)
feat_list = feat_list.take(sortx, axis=0)
pair_list = np.array(pair_list).take(sortx, axis=0)
if top is not None:
feat_list = feat_list[:top]
pair_list = pair_list[0:top]
return pair_list, feat_list
toclass_features = [annot_to_class_feats2(aid, aid2_nid, top=5) for aid in aids]
aidnid_pairs = np.vstack(ut.get_list_column(toclass_features, 0))
feat_list = np.vstack(ut.get_list_column(toclass_features, 1))
score_list = feat_list.T[0:1].T
lbl_list = [aid2_nid[aid] == nid for aid, nid in aidnid_pairs]
from sklearn import svm
#clf1 = svm.LinearSVC()
print('Learning classifiers')
clf3 = svm.SVC(probability=True)
clf3.fit(feat_list, lbl_list)
#prob_true, prob_false = clf3.predict_proba(feat_list).T
clf1 = svm.LinearSVC()
clf1.fit(score_list, lbl_list)
# Score new annots against the training database
tup_ = get_toy_annots(num_annots * 2, num_names, initial_aids=all_aids, initial_nids=all_nids)
aids, nids, aids1, nids1, all_aids, all_nids = tup_
aid2_nid = dict(zip(aids, nids))
toclass_features = [annot_to_class_feats2(aid, aid2_nid) for aid in aids]
aidnid_pairs = np.vstack(ut.get_list_column(toclass_features, 0))
feat_list = np.vstack(ut.get_list_column(toclass_features, 1))
lbl_list = np.array([aid2_nid[aid] == nid for aid, nid in aidnid_pairs])
print('Running tests')
score_list = feat_list.T[0:1].T
tp_feat_list = feat_list[lbl_list]
tn_feat_list = feat_list[~lbl_list]
tp_lbls = lbl_list[lbl_list]
tn_lbls = lbl_list[~lbl_list]
print('num tp: %d' % len(tp_lbls))
print('num fp: %d' % len(tn_lbls))
tp_score_list = score_list[lbl_list]
tn_score_list = score_list[~lbl_list]
print('tp_feat' + ut.repr3(ut.get_stats(tp_feat_list, axis=0), precision=2))
print('tp_feat' + ut.repr3(ut.get_stats(tn_feat_list, axis=0), precision=2))
print('tp_score' + ut.repr2(ut.get_stats(tp_score_list), precision=2))
print('tp_score' + ut.repr2(ut.get_stats(tn_score_list), precision=2))
tp_pred3 = clf3.predict(tp_feat_list)
tn_pred3 = clf3.predict(tn_feat_list)
print((tp_pred3.sum(), tp_pred3.shape))
print((tn_pred3.sum(), tn_pred3.shape))
tp_score3 = clf3.score(tp_feat_list, tp_lbls)
tn_score3 = clf3.score(tn_feat_list, tn_lbls)
tp_pred1 = clf1.predict(tp_score_list)
tn_pred1 = clf1.predict(tn_score_list)
print((tp_pred1.sum(), tp_pred1.shape))
print((tn_pred1.sum(), tn_pred1.shape))
tp_score1 = clf1.score(tp_score_list, tp_lbls)
tn_score1 = clf1.score(tn_score_list, tn_lbls)
print('tp score with rank = %r' % (tp_score3,))
print('tn score with rank = %r' % (tn_score3,))
print('tp score without rank = %r' % (tp_score1,))
print('tn score without rank = %r' % (tn_score1,))
toy_data = {}
return toy_data
[docs]def get_toy_annots(num_annots, num_names=None, initial_aids=None, initial_nids=None, nid_sequence=None, seed=None):
r"""
Args:
num_annots (int):
num_names (int): (default = None)
initial_aids (None): (default = None)
initial_nids (None): (default = None)
nid_sequence (None): (default = None)
seed (None): (default = None)
Returns:
tuple: (aids, nids, aids1, nids1, all_aids, all_nids)
CommandLine:
python -m ibeis.algo.hots.demobayes --exec-get_toy_annots
Example:
>>> # DISABLE_DOCTEST
>>> from ibeis.algo.hots.demobayes import * # NOQA
>>> num_annots = 1
>>> num_names = 5
>>> initial_aids = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=np.int64)
>>> initial_nids = np.array([0, 0, 1, 2, 2, 1, 1, 1, 2, 3], dtype=np.int64)
>>> nid_sequence = np.array([0, 0, 1, 2, 2, 1, 1], dtype=np.int64)
>>> seed = 0
>>> (aids, nids, aids1, nids1, all_aids, all_nids) = get_toy_annots(num_annots, num_names, initial_aids, initial_nids, nid_sequence, seed)
>>> result = ('(aids, nids, aids1, nids1, all_aids, all_nids) = %s' % (ut.repr2((aids, nids, aids1, nids1, all_aids, all_nids), nl=1),))
>>> print(result)
"""
import vtool as vt
if num_names is None:
num_names = num_annots
print('Generating toy data with num_annots=%r' % (num_annots,))
if initial_aids is None:
assert initial_nids is None
first_step = True
initial_aids = []
initial_nids = []
else:
first_step = False
assert initial_nids is not None
aids = np.arange(len(initial_aids), num_annots + len(initial_aids))
rng = vt.ensure_rng(seed)
if nid_sequence is None:
nids = rng.randint(0, num_names, num_annots)
else:
unused_from_sequence = max(len(nid_sequence) - len(initial_aids), 0)
if unused_from_sequence == 0:
nids = rng.randint(0, num_names, num_annots)
elif unused_from_sequence > 0 and unused_from_sequence < num_annots:
num_remain = num_annots - unused_from_sequence
nids = np.append(nid_sequence[-unused_from_sequence:], rng.randint(0, num_names, num_remain))
else:
nids = nid_sequence[-unused_from_sequence]
nids = np.array(ut.take(nid_sequence, range(len(initial_aids), len(initial_aids) + num_annots)))
if first_step:
aids1 = aids
nids1 = nids
else:
aids1 = initial_aids
nids1 = initial_nids
all_nids = np.append(initial_nids, nids)
all_aids = np.append(initial_aids, aids)
import utool
with utool.embed_on_exception_context:
ut.assert_eq(len(aids), len(nids), 'len new')
ut.assert_eq(len(aids1), len(nids1), 'len comp')
ut.assert_eq(len(all_aids), len(all_nids), 'len all')
return aids, nids, aids1, nids1, all_aids, all_nids
toy_params = {
True: {'mu': 1.5, 'sigma': 3.0},
False: {'mu': 0.5, 'sigma': .4}
#True: {'mu': 3.5, 'sigma': 1.1},
#False: {'mu': .3, 'sigma': .7}
#'p': .7},
#'p': .2}
}
#@ut.cached_func('_toy_bayes_data3')
[docs]def get_toy_data_1v1(num_annots=5, num_names=None, **kwargs):
r"""
CommandLine:
python -m ibeis.algo.hots.demobayes --exec-get_toy_data_1v1 --show
Example:
>>> # ENABLE_DOCTEST
>>> from ibeis.algo.hots.demobayes import * # NOQA
>>> toy_data = get_toy_data_1v1()
>>> ut.quit_if_noshow()
>>> import plottool as pt
>>> show_toy_distributions(toy_data['toy_params'])
>>> ut.show_if_requested()
Example1:
>>> # ENABLE_DOCTEST
>>> from ibeis.algo.hots.demobayes import * # NOQA
>>> toy_data = get_toy_data_1v1()
>>> kwargs = {}
>>> initial_aids = toy_data['aids']
>>> initial_nids = toy_data['nids']
>>> num_annots = 1
>>> num_names = 6
>>> toy_data2 = get_toy_data_1v1(num_annots, num_names, initial_aids=initial_aids, initial_nids=initial_nids)
>>> ut.quit_if_noshow()
>>> import plottool as pt
>>> show_toy_distributions(toy_data['toy_params'])
>>> ut.show_if_requested()
Ignore:
>>> num_annots = 1000
>>> num_names = 400
"""
import vtool as vt
tup_ = get_toy_annots(num_annots, num_names, **kwargs)
aids, nids, aids1, nids1, all_aids, all_nids = tup_
rng = vt.ensure_rng(None)
def pairwise_feature(aidx1, aidx2, all_nids=all_nids, toy_params=toy_params):
if aidx1 == aidx2:
score = -1
else:
#rng = np.random.RandomState(int((aidx1 + 13) * (aidx2 + 13)))
nid1 = all_nids[int(aidx1)]
nid2 = all_nids[int(aidx2)]
params = toy_params[nid1 == nid2]
mu, sigma = ut.dict_take(params, ['mu', 'sigma'])
score_ = rng.normal(mu, sigma)
score = np.clip(score_, 0, np.inf)
return score
pairwise_nids = list([tup[::-1] for tup in ut.iprod(nids, nids1)])
pairwise_matches = np.array(
[nid1 == nid2 for nid1, nid2 in pairwise_nids])
pairwise_aidxs = list([tup[::-1] for tup in ut.iprod(aids, aids1)])
pairwise_features = np.array(
[pairwise_feature(aidx1, aidx2) for aidx1, aidx2 in pairwise_aidxs])
#pairwise_scores_mat = pairwise_scores.reshape(num_annots, num_annots)
is_diag = [r < c for r, c, in pairwise_aidxs]
diag_scores = pairwise_features.compress(is_diag)
diag_aidxs = ut.compress(pairwise_aidxs, is_diag)
import utool
with utool.embed_on_exception_context:
diag_nids = ut.compress(pairwise_nids, is_diag)
diag_labels = pairwise_matches.compress(is_diag)
#import utool
#utool.embed()
toy_data = {
'aids': aids,
'nids': nids,
'all_nids': all_nids,
'all_aids': all_aids,
#'pairwise_aidxs': pairwise_aidxs,
#'pairwise_scores': pairwise_scores,
#'pairwise_matches': pairwise_matches,
'diag_labels': diag_labels,
'diag_scores': diag_scores,
'diag_nids': diag_nids,
'diag_aidxs': diag_aidxs,
'toy_params': toy_params,
}
return toy_data
@ut.cached_func('_toy_learn_prob_score5')
[docs]def learn_prob_score(num_scores=5, pad=55, ret_enc=False, use_cache=None):
r"""
Args:
num_scores (int): (default = 5)
Returns:
tuple: (discr_domain, discr_p_same)
CommandLine:
python -m ibeis.algo.hots.demobayes --exec-learn_prob_score --show
Example:
>>> # ENABLE_DOCTEST
>>> from ibeis.algo.hots.demobayes import * # NOQA
>>> num_scores = 2
>>> (discr_domain, discr_p_same, encoder) = learn_prob_score(num_scores, ret_enc=True, use_cache=False)
>>> print('discr_p_same = %r' % (discr_p_same,))
>>> ut.quit_if_noshow()
>>> import plottool as pt
>>> encoder.visualize()
>>> ut.show_if_requested()
"""
num_annots_train = 200
num_names_train = 5
toy_data = get_toy_data_1v1(num_annots_train, num_names_train)
#pairwise_aidxs, pairwise_scores, pairwise_matches = ut.dict_take(
# toy_data, 'pairwise_aidxs, pairwise_scores, pairwise_matches'.split(', '))
diag_scores, diag_labels = ut.dict_take(
toy_data, 'diag_scores, diag_labels'.split(', '))
#is_diag = [r < c for r, c, in pairwise_aidxs]
#diag_scores = pairwise_scores.compress(is_diag)
#diag_labels = pairwise_matches.compress(is_diag)
# Learn P(S_{ij} | M_{ij})
import vtool as vt
encoder = vt.ScoreNormalizer(
reverse=True, monotonize=True,
adjust=4,
)
encoder.fit(X=diag_scores, y=diag_labels, verbose=True)
if False:
import plottool as pt
pt.ensure_pylab_qt4()
encoder.visualize()
#show_toy_distributions()
def discretize_probs(encoder):
p_tp_given_score = encoder.p_tp_given_score / encoder.p_tp_given_score.sum()
bins = len(p_tp_given_score) - (pad * 2)
stride = int(np.ceil(bins / num_scores))
idxs = np.arange(0, bins, stride) + pad
discr_p_same = p_tp_given_score.take(idxs)
discr_p_same = discr_p_same / discr_p_same.sum()
discr_domain = encoder.score_domain.take(idxs)
return discr_domain, discr_p_same
discr_domain, discr_p_same = discretize_probs(encoder)
if ret_enc:
return discr_domain, discr_p_same, encoder
return discr_domain, discr_p_same
[docs]def classify_one_new_unknown():
r"""
Make a model that knows who the previous annots are and tries to classify a new annot
CommandLine:
python -m ibeis.algo.hots.demobayes --exec-classify_one_new_unknown --verbose
python -m ibeis.algo.hots.demobayes --exec-classify_one_new_unknown --show --verbose --present
python3 -m ibeis.algo.hots.demobayes --exec-classify_one_new_unknown --verbose
python3 -m ibeis.algo.hots.demobayes --exec-classify_one_new_unknown --verbose --diskshow --verbose --present --save demo5.png --dpath . --figsize=20,10 --dpi=128 --clipwhite
Example:
>>> # DISABLE_DOCTEST
>>> from ibeis.algo.hots.demobayes import * # NOQA
>>> result = classify_one_new_unknown()
>>> ut.show_if_requested()
"""
if False:
constkw = dict(
num_annots=5, num_names=3,
name_evidence=[0]
#name_evidence=[0, 0, 1, 1, None],
#name_evidence=[{0: .99}, {0: .99}, {1: .99}, {1: .99}, None],
#name_evidence=[0, {0: .99}, {1: .99}, 1, None],
)
test_model(score_evidence=[1, 0, 0, 0, 0, 1], mode=1, **constkw)
#from ibeis.algo.hots.demobayes import *
constkw = dict(
num_annots=4, num_names=4,
)
model, evidence = test_model(
mode=1,
# lll and llh have strikingly different
# probability of M marginals
score_evidence=[0, 0, 1],
other_evidence={
},
**constkw)
[docs]def test_triangle_property():
r"""
CommandLine:
python -m ibeis.algo.hots.demobayes --exec-test_triangle_property --show
Example:
>>> # DISABLE_DOCTEST
>>> from ibeis.algo.hots.demobayes import * # NOQA
>>> result = test_triangle_property()
>>> ut.show_if_requested()
"""
constkw = dict(
num_annots=3, num_names=3,
name_evidence=[],
)
test_model(
mode=1,
other_evidence={
'Mab': False,
'Mac': False,
#'Na': 'fred',
#'Nb': 'sue',
},
**constkw)
[docs]def demo_structure():
r"""
CommandLine:
python -m ibeis.algo.hots.demobayes --exec-demo_structure --show
Example:
>>> # DISABLE_DOCTEST
>>> from ibeis.algo.hots.demobayes import * # NOQA
>>> result = demo_structure()
>>> ut.show_if_requested()
"""
constkw = dict(score_evidence=[], name_evidence=[], mode=3)
model, = test_model(num_annots=4, num_names=4, **constkw)
draw_tree_model(model)
[docs]def make_bayes_notebook():
r"""
CommandLine:
python -m ibeis.algo.hots.demobayes --exec-make_bayes_notebook
Example:
>>> # DISABLE_DOCTEST
>>> from ibeis.algo.hots.demobayes import * # NOQA
>>> result = make_bayes_notebook()
>>> print(result)
"""
from ibeis.templates import generate_notebook
initialize = ut.codeblock(
r'''
# STARTBLOCK
import os
os.environ['UTOOL_NO_CNN'] = 'True'
from ibeis.algo.hots.demobayes import * # NOQA
# Matplotlib stuff
import matplotlib as mpl
%matplotlib inline
%load_ext autoreload
%autoreload
from IPython.core.display import HTML
HTML("<style>body .container { width:99% !important; }</style>")
# ENDBLOCK
'''
)
cell_list_def = [
initialize,
show_model_templates,
demo_modes,
demo_name_annot_complexity,
###demo_model_idependencies,
demo_single_add,
demo_ambiguity,
demo_conflicting_evidence,
demo_annot_idependence_overlap,
]
def format_cell(cell):
if ut.is_funclike(cell):
header = '# ' + ut.to_title_caps(ut.get_funcname(cell))
code = (header, ut.get_func_sourcecode(cell, stripdef=True, stripret=True))
else:
code = (None, cell)
return generate_notebook.format_cells(code)
cell_list = ut.flatten([format_cell(cell) for cell in cell_list_def])
nbstr = generate_notebook.make_notebook(cell_list)
print('nbstr = %s' % (nbstr,))
fpath = 'demobayes.ipynb'
ut.writeto(fpath, nbstr)
ut.startfile(fpath)
[docs]def show_model_templates():
r"""
CommandLine:
python -m ibeis.algo.hots.demobayes --exec-show_model_templates
Example:
>>> # DISABLE_DOCTEST
>>> from ibeis.algo.hots.demobayes import * # NOQA
>>> result = show_model_templates()
>>> ut.show_if_requested()
"""
make_name_model(2, 2, verbose=True, mode=1)
print('-------------')
make_name_model(2, 2, verbose=True, mode=2)
[docs]def demo_single_add():
"""
This demo shows how a name is assigned to a new annotation.
CommandLine:
python -m ibeis.algo.hots.demobayes --exec-demo_single_add --show --present --mode=1
Example:
>>> # DISABLE_DOCTEST
>>> from ibeis.algo.hots.demobayes import * # NOQA
>>> demo_single_add()
>>> ut.show_if_requested()
"""
# Initially there are only two annotations that have a strong match
name_evidence = [{0: .9}] # Soft label
name_evidence = [0] # Hard label
test_model(num_annots=2, num_names=5, score_evidence=[1], name_evidence=name_evidence)
# Adding a new annotation does not change the original probabilites
test_model(num_annots=3, num_names=5, score_evidence=[1], name_evidence=name_evidence)
# Adding evidence that Na matches Nc does not influence the probability
# that Na matches Nb. However the probability that Nb matches Nc goes up.
test_model(num_annots=3, num_names=5, score_evidence=[1, 1], name_evidence=name_evidence)
# However, once Nb is scored against Nb that does increase the likelihood
# that all 3 are fred goes up significantly.
test_model(num_annots=3, num_names=5, score_evidence=[1, 1, 1],
name_evidence=name_evidence)
[docs]def demo_conflicting_evidence():
"""
Notice that the number of annotations in the graph does not affect the
probability of names.
"""
# Initialized with two annots. Each are pretty sure they are someone else
constkw = dict(num_annots=2, num_names=5, score_evidence=[])
test_model(name_evidence=[{0: .9}, {1: .9}], **constkw)
# Having evidence that they are different increases this confidence.
test_model(name_evidence=[{0: .9}, {1: .9}], other_evidence={'Sab': 0}, **constkw)
# However,, confusion is introduced if there is evidence that they are the same
test_model(name_evidence=[{0: .9}, {1: .9}], other_evidence={'Sab': 1}, **constkw)
# When Na is forced to be fred, this doesnt change Nbs evaulatation by more
# than a few points
test_model(name_evidence=[0, {1: .9}], other_evidence={'Sab': 1}, **constkw)
[docs]def demo_ambiguity():
r"""
Test what happens when an annotation need to choose between one of two
names
CommandLine:
python -m ibeis.algo.hots.demobayes --exec-demo_ambiguity --show --verbose --present
Example:
>>> # DISABLE_DOCTEST
>>> from ibeis.algo.hots.demobayes import * # NOQA
>>> result = demo_ambiguity()
>>> ut.show_if_requested()
"""
constkw = dict(
num_annots=3, num_names=3,
name_evidence=[0],
#name_evidence=[],
#name_evidence=[{0: '+eps'}, {1: '+eps'}, {2: '+eps'}],
)
test_model(score_evidence=[0, 0, 1], mode=1,
**constkw)
[docs]def demo_annot_idependence_overlap():
r"""
Given:
* an unknown annotation \d
* three annots with the same name (Fred) \a, \b, and \c
* \a and \b are near duplicates
* (\a and \c) / (\b and \c) are novel views
Goal:
* If \d matches to \a and \b the probably that \d is Fred should not be
much more than if \d matched only \a or only \b.
* The probability that \d is Fred given it matches to any of the 3 annots
alone should be equal
P(\d is Fred | Mad=1) = P(\d is Fred | Mbd=1) = P(\d is Fred | Mcd=1)
* The probability that \d is fred given two matches to any of those two annots
should be greater than the probability given only one.
P(\d is Fred | Mad=1, Mbd=1) > P(\d is Fred | Mad=1)
P(\d is Fred | Mad=1, Mcd=1) > P(\d is Fred | Mad=1)
* The probability that \d is fred given matches to two near duplicate
matches should be less than
if \d matches two non-duplicate matches.
P(\d is Fred | Mad=1, Mcd=1) > P(\d is Fred | Mad=1, Mbd=1)
* The probability that \d is fred given two near duplicates should be only epsilon greater than
a match to either one individually.
P(\d is Fred | Mad=1, Mbd=1) = P(\d is Fred | Mad=1) + \epsilon
Method:
We need to model the fact that there are other causes that create the
effect of a high score. Namely, near duplicates.
This can be done by adding an extra conditional that score depends on
if they match as well as if they are near duplicates.
P(S_ij | Mij) --> P(S_ij | Mij, Dij)
where
Dij is a random variable indicating if the image is a near duplicate.
We can model this as an independant variable
P(Dij) = {True: .5, False: .5}
or as depending on if the names match.
P(Dij | Mij) = {'same': {True: .5, False: .5} diff: {True: 0, False 1}}
CommandLine:
python -m ibeis.algo.hots.demobayes --exec-demo_annot_idependence_overlap --verbose --present --show
Example:
>>> # DISABLE_DOCTEST
>>> from ibeis.algo.hots.demobayes import * # NOQA
>>> result = demo_annot_idependence_overlap()
>>> ut.show_if_requested()
"""
# We will end up making annots a and b fred and c and d sue
constkw = dict(
num_annots=4, num_names=4,
name_evidence=[{0: '+eps'}, {1: '+eps'}, {2: '+eps'}, {3: '+eps'}],
#name_evidence=[{0: .9}, None, None, {1: .9}]
#name_evidence=[0, None, None, None]
#name_evidence=[0, None, None, None]
)
test_model(score_evidence=[1, 1, 1, None, None, None], **constkw)
test_model(score_evidence=[1, 1, 0, None, None, None], **constkw)
test_model(score_evidence=[1, 0, 0, None, None, None], **constkw)
[docs]def demo_modes():
"""
Look at the last result of the different names demo under differet modes
"""
constkw = dict(
num_annots=4, num_names=8,
score_evidence=[1, 0, 0, 0, 0, 1],
#name_evidence=[{0: .9}, None, None, {1: .9}],
#name_evidence=[0, None, None, 1],
name_evidence=[0, None, None, None],
#other_evidence={
# 'Sad': 0,
# 'Sab': 1,
# 'Scd': 1,
# 'Sac': 0,
# 'Sbc': 0,
# 'Sbd': 0,
#}
)
# The first mode uses a hidden Match layer
test_model(mode=1, **constkw)
# The second mode directly maps names to scores
test_model(mode=2, **constkw)
test_model(mode=3, noquery=True, **constkw)
test_model(mode=4, noquery=True, **constkw)
[docs]def demo_name_annot_complexity():
"""
This demo is meant to show the structure of the graph as more annotations
and names are added.
CommandLine:
python -m ibeis.algo.hots.demobayes --exec-demo_name_annot_complexity --show
Example:
>>> # DISABLE_DOCTEST
>>> from ibeis.algo.hots.demobayes import * # NOQA
>>> demo_name_annot_complexity()
>>> ut.show_if_requested()
"""
constkw = dict(score_evidence=[], name_evidence=[], mode=1)
# Initially there are 2 annots and 4 names
model, = test_model(num_annots=2, num_names=4, **constkw)
draw_tree_model(model)
# Adding a name causes the probability of the other names to go down
model, = test_model(num_annots=2, num_names=5, **constkw)
draw_tree_model(model)
# Adding an annotation wihtout matches dos not effect probabilities of
# names
model, = test_model(num_annots=3, num_names=5, **constkw)
draw_tree_model(model)
model, = test_model(num_annots=4, num_names=10, **constkw)
draw_tree_model(model)
# Given A annots, the number of score nodes is (A ** 2 - A) / 2
model, = test_model(num_annots=5, num_names=5, **constkw)
draw_tree_model(model)
#model, = test_model(num_annots=6, num_names=5, score_evidence=[], name_evidence=[], mode=1)
#draw_tree_model(model)
[docs]def demo_model_idependencies():
"""
Independences of the 3 annot 3 name model
CommandLine:
python -m ibeis.algo.hots.demobayes --exec-demo_model_idependencies --mode=1 --num-names=2 --show
python -m ibeis.algo.hots.demobayes --exec-demo_model_idependencies --mode=2
Example:
>>> # DISABLE_DOCTEST
>>> from ibeis.algo.hots.demobayes import * # NOQA
>>> result = demo_model_idependencies()
>>> print(result)
>>> ut.show_if_requested()
"""
num_names = ut.get_argval('--num-names', default=3)
model = test_model(num_annots=num_names, num_names=num_names, score_evidence=[], name_evidence=[])[0]
# This model has the following independenceis
idens = model.get_independencies()
iden_strs = [', '.join(sorted(iden.event1)) +
' _L ' +
','.join(sorted(iden.event2)) +
' | ' +
', '.join(sorted(iden.event3))
for iden in idens.independencies]
print('general idependencies')
print(ut.align(ut.align('\n'.join(sorted(iden_strs)), '_'), '|'))
#ut.embed()
#model.is_active_trail('Na', 'Nb', 'Sab')
# Might not be valid, try and collapse S and M
#xs = list(map(str, idens.independencies))
#import re
#xs = [re.sub(', M..', '', x) for x in xs]
#xs = [re.sub('M..,?', '', x) for x in xs]
#xs = [x for x in xs if not x.startswith('( _')]
#xs = [x for x in xs if not x.endswith('| )')]
#print('\n'.join(sorted(list(set(xs)))))
if __name__ == '__main__':
r"""
CommandLine:
python -m ibeis.algo.hots.demobayes
python -m ibeis.algo.hots.demobayes --allexamples
"""
if ut.VERBOSE:
print('[hs] demobayes')
import multiprocessing
multiprocessing.freeze_support() # for win32
import utool as ut # NOQA
ut.doctest_funcs()