ngboost 0.5.9__tar.gz → 0.5.10.dev0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/PKG-INFO +1 -1
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/__init__.py +8 -1
- ngboost-0.5.10.dev0/ngboost/helpers.py +137 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/pyproject.toml +1 -1
- ngboost-0.5.9/ngboost/helpers.py +0 -23
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/LICENSE +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/README.md +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/api.py +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/distns/__init__.py +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/distns/beta.py +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/distns/beta_bernoulli.py +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/distns/betabinomial.py +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/distns/categorical.py +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/distns/cauchy.py +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/distns/distn.py +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/distns/exponential.py +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/distns/gamma.py +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/distns/halfnormal.py +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/distns/laplace.py +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/distns/logitnormal.py +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/distns/lognormal.py +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/distns/multivariate_normal.py +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/distns/normal.py +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/distns/poisson.py +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/distns/sympy_utils.py +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/distns/t.py +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/distns/utils.py +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/distns/weibull.py +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/evaluation.py +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/learners.py +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/manifold.py +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/ngboost.py +0 -0
- {ngboost-0.5.9 → ngboost-0.5.10.dev0}/ngboost/scores.py +0 -0
|
@@ -7,8 +7,15 @@ except ImportError:
|
|
|
7
7
|
from importlib_metadata import version
|
|
8
8
|
|
|
9
9
|
from .api import NGBClassifier, NGBRegressor, NGBSurvival
|
|
10
|
+
from .helpers import load_ngboost_model
|
|
10
11
|
from .ngboost import NGBoost
|
|
11
12
|
|
|
12
|
-
__all__ = [
|
|
13
|
+
__all__ = [
|
|
14
|
+
"NGBClassifier",
|
|
15
|
+
"NGBRegressor",
|
|
16
|
+
"NGBSurvival",
|
|
17
|
+
"NGBoost",
|
|
18
|
+
"load_ngboost_model",
|
|
19
|
+
]
|
|
13
20
|
|
|
14
21
|
__version__ = version(__name__)
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import threading
|
|
3
|
+
import types as _types
|
|
4
|
+
|
|
5
|
+
import joblib
|
|
6
|
+
import numpy as np
|
|
7
|
+
import sklearn.tree._tree as _sklearn_tree # pylint: disable=c-extension-no-member
|
|
8
|
+
from sklearn.utils import check_array
|
|
9
|
+
|
|
10
|
+
# ---------------------------------------------------------------------------
|
|
11
|
+
# Backward compatibility helpers (issue #389)
|
|
12
|
+
# ---------------------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
_TREE_MODULE_SWAP_LOCK = threading.RLock()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class _CompatTree(_sklearn_tree.Tree): # pylint: disable=too-few-public-methods
|
|
18
|
+
"""Transient subclass of sklearn's Tree used only during loading.
|
|
19
|
+
|
|
20
|
+
Overrides ``__setstate__`` to transparently inject the ``missing_go_to_left``
|
|
21
|
+
field that was added in scikit-learn 1.3, so that models pickled with older
|
|
22
|
+
sklearn can be loaded without raising ``ValueError``.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __setstate__(self, state):
|
|
26
|
+
nodes = state.get("nodes")
|
|
27
|
+
if (
|
|
28
|
+
nodes is not None
|
|
29
|
+
and nodes.dtype.names is not None
|
|
30
|
+
and "missing_go_to_left" not in nodes.dtype.names
|
|
31
|
+
):
|
|
32
|
+
new_dtype = np.dtype(nodes.dtype.descr + [("missing_go_to_left", "u1")])
|
|
33
|
+
new_nodes = np.zeros(nodes.shape, dtype=new_dtype)
|
|
34
|
+
for name in nodes.dtype.names:
|
|
35
|
+
new_nodes[name] = nodes[name]
|
|
36
|
+
new_nodes["missing_go_to_left"] = 1 # default: send missing values left
|
|
37
|
+
state = {**state, "nodes": new_nodes}
|
|
38
|
+
super().__setstate__(state)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _make_compat_tree_module():
|
|
42
|
+
"""Return a drop-in replacement for sklearn.tree._tree with Tree → _CompatTree."""
|
|
43
|
+
mod = _types.ModuleType("sklearn.tree._tree")
|
|
44
|
+
for _attr in dir(_sklearn_tree):
|
|
45
|
+
setattr(mod, _attr, getattr(_sklearn_tree, _attr))
|
|
46
|
+
mod.Tree = _CompatTree
|
|
47
|
+
return mod
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _to_proper_tree(compat_tree):
|
|
51
|
+
"""Re-wrap a _CompatTree as a standard sklearn Tree (same state, proper type)."""
|
|
52
|
+
state = compat_tree.__getstate__()
|
|
53
|
+
n_classes = compat_tree.n_classes
|
|
54
|
+
if isinstance(n_classes, int):
|
|
55
|
+
n_classes = np.array([n_classes], dtype=np.intp)
|
|
56
|
+
proper = _sklearn_tree.Tree( # pylint: disable=c-extension-no-member
|
|
57
|
+
compat_tree.n_features, n_classes.copy(), compat_tree.n_outputs
|
|
58
|
+
)
|
|
59
|
+
proper.__setstate__(state)
|
|
60
|
+
return proper
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _fix_compat_trees(model):
|
|
64
|
+
"""Replace every _CompatTree in model.base_models with a proper sklearn Tree."""
|
|
65
|
+
if not hasattr(model, "base_models"):
|
|
66
|
+
return
|
|
67
|
+
for iter_models in model.base_models:
|
|
68
|
+
for estimator in iter_models:
|
|
69
|
+
if hasattr(estimator, "tree_") and isinstance(estimator.tree_, _CompatTree):
|
|
70
|
+
estimator.tree_ = _to_proper_tree(estimator.tree_)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def load_ngboost_model(filepath):
|
|
74
|
+
"""Load an NGBoost model with backward compatibility for older scikit-learn versions.
|
|
75
|
+
|
|
76
|
+
Scikit-learn 1.3 added a ``missing_go_to_left`` field to the internal node
|
|
77
|
+
structure of decision trees. Models trained and saved with scikit-learn < 1.3
|
|
78
|
+
do not contain this field, so loading them under scikit-learn >= 1.3 raises::
|
|
79
|
+
|
|
80
|
+
ValueError: node array from the pickle has an incompatible dtype
|
|
81
|
+
|
|
82
|
+
This function handles the incompatibility transparently by temporarily replacing
|
|
83
|
+
``sklearn.tree._tree.Tree`` in ``sys.modules`` with a compatible subclass that
|
|
84
|
+
injects the missing field during ``__setstate__``. After loading, all trees are
|
|
85
|
+
converted back to standard sklearn ``Tree`` objects so that subsequent use and
|
|
86
|
+
re-serialisation behave normally.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
filepath: Path to the saved model file (joblib or pickle format).
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
The loaded NGBoost model.
|
|
93
|
+
|
|
94
|
+
Example::
|
|
95
|
+
|
|
96
|
+
from ngboost import load_ngboost_model
|
|
97
|
+
model = load_ngboost_model("my_old_model.pkl")
|
|
98
|
+
preds = model.predict(X)
|
|
99
|
+
"""
|
|
100
|
+
with _TREE_MODULE_SWAP_LOCK:
|
|
101
|
+
compat_module = _make_compat_tree_module()
|
|
102
|
+
original_module = sys.modules.get("sklearn.tree._tree")
|
|
103
|
+
sys.modules["sklearn.tree._tree"] = compat_module
|
|
104
|
+
try:
|
|
105
|
+
model = joblib.load(filepath)
|
|
106
|
+
finally:
|
|
107
|
+
if original_module is None:
|
|
108
|
+
sys.modules.pop("sklearn.tree._tree", None)
|
|
109
|
+
else:
|
|
110
|
+
sys.modules["sklearn.tree._tree"] = original_module
|
|
111
|
+
|
|
112
|
+
_fix_compat_trees(model)
|
|
113
|
+
return model
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
# ---------------------------------------------------------------------------
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def Y_from_censored(T, E=None):
|
|
120
|
+
if T is None:
|
|
121
|
+
return None
|
|
122
|
+
if T.dtype == [
|
|
123
|
+
("Event", "?"),
|
|
124
|
+
("Time", "<f8"),
|
|
125
|
+
]: # already processed. Necessary for when d_score() calls score() as in LogNormalCRPScore
|
|
126
|
+
return T
|
|
127
|
+
T = check_array(T, ensure_2d=False)
|
|
128
|
+
T = T.reshape(T.shape[0])
|
|
129
|
+
if E is None:
|
|
130
|
+
E = np.ones_like(T)
|
|
131
|
+
else:
|
|
132
|
+
E = check_array(E, ensure_2d=False)
|
|
133
|
+
E = E.reshape(E.shape[0])
|
|
134
|
+
Y = np.empty(dtype=[("Event", np.bool_), ("Time", np.float64)], shape=T.shape[0])
|
|
135
|
+
Y["Event"] = E.astype(np.bool_)
|
|
136
|
+
Y["Time"] = T.astype(np.float64)
|
|
137
|
+
return Y
|
ngboost-0.5.9/ngboost/helpers.py
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
from sklearn.utils import check_array
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
def Y_from_censored(T, E=None):
|
|
6
|
-
if T is None:
|
|
7
|
-
return None
|
|
8
|
-
if T.dtype == [
|
|
9
|
-
("Event", "?"),
|
|
10
|
-
("Time", "<f8"),
|
|
11
|
-
]: # already processed. Necessary for when d_score() calls score() as in LogNormalCRPScore
|
|
12
|
-
return T
|
|
13
|
-
T = check_array(T, ensure_2d=False)
|
|
14
|
-
T = T.reshape(T.shape[0])
|
|
15
|
-
if E is None:
|
|
16
|
-
E = np.ones_like(T)
|
|
17
|
-
else:
|
|
18
|
-
E = check_array(E, ensure_2d=False)
|
|
19
|
-
E = E.reshape(E.shape[0])
|
|
20
|
-
Y = np.empty(dtype=[("Event", np.bool_), ("Time", np.float64)], shape=T.shape[0])
|
|
21
|
-
Y["Event"] = E.astype(np.bool_)
|
|
22
|
-
Y["Time"] = T.astype(np.float64)
|
|
23
|
-
return Y
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|