def parse_nodes(self, nodes): self.nodes, ids = {}, deque() node = Node(0, -1, set(nodes["0"]["treated_as_numerical"])) node.rebuild(nodes["0"]["children_ids"], nodes["0"]["prediction"], nodes["0"]["samples"], nodes["0"]["probabilities"], nodes["0"]["label"]) self.nodes[0] = node ids += node.children_ids if not ids: self.leaves.add(node.id) while ids: dict_node = nodes[safe_str(ids.popleft())] if dict_node.get("values") is not None: node = CategoricalNode( dict_node.pop("id"), dict_node.pop("parent_id"), set(dict_node.pop("treated_as_numerical")), dict_node.pop("feature"), dict_node.pop("values"), others=dict_node.pop("others")) else: node = NumericalNode( dict_node.pop("id"), dict_node.pop("parent_id"), set(dict_node.pop("treated_as_numerical")), dict_node.pop("feature"), beginning=dict_node.pop("beginning", None), end=dict_node.pop("end", None)) node.rebuild(**dict_node) if not node.children_ids: self.leaves.add(node.id) self.nodes[node.id] = node ids += node.children_ids
def add_numerical_split_if_siblings(self, parent_node, feature, value): left, right = None, self.get_node(parent_node.children_ids[0]) right_idx = 0 while right is not None and (right.end is None or right.end < value): right_idx += 1 left = right if right_idx < len(parent_node.children_ids): right = self.get_node(parent_node.children_ids[right_idx]) else: right = None if right is None: new_node = NumericalNode(self.last_index, parent_node.id, set(parent_node.treated_as_numerical), feature, beginning=value) self.last_index += 1 self.add_node(new_node) self.update_numerical_node(left, value, True) return {"left": left.jsonify(), "right": new_node.jsonify(), "parent": parent_node.jsonify()} new_node = NumericalNode(self.last_index, parent_node.id, set(parent_node.treated_as_numerical), feature, end=value) self.last_index += 1 if left is not None: self.kill_children(right) new_node.beginning = left.end self.update_numerical_node(right, value, False) self.add_node(new_node, right_idx) return {"left": new_node.jsonify(), "right": right.jsonify(), "parent": parent_node.jsonify()}
def add_numerical_split_no_siblings(self, parent_node, feature, value): self.features[feature]["nr_uses"] += 1 new_node_left = NumericalNode(self.last_index, parent_node.id, set(parent_node.treated_as_numerical), feature, end=value) self.last_index += 1 new_node_right = NumericalNode(self.last_index, parent_node.id, set(parent_node.treated_as_numerical), feature, beginning=value) self.last_index += 1 self.add_node(new_node_left) self.add_node(new_node_right) return {"left": new_node_left.jsonify(), "right": new_node_right.jsonify(), "parent": parent_node.jsonify()}
def parse_nodes(self, nodes, rebuild_nodes=False, numerical_features=None): self.nodes, ids = {}, deque() root_node_dict = nodes["0"] treated_as_numerical = set(root_node_dict["treated_as_numerical"]) if numerical_features is not None: treated_as_numerical.intersection_update(numerical_features) root_node = Node(0, -1, treated_as_numerical) root_node.label = root_node_dict["label"] self.add_node(root_node) ids += root_node_dict["children_ids"] while ids: dict_node = nodes[safe_str(ids.popleft())] treated_as_numerical = set(dict_node["treated_as_numerical"]) feature = dict_node["feature"] if numerical_features is not None: treated_as_numerical.intersection_update(numerical_features) if dict_node.get("values") is not None: node = CategoricalNode(dict_node["id"], dict_node["parent_id"], treated_as_numerical, feature, dict_node["values"], others=dict_node["others"]) else: node = NumericalNode(dict_node["id"], dict_node["parent_id"], treated_as_numerical, feature, beginning=dict_node.get("beginning", None), end=dict_node.get("end", None)) node.label = dict_node["label"] self.add_node(node) if rebuild_nodes: node.rebuild(dict_node["prediction"], dict_node["samples"], dict_node["probabilities"]) ids += dict_node["children_ids"]