From 99e4a6ba21c7f0dddd6488df84bf513bf1ed834d Mon Sep 17 00:00:00 2001 From: Caroline DE POURTALES <cdepourt@montana.irit.fr> Date: Tue, 5 Apr 2022 14:53:49 +0200 Subject: [PATCH] can upload an skl tree --- .gitignore | 8 +- assets/header.css | 11 +- callbacks.py | 40 ++-- callbacks_detached.py | 172 ++++++++++++++++++ .../DecisionTree/DecisionTreeComponent.py | 88 +++++---- pages/application/DecisionTree/utils/data.py | 6 +- pages/application/DecisionTree/utils/dtree.py | 14 +- pages/application/DecisionTree/utils/dtviz.py | 10 +- .../DecisionTree/utils/upload_tree.py | 5 +- pages/application/application.py | 130 +++++++------ requirements.txt | 5 +- tests/adult/adult.pkl | Bin 0 -> 3033 bytes tests/adult/adult_2.pkl | Bin 0 -> 2166 bytes tests/adult/adult_3.pkl | Bin 0 -> 1734 bytes tests/adult/adult_data_00000.inst | 1 + .../decision_tree_classifier_20170212.pkl | Bin 0 -> 1916 bytes tests/iris/iris.csv | 151 +++++++++++++++ tests/iris/iris.pkl | Bin 0 -> 2047 bytes tests/iris/iris.txt | 4 + tests/iris/iris01.json | 4 + tests/iris/iris2.pkl | Bin 0 -> 2047 bytes tests/iris/iris_00000.txt | 1 + tests/zoo/inst/zoo_00.inst | 1 + tests/zoo/inst/zoo_01.inst | 1 + tests/zoo/inst/zoo_02.inst | 1 + tests/zoo/inst/zoo_11.inst | 1 + tests/zoo/zoo.csv | 102 +++++++++++ tests/zoo/zoo.dt | 85 +++++++++ tests/zoo/zoo.json | 18 ++ tests/zoo/zoo.map | 38 ++++ tests/zoo/zoo.pkl | Bin 0 -> 2303 bytes utils.py | 13 +- 32 files changed, 756 insertions(+), 154 deletions(-) create mode 100644 callbacks_detached.py create mode 100644 tests/adult/adult.pkl create mode 100644 tests/adult/adult_2.pkl create mode 100644 tests/adult/adult_3.pkl create mode 100644 tests/adult/adult_data_00000.inst create mode 100644 tests/iris/decision_tree_classifier_20170212.pkl create mode 100644 tests/iris/iris.csv create mode 100644 tests/iris/iris.pkl create mode 100644 tests/iris/iris.txt create mode 100644 tests/iris/iris01.json create mode 100644 tests/iris/iris2.pkl create mode 100644 tests/iris/iris_00000.txt create mode 100644 tests/zoo/inst/zoo_00.inst create mode 100644 tests/zoo/inst/zoo_01.inst create mode 100644 tests/zoo/inst/zoo_02.inst create mode 100644 tests/zoo/inst/zoo_11.inst create mode 100644 tests/zoo/zoo.csv create mode 100644 tests/zoo/zoo.dt create mode 100644 tests/zoo/zoo.json create mode 100644 tests/zoo/zoo.map create mode 100644 tests/zoo/zoo.pkl diff --git a/.gitignore b/.gitignore index 7c8041b..f7db4b6 100644 --- a/.gitignore +++ b/.gitignore @@ -3,10 +3,4 @@ __pycache__ pages/application/DecisionTree/utils/__pycache__ pages/application/DecisionTree/__pycache__ pages/application/__pycache__ -decision_tree_classifier_20170212.pkl -push_command -adult.pkl -adult_data_00000.inst -iris_00000.txt -tests -create_pkl.py \ No newline at end of file +tests/push_command \ No newline at end of file diff --git a/assets/header.css b/assets/header.css index 8da0dd9..3a882ea 100644 --- a/assets/header.css +++ b/assets/header.css @@ -36,6 +36,12 @@ div.sidebar.col-3 { background-color:gray; } +.sidebar .check-boxes{ + width: 100%; + height: 40px; + text-align: center; +} + .sidebar .upload { width: 100%; height: 50px; @@ -49,7 +55,6 @@ div.sidebar.col-3 { .sidebar .Select-control { width: 100%; - height: 30px; line-height: 30px; border-width: 1px; border-radius: 5px; @@ -60,9 +65,9 @@ div.sidebar.col-3 { background-color: rgb(26,26,26); } -.sidebar .sidebar-dropdown{ +.sidebar .dropdown{ width: 100%; - height: 40px; + height: 30px; line-height: 30px; border-width: 1px; border-radius: 5px; diff --git a/callbacks.py b/callbacks.py index 04930d6..5ef62d6 100644 --- a/callbacks.py +++ b/callbacks.py @@ -54,10 +54,13 @@ def register_callbacks(page_home, page_course, page_application, app): if ctx.triggered: ihm_id = ctx.triggered[0]['prop_id'].split('.')[0] model_application = page_application.model + + # Choice of model if ihm_id == 'ml_model_choice' : - model_application.update_ml_model(value_ml_model) - return None, None, None, None, None + model_application.update_ml_model(value_ml_model) + return None, None, None, None, None + # Choice of pkl pretrained model elif ihm_id == 'ml_pretrained_model_choice': if model_application.ml_model is None : raise PreventUpdate @@ -69,6 +72,7 @@ def register_callbacks(page_home, page_course, page_application, app): else : return pretrained_model_filename, None, None, None, None + # Choice of information for the model elif ihm_id == 'model_info_choice': if model_application.ml_model is None : raise PreventUpdate @@ -76,36 +80,38 @@ def register_callbacks(page_home, page_course, page_application, app): model_application.update_pretrained_model_layout_with_info(model_info, model_info_filename) return pretrained_model_filename, model_info_filename, None, model_application.component.network, None + # Choice of instance to explain elif ihm_id == 'ml_instance_choice' : - if model_application.ml_model is None or model_application.pretrained_model is None : + if model_application.ml_model is None or model_application.pretrained_model is None or model_application.enum<=0 or model_application.xtype is None : raise PreventUpdate instance = parse_contents_instance(instance_contents, instance_filename) - model_application.update_instance(instance, enum, xtype) + model_application.update_instance(instance) return pretrained_model_filename, model_info_filename, instance_filename, model_application.component.network, model_application.component.explanation + # Choice of number of expls elif ihm_id == 'number_explanations' : - if model_application.ml_model is None or model_application.pretrained_model is None or model_application.instance is None: + if model_application.ml_model is None or model_application.pretrained_model is None or len(model_application.instance)==0 or model_application.xtype is None: raise PreventUpdate - instance = parse_contents_instance(model_application.instance, instance_filename) - model_application.update_instance(instance, enum, xtype) + model_application.update_enum(enum) return pretrained_model_filename, model_info_filename, instance_filename, model_application.component.network, model_application.component.explanation + # Choice of AxP or CxP elif ihm_id == 'explanation_type' : - if model_application.ml_model is None or model_application.pretrained_model is None or model_application.instance is None: + if model_application.ml_model is None or model_application.pretrained_model is None or len(model_application.instance)==0 or model_application.enum<=0 : raise PreventUpdate - instance = parse_contents_instance(model_application.instance, instance_filename) - model_application.update_instance(instance, enum, xtype) + model_application.update_xtype(xtype) return pretrained_model_filename, model_info_filename, instance_filename, model_application.component.network, model_application.component.explanation + # Choice of solver elif ihm_id == 'solver_sat' : - if model_application.ml_model is None or model_application.pretrained_model is None or model_application.instance is None: + if model_application.ml_model is None or model_application.pretrained_model is None or len(model_application.instance)==0 or model_application.enum<=0 or len(model_application.xtype)==0: raise PreventUpdate - instance = parse_contents_instance(model_application.instance, instance_filename) - model_application.update_instance(instance, enum, xtype, solver=solver) + model_application.update_solver(solver) return pretrained_model_filename, model_info_filename, instance_filename, model_application.component.network, model_application.component.explanation + # Choice of AxP to draw elif ihm_id == 'expl_choice' : - if instance_contents is None : + if model_application.ml_model is None or model_application.pretrained_model is None or len(model_application.instance)==0 or model_application.enum<=0 or len(model_application.xtype)==0: raise PreventUpdate model_application.update_expl(expl_choice) return pretrained_model_filename, model_info_filename, instance_filename, model_application.component.network, model_application.component.explanation @@ -133,14 +139,14 @@ def register_callbacks(page_home, page_course, page_application, app): return False, False, False, options @app.callback( - Output('model_info_choice', 'disabled'), - Input('add_info_model_choice', 'value'), + Output('choice_info_div', 'hidden'), + Input('add_info_model_choice', 'on'), prevent_initial_call=True ) def add_model_info(add_info_model_choice): model_application = page_application.model model_application.update_info_needed(add_info_model_choice) - if add_info_model_choice==1: + if add_info_model_choice: return False else : return True diff --git a/callbacks_detached.py b/callbacks_detached.py new file mode 100644 index 0000000..a8db16f --- /dev/null +++ b/callbacks_detached.py @@ -0,0 +1,172 @@ +import dash +import pandas as pd +from dash import Input, Output, State +from dash.dependencies import Input, Output, State +from dash.exceptions import PreventUpdate + +from utils import parse_contents_graph, parse_contents_instance, parse_contents_data + + +def register_callbacks(page_home, page_course, page_application, app): + page_list = ['home', 'course', 'application'] + + @app.callback( + Output('page-content', 'children'), + Input('url', 'pathname')) + def display_page(pathname): + if pathname == '/': + return page_home + if pathname == '/application': + return page_application.view.layout + if pathname == '/course': + return page_course + + @app.callback(Output('home-link', 'active'), + Output('course-link', 'active'), + Output('application-link', 'active'), + Input('url', 'pathname')) + def navbar_state(pathname): + active_link = ([pathname == f'/{i}' for i in page_list]) + return active_link[0], active_link[1], active_link[2] + + @app.callback( + Output('graph', 'children'), + Input('ml_model_choice', 'value'), + prevent_initial_call=True + ) + def update_ml_type(value_ml_model): + model_application = page_application.model + model_application.update_ml_model(value_ml_model) + return None + + @app.callback( + Output('pretrained_model_filename', 'children'), + Output('graph', 'children'), + Input('ml_pretrained_model_choice', 'contents'), + State('ml_pretrained_model_choice', 'filename'), + prevent_initial_call=True + ) + def update_ml_pretrained_model(pretrained_model_contents, pretrained_model_filename): + model_application = page_application.model + if model_application.ml_model is None : + raise PreventUpdate + graph = parse_contents_graph(pretrained_model_contents, pretrained_model_filename) + model_application.update_pretrained_model(graph) + if not model_application.add_info : + model_application.update_pretrained_model_layout() + return pretrained_model_filename, model_application.component.network + else : + return pretrained_model_filename, None + + @app.callback( + Output('info_filename', 'children'), + Output('graph', 'children'), + Input('model_info_choice', 'contents'), + State('model_info_choice', 'filename'), + prevent_initial_call=True + ) + def update_info_model(model_info, model_info_filename): + model_application = page_application.model + if model_application.ml_model is None : + raise PreventUpdate + model_info = parse_contents_data(model_info, model_info_filename) + model_application.update_pretrained_model_layout_with_info(model_info, model_info_filename) + return model_info_filename, model_application.component.network + + @app.callback( + Output('instance_filename', 'children'), + Output('graph', 'children'), + Output('explanation', 'children'), + Input('ml_instance_choice', 'contents'), + State('ml_instance_choice', 'filename'), + prevent_initial_call=True + ) + def update_instance(instance_contents, instance_filename): + model_application = page_application.model + if model_application.ml_model is None or model_application.pretrained_model is None or model_application.enum<=0 or model_application.xtype is None : + raise PreventUpdate + instance = parse_contents_instance(instance_contents, instance_filename) + model_application.update_instance(instance) + return instance_filename, model_application.component.network, model_application.component.explanation + + @app.callback( + Output('explanation', 'children'), + Input('number_explanations', 'value'), + prevent_initial_call=True + ) + def update_enum(enum): + model_application = page_application.model + if model_application.ml_model is None or model_application.pretrained_model is None or len(model_application.instance)==0 or model_application.xtype is None: + raise PreventUpdate + model_application.update_enum(enum) + return model_application.component.explanation + + @app.callback( + Output('explanation', 'children'), + Input('explanation_type', 'value'), + prevent_initial_call=True + ) + def update_xtype(xtype): + model_application = page_application.model + if model_application.ml_model is None or model_application.pretrained_model is None or len(model_application.instance)==0 or model_application.enum<=0 : + raise PreventUpdate + model_application.update_xtype(xtype) + return model_application.component.explanation + + @app.callback( + Output('explanation', 'children'), + Input('solver_sat', 'value'), + prevent_initial_call=True +) + def update_solver(solver): + model_application = page_application.model + if model_application.ml_model is None or model_application.pretrained_model is None or len(model_application.instance)==0 or model_application.enum<=0 or len(model_application.xtype)==0: + raise PreventUpdate + model_application.update_solver(solver) + return model_application.component.explanation + + @app.callback( + Output('graph', 'children'), + Input('expl_choice', 'value'), + prevent_initial_call=True + ) + def update_expl_choice( expl_choice): + model_application = page_application.model + if model_application.ml_model is None or model_application.pretrained_model is None or len(model_application.instance)==0 or model_application.enum<=0 or len(model_application.xtype)==0: + raise PreventUpdate + model_application.update_expl(expl_choice) + return model_application.component.network + + @app.callback( + Output('explanation', 'hidden'), + Output('navigate_label', 'hidden'), + Output('navigate_dropdown', 'hidden'), + Output('expl_choice', 'options'), + Input('explanation', 'children'), + Input('explanation_type', 'value'), + prevent_initial_call=True + ) + def layout_buttons_navigate_expls(explanation, explanation_type): + if explanation is None or len(explanation_type)==0: + return True, True, True, {} + elif "AXp" not in explanation_type and "CXp" in explanation_type: + return False, True, True, {} + else : + options = {} + model_application = page_application.model + for i in range (len(model_application.list_expls)): + options[str(model_application.list_expls[i])] = model_application.list_expls[i] + return False, False, False, options + + @app.callback( + Output('choice_info_div', 'hidden'), + Input('add_info_model_choice', 'on'), + prevent_initial_call=True + ) + def add_model_info(add_info_model_choice): + model_application = page_application.model + model_application.update_info_needed(add_info_model_choice) + if add_info_model_choice: + return False + else : + return True diff --git a/pages/application/DecisionTree/DecisionTreeComponent.py b/pages/application/DecisionTree/DecisionTreeComponent.py index a1e2363..8a56c32 100644 --- a/pages/application/DecisionTree/DecisionTreeComponent.py +++ b/pages/application/DecisionTree/DecisionTreeComponent.py @@ -15,27 +15,32 @@ from pages.application.DecisionTree.utils.dtviz import (visualize, class DecisionTreeComponent(): - def __init__(self, tree, info=None, type_info=''): - + def __init__(self, tree, type_tree='SKL', info=None, type_info=''): if info is not None and '.csv' in type_info: self.categorical = True data = Data(info) fvmap = data.mapping_features() feature_names = data.names[:-1] - - self.uploaded_dt = UploadedDecisionTree(tree, 'SKL', maxdepth=tree.get_depth(), feature_names=feature_names, nb_classes=tree.n_classes_) + self.uploaded_dt = UploadedDecisionTree(tree, type_tree, maxdepth=tree.get_depth(), feature_names=feature_names, nb_classes=tree.n_classes_) self.dt_format, self.map, features_names_mapping = self.uploaded_dt.dump(fvmap, feat_names=feature_names) - self.mapping_instance = self.create_fvmap_inverse_with_info(features_names_mapping) - elif info is not None and '.txt' in type_info : self.categorical = True fvmap = {} - - self.uploaded_dt = UploadedDecisionTree(tree, 'SKL', maxdepth=tree.get_depth(), feature_names=feature_names, nb_classes=tree.n_classes_) + feature_names = [] + for i,line in enumerate(info.split('\n')): + fid, TYPE = line.split(',')[:2] + dom = line.split(',')[2:] + assert (fid not in feature_names) + feature_names.append(fid) + assert (TYPE in ['Binary', 'Categorical']) + fvmap[f'f{i}'] = dict() + dom = sorted(dom) + for j,v in enumerate(dom): + fvmap[f'f{i}'][j] = (fid, True, v) + self.uploaded_dt = UploadedDecisionTree(tree, type_tree, maxdepth=tree.get_depth(), feature_names=feature_names, nb_classes=tree.n_classes_) self.dt_format, self.map, features_names_mapping = self.uploaded_dt.dump(fvmap, feat_names=feature_names) - self.mapping_instance = self.create_fvmap_inverse_with_info(features_names_mapping) else : self.categorical = False @@ -43,42 +48,46 @@ class DecisionTreeComponent(): feature_names = tree.feature_names_in_ except: feature_names = [f'f{i}' for i in range(tree.n_features_in_)] - - self.uploaded_dt = UploadedDecisionTree(tree, 'SKL', maxdepth=tree.get_depth(), feature_names=feature_names, nb_classes=tree.n_classes_) + self.uploaded_dt = UploadedDecisionTree(tree, type_tree, maxdepth=tree.get_depth(), feature_names=feature_names, nb_classes=tree.n_classes_) self.dt_format, self.map, features_names_mapping = self.uploaded_dt.convert_dt(feat_names=feature_names) - self.mapping_instance = self.create_fvmap_inverse_threashold(features_names_mapping) - - self.dt = DecisionTree(from_dt=self.dt_format, mapfile = self.map) + + self.mapping_instance = self.create_fvmap_inverse(features_names_mapping) + self.dt = DecisionTree(from_dt=self.dt_format, mapfile = self.map, feature_names = feature_names) dot_source = visualize(self.dt) - self.network = [dbc.Row(dash_interactive_graphviz.DashInteractiveGraphviz(dot_source=dot_source, style = {"width": "60%", + self.network = html.Div([dash_interactive_graphviz.DashInteractiveGraphviz(dot_source=dot_source, style = {"width": "60%", "height": "90%", - "background-color": "transparent"}))] + "background-color": "transparent"})]) self.explanation = [] - def create_fvmap_inverse_with_info(self, features_names_mapping) : - mapping_instance = {} - for feat in features_names_mapping : - feat_dic = {} - feature_description = feat.split(',') - name_feat, id_feat = feature_description[1].split(':') + def create_fvmap_inverse(self, instance): + def create_fvmap_inverse_with_info(features_names_mapping) : + mapping_instance = {} + for feat in features_names_mapping : + feat_dic = {} + feature_description = feat.split(',') + name_feat, id_feat = feature_description[1].split(':') - for mapping in feature_description[2:]: - real_value, mapped_value = mapping.split(':') - feat_dic[np.float32(real_value)] = int(mapped_value) - mapping_instance[name_feat] = feat_dic + for mapping in feature_description[2:]: + real_value, mapped_value = mapping.split(':') + feat_dic[np.float32(real_value)] = int(mapped_value) + mapping_instance[name_feat] = feat_dic - return mapping_instance + return mapping_instance + def create_fvmap_inverse_threashold(features_names_mapping) : + mapping_instance = {} + for feat in features_names_mapping : + feature_description = feat.split(',') + name_feat, id_feat = feature_description[1].split(':') + mapping_instance[name_feat] = float(feature_description[2].split(':')[0]) - def create_fvmap_inverse_threashold(self, features_names_mapping) : - mapping_instance = {} - for feat in features_names_mapping : - feature_description = feat.split(',') - name_feat, id_feat = feature_description[1].split(':') - mapping_instance[name_feat] = float(feature_description[2].split(':')[0]) + return mapping_instance - return mapping_instance + if self.categorical : + return create_fvmap_inverse_with_info(instance) + else : + return create_fvmap_inverse_threashold(instance) def translate_instance(self, instance): @@ -114,14 +123,17 @@ class DecisionTreeComponent(): explanation = self.dt.explain(instance_translated, enum=enum, xtype = xtype, solver=solver) dot_source = visualize_instance(self.dt, instance_translated) - self.network = [dbc.Row(dash_interactive_graphviz.DashInteractiveGraphviz( + self.network = html.Div([dash_interactive_graphviz.DashInteractiveGraphviz( dot_source=dot_source, style = {"width": "50%", "height": "80%", "background-color": "transparent"} - ))] + )]) #Creating a clean and nice text component + #instance plotting + self.explanation.append(html.H4("Instance : \n")) + self.explanation.append(html.P(str([str(instance[i]) for i in range (len(instance))]))) for k in explanation.keys() : if k != "List of path explanation(s)": if k in ["List of abductive explanation(s)","List of contrastive explanation(s)"] : @@ -140,8 +152,8 @@ class DecisionTreeComponent(): def draw_explanation(self, instance, expl) : instance = self.translate_instance(instance) dot_source = visualize_expl(self.dt, instance, expl) - self.network = [dbc.Row(dash_interactive_graphviz.DashInteractiveGraphviz( + self.network = html.Div([dash_interactive_graphviz.DashInteractiveGraphviz( dot_source=dot_source, style = {"width": "50%", "height": "80%", - "background-color": "transparent"}))] + "background-color": "transparent"})]) diff --git a/pages/application/DecisionTree/utils/data.py b/pages/application/DecisionTree/utils/data.py index d23ddb6..91aded5 100644 --- a/pages/application/DecisionTree/utils/data.py +++ b/pages/application/DecisionTree/utils/data.py @@ -13,17 +13,13 @@ from __future__ import print_function import collections import itertools -import os, pickle +import pickle import six import gzip from six.moves import range import numpy as np import pandas as pd -#from sklearn.preprocessing import OneHotEncoder -from sklearn.model_selection import train_test_split - - # #============================================================================== class Data(object): diff --git a/pages/application/DecisionTree/utils/dtree.py b/pages/application/DecisionTree/utils/dtree.py index 1e7e270..1eb9de3 100644 --- a/pages/application/DecisionTree/utils/dtree.py +++ b/pages/application/DecisionTree/utils/dtree.py @@ -45,7 +45,7 @@ class DecisionTree(): Simple decision tree class. """ - def __init__(self, from_dt=None, mapfile=None, verbose=0): + def __init__(self, from_dt=None, mapfile=None, feature_names=None, verbose=0): """ Constructor. """ @@ -62,6 +62,7 @@ class DecisionTree(): self.feids = {} self.fdoms = {} self.fvmap = {} + self.feature_names = {f'f{i}' : feature_names[i] for i, f in enumerate(feature_names)} # OHE mapping OHEMap = collections.namedtuple('OHEMap', ['dir', 'opp']) @@ -145,7 +146,6 @@ class DecisionTree(): """ Parse feature-value mapping from a file. """ - self.fvmap = {} lines = mapfile.split('\n') @@ -184,7 +184,6 @@ class DecisionTree(): """ Convert ITI trees with '!=' edges to multi-edges. """ - # new feature domains fdoms = collections.defaultdict(lambda: []) @@ -227,7 +226,6 @@ class DecisionTree(): """ Traverse the tree and extract explicit paths. """ - if root in self.terms: # store the path term = self.terms[root] @@ -242,7 +240,6 @@ class DecisionTree(): """ Run the tree and obtain the prediction given an input instance. """ - root = self.root_node depth = 0 path = [] @@ -297,7 +294,6 @@ class DecisionTree(): Hitting set based encoding of the problem. (currently not incremental -- should be fixed later) """ - sets = [] for t, paths in self.paths.items(): # ignoring the right class @@ -334,12 +330,9 @@ class DecisionTree(): """ #contaiins all the elements for explanation explanation_dic = {} - #instance plotting - explanation_dic["Instance : "] = str([str(inst[i]) for i in range (len(inst))]) self.feids = {f'f{i}': i for i, f in enumerate(inst)} inst = [(f'f{i}', int(inst[i][1])) for i,f in enumerate(inst)] - path, term, depth = self.execute(inst, pathlits) #decision path @@ -347,10 +340,8 @@ class DecisionTree(): explanation_dic["Decision path of instance : "] = decision_path_str explanation_dic["Decision path length : "] = 'Path length is :'+ str(depth) - if self.ohmap.dir: f2v = {fv[0]: fv[1] for fv in inst} - # updating fvmap for printing ohe features for fo, fis in self.ohmap.dir.items(): self.fvmap[tuple([fo, None])] = '(' + ' AND '.join([self.fvmap[tuple([fi, f2v[fi]])] for fi in fis]) + ')' @@ -394,7 +385,6 @@ class DecisionTree(): """ Enumerate contrastive explanations. """ - def process_set(done, target): for s in done: if s <= target: diff --git a/pages/application/DecisionTree/utils/dtviz.py b/pages/application/DecisionTree/utils/dtviz.py index 0c940c6..21ea639 100755 --- a/pages/application/DecisionTree/utils/dtviz.py +++ b/pages/application/DecisionTree/utils/dtviz.py @@ -10,16 +10,14 @@ # #============================================================================== -from pages.application.DecisionTree.utils.dtree import DecisionTree import getopt -import os import pygraphviz -import sys # #============================================================================== def create_legend(g): legend = g.subgraphs()[-1] + legend.graph_attr.update(size="2,2") legend.add_node("a", style = "invis") legend.add_node("b", style = "invis") legend.add_node("c", style = "invis") @@ -50,7 +48,7 @@ def visualize(dt): # non-terminal nodes for n in dt.nodes: - g.add_node(n, label=dt.nodes[n].feat) + g.add_node(n, label=dt.feature_names[dt.nodes[n].feat]) node = g.get_node(n) node.attr['shape'] = 'circle' node.attr['fontsize'] = 13 @@ -98,7 +96,7 @@ def visualize_instance(dt, instance): # non-terminal nodes for n in dt.nodes: - g.add_node(n, label=dt.nodes[n].feat) + g.add_node(n, label=dt.feature_names[dt.nodes[n].feat]) node = g.get_node(n) node.attr['shape'] = 'circle' node.attr['fontsize'] = 13 @@ -156,7 +154,7 @@ def visualize_expl(dt, instance, expl): # non-terminal nodes for n in dt.nodes: - g.add_node(n, label=dt.nodes[n].feat) + g.add_node(n, label=dt.feature_names[dt.nodes[n].feat]) node = g.get_node(n) node.attr['shape'] = 'circle' node.attr['fontsize'] = 13 diff --git a/pages/application/DecisionTree/utils/upload_tree.py b/pages/application/DecisionTree/utils/upload_tree.py index b3e1297..98bf190 100644 --- a/pages/application/DecisionTree/utils/upload_tree.py +++ b/pages/application/DecisionTree/utils/upload_tree.py @@ -14,7 +14,6 @@ from anytree import Node, RenderTree,AsciiStyle import json import numpy as np import math -import os import six @@ -297,8 +296,8 @@ class UploadedDecisionTree: map += f"{len(self.intvs)}" for f in self.intvs: for j,t in enumerate(self.intvs[f][:-1]): - map += f"\n{f} {j} <={t}" - map += f"\n{f} {j+1} >{t}" + map += f"\n{f} {j} <={np.round(float(t),4)}" + map += f"\n{f} {j+1} >{np.round(float(t),4)}" if feat_names is not None: diff --git a/pages/application/application.py b/pages/application/application.py index 925a1b7..db54577 100644 --- a/pages/application/application.py +++ b/pages/application/application.py @@ -1,5 +1,6 @@ from dash import dcc, html import dash_bootstrap_components as dbc +import dash_daq as daq from pages.application.DecisionTree.DecisionTreeComponent import DecisionTreeComponent @@ -23,6 +24,10 @@ class Model(): self.add_info = False self.model_info = '' + self.enum=1 + self.xtype = ['AXp', 'CXp'] + self.solver="g3" + self.instance = '' self.list_expls = [] @@ -47,12 +52,24 @@ class Model(): def update_pretrained_model_layout_with_info(self, model_info, model_info_filename): self.model_info = model_info - self.component = self.component_class(self.pretrained_model, self.model_info, model_info_filename) + self.component = self.component_class(self.pretrained_model, info=self.model_info, type_info=model_info_filename) - def update_instance(self, instance, enum, xtype, solver="g3"): + def update_instance(self, instance): self.instance = instance - self.list_expls = self.component.update_with_explicability(self.instance, enum, xtype, solver) + self.list_expls = self.component.update_with_explicability(self.instance, self.enum, self.xtype, self.solver) + + def update_enum(self, enum): + self.enum = enum + self.list_expls = self.component.update_with_explicability(self.instance, self.enum, self.xtype, self.solver) + def update_xtype(self, xtype): + self.xtype = xtype + self.list_expls = self.component.update_with_explicability(self.instance, self.enum, self.xtype, self.solver) + + def update_solver(self, solver): + self.solver = solver + self.list_expls = self.component.update_with_explicability(self.instance, self.enum, self.xtype, self.solver) + def update_expl(self, expl): self.expl = expl self.component.draw_explanation(self.instance, expl) @@ -62,17 +79,18 @@ class View(): def __init__(self, model): self.model = model - self.ml_menu_models = dcc.Dropdown(self.model.ml_models, + self.ml_menu_models = html.Div([ + html.Br(), + html.Label("Choose the Machine Learning algorithm :"), + html.Br(), + dcc.Dropdown(self.model.ml_models, id='ml_model_choice', - className="sidebar-dropdown") - - self.ml_library_used = dcc.Dropdown(options = [{'label': 'Scikit-learn ', 'value': "SKL"}, - {'label': 'ITI', 'value': "ITI"}, - {'label': 'IAI', 'value': "IAI"}], - id='ml_library_choice', - className="sidebar-dropdown") + className="dropdown")]) self.pretrained_model_upload = html.Div([ + html.Hr(), + html.Label("Choose the pretrained model : "), + html.Br(), dcc.Upload( id='ml_pretrained_model_choice', children=html.Div([ @@ -83,15 +101,20 @@ class View(): ), html.Div(id='pretrained_model_filename')]) - self.add_model_info_choice = dcc.RadioItems(id="add_info_model_choice", - options = [{'label': 'Yes ', 'value': 1}, - {'label': 'No', 'value': 0}], - value=0, className="sidebar-dropdown") + self.add_model_info_choice = html.Div([ + html.Hr(), + html.Label("Do you wish to upload more info for your model ? : "), + html.Br(), + daq.BooleanSwitch(id='add_info_model_choice', on=False, color="#000000",)]) - self.model_info = html.Div([ + self.model_info = html.Div(id="choice_info_div", + hidden=True, + children=[ + html.Hr(), + html.Label("Choose the pretrained model dataset (csv) or feature definition file (txt): "), + html.Br(), dcc.Upload( id='model_info_choice', - disabled=True, children=html.Div([ 'Drag and Drop or ', html.A('Select File') @@ -101,6 +124,9 @@ class View(): html.Div(id='info_filename')]) self.instance_upload = html.Div([ + html.Hr(), + html.Label("Choose the instance to explain : "), + html.Br(), dcc.Upload( id='ml_instance_choice', children=html.Div([ @@ -111,34 +137,7 @@ class View(): ), html.Div(id='instance_filename')]) - self.sidebar = dcc.Tabs(children=[ - dcc.Tab(label='Basic Parameters', children = [ - html.Br(), - html.Label("Choose the Machine Learning algorithm :"), - html.Br(), - self.ml_menu_models, - html.Hr(), - html.Label("Choose the Machine Learning library used :"), - html.Br(), - self.ml_library_used, - html.Hr(), - html.Label("Choose the pretrained model : "), - html.Br(), - self.pretrained_model_upload, - html.Hr(), - html.Label("Do you wish to upload more info for your model ? : "), - html.Br(), - self.add_model_info_choice, - html.Hr(), - html.Label("Choose the pretrained model dataset (csv) or feature definition file (txt): "), - html.Br(), - self.model_info, - html.Hr(), - html.Label("Choose the instance to explain : "), - html.Br(), - self.instance_upload], className="sidebar"), - dcc.Tab(label='Advanced Parameters', children = [ - html.Br(), + self.num_explanation = html.Div([ html.Label("Choose the number of explanations : "), html.Br(), dcc.Input( @@ -146,29 +145,48 @@ class View(): value=1, type="number", placeholder="How many explanations ?", - className="sidebar-dropdown"), - html.Hr(), + className="dropdown"), + html.Hr()]) + + self.type_explanation = html.Div([ html.Label("Choose the kind of explanation : "), html.Br(), dcc.Checklist( id="explanation_type", options={'AXp' : "Abductive Explanation", 'CXp': "Contrastive explanation"}, value = ['AXp', 'CXp'], - className="sidebar-dropdown", + className="check-boxes", inline=True), - html.Hr(), - html.Label("Choose the SAT solver : "), + html.Hr()]) + + self.solver = html.Div([ html.Label("Choose the SAT solver : "), + html.Br(), + dcc.Dropdown(['g3', 'g4', 'lgl', 'mcb', 'mcm', 'mpl', 'm22', 'mc', 'mgh'], 'g3', id='solver_sat') ]) + + self.sidebar = dcc.Tabs(children=[ + dcc.Tab(label='Basic Parameters', children = [ + self.ml_menu_models, + self.pretrained_model_upload, + self.add_model_info_choice, + self.model_info, + self.instance_upload], className="sidebar"), + dcc.Tab(label='Advanced Parameters', children = [ html.Br(), - dcc.Dropdown(['g3', 'g4', 'lgl', 'mcb', 'mcm', 'mpl', 'm22', 'mc', 'mgh'], 'g3', id='solver_sat') + self.num_explanation, + self.type_explanation, + self.solver ], className="sidebar")]) - self.expl_choice = dcc.Dropdown(self.model.list_expls, + self.expl_choice = html.Div([html.H5(id = "navigate_label", hidden=True, children="Navigate through the explanations and plot them on the tree : "), + html.Div(id='navigate_dropdown', hidden=True, + children = [dcc.Dropdown(self.model.list_expls, id='expl_choice', - className="dropdown") + className="dropdown")])]) - self.layout = dbc.Row([ dbc.Col([self.sidebar], width=3, class_name="sidebar"), + self.layout = dbc.Row([ dbc.Col([self.sidebar], + width=3, class_name="sidebar"), dbc.Col([dbc.Row(id = "graph", children=[]), - dbc.Row(html.Div([html.H5(id = "navigate_label", hidden=True, children="Navigate through the explanations and plot them on the tree : "), - html.Div(self.expl_choice, id='navigate_dropdown', hidden=True)]))], width=5, class_name="column_graph"), + dbc.Row(self.expl_choice)], + width=5, class_name="column_graph"), dbc.Col(html.Main(id = "explanation", children=[], hidden=True), width=4)]) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index aab2fca..4f70ae6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,5 +11,6 @@ scipy>=1.2.1 dash_bootstrap_components dash_interactive_graphviz python-sat[pblib,aiger] -pygraphviz -anytree \ No newline at end of file +pygraphviz==1.9 +anytree==2.8.0 +dash_daq==0.5.0 \ No newline at end of file diff --git a/tests/adult/adult.pkl b/tests/adult/adult.pkl new file mode 100644 index 0000000000000000000000000000000000000000..b18b4d6e77cfc501320ebd5650158dd268530d1d GIT binary patch literal 3033 zcmZo*nR<?!0StOXi?ef56N~cnN{Uib_2QFr5{rvdi>LI6xuhm%7H8(?g%qWxI)g+r z(=t<wrc9oq**K+kibfA-a#3bUYEfo>-jp7e^vt}>DLov;1v!}|C8<SIdRUTDi%X{T zaONgf#HXYdlw?ftX6X^k&CH80PRuRHNiB{CtDWM_)FXf_nv<HCHpQE@M*<{Ro|>7S zQ4*h4l$czSnV%OAmUIWZn}LC$hX-VMT54iRX;EtN6u%xm5Fex_J}*B7EW%Tin3s~D z8(&<KSdu!$JEcbyWNc<`L1|HDNo9OWYI0F(VsYveBs0MQ5D&3=ieC?Ba&kd@VopIu zB9bD$ym*+k@tJw?Q@nY4xboujOG^q$ON!&Ccr*5JfQ?Blj-S#anpc`zP^p)kUzDns zTbfgnnOIbmSUIJKC%z~(IX|zsq^LBxWXj|zJ*;4bQ+n9*QXonuPw{4Go#M=xG^Kq? z&=d`CMsKFpDH)PItSKdx1*sq{Oqmu_Iy)e;%sq@YQ~dn=y#D|H{~t_vGn7n8>U0)> z1sEfgF{NZm63D@DH)e?SuoWjK<|KlmH$&B#g9)axZA#FT9$rwm!aWS~Eh{Lo#82rF zLQOm%(J4JFpcFG@@)U2L42cYBkQXv!Ax>oUW^A33q1uULLCKUPZ$^-8?G%j+PH&bT zE>PUXC+C;ul}z!L>|q6Qi>F|kB-uJ8L#c;3%+w4y1Zt-EY4mXAq^6a`Cud~lq)h4I zE&`_^D32ZLjVV2xB^gDj#Toe^H5{-MF{Otu51e>lsdP$@I3y{gro^Mklz?(UhDU}{ z4@xX#sA0x|H$&T$49|>UZ;rMp8D1H|-U4k?GQ2@L(~#m1t4@iwDH%Q)QQit|Q!;!r zg1t4`reyeKM0p#uO)2%Z@MiQD0L8IW1uFvsEP7$_%?yo12=%}|Xj;J9$^Y-$PgjG8 zfXD{#!w#^><^%~aFfgz{X$ZyPARu4Ov&Z(9{WUR&2$;OK%>iaU8(4sWfdfiIs0a2T zs<Zl4L+{)B!3+jT%vt0BGoKa2XJBA}(Gczj`vp^_gl3*yXkQ2sfRGL`4xn_6jQ>G7 z5Cseepfp1=i~*t#L=e<>qy5;g3lZn-`9SL7SjT}K%7*z17ETah7KaNSw~G{3+_%3A zQvj0KwUD5FJH$A%v|Mi6PliPpNS{F^L4CV+T@U^E;l8~W%wZsX8gm`EKr{mb122?D zb`Ar>1N*#pDGusaFWYy(6oAwTtagCb01P}JJ_92CK)7NK4Q&?Jj^>uwPe67j17UYU z^fNF-BI}z_O3;4{zrC_%xG%CdhZz8(8@wH0@xl+{GcYiq$HS>h`d^K=T($oJ^AJeg zhvfwAYgjkWVzJbDdtT%OXflPMzPe1#e==S-?O($ZKFGc`vmFFMGy?;J5R^ub2NyZ5 z*i56#_6K1e0jX<RPtZP)G7vrpB4Ah{!$BCzhGk1wI)DiOu-{>SBH(7=d3y$A`xw?a zh(HuDh(c-9@Dy^mW03KFdem|Ia#+Fuse8AApgTE4tu%C658IzYj)y6P<Ke&})qpaK z`}S)=_Q3FhR0nY=TLMa>x|79WSK=uxn|F8YJCP+kS_rzc!D>!P%fI{f_o3#3sR!8v z_3ip%`zLed4f|Ed>3Ttx1GqY6D@)8NO~qPKf$Ht{DH&0nPVk(Rzu5t7s|J+znFZlH zZ-CG@`XRK>R0z$$0HF^=LujyO1_p)$5imZK)_~9_p!z3FhVU8UA#_0@gnrQtp)>j* z^nn%#{a`7CX82$aw&Fttln>@HFia?g@}cq!-Vpu{sQyEXAp8eu5ISNagl4FN&^l8f z^p2GfTB998Lyc!p$bj%+@(PU*e%dk!?N9=t=Rw_>kPqQAL_%nXAP7C73PLmFK<EZ& zxH-f?_#28L^nqw_?3E_<2tpeM@p*~4sm0({UF;N%9%je%)G0lj;rT_`;MUTV9!}Sk z(&R)?b971%pKoGOW=Ud>LU2i9Nonzv9xngn<kAADEKg8s4wzY-ky$XMhb1U6Idw`8 zb8u?KlpY@E!~(ER_r%ORB(6_>aq*NMK9Bs;qGE-D)FOrQ)YR-LJ?ze)_E1sfl++%9 bcxam|zAUu})IOim!)mB!pl39tG)WHtDsa^m literal 0 HcmV?d00001 diff --git a/tests/adult/adult_2.pkl b/tests/adult/adult_2.pkl new file mode 100644 index 0000000000000000000000000000000000000000..5221943e347e0a7b2b83e0ee33e5c603396536a3 GIT binary patch literal 2166 zcmZo*nVQYP00upx#o0NjiA8yOB}J*Jdhy9QiN(dK#Z!93TvC%Wi!<}{LW)vTok60R zX_=`-QzlQ*Y@AX%MWcr^xhS(FwJ0+`Z%PkKdS+hclpc=af}G5flGLIpJuFG7#U)dE zICB##;!{!!N;0N+GxrGQX6D5gC*~I9q!!16)lTtd>JdN|%}Gs6o8ryiBLNaDPt8ov zD2Y!iN=z=v%+HGlOS*&I&A`CW!viurEj6*Ev?#TBieC>Oh!0W|pO>Ek7U3yM%uC77 zjV~@qEJ>Z>ozf!;GBz`}ptLBnq%uAwHMuA?u{d=Kl9}KDh=<rb#jl4mIk_M{F{dCS z5lInWUOdd&_{_ZcDc(FiTzT>Nr6mQWCB^Ymycv5qz{aE&$4}`I%`43<sMJf&FG|(R zEzK#(Oe`u&ten!r6JL~?oS#=*QdF8;GG+3V9#*izDLw3YDG()-r+728PH|>Tn$kWc zXo`k6qc>CQlnlup)|8UUf>e+erc8?|ogENa<{n0yDSm!_UjP69{|_d-8A_%kbvg^c z0*n#Lm{Kw&3FKh78#Bau*ou=Aa}q((o1yB=!30y;HYI3E4=*TO;T{J0mKBs(;-~Zo zp(Y-X=#(B7P>Pu{d5SkrhD3%m$O{>=5GOKvGqz62Q0+vrpkzvtHzP>4c8W#@r#EvC z7bx!Hlk-dSN~U=8_OODu#Zxd%;%%Lhq13}1W@?5U0yR_oG<vvlQqxM}lQS}NQl|89 z7lG3dl*bPB#*`k;l8mC%;*5Nd8V*>Bn9{?S2TnY&R63<c9Fi1LQ{vHNN<g_F!y`kf z2PGCV)G*_~o1tw=hG#~wH%Hr)46lq}Z-KTc8QvhBX-M&hRi{MTlnkGYC~t+fDH*;Q z!QL8eQ!@NAqPz{-rj&YHcr$tnfa2Kc1``7VEPA0in}Hb`i4f|6ebBUkwUhtfx1X*C z5do16-iIAvk<AJcU|?Wifzl9)!$Cm4nrDygE&FR?5D_qWZJPtke3*Key<mBU2lgSV zv-(v-@7w!vLPWsioJ9_x^oflBK{;S~28II*rb-FTJiE}o5Gnws9AXISyWnxVNMXf& z`@6^v*|pGt4Qv1d13Q#PmS$jhV4wFc#X<e*W%~|Zr~(iru$rKK4Q&?Jj^>uwPk;qH zNFPHbL4Bt#>3=oea@GC^H&_FN_^{jo7ED|a5e9U3y2xq8W*S|#KgbVN0HT`K6SNPc z41^DY2pCq#aDZ9Q0~LeW3*r8--(i0u;AY@?dj@3t7}gQA?~Xyn`{_}~?aN^XgA9DP zf}p-#iKnz|-rce9ge6FjK93d$aB;;}mY7qTinSmBm5c3DGNL-2FMxC~<ZpHW(;86P zXBLF-ya7Vr=!eigQz0}11B5;h4WUm!<tI#r@DH>==m$$7G{Xmbu=yV<Ap9Lr`9q7K z{FM+|qa8wn6*Dj}C}cqRJD~CkjSzm?G6?NZ0-+~VL1=~?u-8kIdIX`RR(xJ!ZfY^O z%88w#(ZlSRo;sz6Gd#a28(fr6>EU!uDNRlU)s<6v_<R$KGD{M36oN|<OG=BU^l<qn zCzlpLWqE>9bHL2vjLd>5JuE?q$*EI%n1fR*ru6VQCl-Kpx+iAlA#r{3i;Ji9@Ok8y z78NTLq!uZZr>164>0x&U71l+SQ&M{b;-M8nd|7G{sPQnRht*KeK+kAOX_6iQaWd-v literal 0 HcmV?d00001 diff --git a/tests/adult/adult_3.pkl b/tests/adult/adult_3.pkl new file mode 100644 index 0000000000000000000000000000000000000000..b17bc94372fe8d7b6db981e73bf34d6f37b1d07b GIT binary patch literal 1734 zcmZo*nYx>e0StOXi?ef56N~cnN{Uib_2QFr5{rvdi>LI6xuhm%7H8(?g%qWxI)g+r z(=t<wrc9oq**K+kibfA-a#3bUYEfo>-jp7e^vt}>DLov;1v!}|C8<SIdRUTDi%X{T zaONgf#HXYdlw?ftX6g~l&CH80PRuRHNiB{Cs|AS)AdBXtCZ<jC=I@aJ36`g3re~DI zrxhh8mt^MW#e*f?!R}^YVCdli8J?D!SW;S)T0F(ChY!RDsfo|aPXUYY6eZ@R<mbj0 zmn4>?PVr9Z5d|5WnOjg=lvz?4pOTtfl$uzaIt9s0Z~(+ZY@XuR!<n315TBS+kdcU_ zh%YZ5W^H_CUi=hqo*u5e`25n6g3^-W_$l6uJse<TQj6oK^oZt_<`z`yCFd8V>gAT^ zlw>9r6(v?q>EVelN=?qsD=sN2O)i--c}fo}SmBf&_Pi8`lF3uN8Cs_}GbT-GpAs}h z!<*5YsdY+*WDjdfNo7GQNDEV@#gxtth%9ptqs<gQKR>Vk|Ns976W$CZQ<6HJ1z-Wj z2xUwunUVx@Fx-t9Vm)ld$%#3Mpy<s|b>?7#scf4PG^K|Z6s~X&gM7;hN-XhHdW29D z4@h)M4+|*8Oqo2zn<qmeLmK3T3|WX18NC@>r(~#hB3V!}CCQr+BwIU0BZJeMsfP;` zck#*jrFkV&yxDtLLEPdgm?p8ePRUT}VGc7jLk@wODSjF~Tsf&}CGp7_nK>y_dbo?g zX$Z<=hk9d54`)e6QEG8UK1dA*EJaM|;mZRj9#|@!(jyK@3aKgaXfh?BT#(_Bq11yC z3mIydap29+HYLL|BiNgxZAyk$MzFU)+msA%kj^xu_`|AGqHRisPezotLfe!K-;7{y zjkYNnei>2T25nPHy)C>My#+vV?9{=?zyOP07HH%#Lum;0z&>bNz}m_G@7qsTgNT60 z2JgcTu*im~hv^5&Gca&C2*_9S?6JLNe@zS`0w%9*a{#3?Wc&}x0n0Nm90*aJ)vp?Q z-`<ZCDgvVBEF!2c?_G+6`qj(!9lRh7P%N<8ffdSxmRt-RP(FluVDBQQ6`N^v+5R9u zL<CGWttV(7SRDfc!$BAWL@Q(v)VIU_M8M6!^Y#qL_A#t;0B0|@vc#OyRICXXl#kn| zWJGm37l3SH$lvS$rZu3n&nyVvc>{#L(GQ`0rb6fgEfD&_QV6|cC4|;!htOcd7#J87 zG9Y}Iyh0<`X{AX$g3w$LpO=`MS`042Vy9^IFgvEFPU+zc&o9ab7Y$Q-I9*dplM_K@ z@01=s-^8NKlEfT^;F83W(&8yST>i<)r3Fw~o}knmFta!#vtUXOOHg8R>XaVl;M9sK zJv`2d1z?@-iJ5swT%Y{n;we3R9{Ht3#R>(fMGEDqso7I{*quR{zo>FbYL7rXw19~( WODzIbMpJrN4fPE4jHZ+(=>Y(kc4*W9 literal 0 HcmV?d00001 diff --git a/tests/adult/adult_data_00000.inst b/tests/adult/adult_data_00000.inst new file mode 100644 index 0000000..c72f4e9 --- /dev/null +++ b/tests/adult/adult_data_00000.inst @@ -0,0 +1 @@ +f0=1,f1=9,f2=9,f3=7,f4=9,f5=5,f6=7,f7=0,f8=5,f9=3,f10=0,f11=15 \ No newline at end of file diff --git a/tests/iris/decision_tree_classifier_20170212.pkl b/tests/iris/decision_tree_classifier_20170212.pkl new file mode 100644 index 0000000000000000000000000000000000000000..006ccc214168eed2a37f7201ccca66648f1112f7 GIT binary patch literal 1916 zcmZo*nOexs00upx#o0NjiA8yOB}J*Jdhy9QiN(dK#Z!93TvC%Wi!<}{LW)vTok60R zX_=`-QzlQ*Y@AX%MWcr^xhS(FwJ0+`Z%PkKdS+hclpc=af}G5flGLIpJuFG7#U)dE zICB##;!{!!N;0N+GxrGQX6D5gC*~I9q!!16)lTtd>JdN|%}Gs6o8rydBLNaDPt8ov zD2Y!iN=z=v%+HGlOS*&I&A`CW!viurEj6*Ev?#TBieC>Oh!0W|pO>Ek7U3yM%uC77 zjV~@qEJ>Z>ozf!;GBz`}ptLBnq%uAwHMuA?u{d=Kl9}KDh=<rb#jl4mIk_M{F{dCS z5lInWUOdd&_{_ZcDc&qSTzT>Nr6mQWCB^Ymycv5qz{aE&$4}`I%`43<sMJf&FG|(R zEzK#(Oe`u&ten!r6JL~?oS#=*QdF8;GG+3V9#*izDLw3YDG()-r+728PH|>Tn$kWc zXo`k6qc?Nwlnlup)|8UUf>e+eCVz`5ogENa<{rkHDSm!_UjP69{|_d-?MtR4b;eH7 z=wS;^Ey*uVoYKP;mReMtnVg@KUo@qMGc2<R6miLkQ&LN&B!T<@cXozY4_k3^Voo9` z#xs<9m@-jpvO%+np=3&uGY2y?YNoVJ37XQw3yKbSIDrC*6_m!}r}PM+ra6%4lpYpP zLYp#qiZ@G!M20lT=NYmPpD}tfwob_~>O``jWJ;1ZBS^M(ibe*fH**gcD9YoL^Gowe zrg(Gqu!6Y7Q!q{9Y@L#!)WaNRYK9273^hNE9<H3!w37JbjLe*rDLvdp;DiU|u|qvE zrH8X5qbRjFBOj!O1D1@Y^zh|@QyeU5Pw5edq@UE3cr=+3P}a%tM-R{pW7LQP1*bPd z+mwuej3{r8wka8b8ByK>ZBsIWKswWqq5`W<iMA;j!5N9(3T;y|LNcPfHQJ_Rgk~gq z8?;R+^|tV4^cDam45uHA3=E9WC}TpS85kI5%$&*Wa4^YuHM7%G`%I`jm~x1603|YH z{13_j%QG+>fYJ;~Fb0@*bbuuhHZY%o0mf%wU?@mS`(+<tEGrnl;l4dQM}pKH2y|cp z(F_a>tWX-}UWh(nhX*VVHWtJjwAX~ngQ*4=qTQ(s)&M0M9EsHTz#irgh)xLyXtBz` z0TDnZFPu3e?x11q6Ps7R!CnqohQW@YeMK_I3uTU9#IO$<>~IQKJV>C}XW=jfl;PRR z5_3vZv1SucVbeY(BeB!@21KW$1DI}bhR_TSP#P)@mc&9}sE4V6nZp4!2P)ox%RHDm z7!6g=@WCF!vPCrqE-r#54pGg(011N9q#i+N?vBq(%uOu@m*=1&lczYfATdWTCp9m< xBx6bsH-uZBnF8YR6r`3QOG3C1$<!W!cxd?+Uj`~|K@}vcp`L-B(Uj68JphtUcMSjl literal 0 HcmV?d00001 diff --git a/tests/iris/iris.csv b/tests/iris/iris.csv new file mode 100644 index 0000000..1b9d029 --- /dev/null +++ b/tests/iris/iris.csv @@ -0,0 +1,151 @@ +"sepal.length","sepal.width","petal.length","petal.width","variety" +5.1,3.5,1.4,.2,"Setosa" +4.9,3,1.4,.2,"Setosa" +4.7,3.2,1.3,.2,"Setosa" +4.6,3.1,1.5,.2,"Setosa" +5,3.6,1.4,.2,"Setosa" +5.4,3.9,1.7,.4,"Setosa" +4.6,3.4,1.4,.3,"Setosa" +5,3.4,1.5,.2,"Setosa" +4.4,2.9,1.4,.2,"Setosa" +4.9,3.1,1.5,.1,"Setosa" +5.4,3.7,1.5,.2,"Setosa" +4.8,3.4,1.6,.2,"Setosa" +4.8,3,1.4,.1,"Setosa" +4.3,3,1.1,.1,"Setosa" +5.8,4,1.2,.2,"Setosa" +5.7,4.4,1.5,.4,"Setosa" +5.4,3.9,1.3,.4,"Setosa" +5.1,3.5,1.4,.3,"Setosa" +5.7,3.8,1.7,.3,"Setosa" +5.1,3.8,1.5,.3,"Setosa" +5.4,3.4,1.7,.2,"Setosa" +5.1,3.7,1.5,.4,"Setosa" +4.6,3.6,1,.2,"Setosa" +5.1,3.3,1.7,.5,"Setosa" +4.8,3.4,1.9,.2,"Setosa" +5,3,1.6,.2,"Setosa" +5,3.4,1.6,.4,"Setosa" +5.2,3.5,1.5,.2,"Setosa" +5.2,3.4,1.4,.2,"Setosa" +4.7,3.2,1.6,.2,"Setosa" +4.8,3.1,1.6,.2,"Setosa" +5.4,3.4,1.5,.4,"Setosa" +5.2,4.1,1.5,.1,"Setosa" +5.5,4.2,1.4,.2,"Setosa" +4.9,3.1,1.5,.2,"Setosa" +5,3.2,1.2,.2,"Setosa" +5.5,3.5,1.3,.2,"Setosa" +4.9,3.6,1.4,.1,"Setosa" +4.4,3,1.3,.2,"Setosa" +5.1,3.4,1.5,.2,"Setosa" +5,3.5,1.3,.3,"Setosa" +4.5,2.3,1.3,.3,"Setosa" +4.4,3.2,1.3,.2,"Setosa" +5,3.5,1.6,.6,"Setosa" +5.1,3.8,1.9,.4,"Setosa" +4.8,3,1.4,.3,"Setosa" +5.1,3.8,1.6,.2,"Setosa" +4.6,3.2,1.4,.2,"Setosa" +5.3,3.7,1.5,.2,"Setosa" +5,3.3,1.4,.2,"Setosa" +7,3.2,4.7,1.4,"Versicolor" +6.4,3.2,4.5,1.5,"Versicolor" +6.9,3.1,4.9,1.5,"Versicolor" +5.5,2.3,4,1.3,"Versicolor" +6.5,2.8,4.6,1.5,"Versicolor" +5.7,2.8,4.5,1.3,"Versicolor" +6.3,3.3,4.7,1.6,"Versicolor" +4.9,2.4,3.3,1,"Versicolor" +6.6,2.9,4.6,1.3,"Versicolor" +5.2,2.7,3.9,1.4,"Versicolor" +5,2,3.5,1,"Versicolor" +5.9,3,4.2,1.5,"Versicolor" +6,2.2,4,1,"Versicolor" +6.1,2.9,4.7,1.4,"Versicolor" +5.6,2.9,3.6,1.3,"Versicolor" +6.7,3.1,4.4,1.4,"Versicolor" +5.6,3,4.5,1.5,"Versicolor" +5.8,2.7,4.1,1,"Versicolor" +6.2,2.2,4.5,1.5,"Versicolor" +5.6,2.5,3.9,1.1,"Versicolor" +5.9,3.2,4.8,1.8,"Versicolor" +6.1,2.8,4,1.3,"Versicolor" +6.3,2.5,4.9,1.5,"Versicolor" +6.1,2.8,4.7,1.2,"Versicolor" +6.4,2.9,4.3,1.3,"Versicolor" +6.6,3,4.4,1.4,"Versicolor" +6.8,2.8,4.8,1.4,"Versicolor" +6.7,3,5,1.7,"Versicolor" +6,2.9,4.5,1.5,"Versicolor" +5.7,2.6,3.5,1,"Versicolor" +5.5,2.4,3.8,1.1,"Versicolor" +5.5,2.4,3.7,1,"Versicolor" +5.8,2.7,3.9,1.2,"Versicolor" +6,2.7,5.1,1.6,"Versicolor" +5.4,3,4.5,1.5,"Versicolor" +6,3.4,4.5,1.6,"Versicolor" +6.7,3.1,4.7,1.5,"Versicolor" +6.3,2.3,4.4,1.3,"Versicolor" +5.6,3,4.1,1.3,"Versicolor" +5.5,2.5,4,1.3,"Versicolor" +5.5,2.6,4.4,1.2,"Versicolor" +6.1,3,4.6,1.4,"Versicolor" +5.8,2.6,4,1.2,"Versicolor" +5,2.3,3.3,1,"Versicolor" +5.6,2.7,4.2,1.3,"Versicolor" +5.7,3,4.2,1.2,"Versicolor" +5.7,2.9,4.2,1.3,"Versicolor" +6.2,2.9,4.3,1.3,"Versicolor" +5.1,2.5,3,1.1,"Versicolor" +5.7,2.8,4.1,1.3,"Versicolor" +6.3,3.3,6,2.5,"Virginica" +5.8,2.7,5.1,1.9,"Virginica" +7.1,3,5.9,2.1,"Virginica" +6.3,2.9,5.6,1.8,"Virginica" +6.5,3,5.8,2.2,"Virginica" +7.6,3,6.6,2.1,"Virginica" +4.9,2.5,4.5,1.7,"Virginica" +7.3,2.9,6.3,1.8,"Virginica" +6.7,2.5,5.8,1.8,"Virginica" +7.2,3.6,6.1,2.5,"Virginica" +6.5,3.2,5.1,2,"Virginica" +6.4,2.7,5.3,1.9,"Virginica" +6.8,3,5.5,2.1,"Virginica" +5.7,2.5,5,2,"Virginica" +5.8,2.8,5.1,2.4,"Virginica" +6.4,3.2,5.3,2.3,"Virginica" +6.5,3,5.5,1.8,"Virginica" +7.7,3.8,6.7,2.2,"Virginica" +7.7,2.6,6.9,2.3,"Virginica" +6,2.2,5,1.5,"Virginica" +6.9,3.2,5.7,2.3,"Virginica" +5.6,2.8,4.9,2,"Virginica" +7.7,2.8,6.7,2,"Virginica" +6.3,2.7,4.9,1.8,"Virginica" +6.7,3.3,5.7,2.1,"Virginica" +7.2,3.2,6,1.8,"Virginica" +6.2,2.8,4.8,1.8,"Virginica" +6.1,3,4.9,1.8,"Virginica" +6.4,2.8,5.6,2.1,"Virginica" +7.2,3,5.8,1.6,"Virginica" +7.4,2.8,6.1,1.9,"Virginica" +7.9,3.8,6.4,2,"Virginica" +6.4,2.8,5.6,2.2,"Virginica" +6.3,2.8,5.1,1.5,"Virginica" +6.1,2.6,5.6,1.4,"Virginica" +7.7,3,6.1,2.3,"Virginica" +6.3,3.4,5.6,2.4,"Virginica" +6.4,3.1,5.5,1.8,"Virginica" +6,3,4.8,1.8,"Virginica" +6.9,3.1,5.4,2.1,"Virginica" +6.7,3.1,5.6,2.4,"Virginica" +6.9,3.1,5.1,2.3,"Virginica" +5.8,2.7,5.1,1.9,"Virginica" +6.8,3.2,5.9,2.3,"Virginica" +6.7,3.3,5.7,2.5,"Virginica" +6.7,3,5.2,2.3,"Virginica" +6.3,2.5,5,1.9,"Virginica" +6.5,3,5.2,2,"Virginica" +6.2,3.4,5.4,2.3,"Virginica" +5.9,3,5.1,1.8,"Virginica" \ No newline at end of file diff --git a/tests/iris/iris.pkl b/tests/iris/iris.pkl new file mode 100644 index 0000000000000000000000000000000000000000..cf2d521581ec57be284bb87b75316940c16fdcb7 GIT binary patch literal 2047 zcmZo*naan+00upx#o0NjiA8yOB}J*Jdhy9QiN(dK#Z!93TvC%Wi!<}{LW)vTok60R zX_=`-QzlQ*Y@AX%MWcr^xhS(FwJ0+`Z%PkKdS+hclpc=af}G5flGLIpJuFG7#U)dE zICB##;!{!!N;0N+GxrGQX6D5gC*~I9q!!16)lTtd>JdN|%}Gs6o8rybBLNaDPt8ov zD2Y!iN=z=v%+HGlOS*&I&A`CW!viurEj6*Ev?#TBieC>Oh!0W|pO>Ek7U3yM%uC77 zjV~@qEJ>Z>*CPrtH8Z!Mv?#NrGCn0WxhOTUICTn=kzoJFLoA-+*Tb2dTo9j_Q;?B} zq=+vs9%gHNW?uXhZ<Zdey!iaml7iBb;&_njIl#uG7ROKN5zfj_%E?U9%PY+-sEjYj zOwP_pozf%d2jV&w6(v@N7bO-HAO|c*acL4*|CAn9u&yaR?0G4PAhlB_Pw8PT&PXgs zo#M^hI;Dp-zbFM1+KkRqdRS9RDhpDlWXQl+lc)4BhZ-79@n-O5Y@ZS|MZ=r9htXz= zpP!$%fj5gcN6D0=9<Ickoc!|m+}y;1DIKLrN(>AP!3+!xsSFGZB@7G<`3wvU#S9D# zi3|)3AURmj!)TCL7*u@`RBa{$14A-YZw{0O$$`{@Fi1T}4M;4Vfq?<U&V$k*eaLoA z-3PS^6u{sx0f(t5I9T+O^NUjTa!YecG9iJ}!&aP}n3D)fqZz6_OqmwQUeD0<^Yioi z|NsAgFyYNmG9}5GgBfc6l(s2BQ+jwo2?!pwpm=2k<%;+zJwm9t1SC48hXs^1rc9pV z&5|Jj$rKsV8FCr&-i)nNG88kEGL$onGPFBNlVG+?4Pb=W2Z@l{DH<7^-poB*pyV2# zoL`z(GR2#-hZV#vo`Pm3C)`Zc9_BDpGi1N@FxE`*)9B&KNlhz>PtM59Ntx2aT?EcM zP#!zfS5ta8OEQX5i!<^;YB*q7VM-5Q9yrs$a_5vDaY!CWO^HX7DFNmF3~%B>*qfnk zN`_BHm^Vk;lnmdDFmHjjDH(nsy=eqv$6KOpN``+%thYkjl#GCkFmH{vDH(wovEBx4 zQ%b!pycxX(N~R=%0~i{t4A4RiPBSntoH%oa#o<vB)1Cy+r}pKL;D?Y0VjV!q0U7^; zav%yA4nS!JO&9}2H@G;!B9slpXJBA}@gdwl_D!?6F1DS&Z|?^YfRGKr4lEEB11pq< zxtD=~;li0S!VVDOGxiz~29$Im=*|n9r<O-rueAr|FQ_I41_noh`ecq5${a7eV-NEO zM6ZMcJA}c&0i}`LS&)_{><}=`r{s^#Dtk4kJcM#4+CJ3q;vlFGVm<?dGK>MD8yp>` z>VO!ax`3@LF{d;YGuL=CdNa4fa$_twv4FKSxIhEj2}-*{Xt+376&3<bJxoP|BSb%g z2$Y6OG&n%{AMBwbFbXOz0HtBVP<0J3d(gxg7|_&1<w1d=0A-gZ^$5g63#|CE)FMzV RKBb4%P|rZmXi9049spa?ZJ_`F literal 0 HcmV?d00001 diff --git a/tests/iris/iris.txt b/tests/iris/iris.txt new file mode 100644 index 0000000..d356f5d --- /dev/null +++ b/tests/iris/iris.txt @@ -0,0 +1,4 @@ +sepal.length,Categorical,7.6,6.8,7.1,4.9,4.4,6.2,6,7.3,5.9,7.4,5.2,5.6,4.8,6.5,5.5,4.6,6.6,6.4,7,4.5,7.2,5.1,5.8,5.3,6.9,6.1,6.7,4.7,7.7,6.3,5.7,7.9,5.4,4.3,5 +sepal.width,Categorical,4.2,4.4,3.1,2.4,2.9,2,3.8,4.1,4,3.2,2.7,3.3,2.2,2.5,2.3,3.6,3.5,3.9,2.8,2.6,3.7,3,3.4 +petal.length,Categorical,4.2,4.9,4.4,6,5.9,5.2,5.6,4.8,1,5.5,4.6,6.6,1.1,3.8,1.5,6.4,4.1,4,4.5,1.6,3.3,1.4,5.1,1.7,5.8,3.5,3.6,5.3,1.9,6.9,6.1,6.7,4.7,3.9,1.2,1.3,6.3,5.7,3.7,5.4,3,4.3,5 +petal.width,Categorical,2.4,.2,1,2,1.1,1.5,.6,.5,2.2,.3,1.6,1.4,2.5,1.7,2.3,1.8,2.1,1.9,1.2,1.3,.1,.4 \ No newline at end of file diff --git a/tests/iris/iris01.json b/tests/iris/iris01.json new file mode 100644 index 0000000..59c0840 --- /dev/null +++ b/tests/iris/iris01.json @@ -0,0 +1,4 @@ +{"sepal.length":4.9, +"sepal.width":3, +"petal.length":1.4, +"petal.width":0.2} diff --git a/tests/iris/iris2.pkl b/tests/iris/iris2.pkl new file mode 100644 index 0000000000000000000000000000000000000000..cf2d521581ec57be284bb87b75316940c16fdcb7 GIT binary patch literal 2047 zcmZo*naan+00upx#o0NjiA8yOB}J*Jdhy9QiN(dK#Z!93TvC%Wi!<}{LW)vTok60R zX_=`-QzlQ*Y@AX%MWcr^xhS(FwJ0+`Z%PkKdS+hclpc=af}G5flGLIpJuFG7#U)dE zICB##;!{!!N;0N+GxrGQX6D5gC*~I9q!!16)lTtd>JdN|%}Gs6o8rybBLNaDPt8ov zD2Y!iN=z=v%+HGlOS*&I&A`CW!viurEj6*Ev?#TBieC>Oh!0W|pO>Ek7U3yM%uC77 zjV~@qEJ>Z>*CPrtH8Z!Mv?#NrGCn0WxhOTUICTn=kzoJFLoA-+*Tb2dTo9j_Q;?B} zq=+vs9%gHNW?uXhZ<Zdey!iaml7iBb;&_njIl#uG7ROKN5zfj_%E?U9%PY+-sEjYj zOwP_pozf%d2jV&w6(v@N7bO-HAO|c*acL4*|CAn9u&yaR?0G4PAhlB_Pw8PT&PXgs zo#M^hI;Dp-zbFM1+KkRqdRS9RDhpDlWXQl+lc)4BhZ-79@n-O5Y@ZS|MZ=r9htXz= zpP!$%fj5gcN6D0=9<Ickoc!|m+}y;1DIKLrN(>AP!3+!xsSFGZB@7G<`3wvU#S9D# zi3|)3AURmj!)TCL7*u@`RBa{$14A-YZw{0O$$`{@Fi1T}4M;4Vfq?<U&V$k*eaLoA z-3PS^6u{sx0f(t5I9T+O^NUjTa!YecG9iJ}!&aP}n3D)fqZz6_OqmwQUeD0<^Yioi z|NsAgFyYNmG9}5GgBfc6l(s2BQ+jwo2?!pwpm=2k<%;+zJwm9t1SC48hXs^1rc9pV z&5|Jj$rKsV8FCr&-i)nNG88kEGL$onGPFBNlVG+?4Pb=W2Z@l{DH<7^-poB*pyV2# zoL`z(GR2#-hZV#vo`Pm3C)`Zc9_BDpGi1N@FxE`*)9B&KNlhz>PtM59Ntx2aT?EcM zP#!zfS5ta8OEQX5i!<^;YB*q7VM-5Q9yrs$a_5vDaY!CWO^HX7DFNmF3~%B>*qfnk zN`_BHm^Vk;lnmdDFmHjjDH(nsy=eqv$6KOpN``+%thYkjl#GCkFmH{vDH(wovEBx4 zQ%b!pycxX(N~R=%0~i{t4A4RiPBSntoH%oa#o<vB)1Cy+r}pKL;D?Y0VjV!q0U7^; zav%yA4nS!JO&9}2H@G;!B9slpXJBA}@gdwl_D!?6F1DS&Z|?^YfRGKr4lEEB11pq< zxtD=~;li0S!VVDOGxiz~29$Im=*|n9r<O-rueAr|FQ_I41_noh`ecq5${a7eV-NEO zM6ZMcJA}c&0i}`LS&)_{><}=`r{s^#Dtk4kJcM#4+CJ3q;vlFGVm<?dGK>MD8yp>` z>VO!ax`3@LF{d;YGuL=CdNa4fa$_twv4FKSxIhEj2}-*{Xt+376&3<bJxoP|BSb%g z2$Y6OG&n%{AMBwbFbXOz0HtBVP<0J3d(gxg7|_&1<w1d=0A-gZ^$5g63#|CE)FMzV RKBb4%P|rZmXi9049spa?ZJ_`F literal 0 HcmV?d00001 diff --git a/tests/iris/iris_00000.txt b/tests/iris/iris_00000.txt new file mode 100644 index 0000000..108004d --- /dev/null +++ b/tests/iris/iris_00000.txt @@ -0,0 +1 @@ +sepal.length=4.3,sepal.width=2.0,petal.length=1.0,petal.width=0.1 \ No newline at end of file diff --git a/tests/zoo/inst/zoo_00.inst b/tests/zoo/inst/zoo_00.inst new file mode 100644 index 0000000..8d6abc5 --- /dev/null +++ b/tests/zoo/inst/zoo_00.inst @@ -0,0 +1 @@ +f0=1,f1=0,f1=0,f1=1,f1=0,f1=0,f1=1,f1=1,f1=1,f1=1,f1=0,f1=0,f1=4,f1=0,f1=0,f1=1 \ No newline at end of file diff --git a/tests/zoo/inst/zoo_01.inst b/tests/zoo/inst/zoo_01.inst new file mode 100644 index 0000000..4a6df51 --- /dev/null +++ b/tests/zoo/inst/zoo_01.inst @@ -0,0 +1 @@ +1,0,0,1,0,0,0,1,1,1,0,0,4,1,0,1 \ No newline at end of file diff --git a/tests/zoo/inst/zoo_02.inst b/tests/zoo/inst/zoo_02.inst new file mode 100644 index 0000000..d72c0ae --- /dev/null +++ b/tests/zoo/inst/zoo_02.inst @@ -0,0 +1 @@ +0,0,1,0,0,1,1,1,1,0,0,1,0,1,0,0 \ No newline at end of file diff --git a/tests/zoo/inst/zoo_11.inst b/tests/zoo/inst/zoo_11.inst new file mode 100644 index 0000000..0fa9d7c --- /dev/null +++ b/tests/zoo/inst/zoo_11.inst @@ -0,0 +1 @@ +0,1,1,0,1,0,0,0,1,1,0,0,2,1,1,0 \ No newline at end of file diff --git a/tests/zoo/zoo.csv b/tests/zoo/zoo.csv new file mode 100644 index 0000000..7eb9774 --- /dev/null +++ b/tests/zoo/zoo.csv @@ -0,0 +1,102 @@ +hair,feathers,eggs,milk,airborne,aquatic,predator,toothed,backbone,breathes,venomous,fins,legs,tail,domestic,catsize,class_type +1,0,0,1,0,0,1,1,1,1,0,0,4,0,0,1,mammal +1,0,0,1,0,0,0,1,1,1,0,0,4,1,0,1,mammal +0,0,1,0,0,1,1,1,1,0,0,1,0,1,0,0,fish +1,0,0,1,0,0,1,1,1,1,0,0,4,0,0,1,mammal +1,0,0,1,0,0,1,1,1,1,0,0,4,1,0,1,mammal +1,0,0,1,0,0,0,1,1,1,0,0,4,1,0,1,mammal +1,0,0,1,0,0,0,1,1,1,0,0,4,1,1,1,mammal +0,0,1,0,0,1,0,1,1,0,0,1,0,1,1,0,fish +0,0,1,0,0,1,1,1,1,0,0,1,0,1,0,0,fish +1,0,0,1,0,0,0,1,1,1,0,0,4,0,1,0,mammal +1,0,0,1,0,0,1,1,1,1,0,0,4,1,0,1,mammal +0,1,1,0,1,0,0,0,1,1,0,0,2,1,1,0,bird +0,0,1,0,0,1,1,1,1,0,0,1,0,1,0,0,fish +0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,invertebrate +0,0,1,0,0,1,1,0,0,0,0,0,4,0,0,0,invertebrate +0,0,1,0,0,1,1,0,0,0,0,0,6,0,0,0,invertebrate +0,1,1,0,1,0,1,0,1,1,0,0,2,1,0,0,bird +1,0,0,1,0,0,0,1,1,1,0,0,4,1,0,1,mammal +0,0,1,0,0,1,1,1,1,0,0,1,0,1,0,1,fish +0,0,0,1,0,1,1,1,1,1,0,1,0,1,0,1,mammal +0,1,1,0,1,0,0,0,1,1,0,0,2,1,1,0,bird +0,1,1,0,1,1,0,0,1,1,0,0,2,1,0,0,bird +1,0,0,1,0,0,0,1,1,1,0,0,4,1,0,1,mammal +0,1,1,0,1,0,0,0,1,1,0,0,2,1,0,1,bird +0,0,1,0,0,0,0,0,0,1,0,0,6,0,0,0,bug +0,0,1,0,0,1,1,1,1,1,0,0,4,0,0,0,amphibian +0,0,1,0,0,1,1,1,1,1,1,0,4,0,0,0,amphibian +1,0,0,1,1,0,0,1,1,1,0,0,2,1,0,0,mammal +1,0,0,1,0,0,0,1,1,1,0,0,4,1,0,1,mammal +1,0,0,1,0,0,1,1,1,1,0,0,2,0,1,1,mammal +0,0,1,0,1,0,0,0,0,1,0,0,6,0,0,0,bug +1,0,0,1,0,0,0,1,1,1,0,0,4,1,1,1,mammal +1,0,0,1,0,0,0,1,1,1,0,0,2,0,0,1,mammal +0,1,1,0,1,1,1,0,1,1,0,0,2,1,0,0,bird +0,0,1,0,0,1,0,1,1,0,0,1,0,1,0,0,fish +1,0,0,1,0,0,0,1,1,1,0,0,4,1,1,0,mammal +1,0,0,1,0,0,0,1,1,1,0,0,4,1,0,0,mammal +0,1,1,0,1,0,1,0,1,1,0,0,2,1,0,0,bird +0,0,1,0,0,1,1,1,1,0,0,1,0,1,0,0,fish +1,0,1,0,1,0,0,0,0,1,1,0,6,0,1,0,bug +1,0,1,0,1,0,0,0,0,1,0,0,6,0,0,0,bug +0,1,1,0,0,0,1,0,1,1,0,0,2,1,0,0,bird +0,0,1,0,1,0,1,0,0,1,0,0,6,0,0,0,bug +0,1,1,0,1,0,0,0,1,1,0,0,2,1,0,0,bird +1,0,0,1,0,0,1,1,1,1,0,0,4,1,0,1,mammal +1,0,0,1,0,0,1,1,1,1,0,0,4,1,0,1,mammal +0,0,1,0,0,1,1,0,0,0,0,0,6,0,0,0,invertebrate +1,0,0,1,0,0,1,1,1,1,0,0,4,1,0,1,mammal +1,0,0,1,0,1,1,1,1,1,0,0,4,1,0,1,mammal +1,0,0,1,0,0,1,1,1,1,0,0,4,1,0,0,mammal +1,0,0,1,0,0,1,1,1,1,0,0,4,1,0,1,mammal +1,0,1,0,1,0,0,0,0,1,0,0,6,0,0,0,bug +0,0,1,0,0,1,1,1,1,1,0,0,4,1,0,0,amphibian +0,0,1,0,0,1,1,0,0,0,0,0,8,0,0,1,invertebrate +1,0,0,1,0,0,1,1,1,1,0,0,4,1,0,0,mammal +1,0,0,1,0,0,0,1,1,1,0,0,4,1,0,1,mammal +0,1,1,0,0,0,0,0,1,1,0,0,2,1,0,1,bird +0,1,1,0,1,0,0,0,1,1,0,0,2,1,1,0,bird +0,1,1,0,0,1,1,0,1,1,0,0,2,1,0,1,bird +0,1,1,0,1,0,0,0,1,1,0,0,2,1,0,0,bird +0,0,1,0,0,1,1,1,1,0,0,1,0,1,0,1,fish +0,0,1,0,0,1,1,1,1,0,0,1,0,1,0,0,fish +0,0,1,0,0,0,1,1,1,1,1,0,0,1,0,0,reptile +1,0,1,1,0,1,1,0,1,1,0,0,4,1,0,1,mammal +1,0,0,1,0,0,1,1,1,1,0,0,4,1,0,1,mammal +1,0,0,1,0,0,0,1,1,1,0,0,4,1,1,1,mammal +0,0,0,1,0,1,1,1,1,1,0,1,0,1,0,1,mammal +1,0,0,1,0,0,1,1,1,1,0,0,4,1,0,1,mammal +1,0,0,1,0,0,1,1,1,1,0,0,4,1,1,1,mammal +1,0,0,1,0,0,1,1,1,1,0,0,4,1,0,1,mammal +1,0,0,1,0,0,0,1,1,1,0,0,4,1,1,1,mammal +0,1,1,0,0,0,1,0,1,1,0,0,2,1,0,1,bird +0,0,0,0,0,0,1,0,0,1,1,0,8,1,0,0,invertebrate +0,0,1,0,0,1,0,1,1,0,0,1,0,1,0,0,fish +1,0,0,1,0,1,1,1,1,1,0,1,0,0,0,1,mammal +1,0,0,1,0,1,1,1,1,1,0,1,2,1,0,1,mammal +0,0,0,0,0,1,1,1,1,0,1,0,0,1,0,0,reptile +0,0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,invertebrate +0,1,1,0,1,1,1,0,1,1,0,0,2,1,0,0,bird +0,1,1,0,1,1,1,0,1,1,0,0,2,1,0,0,bird +0,0,1,0,0,0,1,1,1,1,0,0,0,1,0,0,reptile +0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,invertebrate +0,0,1,0,0,1,0,1,1,0,0,1,0,1,0,0,fish +0,1,1,0,1,0,0,0,1,1,0,0,2,1,0,0,bird +1,0,0,1,0,0,0,1,1,1,0,0,2,1,0,0,mammal +0,0,1,0,0,1,1,0,0,0,0,0,5,0,0,0,invertebrate +0,0,1,0,0,1,1,1,1,0,1,1,0,1,0,1,fish +0,1,1,0,1,1,0,0,1,1,0,0,2,1,0,1,bird +0,0,1,0,0,0,0,0,0,1,0,0,6,0,0,0,bug +0,0,1,0,0,1,0,1,1,1,0,0,4,0,0,0,amphibian +0,0,1,0,0,0,0,0,1,1,0,0,4,1,0,1,reptile +0,0,1,0,0,0,1,1,1,1,0,0,4,1,0,0,reptile +0,0,1,0,0,1,1,1,1,0,0,1,0,1,0,1,fish +1,0,0,1,1,0,0,1,1,1,0,0,2,1,0,0,mammal +1,0,0,1,0,0,0,1,1,1,0,0,4,1,0,0,mammal +0,1,1,0,1,0,1,0,1,1,0,0,2,1,0,1,bird +1,0,0,1,0,0,0,1,1,1,0,0,2,1,0,1,mammal +1,0,1,0,1,0,0,0,0,1,1,0,6,0,0,0,bug +1,0,0,1,0,0,1,1,1,1,0,0,4,1,0,1,mammal +0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,invertebrate +0,1,1,0,1,0,0,0,1,1,0,0,2,1,0,0,bird \ No newline at end of file diff --git a/tests/zoo/zoo.dt b/tests/zoo/zoo.dt new file mode 100644 index 0000000..a1ee642 --- /dev/null +++ b/tests/zoo/zoo.dt @@ -0,0 +1,85 @@ +41 +1 +I 1 2 3 6 9 10 12 14 17 18 20 21 22 24 28 30 33 35 37 38 +T 4 5 7 8 11 13 15 16 19 23 25 26 27 29 31 32 34 36 39 40 41 +4 T bug +5 T mammal +7 T bird +8 T bug +11 T mammal +13 T fish +15 T bird +16 T reptile +19 T mammal +23 T reptile +25 T reptile +26 T bird +27 T fish +29 T amphibian +31 T amphibian +32 T reptile +34 T invertebrate +36 T invertebrate +39 T invertebrate +40 T bug +41 T invertebrate +1 f4 0 2 +1 f4 1 9 +2 f0 0 3 +2 f0 1 6 +3 f10 0 4 +3 f10 1 5 +6 f12 1 7 +6 f12 5 7 +6 f12 9 7 +6 f12 11 7 +6 f12 3 8 +6 f12 7 8 +9 f15 0 10 +9 f15 1 17 +10 f3 0 11 +10 f3 1 12 +12 f11 0 13 +12 f11 1 14 +14 f12 1 15 +14 f12 9 15 +14 f12 3 16 +14 f12 5 16 +14 f12 7 16 +14 f12 11 16 +17 f8 0 18 +17 f8 1 33 +18 f0 0 19 +18 f0 1 20 +20 f12 1 21 +20 f12 9 21 +20 f12 3 28 +20 f12 5 28 +20 f12 7 28 +20 f12 11 28 +21 f6 0 22 +21 f6 1 27 +22 f10 0 23 +22 f10 1 24 +24 f12 9 25 +24 f12 1 26 +24 f12 3 26 +24 f12 5 26 +24 f12 7 26 +24 f12 11 26 +28 f10 0 29 +28 f10 1 30 +30 f5 0 31 +30 f5 1 32 +33 f5 0 34 +33 f5 1 35 +35 f13 0 36 +35 f13 1 37 +37 f9 0 38 +37 f9 1 41 +38 f12 1 39 +38 f12 5 39 +38 f12 9 39 +38 f12 11 39 +38 f12 3 40 +38 f12 7 40 diff --git a/tests/zoo/zoo.json b/tests/zoo/zoo.json new file mode 100644 index 0000000..506568b --- /dev/null +++ b/tests/zoo/zoo.json @@ -0,0 +1,18 @@ +{ +"hair":1, +"feathers":0, +"eggs":0, +"milk":1, +"airborne":0, +"aquatic":0, +"predator":0, +"toothed":1, +"backbone":1, +"breathes":1, +"venomous":0, +"fins":0, +"legs":6, +"tail":1, +"domestic":0, +"catsize":1 +} diff --git a/tests/zoo/zoo.map b/tests/zoo/zoo.map new file mode 100644 index 0000000..89838b1 --- /dev/null +++ b/tests/zoo/zoo.map @@ -0,0 +1,38 @@ +Categorical +16 +f0 0 =1 +f0 1 =0 +f1 0 =1 +f1 1 =0 +f2 0 =1 +f2 1 =0 +f3 0 =1 +f3 1 =0 +f4 0 =1 +f4 1 =0 +f5 0 =1 +f5 1 =0 +f6 0 =1 +f6 1 =0 +f7 0 =1 +f7 1 =0 +f8 0 =1 +f8 1 =0 +f9 0 =1 +f9 1 =0 +f10 0 =1 +f10 1 =0 +f11 0 =1 +f11 1 =0 +f12 1 =2 +f12 3 =6 +f12 5 =5 +f12 7 =8 +f12 9 =0 +f12 11 =4 +f13 0 =1 +f13 1 =0 +f14 0 =1 +f14 1 =0 +f15 0 =1 +f15 1 =0 diff --git a/tests/zoo/zoo.pkl b/tests/zoo/zoo.pkl new file mode 100644 index 0000000000000000000000000000000000000000..edfd6540dd861d1260292b0bce1efe6d6a809461 GIT binary patch literal 2303 zcmZo*naan+00upx#o0NjiA8yOB}J*Jdhy9QiN(dK#Z!93TvC%Wi!<}{LW)vTok60R zX_=`-QzlQ*Y@AX%MWcr^xhS(FwJ0+`Z%PkKdS+hclpc=af}G5flGLIpJuFG7#U)dE zICB##;!{!!N;0N+GxrGQX6D5gC*~I9q!!16)lTtd>JdN|%}Gs6o8rybBLNaDPt8ov zD2Y!iN=z=v%+HGlOS*&I&A`CW!viurEj6*Ev?#TBieC>Oh!0W|pO>Ek7U3yM%uC77 zjV~@qEJ>Z>*CPrtH8Z!Mv?#NrGCn0WxhOTUICTn=kzoJFLoA-+*Tb2dTo9j_Q;?B} zq=+vs9%gHNW?uXhZ-E}Jy!iaml7iBb;&_njIl#uG7ROKN5zfj_%E?U9%PY+-sEjYj zOwP_pozf%d2jV&w6(v@N7bO-HAO|c*acL4*|CAn9u&yaR?0G4PAhlB_Pw8PT&PXgs zo#M^jI;Dp-zbFM1+KkRqdRS9RDhpDlWXQl+lc)4BhZ-79@n-O5Y@ZS|MZ=r9htXz= zpP!$%fj5gcN6D0=9<Ickoc!|m+}y;1DIKLri3|)3xeN>p1q=)f84L^znG6gJNl+Rj zmj?@bC=HV<VqjoMfr{ayK<Y~w7#Py=DMFG<gW6pTbq|shRwl^3AUBpVFfgPtFff4J zRRU#$>;~~c{(y;r{0icOXb=XmbFi8W5d`T6nF|UZkQpHRK<Yta5EZE8)O}DsD1m_E z6r3hR!O^OhoL`ixms^@sk_n029=77-#GFJ>9?MYeVal{Xj=Bs@KR-XO|NsC02NT{5 zB~y}|IoP4*PidPHG^K|ZlmXyL6O=AlLAg49N{<j~E(eKD>0tq7?J1L|cnf4mKr(fP zbcS4pyf<U(lnliTr3~c^qYUki(j=HIQv(<w_CXR<?G%j+PH*NOE>L!hPtGsRE1BZW z-opyw7EeJllO1lRY7cXmsTs20dKhb__-XWT<)o&S#3yHD=A=yN;VuH_eJGC|>Z>U| zoFy4Wsl^%jAT=DYtURTMFAtpQVWrEI9&tz>PECnNlPLj}UK!rRg|Ih6+msBSj4*GG zwka9D8DZW6ZBsJ*Kzh>%#*Vi{+msCdj971lwka6_8DZWUZBsG=Gh)3B+NP9xTX-{i z3zSSr0tYZOSQ*$L!OOr5r6JS<`;;XA;=iG<?DZi65VFDD0a}PNutG!_VCF!$59}w* zTf67<t(W#n5CJIZ=m0aH1uDV;r6JS<`@Y8(eUB|(+DkwLprnNZDET4de^3ro!2t;U zz@7)ffRY*n^;v=~d_uB5s09pMFb0@bA!r|183O|YFN^`EwH&7EfEf%7J#1x(Ii;zX zso0y*o4p;DJ7U3+2hqae0HIZ&v;>qEfYLC&7L+dnrHR!CF`a<{T^~#wW<I)oFnO3h z7#~K%^x@*e#9{7)@nJN~J{TWHquU1y7nnS?XjphMFicf|npv9EBM=WQ@Z!r-i$JZI QDLt%)dIow%Q%aNc0FKT|f&c&j literal 0 HcmV?d00001 diff --git a/utils.py b/utils.py index b342910..42b30c9 100644 --- a/utils.py +++ b/utils.py @@ -2,6 +2,7 @@ import base64 import io import pickle import joblib +import json import numpy as np from dash import html @@ -43,14 +44,16 @@ def parse_contents_instance(contents, filename): try: if '.csv' in filename: data = decoded.decode('utf-8') + data = str(data).strip().split(',') + data = list(map(lambda i: tuple([i[0], np.float32(i[1])]), [i.split('=') for i in data])) elif '.txt' in filename: - data = decoded.decode('utf-8') - elif '.json' in filename: data = decoded.decode('utf-8') - else : + data = str(data).strip().split(',') + data = list(map(lambda i: tuple([i[0], np.float32(i[1])]), [i.split('=') for i in data])) + elif '.json' in filename: data = decoded.decode('utf-8') - data = str(data).strip().split(',') - data = list(map(lambda i: tuple([i[0], np.float32(i[1])]), [i.split('=') for i in data])) + data = json.loads(data) + data = list(tuple(data.items())) except Exception as e: print(e) return html.Div([ -- GitLab