We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Conversion of HistGradientBoosting fails with scikit-learn 0.24


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `skl2onnx/common/tree_ensemble.py`
Content:
```
1 # -------------------------------------------------------------------------
2 # Copyright (c) Microsoft Corporation. All rights reserved.
3 # Licensed under the MIT License. See License.txt in the project root for
4 # license information.
5 # --------------------------------------------------------------------------
6 """
7 Common functions to convert any learner based on trees.
8 """
9 import numpy as np
10 
11 
12 def get_default_tree_classifier_attribute_pairs():
13     attrs = {}
14     attrs['post_transform'] = 'NONE'
15     attrs['nodes_treeids'] = []
16     attrs['nodes_nodeids'] = []
17     attrs['nodes_featureids'] = []
18     attrs['nodes_modes'] = []
19     attrs['nodes_values'] = []
20     attrs['nodes_truenodeids'] = []
21     attrs['nodes_falsenodeids'] = []
22     attrs['nodes_missing_value_tracks_true'] = []
23     attrs['nodes_hitrates'] = []
24     attrs['class_treeids'] = []
25     attrs['class_nodeids'] = []
26     attrs['class_ids'] = []
27     attrs['class_weights'] = []
28     return attrs
29 
30 
31 def get_default_tree_regressor_attribute_pairs():
32     attrs = {}
33     attrs['post_transform'] = 'NONE'
34     attrs['n_targets'] = 0
35     attrs['nodes_treeids'] = []
36     attrs['nodes_nodeids'] = []
37     attrs['nodes_featureids'] = []
38     attrs['nodes_modes'] = []
39     attrs['nodes_values'] = []
40     attrs['nodes_truenodeids'] = []
41     attrs['nodes_falsenodeids'] = []
42     attrs['nodes_missing_value_tracks_true'] = []
43     attrs['nodes_hitrates'] = []
44     attrs['target_treeids'] = []
45     attrs['target_nodeids'] = []
46     attrs['target_ids'] = []
47     attrs['target_weights'] = []
48     return attrs
49 
50 
51 def find_switch_point(fy, nfy):
52     """
53     Finds the double so that
54     ``(float)x != (float)(x + espilon)``.
55     """
56     a = np.float64(fy)
57     b = np.float64(nfy)
58     fa = np.float32(a)
59     a0, b0 = a, a
60     while a != a0 or b != b0:
61         a0, b0 = a, b
62         m = (a + b) / 2
63         fm = np.float32(m)
64         if fm == fa:
65             a = m
66             fa = fm
67         else:
68             b = m
69     return a
70 
71 
72 def sklearn_threshold(dy, dtype, mode):
73     """
74     *scikit-learn* does not compare x to a threshold
75     but (float)x to a double threshold. As we need a float
76     threshold, we need a different value than the threshold
77     rounded to float. For floats, it finds float *w* which
78     verifies::
79 
80         (float)x <= y <=> (float)x <= w
81 
82     For doubles, it finds double *w* which verifies::
83 
84         (float)x <= y <=> x <= w
85     """
86     if mode == "BRANCH_LEQ":
87         if dtype == np.float32:
88             fy = np.float32(dy)
89             if fy == dy:
90                 return np.float64(fy)
91             if fy < dy:
92                 return np.float64(fy)
93             eps = max(abs(fy), np.finfo(np.float32).eps) * 10
94             nfy = np.nextafter([fy], [fy - eps], dtype=np.float32)[0]
95             return np.float64(nfy)
96         elif dtype == np.float64:
97             fy = np.float32(dy)
98             eps = max(abs(fy), np.finfo(np.float32).eps) * 10
99             afy = np.nextafter([fy], [fy - eps], dtype=np.float32)[0]
100             afy2 = find_switch_point(afy, fy)
101             if fy > dy > afy2:
102                 return afy2
103             bfy = np.nextafter([fy], [fy + eps], dtype=np.float32)[0]
104             bfy2 = find_switch_point(fy, bfy)
105             if fy <= dy <= bfy2:
106                 return bfy2
107             return np.float64(fy)
108         raise TypeError("Unexpected dtype {}.".format(dtype))
109     raise RuntimeError("Threshold is not changed for other mode and "
110                        "'BRANCH_LEQ' (actually '{}').".format(mode))
111 
112 
113 def add_node(attr_pairs, is_classifier, tree_id, tree_weight, node_id,
114              feature_id, mode, value, true_child_id, false_child_id,
115              weights, weight_id_bias, leaf_weights_are_counts,
116              adjust_threshold_for_sklearn, dtype,
117              nodes_missing_value_tracks_true=False):
118     attr_pairs['nodes_treeids'].append(tree_id)
119     attr_pairs['nodes_nodeids'].append(node_id)
120     attr_pairs['nodes_featureids'].append(feature_id)
121     attr_pairs['nodes_modes'].append(mode)
122     if adjust_threshold_for_sklearn and mode != 'LEAF':
123         attr_pairs['nodes_values'].append(
124             sklearn_threshold(value, dtype, mode))
125     else:
126         attr_pairs['nodes_values'].append(value)
127     attr_pairs['nodes_truenodeids'].append(true_child_id)
128     attr_pairs['nodes_falsenodeids'].append(false_child_id)
129     attr_pairs['nodes_missing_value_tracks_true'].append(
130         nodes_missing_value_tracks_true)
131     attr_pairs['nodes_hitrates'].append(1.)
132 
133     # Add leaf information for making prediction
134     if mode == 'LEAF':
135         flattened_weights = weights.flatten()
136         factor = tree_weight
137         # If the values stored at leaves are counts of possible classes, we
138         # need convert them to probabilities by doing a normalization.
139         if leaf_weights_are_counts:
140             s = sum(flattened_weights)
141             factor /= float(s) if s != 0. else 1.
142         flattened_weights = [w * factor for w in flattened_weights]
143         if len(flattened_weights) == 2 and is_classifier:
144             flattened_weights = [flattened_weights[1]]
145 
146         # Note that attribute names for making prediction are different for
147         # classifiers and regressors
148         if is_classifier:
149             for i, w in enumerate(flattened_weights):
150                 attr_pairs['class_treeids'].append(tree_id)
151                 attr_pairs['class_nodeids'].append(node_id)
152                 attr_pairs['class_ids'].append(i + weight_id_bias)
153                 attr_pairs['class_weights'].append(w)
154         else:
155             for i, w in enumerate(flattened_weights):
156                 attr_pairs['target_treeids'].append(tree_id)
157                 attr_pairs['target_nodeids'].append(node_id)
158                 attr_pairs['target_ids'].append(i + weight_id_bias)
159                 attr_pairs['target_weights'].append(w)
160 
161 
162 def add_tree_to_attribute_pairs(attr_pairs, is_classifier, tree, tree_id,
163                                 tree_weight, weight_id_bias,
164                                 leaf_weights_are_counts,
165                                 adjust_threshold_for_sklearn=False,
166                                 dtype=None):
167     for i in range(tree.node_count):
168         node_id = i
169         weight = tree.value[i]
170 
171         if tree.children_left[i] > i or tree.children_right[i] > i:
172             mode = 'BRANCH_LEQ'
173             feat_id = tree.feature[i]
174             threshold = tree.threshold[i]
175             left_child_id = int(tree.children_left[i])
176             right_child_id = int(tree.children_right[i])
177         else:
178             mode = 'LEAF'
179             feat_id = 0
180             threshold = 0.
181             left_child_id = 0
182             right_child_id = 0
183 
184         add_node(attr_pairs, is_classifier, tree_id, tree_weight, node_id,
185                  feat_id, mode, threshold, left_child_id, right_child_id,
186                  weight, weight_id_bias, leaf_weights_are_counts,
187                  adjust_threshold_for_sklearn=adjust_threshold_for_sklearn,
188                  dtype=dtype)
189 
190 
191 def add_tree_to_attribute_pairs_hist_gradient_boosting(
192         attr_pairs, is_classifier, tree, tree_id,
193         tree_weight, weight_id_bias,
194         leaf_weights_are_counts,
195         adjust_threshold_for_sklearn=False,
196         dtype=None):
197     for i, node in enumerate(tree.nodes):
198         node_id = i
199         weight = node['value']
200 
201         if node['is_leaf']:
202             mode = 'LEAF'
203             feat_id = 0
204             threshold = 0.
205             left_child_id = 0
206             right_child_id = 0
207             missing = False
208         else:
209             mode = 'BRANCH_LEQ'
210             feat_id = node['feature_idx']
211             threshold = node['threshold']
212             left_child_id = node['left']
213             right_child_id = node['right']
214             missing = node['missing_go_to_left']
215 
216         add_node(attr_pairs, is_classifier, tree_id, tree_weight, node_id,
217                  feat_id, mode, threshold, left_child_id, right_child_id,
218                  weight, weight_id_bias, leaf_weights_are_counts,
219                  adjust_threshold_for_sklearn=adjust_threshold_for_sklearn,
220                  dtype=dtype, nodes_missing_value_tracks_true=missing)
221
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/skl2onnx/common/tree_ensemble.py b/skl2onnx/common/tree_ensemble.py
--- a/skl2onnx/common/tree_ensemble.py
+++ b/skl2onnx/common/tree_ensemble.py
@@ -208,7 +208,10 @@
         else:
             mode = 'BRANCH_LEQ'
             feat_id = node['feature_idx']
-            threshold = node['threshold']
+            try:
+                threshold = node['threshold']
+            except ValueError:
+                threshold = node['num_threshold']
             left_child_id = node['left']
             right_child_id = node['right']
             missing = node['missing_go_to_left']

{"golden_diff": "diff --git a/skl2onnx/common/tree_ensemble.py b/skl2onnx/common/tree_ensemble.py\n--- a/skl2onnx/common/tree_ensemble.py\n+++ b/skl2onnx/common/tree_ensemble.py\n@@ -208,7 +208,10 @@\n         else:\n             mode = 'BRANCH_LEQ'\n             feat_id = node['feature_idx']\n-            threshold = node['threshold']\n+            try:\n+                threshold = node['threshold']\n+            except ValueError:\n+                threshold = node['num_threshold']\n             left_child_id = node['left']\n             right_child_id = node['right']\n             missing = node['missing_go_to_left']\n", "issue": "Conversion of HistGradientBoosting fails with scikit-learn 0.24\n\n", "before_files": [{"content": "# -------------------------------------------------------------------------\n# Copyright (c) Microsoft Corporation. All rights reserved.\n# Licensed under the MIT License. See License.txt in the project root for\n# license information.\n# --------------------------------------------------------------------------\n\"\"\"\nCommon functions to convert any learner based on trees.\n\"\"\"\nimport numpy as np\n\n\ndef get_default_tree_classifier_attribute_pairs():\n    attrs = {}\n    attrs['post_transform'] = 'NONE'\n    attrs['nodes_treeids'] = []\n    attrs['nodes_nodeids'] = []\n    attrs['nodes_featureids'] = []\n    attrs['nodes_modes'] = []\n    attrs['nodes_values'] = []\n    attrs['nodes_truenodeids'] = []\n    attrs['nodes_falsenodeids'] = []\n    attrs['nodes_missing_value_tracks_true'] = []\n    attrs['nodes_hitrates'] = []\n    attrs['class_treeids'] = []\n    attrs['class_nodeids'] = []\n    attrs['class_ids'] = []\n    attrs['class_weights'] = []\n    return attrs\n\n\ndef get_default_tree_regressor_attribute_pairs():\n    attrs = {}\n    attrs['post_transform'] = 'NONE'\n    attrs['n_targets'] = 0\n    attrs['nodes_treeids'] = []\n    attrs['nodes_nodeids'] = []\n    attrs['nodes_featureids'] = []\n    attrs['nodes_modes'] = []\n    attrs['nodes_values'] = []\n    attrs['nodes_truenodeids'] = []\n    attrs['nodes_falsenodeids'] = []\n    attrs['nodes_missing_value_tracks_true'] = []\n    attrs['nodes_hitrates'] = []\n    attrs['target_treeids'] = []\n    attrs['target_nodeids'] = []\n    attrs['target_ids'] = []\n    attrs['target_weights'] = []\n    return attrs\n\n\ndef find_switch_point(fy, nfy):\n    \"\"\"\n    Finds the double so that\n    ``(float)x != (float)(x + espilon)``.\n    \"\"\"\n    a = np.float64(fy)\n    b = np.float64(nfy)\n    fa = np.float32(a)\n    a0, b0 = a, a\n    while a != a0 or b != b0:\n        a0, b0 = a, b\n        m = (a + b) / 2\n        fm = np.float32(m)\n        if fm == fa:\n            a = m\n            fa = fm\n        else:\n            b = m\n    return a\n\n\ndef sklearn_threshold(dy, dtype, mode):\n    \"\"\"\n    *scikit-learn* does not compare x to a threshold\n    but (float)x to a double threshold. As we need a float\n    threshold, we need a different value than the threshold\n    rounded to float. For floats, it finds float *w* which\n    verifies::\n\n        (float)x <= y <=> (float)x <= w\n\n    For doubles, it finds double *w* which verifies::\n\n        (float)x <= y <=> x <= w\n    \"\"\"\n    if mode == \"BRANCH_LEQ\":\n        if dtype == np.float32:\n            fy = np.float32(dy)\n            if fy == dy:\n                return np.float64(fy)\n            if fy < dy:\n                return np.float64(fy)\n            eps = max(abs(fy), np.finfo(np.float32).eps) * 10\n            nfy = np.nextafter([fy], [fy - eps], dtype=np.float32)[0]\n            return np.float64(nfy)\n        elif dtype == np.float64:\n            fy = np.float32(dy)\n            eps = max(abs(fy), np.finfo(np.float32).eps) * 10\n            afy = np.nextafter([fy], [fy - eps], dtype=np.float32)[0]\n            afy2 = find_switch_point(afy, fy)\n            if fy > dy > afy2:\n                return afy2\n            bfy = np.nextafter([fy], [fy + eps], dtype=np.float32)[0]\n            bfy2 = find_switch_point(fy, bfy)\n            if fy <= dy <= bfy2:\n                return bfy2\n            return np.float64(fy)\n        raise TypeError(\"Unexpected dtype {}.\".format(dtype))\n    raise RuntimeError(\"Threshold is not changed for other mode and \"\n                       \"'BRANCH_LEQ' (actually '{}').\".format(mode))\n\n\ndef add_node(attr_pairs, is_classifier, tree_id, tree_weight, node_id,\n             feature_id, mode, value, true_child_id, false_child_id,\n             weights, weight_id_bias, leaf_weights_are_counts,\n             adjust_threshold_for_sklearn, dtype,\n             nodes_missing_value_tracks_true=False):\n    attr_pairs['nodes_treeids'].append(tree_id)\n    attr_pairs['nodes_nodeids'].append(node_id)\n    attr_pairs['nodes_featureids'].append(feature_id)\n    attr_pairs['nodes_modes'].append(mode)\n    if adjust_threshold_for_sklearn and mode != 'LEAF':\n        attr_pairs['nodes_values'].append(\n            sklearn_threshold(value, dtype, mode))\n    else:\n        attr_pairs['nodes_values'].append(value)\n    attr_pairs['nodes_truenodeids'].append(true_child_id)\n    attr_pairs['nodes_falsenodeids'].append(false_child_id)\n    attr_pairs['nodes_missing_value_tracks_true'].append(\n        nodes_missing_value_tracks_true)\n    attr_pairs['nodes_hitrates'].append(1.)\n\n    # Add leaf information for making prediction\n    if mode == 'LEAF':\n        flattened_weights = weights.flatten()\n        factor = tree_weight\n        # If the values stored at leaves are counts of possible classes, we\n        # need convert them to probabilities by doing a normalization.\n        if leaf_weights_are_counts:\n            s = sum(flattened_weights)\n            factor /= float(s) if s != 0. else 1.\n        flattened_weights = [w * factor for w in flattened_weights]\n        if len(flattened_weights) == 2 and is_classifier:\n            flattened_weights = [flattened_weights[1]]\n\n        # Note that attribute names for making prediction are different for\n        # classifiers and regressors\n        if is_classifier:\n            for i, w in enumerate(flattened_weights):\n                attr_pairs['class_treeids'].append(tree_id)\n                attr_pairs['class_nodeids'].append(node_id)\n                attr_pairs['class_ids'].append(i + weight_id_bias)\n                attr_pairs['class_weights'].append(w)\n        else:\n            for i, w in enumerate(flattened_weights):\n                attr_pairs['target_treeids'].append(tree_id)\n                attr_pairs['target_nodeids'].append(node_id)\n                attr_pairs['target_ids'].append(i + weight_id_bias)\n                attr_pairs['target_weights'].append(w)\n\n\ndef add_tree_to_attribute_pairs(attr_pairs, is_classifier, tree, tree_id,\n                                tree_weight, weight_id_bias,\n                                leaf_weights_are_counts,\n                                adjust_threshold_for_sklearn=False,\n                                dtype=None):\n    for i in range(tree.node_count):\n        node_id = i\n        weight = tree.value[i]\n\n        if tree.children_left[i] > i or tree.children_right[i] > i:\n            mode = 'BRANCH_LEQ'\n            feat_id = tree.feature[i]\n            threshold = tree.threshold[i]\n            left_child_id = int(tree.children_left[i])\n            right_child_id = int(tree.children_right[i])\n        else:\n            mode = 'LEAF'\n            feat_id = 0\n            threshold = 0.\n            left_child_id = 0\n            right_child_id = 0\n\n        add_node(attr_pairs, is_classifier, tree_id, tree_weight, node_id,\n                 feat_id, mode, threshold, left_child_id, right_child_id,\n                 weight, weight_id_bias, leaf_weights_are_counts,\n                 adjust_threshold_for_sklearn=adjust_threshold_for_sklearn,\n                 dtype=dtype)\n\n\ndef add_tree_to_attribute_pairs_hist_gradient_boosting(\n        attr_pairs, is_classifier, tree, tree_id,\n        tree_weight, weight_id_bias,\n        leaf_weights_are_counts,\n        adjust_threshold_for_sklearn=False,\n        dtype=None):\n    for i, node in enumerate(tree.nodes):\n        node_id = i\n        weight = node['value']\n\n        if node['is_leaf']:\n            mode = 'LEAF'\n            feat_id = 0\n            threshold = 0.\n            left_child_id = 0\n            right_child_id = 0\n            missing = False\n        else:\n            mode = 'BRANCH_LEQ'\n            feat_id = node['feature_idx']\n            threshold = node['threshold']\n            left_child_id = node['left']\n            right_child_id = node['right']\n            missing = node['missing_go_to_left']\n\n        add_node(attr_pairs, is_classifier, tree_id, tree_weight, node_id,\n                 feat_id, mode, threshold, left_child_id, right_child_id,\n                 weight, weight_id_bias, leaf_weights_are_counts,\n                 adjust_threshold_for_sklearn=adjust_threshold_for_sklearn,\n                 dtype=dtype, nodes_missing_value_tracks_true=missing)\n", "path": "skl2onnx/common/tree_ensemble.py"}], "after_files": [{"content": "# -------------------------------------------------------------------------\n# Copyright (c) Microsoft Corporation. All rights reserved.\n# Licensed under the MIT License. See License.txt in the project root for\n# license information.\n# --------------------------------------------------------------------------\n\"\"\"\nCommon functions to convert any learner based on trees.\n\"\"\"\nimport numpy as np\n\n\ndef get_default_tree_classifier_attribute_pairs():\n    attrs = {}\n    attrs['post_transform'] = 'NONE'\n    attrs['nodes_treeids'] = []\n    attrs['nodes_nodeids'] = []\n    attrs['nodes_featureids'] = []\n    attrs['nodes_modes'] = []\n    attrs['nodes_values'] = []\n    attrs['nodes_truenodeids'] = []\n    attrs['nodes_falsenodeids'] = []\n    attrs['nodes_missing_value_tracks_true'] = []\n    attrs['nodes_hitrates'] = []\n    attrs['class_treeids'] = []\n    attrs['class_nodeids'] = []\n    attrs['class_ids'] = []\n    attrs['class_weights'] = []\n    return attrs\n\n\ndef get_default_tree_regressor_attribute_pairs():\n    attrs = {}\n    attrs['post_transform'] = 'NONE'\n    attrs['n_targets'] = 0\n    attrs['nodes_treeids'] = []\n    attrs['nodes_nodeids'] = []\n    attrs['nodes_featureids'] = []\n    attrs['nodes_modes'] = []\n    attrs['nodes_values'] = []\n    attrs['nodes_truenodeids'] = []\n    attrs['nodes_falsenodeids'] = []\n    attrs['nodes_missing_value_tracks_true'] = []\n    attrs['nodes_hitrates'] = []\n    attrs['target_treeids'] = []\n    attrs['target_nodeids'] = []\n    attrs['target_ids'] = []\n    attrs['target_weights'] = []\n    return attrs\n\n\ndef find_switch_point(fy, nfy):\n    \"\"\"\n    Finds the double so that\n    ``(float)x != (float)(x + espilon)``.\n    \"\"\"\n    a = np.float64(fy)\n    b = np.float64(nfy)\n    fa = np.float32(a)\n    a0, b0 = a, a\n    while a != a0 or b != b0:\n        a0, b0 = a, b\n        m = (a + b) / 2\n        fm = np.float32(m)\n        if fm == fa:\n            a = m\n            fa = fm\n        else:\n            b = m\n    return a\n\n\ndef sklearn_threshold(dy, dtype, mode):\n    \"\"\"\n    *scikit-learn* does not compare x to a threshold\n    but (float)x to a double threshold. As we need a float\n    threshold, we need a different value than the threshold\n    rounded to float. For floats, it finds float *w* which\n    verifies::\n\n        (float)x <= y <=> (float)x <= w\n\n    For doubles, it finds double *w* which verifies::\n\n        (float)x <= y <=> x <= w\n    \"\"\"\n    if mode == \"BRANCH_LEQ\":\n        if dtype == np.float32:\n            fy = np.float32(dy)\n            if fy == dy:\n                return np.float64(fy)\n            if fy < dy:\n                return np.float64(fy)\n            eps = max(abs(fy), np.finfo(np.float32).eps) * 10\n            nfy = np.nextafter([fy], [fy - eps], dtype=np.float32)[0]\n            return np.float64(nfy)\n        elif dtype == np.float64:\n            fy = np.float32(dy)\n            eps = max(abs(fy), np.finfo(np.float32).eps) * 10\n            afy = np.nextafter([fy], [fy - eps], dtype=np.float32)[0]\n            afy2 = find_switch_point(afy, fy)\n            if fy > dy > afy2:\n                return afy2\n            bfy = np.nextafter([fy], [fy + eps], dtype=np.float32)[0]\n            bfy2 = find_switch_point(fy, bfy)\n            if fy <= dy <= bfy2:\n                return bfy2\n            return np.float64(fy)\n        raise TypeError(\"Unexpected dtype {}.\".format(dtype))\n    raise RuntimeError(\"Threshold is not changed for other mode and \"\n                       \"'BRANCH_LEQ' (actually '{}').\".format(mode))\n\n\ndef add_node(attr_pairs, is_classifier, tree_id, tree_weight, node_id,\n             feature_id, mode, value, true_child_id, false_child_id,\n             weights, weight_id_bias, leaf_weights_are_counts,\n             adjust_threshold_for_sklearn, dtype,\n             nodes_missing_value_tracks_true=False):\n    attr_pairs['nodes_treeids'].append(tree_id)\n    attr_pairs['nodes_nodeids'].append(node_id)\n    attr_pairs['nodes_featureids'].append(feature_id)\n    attr_pairs['nodes_modes'].append(mode)\n    if adjust_threshold_for_sklearn and mode != 'LEAF':\n        attr_pairs['nodes_values'].append(\n            sklearn_threshold(value, dtype, mode))\n    else:\n        attr_pairs['nodes_values'].append(value)\n    attr_pairs['nodes_truenodeids'].append(true_child_id)\n    attr_pairs['nodes_falsenodeids'].append(false_child_id)\n    attr_pairs['nodes_missing_value_tracks_true'].append(\n        nodes_missing_value_tracks_true)\n    attr_pairs['nodes_hitrates'].append(1.)\n\n    # Add leaf information for making prediction\n    if mode == 'LEAF':\n        flattened_weights = weights.flatten()\n        factor = tree_weight\n        # If the values stored at leaves are counts of possible classes, we\n        # need convert them to probabilities by doing a normalization.\n        if leaf_weights_are_counts:\n            s = sum(flattened_weights)\n            factor /= float(s) if s != 0. else 1.\n        flattened_weights = [w * factor for w in flattened_weights]\n        if len(flattened_weights) == 2 and is_classifier:\n            flattened_weights = [flattened_weights[1]]\n\n        # Note that attribute names for making prediction are different for\n        # classifiers and regressors\n        if is_classifier:\n            for i, w in enumerate(flattened_weights):\n                attr_pairs['class_treeids'].append(tree_id)\n                attr_pairs['class_nodeids'].append(node_id)\n                attr_pairs['class_ids'].append(i + weight_id_bias)\n                attr_pairs['class_weights'].append(w)\n        else:\n            for i, w in enumerate(flattened_weights):\n                attr_pairs['target_treeids'].append(tree_id)\n                attr_pairs['target_nodeids'].append(node_id)\n                attr_pairs['target_ids'].append(i + weight_id_bias)\n                attr_pairs['target_weights'].append(w)\n\n\ndef add_tree_to_attribute_pairs(attr_pairs, is_classifier, tree, tree_id,\n                                tree_weight, weight_id_bias,\n                                leaf_weights_are_counts,\n                                adjust_threshold_for_sklearn=False,\n                                dtype=None):\n    for i in range(tree.node_count):\n        node_id = i\n        weight = tree.value[i]\n\n        if tree.children_left[i] > i or tree.children_right[i] > i:\n            mode = 'BRANCH_LEQ'\n            feat_id = tree.feature[i]\n            threshold = tree.threshold[i]\n            left_child_id = int(tree.children_left[i])\n            right_child_id = int(tree.children_right[i])\n        else:\n            mode = 'LEAF'\n            feat_id = 0\n            threshold = 0.\n            left_child_id = 0\n            right_child_id = 0\n\n        add_node(attr_pairs, is_classifier, tree_id, tree_weight, node_id,\n                 feat_id, mode, threshold, left_child_id, right_child_id,\n                 weight, weight_id_bias, leaf_weights_are_counts,\n                 adjust_threshold_for_sklearn=adjust_threshold_for_sklearn,\n                 dtype=dtype)\n\n\ndef add_tree_to_attribute_pairs_hist_gradient_boosting(\n        attr_pairs, is_classifier, tree, tree_id,\n        tree_weight, weight_id_bias,\n        leaf_weights_are_counts,\n        adjust_threshold_for_sklearn=False,\n        dtype=None):\n    for i, node in enumerate(tree.nodes):\n        node_id = i\n        weight = node['value']\n\n        if node['is_leaf']:\n            mode = 'LEAF'\n            feat_id = 0\n            threshold = 0.\n            left_child_id = 0\n            right_child_id = 0\n            missing = False\n        else:\n            mode = 'BRANCH_LEQ'\n            feat_id = node['feature_idx']\n            try:\n                threshold = node['threshold']\n            except ValueError:\n                threshold = node['num_threshold']\n            left_child_id = node['left']\n            right_child_id = node['right']\n            missing = node['missing_go_to_left']\n\n        add_node(attr_pairs, is_classifier, tree_id, tree_weight, node_id,\n                 feat_id, mode, threshold, left_child_id, right_child_id,\n                 weight, weight_id_bias, leaf_weights_are_counts,\n                 adjust_threshold_for_sklearn=adjust_threshold_for_sklearn,\n                 dtype=dtype, nodes_missing_value_tracks_true=missing)\n", "path": "skl2onnx/common/tree_ensemble.py"}]}