diff --git a/app.py b/app.py index 7ccf049fa4807a8556feb52d9f0a09f4f8cff634..bb9a5c6ec252470a66df79137cf6ce4913a00101 100644 --- a/app.py +++ b/app.py @@ -1,15 +1,88 @@ # Run this app with `python app.py` and # visit http://127.0.0.1:8050/ in your web browser. -from pages.layout import create_layout - import dash import json +from dash import dcc +from dash import html +from dash import dcc, html, Input, Output +import dash_bootstrap_components as dbc + +from pages.application.layout_application import Model, View +''' +Loading data +''' models_data = open('data_retriever.json') -data = json.load(models_data) +data = json.load(models_data)["data"] + +app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP]) + + + + + +''' +Construction of the layout +''' +model = Model(data) +view = View(model) +tabs = dcc.Tabs([ + dcc.Tab(label='Course on Explainable AI', children=[]), + view.tab, +]) + +app.layout = html.Div([ + html.H1('FXToolKit'), + tabs]) + + + + + + + +''' +Callback for the app +''' +@app.callback( + Output('ml_datasets_choice', 'options'), + Output('ml_instances_choice', 'options'), + Output('graph', 'children'), + Output('explanation', 'children'), + Input('ml_model_choice', 'value'), + Input('ml_datasets_choice', 'value'), + Input('ml_instances_choice', 'value'), + prevent_initial_call=True +) +def update_ml_type(value_ml_model, value_dataset, value_instance): + + + ctx = dash.callback_context + if ctx.triggered: + dropdown_id = ctx.triggered[0]['prop_id'].split('.')[0] + if dropdown_id == 'ml_model_choice' : + model.update_ml_model(value_ml_model) + return model.datasets, [], "", "" + + elif dropdown_id == 'ml_datasets_choice': + + model.update_dataset(value_dataset) + view.update_dataset() + return model.datasets, model.instances, view.component.network, "" + + elif dropdown_id == 'ml_instances_choice' : + + model.update_instance(value_instance) + view.update_instance() + return model.datasets, model.instances, view.component.network, view.component.explanation + + + + -app = dash.Dash(__name__) +''' +Launching app +''' if __name__ == '__main__': - app.layout = create_layout(data) app.run_server(debug=True) \ No newline at end of file diff --git a/data_retriever.json b/data_retriever.json index 059c84316194bc10747b5659c377c89bea1564fe..986722fc275d24567f6250e02e45ce4cb11eb509 100644 --- a/data_retriever.json +++ b/data_retriever.json @@ -5,8 +5,15 @@ "ml_type" : "DecisionTree", "trained_models" : "pages/application/DecisionTree/trained_models", "instances" : "pages/application/DecisionTree/instances/", - "explicability_algorithm" : "pages/application/DecisionTree/decision_tree_explicability", + "map" : "pages/application/DecisionTree/map/", "component" : "DecisionTreeComponent" + }, + { + "ml_type" : "NaiveBayes", + "trained_models" : "pages/application/NaiveBayes/trained_models", + "instances" : "pages/application/NaiveBayes/instances/", + "map" : "pages/application/NaiveBayes/map/", + "component" : "NaiveBayesComponent" } ] diff --git a/pages/__pycache__/layout.cpython-38.pyc b/pages/__pycache__/layout.cpython-38.pyc deleted file mode 100644 index 7eafe19fdf636c56577100fc7a56db2e308501d6..0000000000000000000000000000000000000000 Binary files a/pages/__pycache__/layout.cpython-38.pyc and /dev/null differ diff --git a/pages/application/DecisionTree/DecisionTreeComponent.py b/pages/application/DecisionTree/DecisionTreeComponent.py index 1aa75316655d76f73fa1e8614efb44d2e5ef2a2c..bfdc1aa9a06d25a788002edaec2f9537e3f6a52f 100644 --- a/pages/application/DecisionTree/DecisionTreeComponent.py +++ b/pages/application/DecisionTree/DecisionTreeComponent.py @@ -1,18 +1,35 @@ from dash import dcc, html, Input, Output, callback -from pages.application.DecisionTree.utils.dtviz import visualize +from pages.application.DecisionTree.utils.dtviz import visualize, visualize_instance from pages.application.DecisionTree.utils.dtree import DecisionTree +import dash_interactive_graphviz class DecisionTreeComponent(): - def __init__(self): + def __init__(self, dataset): - self.network = html.Img() + map = "pages/application/DecisionTree/map/"+ dataset + "/" + dataset + ".map" - def update(self, dataset) : - print(dataset) - dt = DecisionTree(from_file = "pages/application/DecisionTree/trained_models/"+dataset+'/'+dataset+".dt") - visualize(dt, "svg", "pages/application/component.svg") - self.network = html.Img(src="pages/application/component.svg") + self.dt = DecisionTree(from_file = "pages/application/DecisionTree/trained_models/"+dataset+'/'+dataset+".dt", mapfile = map) + dot_source = visualize(self.dt) - def update_with_explicability(self, instance) : - self.network = self.network \ No newline at end of file + self.network = dash_interactive_graphviz.DashInteractiveGraphviz( + dot_source=dot_source + ) + + self.explanation = dcc.Textarea(value = "", style = { "font_size" : "15px", + "width": "40rem", + "height": "40rem", + "margin-bottom": "5rem", + "background-color": "#f8f9fa", + }) + + def update_with_explicability(self, dataset, instance) : + instance = open("pages/application/DecisionTree/instances/"+ dataset + "/" + instance, "r") + instance = str(instance.read()).strip().split(',') + + dot_source = visualize_instance(self.dt, instance) + self.network = dash_interactive_graphviz.DashInteractiveGraphviz( + dot_source=dot_source + ) + + self.explanation.value = self.dt.explain(instance) diff --git a/pages/application/DecisionTree/__pycache__/DecisionTreeComponent.cpython-38.pyc b/pages/application/DecisionTree/__pycache__/DecisionTreeComponent.cpython-38.pyc deleted file mode 100644 index f5252efad4cc8643fff3886e9cf6c5e95f5a45f9..0000000000000000000000000000000000000000 Binary files a/pages/application/DecisionTree/__pycache__/DecisionTreeComponent.cpython-38.pyc and /dev/null differ diff --git a/pages/application/DecisionTree/map/australian/ITI/australian.map b/pages/application/DecisionTree/map/australian/australian.map similarity index 100% rename from pages/application/DecisionTree/map/australian/ITI/australian.map rename to pages/application/DecisionTree/map/australian/australian.map diff --git a/pages/application/DecisionTree/map/cancer/ITI/cancer.map b/pages/application/DecisionTree/map/cancer/cancer.map similarity index 100% rename from pages/application/DecisionTree/map/cancer/ITI/cancer.map rename to pages/application/DecisionTree/map/cancer/cancer.map diff --git a/pages/application/DecisionTree/map/car/ITI/car.map b/pages/application/DecisionTree/map/car/car.map similarity index 100% rename from pages/application/DecisionTree/map/car/ITI/car.map rename to pages/application/DecisionTree/map/car/car.map diff --git a/pages/application/DecisionTree/utils/__pycache__/_fileio.cpython-38.pyc b/pages/application/DecisionTree/utils/__pycache__/_fileio.cpython-38.pyc deleted file mode 100644 index 7cbc69f32333697f6146d5270c0652e8d7410e9a..0000000000000000000000000000000000000000 Binary files a/pages/application/DecisionTree/utils/__pycache__/_fileio.cpython-38.pyc and /dev/null differ diff --git a/pages/application/DecisionTree/utils/__pycache__/dtree.cpython-38.pyc b/pages/application/DecisionTree/utils/__pycache__/dtree.cpython-38.pyc deleted file mode 100644 index 94a4fc9fd19d1416fbac2d2b8582f1ad6d77b472..0000000000000000000000000000000000000000 Binary files a/pages/application/DecisionTree/utils/__pycache__/dtree.cpython-38.pyc and /dev/null differ diff --git a/pages/application/DecisionTree/utils/__pycache__/dtviz.cpython-38.pyc b/pages/application/DecisionTree/utils/__pycache__/dtviz.cpython-38.pyc deleted file mode 100644 index 0ad57d58fe6e5a6d997f8691f57169a46e1f1829..0000000000000000000000000000000000000000 Binary files a/pages/application/DecisionTree/utils/__pycache__/dtviz.cpython-38.pyc and /dev/null differ diff --git a/pages/application/DecisionTree/utils/dtree.py b/pages/application/DecisionTree/utils/dtree.py index 32adfdecc02d118c08a87c64c0c149f15b6e9164..fd881ee0c9086a1c293e51f80bff700d6ccd19f0 100644 --- a/pages/application/DecisionTree/utils/dtree.py +++ b/pages/application/DecisionTree/utils/dtree.py @@ -351,8 +351,7 @@ class DecisionTree(): # returning the set of sets with no duplicates return list(dict.fromkeys(sets)) - def explain(self, inst, enum=1, pathlits=False, solver='g3', xtype='abd', - htype='sorted'): + def explain(self, inst, enum=5, pathlits=False, solver='g3', htype='sorted'): """ Compute a given number of explanations. """ @@ -364,14 +363,16 @@ class DecisionTree(): else: # input expected by Yacine - 'value1,value2,...' inst = list(map(lambda i : tuple(['f{0}'.format(i[0]), int(i[1])]), [(i, j) for i,j in enumerate(inst)])) - + print(inst) inst_orig = inst[:] path, term, depth = self.execute(inst, pathlits) + print(path) + explanation = str(inst) + "\n \n" #print('c instance: IF {0} THEN class={1}'.format(' AND '.join([self.fvmap[p] for p in inst_orig]), term)) #print(term) - print('c instance: IF {0} THEN class={1}'.format(' AND '.join([self.fvmap[ inst_orig[self.feids[self.nodes[n].feat]] ] for n in path]), term)) - print('c path len:', depth) + explanation += 'c instance: IF {0} THEN class={1}'.format(' AND '.join([self.fvmap[ inst_orig[self.feids[self.nodes[n].feat]] ] for n in path]), term) + "\n" + explanation +='c path len:'+ str(depth)+ "\n \n \n" if self.ohmap.dir: f2v = {fv[0]: fv[1] for fv in inst} @@ -383,30 +384,34 @@ class DecisionTree(): # computing the sets to hit to_hit = self.prepare_sets(inst, term) - if xtype == 'abd': - self.enumerate_abductive(to_hit, enum, solver, htype, term) - else: - self.enumerate_contrastive(to_hit, term) + explanation += "Abductive explanation : " + "\n \n" + explanation += self.enumerate_abductive(to_hit, enum, solver, htype, term) + explanation += "Contrastive explanation : "+ "\n \n" + explanation += self.enumerate_contrastive(to_hit, term) + + return explanation def enumerate_abductive(self, to_hit, enum, solver, htype, term): """ Enumerate abductive explanations. """ - + explanation = "" with Hitman(bootstrap_with=to_hit, solver=solver, htype=htype) as hitman: expls = [] for i, expl in enumerate(hitman.enumerate(), 1): - print('c expl: IF {0} THEN class={1}'.format(' AND '.join([self.fvmap[p] for p in sorted(expl, key=lambda p: p[0])]), term)) + explanation += 'c expl: IF {0} THEN class={1}'.format(' AND '.join([self.fvmap[p] for p in sorted(expl, key=lambda p: p[0])]), term) + "\n" expls.append(expl) if i == enum: break - print('c nof expls:', i) - print('c min expl:', min([len(e) for e in expls])) - print('c max expl:', max([len(e) for e in expls])) - print('c avg expl: {0:.2f}'.format(sum([len(e) for e in expls]) / len(expls))) + explanation += 'c nof expls:' + str(i)+ "\n" + explanation += 'c min expl:'+ str( min([len(e) for e in expls]))+ "\n" + explanation += 'c max expl:'+ str( max([len(e) for e in expls]))+ "\n" + explanation += 'c avg expl: {0:.2f}'.format(sum([len(e) for e in expls]) / len(expls))+ "\n \n \n" + + return explanation def enumerate_contrastive(self, to_hit, term): """ @@ -424,14 +429,17 @@ class DecisionTree(): to_hit = [set(s) for s in to_hit] to_hit.sort(key=lambda s: len(s)) expls = list(reduce(process_set, to_hit, [])) - + explanation = "" for expl in expls: - print('c expl: IF {0} THEN class!={1}'.format(' OR '.join(['!{0}'.format(self.fvmap[p]) for p in sorted(expl, key=lambda p: p[0])]), term)) + explanation += 'c expl: IF {0} THEN class!={1}'.format(' OR '.join(['!{0}'.format(self.fvmap[p]) for p in sorted(expl, key=lambda p: p[0])]), term)+ "\n" + + + explanation +='c nof expls:'+ str(len(expls))+ "\n" + explanation +='c min expl:'+ str( min([len(e) for e in expls]))+ "\n" + explanation +='c max expl:'+ str( max([len(e) for e in expls]))+ "\n" + explanation +='c avg expl: {0:.2f}'.format(sum([len(e) for e in expls]) / len(expls))+ "\n" - print('c nof expls:', len(expls)) - print('c min expl:', min([len(e) for e in expls])) - print('c max expl:', max([len(e) for e in expls])) - print('c avg expl: {0:.2f}'.format(sum([len(e) for e in expls]) / len(expls))) + return explanation def execute_path(self, path): """ diff --git a/pages/application/DecisionTree/utils/dtviz.py b/pages/application/DecisionTree/utils/dtviz.py index bc91989025d05e69f8fc18e3df90d646ff296350..f91189dae4f976f8615e451051b62aff5a73303b 100755 --- a/pages/application/DecisionTree/utils/dtviz.py +++ b/pages/application/DecisionTree/utils/dtviz.py @@ -19,7 +19,7 @@ import sys # #============================================================================== -def visualize(dt, fmt, output): +def visualize(dt): """ Visualize a DT with graphviz. """ @@ -57,6 +57,67 @@ def visualize(dt, fmt, output): edge.attr['arrowsize'] = 0.8 # saving file + g.in_edges g.layout(prog='dot') - g.draw(path=output, format=fmt) + return(g.to_string()) +# +#============================================================================== +def visualize_instance(dt, instance): + """ + Visualize a DT with graphviz and plot the running instance. + """ + if '=' in instance[0]: + instance = list(map(lambda i: tuple([i[0], int(i[1])]), [i.split('=') for i in instance])) + + else: + instance = list(map(lambda i : tuple(['f{0}'.format(i[0]), int(i[1])]), [(i, j) for i,j in enumerate(instance)])) + + #path that follows the instance - colored in blue + path, term, depth = dt.execute(instance) + edges_instance = [] + for i in range (len(path)-1) : + edges_instance.append((path[i], path[i+1])) + edges_instance.append((path[-1],"term:"+term)) + + g = pygraphviz.AGraph(directed=True, strict=True) + g.edge_attr['dir'] = 'forward' + + g.graph_attr['rankdir'] = 'TB' + + # non-terminal nodes + for n in dt.nodes: + g.add_node(n, label='{0}\\n({1})'.format(dt.nodes[n].feat, n)) + node = g.get_node(n) + node.attr['shape'] = 'circle' + node.attr['fontsize'] = 13 + + # terminal nodes + for n in dt.terms: + g.add_node(n, label='{0}\\n({1})'.format(dt.terms[n], n)) + node = g.get_node(n) + node.attr['shape'] = 'square' + node.attr['fontsize'] = 13 + + # transitions + for n1 in dt.nodes: + for v in dt.nodes[n1].vals: + n2 = dt.nodes[n1].vals[v] + n2_type = g.get_node(n2).attr['shape'] + g.add_edge(n1, n2) + edge = g.get_edge(n1, n2) + if len(v) == 1: + edge.attr['label'] = dt.fvmap[tuple([dt.nodes[n1].feat, tuple(v)[0]])] + else: + edge.attr['label'] = '{0}'.format('\n'.join([dt.fvmap[tuple([dt.nodes[n1].feat, val])] for val in tuple(v)])) + + #instance path in blue + if ((n1,n2) in edges_instance) or (n2_type=='square' and (n1, "term:"+ dt.terms[n2]) in edges_instance): + edge.attr['color'] = 'blue' + + edge.attr['fontsize'] = 10 + edge.attr['arrowsize'] = 0.8 + + # saving file + g.layout(prog='dot') + return(g.to_string()) diff --git a/pages/application/DecisionTree/decision_tree_explicability.py b/pages/application/NaiveBayes/NaiveBayesComponent.py similarity index 100% rename from pages/application/DecisionTree/decision_tree_explicability.py rename to pages/application/NaiveBayes/NaiveBayesComponent.py diff --git a/pages/application/__pycache__/layout_application.cpython-38.pyc b/pages/application/__pycache__/layout_application.cpython-38.pyc deleted file mode 100644 index 3d0fbeba535a0e13a76bce789577bdda2964becc..0000000000000000000000000000000000000000 Binary files a/pages/application/__pycache__/layout_application.cpython-38.pyc and /dev/null differ diff --git a/pages/application/__pycache__/utils_data.cpython-38.pyc b/pages/application/__pycache__/utils_data.cpython-38.pyc deleted file mode 100644 index 3ce531e0f54819e127c16fbc8130884baa58077d..0000000000000000000000000000000000000000 Binary files a/pages/application/__pycache__/utils_data.cpython-38.pyc and /dev/null differ diff --git a/pages/application/component.svg b/pages/application/component.svg deleted file mode 100644 index ad48872931ac0ffdedf08f04774f58c334916d86..0000000000000000000000000000000000000000 --- a/pages/application/component.svg +++ /dev/null @@ -1,467 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" - "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> -<!-- Generated by graphviz version 2.43.0 (0) - --> -<!-- Pages: 1 --> -<svg width="749pt" height="797pt" - viewBox="0.00 0.00 749.00 796.82" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> -<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 792.82)"> -<polygon fill="white" stroke="transparent" points="-4,4 -4,-792.82 745,-792.82 745,4 -4,4"/> -<!-- 1 --> -<g id="node1" class="node"> -<title>1</title> -<ellipse fill="none" stroke="black" cx="217" cy="-763.32" rx="25.5" ry="25.5"/> -<text text-anchor="middle" x="217" y="-766.92" font-family="Times,serif" font-size="13.00">f7</text> -<text text-anchor="middle" x="217" y="-752.92" font-family="Times,serif" font-size="13.00">(1)</text> -</g> -<!-- 2 --> -<g id="node2" class="node"> -<title>2</title> -<ellipse fill="none" stroke="black" cx="180" cy="-664" rx="27" ry="27"/> -<text text-anchor="middle" x="180" y="-667.6" font-family="Times,serif" font-size="13.00">f11</text> -<text text-anchor="middle" x="180" y="-653.6" font-family="Times,serif" font-size="13.00">(2)</text> -</g> -<!-- 1->2 --> -<g id="edge1" class="edge"> -<title>1->2</title> -<path fill="none" stroke="black" d="M208.23,-739.26C203.44,-726.66 197.44,-710.87 192.2,-697.1"/> -<polygon fill="black" stroke="black" points="194.68,-695.74 189.22,-689.25 189.44,-697.72 194.68,-695.74"/> -<text text-anchor="middle" x="213.5" y="-711.87" font-family="Times,serif" font-size="10.00">f7=0</text> -</g> -<!-- 9 --> -<g id="node3" class="node"> -<title>9</title> -<ellipse fill="none" stroke="black" cx="268" cy="-664" rx="25.5" ry="25.5"/> -<text text-anchor="middle" x="268" y="-667.6" font-family="Times,serif" font-size="13.00">f8</text> -<text text-anchor="middle" x="268" y="-653.6" font-family="Times,serif" font-size="13.00">(9)</text> -</g> -<!-- 1->9 --> -<g id="edge2" class="edge"> -<title>1->9</title> -<path fill="none" stroke="black" d="M228.57,-740.24C235.68,-726.67 244.87,-709.14 252.59,-694.41"/> -<polygon fill="black" stroke="black" points="255.24,-695.38 256.47,-686.99 250.28,-692.78 255.24,-695.38"/> -<text text-anchor="middle" x="257.5" y="-711.87" font-family="Times,serif" font-size="10.00">f7=1</text> -</g> -<!-- 3 --> -<g id="node4" class="node"> -<title>3</title> -<ellipse fill="none" stroke="black" cx="72" cy="-559.01" rx="25.5" ry="25.5"/> -<text text-anchor="middle" x="72" y="-562.61" font-family="Times,serif" font-size="13.00">f6</text> -<text text-anchor="middle" x="72" y="-548.61" font-family="Times,serif" font-size="13.00">(3)</text> -</g> -<!-- 2->3 --> -<g id="edge3" class="edge"> -<title>2->3</title> -<path fill="none" stroke="black" d="M160.94,-644.82C142.83,-627.55 115.53,-601.52 95.96,-582.86"/> -<polygon fill="black" stroke="black" points="97.87,-580.82 90.15,-577.32 94.01,-584.87 97.87,-580.82"/> -<text text-anchor="middle" x="148.5" y="-611.13" font-family="Times,serif" font-size="10.00">f11=3</text> -</g> -<!-- 6 --> -<g id="node5" class="node"> -<title>6</title> -<ellipse fill="none" stroke="black" cx="180" cy="-559.01" rx="25.5" ry="25.5"/> -<text text-anchor="middle" x="180" y="-562.61" font-family="Times,serif" font-size="13.00">f6</text> -<text text-anchor="middle" x="180" y="-548.61" font-family="Times,serif" font-size="13.00">(6)</text> -</g> -<!-- 2->6 --> -<g id="edge4" class="edge"> -<title>2->6</title> -<path fill="none" stroke="black" d="M180,-637.01C180,-623.56 180,-607.01 180,-592.7"/> -<polygon fill="black" stroke="black" points="182.8,-592.57 180,-584.57 177.2,-592.57 182.8,-592.57"/> -<text text-anchor="middle" x="195.5" y="-611.13" font-family="Times,serif" font-size="10.00">f11=2</text> -</g> -<!-- 10 --> -<g id="node6" class="node"> -<title>10</title> -<ellipse fill="none" stroke="black" cx="268" cy="-559.01" rx="31" ry="31"/> -<text text-anchor="middle" x="268" y="-562.61" font-family="Times,serif" font-size="13.00">f3</text> -<text text-anchor="middle" x="268" y="-548.61" font-family="Times,serif" font-size="13.00">(10)</text> -</g> -<!-- 9->10 --> -<g id="edge5" class="edge"> -<title>9->10</title> -<path fill="none" stroke="black" d="M268,-638.33C268,-626.4 268,-611.82 268,-598.48"/> -<polygon fill="black" stroke="black" points="270.8,-598.37 268,-590.37 265.2,-598.37 270.8,-598.37"/> -<text text-anchor="middle" x="280.5" y="-611.13" font-family="Times,serif" font-size="10.00">f8=0</text> -</g> -<!-- 23 --> -<g id="node7" class="node"> -<title>23</title> -<ellipse fill="none" stroke="black" cx="461" cy="-559.01" rx="31" ry="31"/> -<text text-anchor="middle" x="461" y="-562.61" font-family="Times,serif" font-size="13.00">f9</text> -<text text-anchor="middle" x="461" y="-548.61" font-family="Times,serif" font-size="13.00">(23)</text> -</g> -<!-- 9->23 --> -<g id="edge6" class="edge"> -<title>9->23</title> -<path fill="none" stroke="black" d="M290.14,-651.18C323.6,-633.33 387.34,-599.32 426.8,-578.27"/> -<polygon fill="black" stroke="black" points="428.14,-580.73 433.87,-574.49 425.49,-575.79 428.14,-580.73"/> -<text text-anchor="middle" x="383.5" y="-611.13" font-family="Times,serif" font-size="10.00">f8=1</text> -</g> -<!-- 4 --> -<g id="node8" class="node"> -<title>4</title> -<polygon fill="none" stroke="black" points="36,-467.79 0,-467.79 0,-431.79 36,-431.79 36,-467.79"/> -<text text-anchor="middle" x="18" y="-453.39" font-family="Times,serif" font-size="13.00">0</text> -<text text-anchor="middle" x="18" y="-439.39" font-family="Times,serif" font-size="13.00">(4)</text> -</g> -<!-- 3->4 --> -<g id="edge7" class="edge"> -<title>3->4</title> -<path fill="none" stroke="black" d="M55.85,-538.8C49.33,-530.34 42.15,-520.03 37,-509.9 31.55,-499.18 27.25,-486.58 24.12,-475.77"/> -<polygon fill="black" stroke="black" points="26.78,-474.88 21.96,-467.91 21.38,-476.37 26.78,-474.88"/> -<text text-anchor="middle" x="52.5" y="-501.9" font-family="Times,serif" font-size="10.00">f6=31</text> -</g> -<!-- 5 --> -<g id="node9" class="node"> -<title>5</title> -<polygon fill="none" stroke="black" points="90,-467.79 54,-467.79 54,-431.79 90,-431.79 90,-467.79"/> -<text text-anchor="middle" x="72" y="-453.39" font-family="Times,serif" font-size="13.00">0</text> -<text text-anchor="middle" x="72" y="-439.39" font-family="Times,serif" font-size="13.00">(5)</text> -</g> -<!-- 3->5 --> -<g id="edge8" class="edge"> -<title>3->5</title> -<path fill="none" stroke="black" d="M72,-533.41C72,-516.2 72,-493.27 72,-475.94"/> -<polygon fill="black" stroke="black" points="74.8,-475.93 72,-467.93 69.2,-475.93 74.8,-475.93"/> -<text text-anchor="middle" x="87.5" y="-501.9" font-family="Times,serif" font-size="10.00">f6=30</text> -</g> -<!-- 7 --> -<g id="node10" class="node"> -<title>7</title> -<polygon fill="none" stroke="black" points="144,-467.79 108,-467.79 108,-431.79 144,-431.79 144,-467.79"/> -<text text-anchor="middle" x="126" y="-453.39" font-family="Times,serif" font-size="13.00">1</text> -<text text-anchor="middle" x="126" y="-439.39" font-family="Times,serif" font-size="13.00">(7)</text> -</g> -<!-- 6->7 --> -<g id="edge9" class="edge"> -<title>6->7</title> -<path fill="none" stroke="black" d="M162.93,-540.03C155.59,-531.47 147.46,-520.74 142,-509.9 136.67,-499.31 132.94,-486.72 130.44,-475.89"/> -<polygon fill="black" stroke="black" points="133.17,-475.25 128.76,-468.01 127.69,-476.42 133.17,-475.25"/> -<text text-anchor="middle" x="160.5" y="-501.9" font-family="Times,serif" font-size="10.00">f6=133</text> -</g> -<!-- 8 --> -<g id="node11" class="node"> -<title>8</title> -<polygon fill="none" stroke="black" points="204,-467.79 168,-467.79 168,-431.79 204,-431.79 204,-467.79"/> -<text text-anchor="middle" x="186" y="-453.39" font-family="Times,serif" font-size="13.00">0</text> -<text text-anchor="middle" x="186" y="-439.39" font-family="Times,serif" font-size="13.00">(8)</text> -</g> -<!-- 6->8 --> -<g id="edge10" class="edge"> -<title>6->8</title> -<path fill="none" stroke="black" d="M181.38,-533.41C182.34,-516.2 183.62,-493.27 184.59,-475.94"/> -<polygon fill="black" stroke="black" points="187.39,-476.07 185.04,-467.93 181.8,-475.76 187.39,-476.07"/> -<text text-anchor="middle" x="202.5" y="-501.9" font-family="Times,serif" font-size="10.00">f6=132</text> -</g> -<!-- 11 --> -<g id="node12" class="node"> -<title>11</title> -<ellipse fill="none" stroke="black" cx="253" cy="-449.79" rx="31" ry="31"/> -<text text-anchor="middle" x="253" y="-453.39" font-family="Times,serif" font-size="13.00">f12</text> -<text text-anchor="middle" x="253" y="-439.39" font-family="Times,serif" font-size="13.00">(11)</text> -</g> -<!-- 10->11 --> -<g id="edge11" class="edge"> -<title>10->11</title> -<path fill="none" stroke="black" d="M263.82,-528.15C262.13,-516.05 260.15,-501.93 258.36,-489.09"/> -<polygon fill="black" stroke="black" points="261.09,-488.4 257.21,-480.87 255.55,-489.18 261.09,-488.4"/> -<text text-anchor="middle" x="273.5" y="-501.9" font-family="Times,serif" font-size="10.00">f3=1</text> -</g> -<!-- 20 --> -<g id="node13" class="node"> -<title>20</title> -<ellipse fill="none" stroke="black" cx="333" cy="-449.79" rx="31" ry="31"/> -<text text-anchor="middle" x="333" y="-453.39" font-family="Times,serif" font-size="13.00">f4</text> -<text text-anchor="middle" x="333" y="-439.39" font-family="Times,serif" font-size="13.00">(20)</text> -</g> -<!-- 10->20 --> -<g id="edge12" class="edge"> -<title>10->20</title> -<path fill="none" stroke="black" d="M283.73,-532.06C292.53,-517.55 303.59,-499.31 312.99,-483.79"/> -<polygon fill="black" stroke="black" points="315.43,-485.17 317.18,-476.88 310.64,-482.27 315.43,-485.17"/> -<text text-anchor="middle" x="315.5" y="-501.9" font-family="Times,serif" font-size="10.00">f3=0</text> -</g> -<!-- 24 --> -<g id="node14" class="node"> -<title>24</title> -<ellipse fill="none" stroke="black" cx="461" cy="-449.79" rx="31" ry="31"/> -<text text-anchor="middle" x="461" y="-453.39" font-family="Times,serif" font-size="13.00">f5</text> -<text text-anchor="middle" x="461" y="-439.39" font-family="Times,serif" font-size="13.00">(24)</text> -</g> -<!-- 23->24 --> -<g id="edge13" class="edge"> -<title>23->24</title> -<path fill="none" stroke="black" d="M461,-527.86C461,-515.87 461,-501.93 461,-489.22"/> -<polygon fill="black" stroke="black" points="463.8,-489.09 461,-481.09 458.2,-489.09 463.8,-489.09"/> -<text text-anchor="middle" x="476.5" y="-501.9" font-family="Times,serif" font-size="10.00">f9=23</text> -</g> -<!-- 27 --> -<g id="node15" class="node"> -<title>27</title> -<ellipse fill="none" stroke="black" cx="574" cy="-449.79" rx="31" ry="31"/> -<text text-anchor="middle" x="574" y="-453.39" font-family="Times,serif" font-size="13.00">f4</text> -<text text-anchor="middle" x="574" y="-439.39" font-family="Times,serif" font-size="13.00">(27)</text> -</g> -<!-- 23->27 --> -<g id="edge14" class="edge"> -<title>23->27</title> -<path fill="none" stroke="black" d="M483.33,-536.83C501.2,-519.87 526.39,-495.97 545.68,-477.66"/> -<polygon fill="black" stroke="black" points="547.84,-479.47 551.72,-471.93 543.99,-475.4 547.84,-479.47"/> -<text text-anchor="middle" x="536.5" y="-501.9" font-family="Times,serif" font-size="10.00">f9=22</text> -</g> -<!-- 13 --> -<g id="node16" class="node"> -<title>13</title> -<ellipse fill="none" stroke="black" cx="182" cy="-340.56" rx="31" ry="31"/> -<text text-anchor="middle" x="182" y="-344.16" font-family="Times,serif" font-size="13.00">f5</text> -<text text-anchor="middle" x="182" y="-330.16" font-family="Times,serif" font-size="13.00">(13)</text> -</g> -<!-- 11->13 --> -<g id="edge15" class="edge"> -<title>11->13</title> -<path fill="none" stroke="black" d="M230,-428.79C221.66,-420.68 212.65,-410.84 206,-400.68 201.45,-393.73 197.51,-385.77 194.2,-378.01"/> -<polygon fill="black" stroke="black" points="196.7,-376.72 191.12,-370.34 191.5,-378.81 196.7,-376.72"/> -<text text-anchor="middle" x="227.5" y="-392.68" font-family="Times,serif" font-size="10.00">f12=162</text> -</g> -<!-- 12 --> -<g id="node17" class="node"> -<title>12</title> -<polygon fill="none" stroke="black" points="275,-362.56 231,-362.56 231,-318.56 275,-318.56 275,-362.56"/> -<text text-anchor="middle" x="253" y="-344.16" font-family="Times,serif" font-size="13.00">1</text> -<text text-anchor="middle" x="253" y="-330.16" font-family="Times,serif" font-size="13.00">(12)</text> -</g> -<!-- 11->12 --> -<g id="edge16" class="edge"> -<title>11->12</title> -<path fill="none" stroke="black" d="M253,-418.64C253,-403.72 253,-385.79 253,-370.98"/> -<polygon fill="black" stroke="black" points="255.8,-370.67 253,-362.67 250.2,-370.67 255.8,-370.67"/> -<text text-anchor="middle" x="274.5" y="-392.68" font-family="Times,serif" font-size="10.00">f12=163</text> -</g> -<!-- 21 --> -<g id="node18" class="node"> -<title>21</title> -<polygon fill="none" stroke="black" points="339,-362.56 295,-362.56 295,-318.56 339,-318.56 339,-362.56"/> -<text text-anchor="middle" x="317" y="-344.16" font-family="Times,serif" font-size="13.00">1</text> -<text text-anchor="middle" x="317" y="-330.16" font-family="Times,serif" font-size="13.00">(21)</text> -</g> -<!-- 20->21 --> -<g id="edge17" class="edge"> -<title>20->21</title> -<path fill="none" stroke="black" d="M328.54,-418.92C326.3,-403.86 323.58,-385.67 321.35,-370.72"/> -<polygon fill="black" stroke="black" points="324.12,-370.28 320.17,-362.78 318.58,-371.1 324.12,-370.28"/> -<text text-anchor="middle" x="341.5" y="-392.68" font-family="Times,serif" font-size="10.00">f4=19</text> -</g> -<!-- 22 --> -<g id="node19" class="node"> -<title>22</title> -<polygon fill="none" stroke="black" points="401,-362.56 357,-362.56 357,-318.56 401,-318.56 401,-362.56"/> -<text text-anchor="middle" x="379" y="-344.16" font-family="Times,serif" font-size="13.00">0</text> -<text text-anchor="middle" x="379" y="-330.16" font-family="Times,serif" font-size="13.00">(22)</text> -</g> -<!-- 20->22 --> -<g id="edge18" class="edge"> -<title>20->22</title> -<path fill="none" stroke="black" d="M347.09,-421.8C350.48,-414.98 353.99,-407.61 357,-400.68 361.27,-390.85 365.48,-379.9 369.07,-370.12"/> -<polygon fill="black" stroke="black" points="371.71,-371.05 371.8,-362.57 366.45,-369.14 371.71,-371.05"/> -<text text-anchor="middle" x="376.5" y="-392.68" font-family="Times,serif" font-size="10.00">f4=18</text> -</g> -<!-- 25 --> -<g id="node20" class="node"> -<title>25</title> -<polygon fill="none" stroke="black" points="463,-362.56 419,-362.56 419,-318.56 463,-318.56 463,-362.56"/> -<text text-anchor="middle" x="441" y="-344.16" font-family="Times,serif" font-size="13.00">1</text> -<text text-anchor="middle" x="441" y="-330.16" font-family="Times,serif" font-size="13.00">(25)</text> -</g> -<!-- 24->25 --> -<g id="edge19" class="edge"> -<title>24->25</title> -<path fill="none" stroke="black" d="M453.91,-419.35C452.53,-413.19 451.15,-406.74 450,-400.68 448.15,-390.97 446.44,-380.32 445.01,-370.76"/> -<polygon fill="black" stroke="black" points="447.76,-370.2 443.83,-362.69 442.22,-371.01 447.76,-370.2"/> -<text text-anchor="middle" x="465.5" y="-392.68" font-family="Times,serif" font-size="10.00">f5=15</text> -</g> -<!-- 26 --> -<g id="node21" class="node"> -<title>26</title> -<polygon fill="none" stroke="black" points="525,-362.56 481,-362.56 481,-318.56 525,-318.56 525,-362.56"/> -<text text-anchor="middle" x="503" y="-344.16" font-family="Times,serif" font-size="13.00">0</text> -<text text-anchor="middle" x="503" y="-330.16" font-family="Times,serif" font-size="13.00">(26)</text> -</g> -<!-- 24->26 --> -<g id="edge20" class="edge"> -<title>24->26</title> -<path fill="none" stroke="black" d="M472.81,-420.88C475.55,-414.27 478.41,-407.24 481,-400.68 484.86,-390.89 488.92,-380.12 492.48,-370.48"/> -<polygon fill="black" stroke="black" points="495.21,-371.17 495.35,-362.7 489.95,-369.24 495.21,-371.17"/> -<text text-anchor="middle" x="500.5" y="-392.68" font-family="Times,serif" font-size="10.00">f5=14</text> -</g> -<!-- 28 --> -<g id="node22" class="node"> -<title>28</title> -<ellipse fill="none" stroke="black" cx="574" cy="-340.56" rx="31" ry="31"/> -<text text-anchor="middle" x="574" y="-344.16" font-family="Times,serif" font-size="13.00">f6</text> -<text text-anchor="middle" x="574" y="-330.16" font-family="Times,serif" font-size="13.00">(28)</text> -</g> -<!-- 27->28 --> -<g id="edge21" class="edge"> -<title>27->28</title> -<path fill="none" stroke="black" d="M574,-418.64C574,-406.64 574,-392.7 574,-380"/> -<polygon fill="black" stroke="black" points="576.8,-379.86 574,-371.86 571.2,-379.86 576.8,-379.86"/> -<text text-anchor="middle" x="589.5" y="-392.68" font-family="Times,serif" font-size="10.00">f4=15</text> -</g> -<!-- 31 --> -<g id="node23" class="node"> -<title>31</title> -<ellipse fill="none" stroke="black" cx="654" cy="-340.56" rx="31" ry="31"/> -<text text-anchor="middle" x="654" y="-344.16" font-family="Times,serif" font-size="13.00">f13</text> -<text text-anchor="middle" x="654" y="-330.16" font-family="Times,serif" font-size="13.00">(31)</text> -</g> -<!-- 27->31 --> -<g id="edge22" class="edge"> -<title>27->31</title> -<path fill="none" stroke="black" d="M592.15,-424.46C603.53,-409.21 618.3,-389.41 630.56,-372.98"/> -<polygon fill="black" stroke="black" points="633.1,-374.26 635.64,-366.17 628.61,-370.91 633.1,-374.26"/> -<text text-anchor="middle" x="632.5" y="-392.68" font-family="Times,serif" font-size="10.00">f4=14</text> -</g> -<!-- 15 --> -<g id="node24" class="node"> -<title>15</title> -<ellipse fill="none" stroke="black" cx="141" cy="-231.34" rx="31" ry="31"/> -<text text-anchor="middle" x="141" y="-234.94" font-family="Times,serif" font-size="13.00">f5</text> -<text text-anchor="middle" x="141" y="-220.94" font-family="Times,serif" font-size="13.00">(15)</text> -</g> -<!-- 13->15 --> -<g id="edge23" class="edge"> -<title>13->15</title> -<path fill="none" stroke="black" d="M171.12,-311.11C166.08,-297.92 160.03,-282.1 154.68,-268.11"/> -<polygon fill="black" stroke="black" points="157.26,-267.02 151.79,-260.55 152.03,-269.02 157.26,-267.02"/> -<text text-anchor="middle" x="175.5" y="-283.45" font-family="Times,serif" font-size="10.00">f5=2</text> -</g> -<!-- 14 --> -<g id="node25" class="node"> -<title>14</title> -<polygon fill="none" stroke="black" points="234,-253.34 190,-253.34 190,-209.34 234,-209.34 234,-253.34"/> -<text text-anchor="middle" x="212" y="-234.94" font-family="Times,serif" font-size="13.00">1</text> -<text text-anchor="middle" x="212" y="-220.94" font-family="Times,serif" font-size="13.00">(14)</text> -</g> -<!-- 13->14 --> -<g id="edge24" class="edge"> -<title>13->14</title> -<path fill="none" stroke="black" d="M190.2,-310.26C194.44,-295.09 199.61,-276.62 203.85,-261.47"/> -<polygon fill="black" stroke="black" points="206.64,-261.9 206.1,-253.44 201.25,-260.39 206.64,-261.9"/> -<text text-anchor="middle" x="210.5" y="-283.45" font-family="Times,serif" font-size="10.00">f5=3</text> -</g> -<!-- 29 --> -<g id="node30" class="node"> -<title>29</title> -<polygon fill="none" stroke="black" points="538,-253.34 494,-253.34 494,-209.34 538,-209.34 538,-253.34"/> -<text text-anchor="middle" x="516" y="-234.94" font-family="Times,serif" font-size="13.00">0</text> -<text text-anchor="middle" x="516" y="-220.94" font-family="Times,serif" font-size="13.00">(29)</text> -</g> -<!-- 28->29 --> -<g id="edge29" class="edge"> -<title>28->29</title> -<path fill="none" stroke="black" d="M553.1,-317.31C546.63,-309.56 539.91,-300.53 535,-291.45 529.9,-282.03 525.89,-271.01 522.9,-261.05"/> -<polygon fill="black" stroke="black" points="525.59,-260.28 520.72,-253.35 520.21,-261.81 525.59,-260.28"/> -<text text-anchor="middle" x="553.5" y="-283.45" font-family="Times,serif" font-size="10.00">f6=111</text> -</g> -<!-- 30 --> -<g id="node31" class="node"> -<title>30</title> -<polygon fill="none" stroke="black" points="600,-253.34 556,-253.34 556,-209.34 600,-209.34 600,-253.34"/> -<text text-anchor="middle" x="578" y="-234.94" font-family="Times,serif" font-size="13.00">1</text> -<text text-anchor="middle" x="578" y="-220.94" font-family="Times,serif" font-size="13.00">(30)</text> -</g> -<!-- 28->30 --> -<g id="edge30" class="edge"> -<title>28->30</title> -<path fill="none" stroke="black" d="M575.12,-309.41C575.68,-294.5 576.35,-276.57 576.9,-261.76"/> -<polygon fill="black" stroke="black" points="579.71,-261.54 577.21,-253.44 574.11,-261.33 579.71,-261.54"/> -<text text-anchor="middle" x="595.5" y="-283.45" font-family="Times,serif" font-size="10.00">f6=110</text> -</g> -<!-- 32 --> -<g id="node32" class="node"> -<title>32</title> -<polygon fill="none" stroke="black" points="671,-253.34 627,-253.34 627,-209.34 671,-209.34 671,-253.34"/> -<text text-anchor="middle" x="649" y="-234.94" font-family="Times,serif" font-size="13.00">0</text> -<text text-anchor="middle" x="649" y="-220.94" font-family="Times,serif" font-size="13.00">(32)</text> -</g> -<!-- 31->32 --> -<g id="edge31" class="edge"> -<title>31->32</title> -<path fill="none" stroke="black" d="M651.2,-309.56C650.72,-303.56 650.29,-297.31 650,-291.45 649.51,-281.7 649.25,-271.03 649.11,-261.48"/> -<polygon fill="black" stroke="black" points="651.91,-261.39 649.02,-253.42 646.31,-261.45 651.91,-261.39"/> -<text text-anchor="middle" x="671.5" y="-283.45" font-family="Times,serif" font-size="10.00">f13=345</text> -</g> -<!-- 33 --> -<g id="node33" class="node"> -<title>33</title> -<polygon fill="none" stroke="black" points="737,-253.34 693,-253.34 693,-209.34 737,-209.34 737,-253.34"/> -<text text-anchor="middle" x="715" y="-234.94" font-family="Times,serif" font-size="13.00">1</text> -<text text-anchor="middle" x="715" y="-220.94" font-family="Times,serif" font-size="13.00">(33)</text> -</g> -<!-- 31->33 --> -<g id="edge32" class="edge"> -<title>31->33</title> -<path fill="none" stroke="black" d="M674.66,-317.18C681.12,-309.42 687.88,-300.42 693,-291.45 698.35,-282.07 702.85,-271.14 706.35,-261.25"/> -<polygon fill="black" stroke="black" points="709.03,-262.08 708.94,-253.6 703.72,-260.28 709.03,-262.08"/> -<text text-anchor="middle" x="719.5" y="-283.45" font-family="Times,serif" font-size="10.00">f13=344</text> -</g> -<!-- 16 --> -<g id="node26" class="node"> -<title>16</title> -<ellipse fill="none" stroke="black" cx="105" cy="-122.11" rx="31" ry="31"/> -<text text-anchor="middle" x="105" y="-125.71" font-family="Times,serif" font-size="13.00">f13</text> -<text text-anchor="middle" x="105" y="-111.71" font-family="Times,serif" font-size="13.00">(16)</text> -</g> -<!-- 15->16 --> -<g id="edge25" class="edge"> -<title>15->16</title> -<path fill="none" stroke="black" d="M130.04,-201.95C127.65,-195.49 125.18,-188.64 123,-182.23 120.57,-175.06 118.12,-167.36 115.83,-159.96"/> -<polygon fill="black" stroke="black" points="118.44,-158.93 113.43,-152.09 113.09,-160.56 118.44,-158.93"/> -<text text-anchor="middle" x="138.5" y="-174.23" font-family="Times,serif" font-size="10.00">f5=15</text> -</g> -<!-- 19 --> -<g id="node27" class="node"> -<title>19</title> -<polygon fill="none" stroke="black" points="198,-144.11 154,-144.11 154,-100.11 198,-100.11 198,-144.11"/> -<text text-anchor="middle" x="176" y="-125.71" font-family="Times,serif" font-size="13.00">0</text> -<text text-anchor="middle" x="176" y="-111.71" font-family="Times,serif" font-size="13.00">(19)</text> -</g> -<!-- 15->19 --> -<g id="edge26" class="edge"> -<title>15->19</title> -<path fill="none" stroke="black" d="M150.38,-201.6C155.38,-186.28 161.52,-167.48 166.53,-152.12"/> -<polygon fill="black" stroke="black" points="169.22,-152.91 169.04,-144.44 163.89,-151.17 169.22,-152.91"/> -<text text-anchor="middle" x="175.5" y="-174.23" font-family="Times,serif" font-size="10.00">f5=14</text> -</g> -<!-- 17 --> -<g id="node28" class="node"> -<title>17</title> -<polygon fill="none" stroke="black" points="94,-44 50,-44 50,0 94,0 94,-44"/> -<text text-anchor="middle" x="72" y="-25.6" font-family="Times,serif" font-size="13.00">0</text> -<text text-anchor="middle" x="72" y="-11.6" font-family="Times,serif" font-size="13.00">(17)</text> -</g> -<!-- 16->17 --> -<g id="edge27" class="edge"> -<title>16->17</title> -<path fill="none" stroke="black" d="M85.49,-97.53C80.45,-90.12 75.7,-81.62 73,-73 70.99,-66.59 70.11,-59.49 69.85,-52.7"/> -<polygon fill="black" stroke="black" points="72.65,-52.34 69.82,-44.34 67.05,-52.35 72.65,-52.34"/> -<text text-anchor="middle" x="94.5" y="-65" font-family="Times,serif" font-size="10.00">f13=199</text> -</g> -<!-- 18 --> -<g id="node29" class="node"> -<title>18</title> -<polygon fill="none" stroke="black" points="160,-44 116,-44 116,0 160,0 160,-44"/> -<text text-anchor="middle" x="138" y="-25.6" font-family="Times,serif" font-size="13.00">1</text> -<text text-anchor="middle" x="138" y="-11.6" font-family="Times,serif" font-size="13.00">(18)</text> -</g> -<!-- 16->18 --> -<g id="edge28" class="edge"> -<title>16->18</title> -<path fill="none" stroke="black" d="M114.63,-92.47C118.95,-79.64 124.03,-64.53 128.35,-51.69"/> -<polygon fill="black" stroke="black" points="131.03,-52.51 130.93,-44.03 125.72,-50.72 131.03,-52.51"/> -<text text-anchor="middle" x="146.5" y="-65" font-family="Times,serif" font-size="10.00">f13=198</text> -</g> -</g> -</svg> diff --git a/pages/application/layout_application.py b/pages/application/layout_application.py index 28c6fb68052ed77ba59f95cfd1abece9a48c7591..49727746c0e161b08d73c9db5234d0275a063559 100644 --- a/pages/application/layout_application.py +++ b/pages/application/layout_application.py @@ -1,7 +1,6 @@ -from dash import dcc, html, Input, Output, callback +from dash import dcc, html, Input, Output import dash import dash_bootstrap_components as dbc -import visdcc import pandas as pd import numpy as np from os import listdir @@ -9,68 +8,23 @@ from os.path import isfile, join import importlib from pages.application.utils_data import extract_data - -def create_tab_application(data): - model = Model(data) - view = View(model) - - @callback( - Output('ml_datasets_choice', 'options'), - Input('ml_model_choice', 'value') - ) - def update_ml_type(value): - model.update_ml_model(value) - view.update_ml_model() - return model.datasets - - @callback( - Output('ml_instances_choice', 'options'), - Output('model_layout', 'children'), - Input('ml_datasets_choice', 'value'), - Input('ml_instances_choice', 'value') - ) - def update_dataset(value_dataset, value_instance): - if model.ml_model!='': - ctx = dash.callback_context - - if ctx.triggered: - dropdown = button_id = ctx.triggered[0]['prop_id'].split('.')[0] - if dropdown == 'ml_datasets_choice': - model.update_dataset(value_dataset) - model_layout = view.update_dataset() - return model.instances, model_layout - - else : - model.update_instance(value_instance) - model_layout = view.update_instance() - return model.instances, model_layout - else : - return [], html.Div(children=[]) - - return view.create_tab() - +from pages.application.DecisionTree.DecisionTreeComponent import DecisionTreeComponent SIDEBAR_STYLE = { - "width": "20rem", - "margin-bottom": "5rem", - "background-color": "#f8f9fa", } CONTENT_STYLE = { - "padding": "2rem 1rem", } - class Model(): def __init__(self, data): - names_models, dict_data_models, dict_data_instances, dict_components, dict_expl = extract_data(data) + names_models, dict_data_models, dict_data_instances, dict_components = extract_data(data) self.dict_data_models = dict_data_models self.dict_data_instances = dict_data_instances self.dict_components = dict_components - self.dict_expl = dict_expl self.ml_models = names_models self.ml_model = '' @@ -83,8 +37,6 @@ class Model(): self.component_class = '' - self.explicability_algorithm = '' - def update_ml_model(self, ml_model_update): self.ml_model = ml_model_update @@ -92,8 +44,6 @@ class Model(): self.component_class = self.dict_components[self.ml_model] - self.explicability_algorithm = self.dict_expl[self.ml_model] - def update_dataset(self, dataset_update): self.dataset = dataset_update @@ -111,41 +61,28 @@ class View(): self.datasets_menu_models = dcc.Dropdown(self.model.datasets, id='ml_datasets_choice') self.instances_menu = dcc.Dropdown(self.model.instances, id='ml_instances_choice') - self.sidebar = html.Div([ - html.Label("Choose the Machine Learning algorithm :"), - html.Br(), - self.ml_menu_models, - html.Hr(), - html.Label("Choose the dataset : "), - html.Br(), - self.datasets_menu_models, - html.Hr(), - html.Label("Choose the instance to explain : "), - html.Br(), - self.instances_menu], - style=SIDEBAR_STYLE) - self.component = '' - self.model_layout = html.Div( - id="model_layout", - style= CONTENT_STYLE) - - def create_tab(self): - return dcc.Tab(label='Application on Explainable AI', children=[ - html.Div(children=[ - self.sidebar, - self.model_layout - ]) - ]) - - def update_ml_model(self): - cls = getattr(importlib.import_module("pages.application.DecisionTree."+self.model.component_class), self.model.component_class) - self.component = cls() + self.sidebar = dbc.Col([ + html.Label("Choose the Machine Learning algorithm :"), + html.Br(), + self.ml_menu_models, + html.Hr(), + html.Label("Choose the dataset : "), + html.Br(), + self.datasets_menu_models, + html.Hr(), + html.Label("Choose the instance to explain : "), + html.Br(), + self.instances_menu], width=2) + self.layout = dbc.Row([self.sidebar, + dbc.Col(html.Div(id = "graph", children=" "), width=5), + dbc.Col(html.Div(id = "explanation", children=" "), width=3)]) + self.tab = dcc.Tab(label='Application on Explainable AI', children=self.layout) def update_dataset(self): - self.component.update(self.model.dataset) - return html.Div(children=[self.component.network]) + class_ = globals()[self.model.component_class] + self.component = class_(self.model.dataset) + def update_instance(self): - self.component.update_with_explicability(self.model.instance) - return html.Div(children=[self.component.network]) \ No newline at end of file + self.component.update_with_explicability(self.model.dataset, self.model.instance) \ No newline at end of file diff --git a/pages/application/utils_data.py b/pages/application/utils_data.py index f2a814cc42d6059534c6e160ee3a0c2c8fe5f722..7b7a5fedd69ab33f9f3631e9fff232f2b47aa1b1 100644 --- a/pages/application/utils_data.py +++ b/pages/application/utils_data.py @@ -9,21 +9,19 @@ from os.path import isfile, join import importlib def extract_data(data): - names_models = [data['data'][i]['ml_type'] for i in range (len(data))] + names_models = [data[i]['ml_type'] for i in range (len(data))] dict_data_models = {} dict_data_instances = {} dict_components = {} - dict_expl = {} for i in range (len(data)) : - ml_type = data['data'][i]['ml_type'] - dict_components[ml_type] = data['data'][i]['component'] - dict_expl[ml_type] = data['data'][i]['explicability_algorithm'] - dict_data_models[ml_type] = [f for f in listdir(data['data'][i]['trained_models'])] - dict_data_instances = {} + ml_type = data[i]['ml_type'] + dict_components[ml_type] = data[i]['component'] + dict_data_models[ml_type] = [f for f in listdir(data[i]['trained_models'])] + dict_dataset_instances = {} for j in range (len(dict_data_models[ml_type])) : dataset = dict_data_models[ml_type][j] - dict_data_instances[dataset] = [f for f in listdir(data['data'][i]['instances']+dataset) if isfile(join(data['data'][i]['instances']+dataset, f))] - dict_data_instances[ml_type] = dict_data_instances + dict_dataset_instances[dataset] = [f for f in listdir(data[i]['instances']+dataset) if isfile(join(data[i]['instances']+dataset, f))] + dict_data_instances[ml_type] = dict_dataset_instances - return names_models, dict_data_models, dict_data_instances, dict_components, dict_expl \ No newline at end of file + return names_models, dict_data_models, dict_data_instances, dict_components \ No newline at end of file diff --git a/pages/layout.py b/pages/layout.py deleted file mode 100644 index 41742caf6dce6c6bd0cbe838ac010f806298a9f0..0000000000000000000000000000000000000000 --- a/pages/layout.py +++ /dev/null @@ -1,20 +0,0 @@ -from dash import dcc -from dash import html -import visdcc -import pandas as pd -import numpy as np - -from pages.application.layout_application import create_tab_application - - -def create_tabs(data): - tabs = dcc.Tabs([ - dcc.Tab(label='Course on Explainable AI', children=[]), - create_tab_application(data), - ]) - return tabs - -def create_layout(data): - return html.Div([ - html.H1('FXToolKit'), - create_tabs(data) ]) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 860116d298e3a0b1a3c75de760fc59ff742fd9d1..9e95cabfcef3caf21e52c9efdcd64ddfc2f7ccd4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,4 +8,6 @@ numpy>=1.16.2 pandas>=0.24.2 scikit-learn>=0.20.3 scipy>=1.2.1 -visdcc +dash_bootstrap_components +dash_interactive_graphviz +importlib