Return a dot language specification of a graph which describes the relationship between hyperparameters. Each hyperparameter within the pyll expression `expr` is represented by a rectangular node, and each value of each choice node that creates a conditional variable in the sear
(expr)
| 12 | |
| 13 | |
| 14 | def dot_hyperparameters(expr): |
| 15 | """ |
| 16 | Return a dot language specification of a graph which describes the |
| 17 | relationship between hyperparameters. Each hyperparameter within the |
| 18 | pyll expression `expr` is represented by a rectangular node, and |
| 19 | each value of each choice node that creates a conditional variable |
| 20 | in the search space is represented by an elliptical node. |
| 21 | |
| 22 | The direction of the arrows corresponds to the sequence of events |
| 23 | in an ancestral sampling process. |
| 24 | |
| 25 | E.g.: |
| 26 | >>> open('foo.dot', 'w').write(dot_hyperparameters(search_space())) |
| 27 | |
| 28 | Then later from the shell, type e.g. |
| 29 | dot -Tpng foo.dot > foo.png && eog foo.png |
| 30 | |
| 31 | Graphviz has other tools too: http://www.graphviz.org |
| 32 | |
| 33 | """ |
| 34 | conditions = () |
| 35 | hps = {} |
| 36 | expr_to_config(expr, conditions, hps) |
| 37 | rval = io.StringIO() |
| 38 | print("digraph {", file=rval) |
| 39 | edges = set() |
| 40 | |
| 41 | def var_node(a): |
| 42 | print('"%s" [ shape=box];' % a, file=rval) |
| 43 | |
| 44 | def cond_node(a): |
| 45 | print('"%s" [ shape=ellipse];' % a, file=rval) |
| 46 | |
| 47 | def edge(a, b): |
| 48 | text = f'"{a}" -> "{b}";' |
| 49 | if text not in edges: |
| 50 | print(text, file=rval) |
| 51 | edges.add(text) |
| 52 | |
| 53 | for hp, dct in list(hps.items()): |
| 54 | # create the node |
| 55 | var_node(hp) |
| 56 | |
| 57 | # create an edge from anything it depends on |
| 58 | for and_conds in dct["conditions"]: |
| 59 | if len(and_conds) > 1: |
| 60 | parent_label = " & ".join( |
| 61 | ["%(name)s%(op)s%(val)s" % cond.__dict__ for cond in and_conds] |
| 62 | ) |
| 63 | cond_node(parent_label) |
| 64 | edge(parent_label, hp) |
| 65 | for cond in and_conds: |
| 66 | sub_parent_label = f"{cond.name}{cond.op}{cond.val}" |
| 67 | cond_node(sub_parent_label) |
| 68 | edge(cond.name, sub_parent_label) |
| 69 | edge(sub_parent_label, parent_label) |
| 70 | elif len(and_conds) == 1: |
| 71 | parent_label = "{}{}{}".format( |
nothing calls this directly
no test coverage detected