mlquantify 0.1.8__py3-none-any.whl → 0.1.10__py3-none-any.whl
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.
- mlquantify/__init__.py +10 -29
- mlquantify/adjust_counting/__init__.py +24 -0
- mlquantify/adjust_counting/_adjustment.py +648 -0
- mlquantify/adjust_counting/_base.py +245 -0
- mlquantify/adjust_counting/_counting.py +153 -0
- mlquantify/adjust_counting/_utils.py +109 -0
- mlquantify/base.py +117 -519
- mlquantify/base_aggregative.py +209 -0
- mlquantify/calibration.py +1 -0
- mlquantify/confidence.py +329 -0
- mlquantify/likelihood/__init__.py +5 -0
- mlquantify/likelihood/_base.py +147 -0
- mlquantify/likelihood/_classes.py +430 -0
- mlquantify/meta/__init__.py +1 -0
- mlquantify/meta/_classes.py +785 -0
- mlquantify/metrics/__init__.py +21 -0
- mlquantify/metrics/_oq.py +109 -0
- mlquantify/metrics/_rq.py +98 -0
- mlquantify/{evaluation/measures.py → metrics/_slq.py} +51 -36
- mlquantify/mixture/__init__.py +7 -0
- mlquantify/mixture/_base.py +147 -0
- mlquantify/mixture/_classes.py +458 -0
- mlquantify/mixture/_utils.py +163 -0
- mlquantify/model_selection/__init__.py +9 -0
- mlquantify/model_selection/_protocol.py +358 -0
- mlquantify/model_selection/_search.py +315 -0
- mlquantify/model_selection/_split.py +1 -0
- mlquantify/multiclass.py +350 -0
- mlquantify/neighbors/__init__.py +9 -0
- mlquantify/neighbors/_base.py +168 -0
- mlquantify/neighbors/_classes.py +150 -0
- mlquantify/{classification/methods.py → neighbors/_classification.py} +37 -62
- mlquantify/neighbors/_kde.py +268 -0
- mlquantify/neighbors/_utils.py +131 -0
- mlquantify/neural/__init__.py +1 -0
- mlquantify/utils/__init__.py +47 -2
- mlquantify/utils/_artificial.py +27 -0
- mlquantify/utils/_constraints.py +219 -0
- mlquantify/utils/_context.py +21 -0
- mlquantify/utils/_decorators.py +36 -0
- mlquantify/utils/_exceptions.py +12 -0
- mlquantify/utils/_get_scores.py +159 -0
- mlquantify/utils/_load.py +18 -0
- mlquantify/utils/_parallel.py +6 -0
- mlquantify/utils/_random.py +36 -0
- mlquantify/utils/_sampling.py +273 -0
- mlquantify/utils/_tags.py +44 -0
- mlquantify/utils/_validation.py +447 -0
- mlquantify/utils/prevalence.py +64 -0
- {mlquantify-0.1.8.dist-info → mlquantify-0.1.10.dist-info}/METADATA +2 -1
- mlquantify-0.1.10.dist-info/RECORD +53 -0
- mlquantify/classification/__init__.py +0 -1
- mlquantify/evaluation/__init__.py +0 -14
- mlquantify/evaluation/protocol.py +0 -289
- mlquantify/methods/__init__.py +0 -37
- mlquantify/methods/aggregative.py +0 -1159
- mlquantify/methods/meta.py +0 -472
- mlquantify/methods/mixture_models.py +0 -1003
- mlquantify/methods/non_aggregative.py +0 -136
- mlquantify/methods/threshold_optimization.py +0 -869
- mlquantify/model_selection.py +0 -377
- mlquantify/plots.py +0 -367
- mlquantify/utils/general.py +0 -371
- mlquantify/utils/method.py +0 -449
- mlquantify-0.1.8.dist-info/RECORD +0 -22
- {mlquantify-0.1.8.dist-info → mlquantify-0.1.10.dist-info}/WHEEL +0 -0
- {mlquantify-0.1.8.dist-info → mlquantify-0.1.10.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
import numbers
|
|
3
|
+
import numpy as np
|
|
4
|
+
from abc import ABC, abstractmethod
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class Interval:
|
|
9
|
+
"""Represents a numeric range constraint."""
|
|
10
|
+
left: float | int | None
|
|
11
|
+
right: float | int | None
|
|
12
|
+
inclusive_left: bool = True
|
|
13
|
+
inclusive_right: bool = True
|
|
14
|
+
discrete: bool = False
|
|
15
|
+
|
|
16
|
+
def is_satisfied_by(self, value):
|
|
17
|
+
if not isinstance(value, (int, float, np.number)):
|
|
18
|
+
return False
|
|
19
|
+
if self.left is not None:
|
|
20
|
+
if self.inclusive_left and value < self.left:
|
|
21
|
+
return False
|
|
22
|
+
if not self.inclusive_left and value <= self.left:
|
|
23
|
+
return False
|
|
24
|
+
if self.right is not None:
|
|
25
|
+
if self.inclusive_right and value > self.right:
|
|
26
|
+
return False
|
|
27
|
+
if not self.inclusive_right and value >= self.right:
|
|
28
|
+
return False
|
|
29
|
+
if self.discrete and not float(value).is_integer():
|
|
30
|
+
return False
|
|
31
|
+
return True
|
|
32
|
+
|
|
33
|
+
def __str__(self):
|
|
34
|
+
left_bracket = "[" if self.inclusive_left else "("
|
|
35
|
+
right_bracket = "]" if self.inclusive_right else ")"
|
|
36
|
+
return f"{left_bracket}{self.left}, {self.right}{right_bracket}"
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass
|
|
40
|
+
class Options:
|
|
41
|
+
"""Represents a fixed set of allowed values."""
|
|
42
|
+
options: list
|
|
43
|
+
|
|
44
|
+
def is_satisfied_by(self, value):
|
|
45
|
+
return value in self.options
|
|
46
|
+
|
|
47
|
+
def __str__(self):
|
|
48
|
+
return f"one of {self.options}"
|
|
49
|
+
|
|
50
|
+
@dataclass
|
|
51
|
+
class _ArrayLikes:
|
|
52
|
+
"""Constraint representing array-likes"""
|
|
53
|
+
|
|
54
|
+
def is_satisfied_by(self, val):
|
|
55
|
+
from mlquantify.utils._validation import _is_arraylike_not_scalar
|
|
56
|
+
return _is_arraylike_not_scalar(val)
|
|
57
|
+
|
|
58
|
+
def __str__(self):
|
|
59
|
+
return "an array-like"
|
|
60
|
+
|
|
61
|
+
@dataclass
|
|
62
|
+
class HasMethods:
|
|
63
|
+
"""Ensures that an object implements specific methods."""
|
|
64
|
+
methods: list[str]
|
|
65
|
+
|
|
66
|
+
def is_satisfied_by(self, value):
|
|
67
|
+
return all(hasattr(value, m) and callable(getattr(value, m)) for m in self.methods)
|
|
68
|
+
|
|
69
|
+
def __str__(self):
|
|
70
|
+
return f"an object implementing {', '.join(self.methods)}"
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@dataclass
|
|
74
|
+
class Hidden:
|
|
75
|
+
"""Used for internal constraints not shown to the user."""
|
|
76
|
+
constraint: object
|
|
77
|
+
|
|
78
|
+
def is_satisfied_by(self, value):
|
|
79
|
+
return self.constraint.is_satisfied_by(value)
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
def hidden(self):
|
|
83
|
+
return True
|
|
84
|
+
|
|
85
|
+
def __str__(self):
|
|
86
|
+
return "<hidden constraint>"
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _type_name(t):
|
|
90
|
+
"""Convert type into human readable string."""
|
|
91
|
+
module = t.__module__
|
|
92
|
+
qualname = t.__qualname__
|
|
93
|
+
if module == "builtins":
|
|
94
|
+
return qualname
|
|
95
|
+
elif t == numbers.Real:
|
|
96
|
+
return "float"
|
|
97
|
+
elif t == numbers.Integral:
|
|
98
|
+
return "int"
|
|
99
|
+
return f"{module}.{qualname}"
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class _Constraint(ABC):
|
|
104
|
+
"""Base class for the constraint objects."""
|
|
105
|
+
|
|
106
|
+
def __init__(self):
|
|
107
|
+
self.hidden = False
|
|
108
|
+
|
|
109
|
+
@abstractmethod
|
|
110
|
+
def is_satisfied_by(self, val):
|
|
111
|
+
"""Whether or not a value satisfies the constraint.
|
|
112
|
+
|
|
113
|
+
Parameters
|
|
114
|
+
----------
|
|
115
|
+
val : object
|
|
116
|
+
The value to check.
|
|
117
|
+
|
|
118
|
+
Returns
|
|
119
|
+
-------
|
|
120
|
+
is_satisfied : bool
|
|
121
|
+
Whether or not the constraint is satisfied by this value.
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
@abstractmethod
|
|
125
|
+
def __str__(self):
|
|
126
|
+
"""A human readable representational string of the constraint."""
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class _InstancesOf(_Constraint):
|
|
131
|
+
"""Constraint representing instances of a given type.
|
|
132
|
+
|
|
133
|
+
Parameters
|
|
134
|
+
----------
|
|
135
|
+
type : type
|
|
136
|
+
The valid type.
|
|
137
|
+
"""
|
|
138
|
+
|
|
139
|
+
def __init__(self, type):
|
|
140
|
+
super().__init__()
|
|
141
|
+
self.type = type
|
|
142
|
+
|
|
143
|
+
def is_satisfied_by(self, val):
|
|
144
|
+
return isinstance(val, self.type)
|
|
145
|
+
|
|
146
|
+
def __str__(self):
|
|
147
|
+
return f"an instance of {_type_name(self.type)!r}"
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def make_constraint(obj):
|
|
151
|
+
"""Normalize strings and simple types into constraint objects."""
|
|
152
|
+
if isinstance(obj, str) and obj == "array-like":
|
|
153
|
+
return _ArrayLikes()
|
|
154
|
+
if isinstance(obj, (Interval, Options, HasMethods, Hidden, CallableConstraint)):
|
|
155
|
+
return obj
|
|
156
|
+
if isinstance(obj, type):
|
|
157
|
+
return _InstancesOf(obj)
|
|
158
|
+
if isinstance(obj, str):
|
|
159
|
+
return StringConstraint(obj)
|
|
160
|
+
if obj is None:
|
|
161
|
+
return NoneConstraint()
|
|
162
|
+
raise TypeError(f"Unsupported constraint type: {obj!r}")
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
@dataclass
|
|
166
|
+
class TypeConstraint:
|
|
167
|
+
type_: type
|
|
168
|
+
|
|
169
|
+
def is_satisfied_by(self, value):
|
|
170
|
+
return isinstance(value, self.type_)
|
|
171
|
+
|
|
172
|
+
def __str__(self):
|
|
173
|
+
return f"instance of {self.type_.__name__}"
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
@dataclass
|
|
177
|
+
class CallableConstraint:
|
|
178
|
+
|
|
179
|
+
def is_satisfied_by(self, value):
|
|
180
|
+
return callable(value)
|
|
181
|
+
|
|
182
|
+
def __str__(self):
|
|
183
|
+
return f"a callable"
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
@dataclass
|
|
187
|
+
class StringConstraint:
|
|
188
|
+
"""Predefined string keywords (e.g., 'array-like', 'random_state')."""
|
|
189
|
+
keyword: str
|
|
190
|
+
|
|
191
|
+
def is_satisfied_by(self, value):
|
|
192
|
+
import scipy.sparse as sp
|
|
193
|
+
import numpy as np
|
|
194
|
+
|
|
195
|
+
if self.keyword == "array-like":
|
|
196
|
+
return isinstance(value, (list, tuple, np.ndarray))
|
|
197
|
+
if self.keyword == "sparse matrix":
|
|
198
|
+
return sp.issparse(value)
|
|
199
|
+
if self.keyword == "boolean":
|
|
200
|
+
return isinstance(value, bool)
|
|
201
|
+
if self.keyword == "random_state":
|
|
202
|
+
return isinstance(value, (np.random.RandomState, int, type(None)))
|
|
203
|
+
if self.keyword == "nan":
|
|
204
|
+
return value is np.nan
|
|
205
|
+
return False
|
|
206
|
+
|
|
207
|
+
def __str__(self):
|
|
208
|
+
return self.keyword
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
@dataclass
|
|
212
|
+
class NoneConstraint:
|
|
213
|
+
"""Allows None as valid value."""
|
|
214
|
+
|
|
215
|
+
def is_satisfied_by(self, value):
|
|
216
|
+
return value is None
|
|
217
|
+
|
|
218
|
+
def __str__(self):
|
|
219
|
+
return "None"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import contextlib
|
|
2
|
+
import threading
|
|
3
|
+
|
|
4
|
+
# Thread-local flag para suportar execuções paralelas
|
|
5
|
+
_validation_context = threading.local()
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@contextlib.contextmanager
|
|
9
|
+
def validation_context(skip: bool = False):
|
|
10
|
+
"""Context manager para controlar se a validação deve ser ignorada."""
|
|
11
|
+
old_state = getattr(_validation_context, "skip_validation", False)
|
|
12
|
+
_validation_context.skip_validation = skip
|
|
13
|
+
try:
|
|
14
|
+
yield
|
|
15
|
+
finally:
|
|
16
|
+
_validation_context.skip_validation = old_state
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def is_validation_skipped():
|
|
20
|
+
"""Verifica se a validação está desativada no contexto atual."""
|
|
21
|
+
return getattr(_validation_context, "skip_validation", False)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from functools import wraps
|
|
2
|
+
|
|
3
|
+
from mlquantify.utils._validation import _is_fitted
|
|
4
|
+
from mlquantify.utils._context import validation_context, is_validation_skipped
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def _fit_context(prefer_skip_nested_validation: bool = False):
|
|
8
|
+
"""
|
|
9
|
+
Decorator to manage validation context during the fit process.
|
|
10
|
+
|
|
11
|
+
Parameters
|
|
12
|
+
----------
|
|
13
|
+
prefer_skip_nested_validation : bool, optional
|
|
14
|
+
If True, prefer to skip nested validation during fitting, by default False.
|
|
15
|
+
"""
|
|
16
|
+
def decorator(fit_method):
|
|
17
|
+
@wraps(fit_method)
|
|
18
|
+
def wrapper(estimator, *args, **kwargs):
|
|
19
|
+
global_skip_validation = is_validation_skipped()
|
|
20
|
+
|
|
21
|
+
# Avoid validation for partial_fit if already fitted
|
|
22
|
+
partial_fit_and_fitted = (
|
|
23
|
+
fit_method.__name__ == "partial_fit" and _is_fitted(estimator)
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
if not global_skip_validation and not partial_fit_and_fitted:
|
|
27
|
+
estimator._validate_params()
|
|
28
|
+
|
|
29
|
+
with validation_context(
|
|
30
|
+
skip=(prefer_skip_nested_validation or global_skip_validation)
|
|
31
|
+
):
|
|
32
|
+
return fit_method(estimator, *args, **kwargs)
|
|
33
|
+
|
|
34
|
+
return wrapper
|
|
35
|
+
|
|
36
|
+
return decorator
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# mlquantify/utils/_exceptions.py
|
|
2
|
+
class InputValidationError(ValueError):
|
|
3
|
+
"""Raised when invalid predictions are passed to a quantifier."""
|
|
4
|
+
pass
|
|
5
|
+
|
|
6
|
+
class InvalidParameterError(ValueError):
|
|
7
|
+
"""Raised when a parameter value does not meet its constraint."""
|
|
8
|
+
pass
|
|
9
|
+
|
|
10
|
+
class NotFittedError(ValueError):
|
|
11
|
+
"""Raised when an operation is attempted on an unfitted quantifier."""
|
|
12
|
+
pass
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from sklearn.model_selection import KFold, StratifiedKFold
|
|
3
|
+
|
|
4
|
+
def apply_cross_validation(
|
|
5
|
+
model,
|
|
6
|
+
X: np.ndarray,
|
|
7
|
+
y: np.ndarray,
|
|
8
|
+
cv= 5,
|
|
9
|
+
function= 'predict_proba',
|
|
10
|
+
stratified= True,
|
|
11
|
+
random_state= None,
|
|
12
|
+
shuffle= True):
|
|
13
|
+
"""
|
|
14
|
+
Perform cross-validation and return predictions with true labels for each fold.
|
|
15
|
+
|
|
16
|
+
Parameters:
|
|
17
|
+
-----------
|
|
18
|
+
model : estimator
|
|
19
|
+
Model with fit and predict/predict_proba methods
|
|
20
|
+
X : np.ndarray
|
|
21
|
+
Feature matrix
|
|
22
|
+
y : np.ndarray
|
|
23
|
+
Target vector
|
|
24
|
+
cv : int, default=5
|
|
25
|
+
Number of cross-validation folds
|
|
26
|
+
function : str, default='predict_proba'
|
|
27
|
+
Method to use for predictions ('predict' or 'predict_proba' or any callable)
|
|
28
|
+
stratified : bool, default=True
|
|
29
|
+
Whether to use stratified cross-validation
|
|
30
|
+
random_state : int or None, default=None
|
|
31
|
+
Random state for reproducibility
|
|
32
|
+
shuffle : bool, default=True
|
|
33
|
+
Whether to shuffle data before splitting
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
--------
|
|
37
|
+
Tuple[np.ndarray, np.ndarray]
|
|
38
|
+
predictions, true_labels for all folds
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
# Choose cross-validation strategy
|
|
42
|
+
if stratified:
|
|
43
|
+
cv_splitter = StratifiedKFold(
|
|
44
|
+
n_splits=cv,
|
|
45
|
+
shuffle=shuffle,
|
|
46
|
+
random_state=random_state
|
|
47
|
+
)
|
|
48
|
+
else:
|
|
49
|
+
cv_splitter = KFold(
|
|
50
|
+
n_splits=cv,
|
|
51
|
+
shuffle=shuffle,
|
|
52
|
+
random_state=random_state
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# Pre-allocate arrays
|
|
56
|
+
all_predictions = []
|
|
57
|
+
all_true_labels = []
|
|
58
|
+
|
|
59
|
+
# Perform cross-validation
|
|
60
|
+
for train_idx, test_idx in cv_splitter.split(X, y):
|
|
61
|
+
X_train, X_test = X[train_idx], X[test_idx]
|
|
62
|
+
y_train, y_test = y[train_idx], y[test_idx]
|
|
63
|
+
|
|
64
|
+
# Fit model
|
|
65
|
+
model.fit(X_train, y_train)
|
|
66
|
+
|
|
67
|
+
if type(function) is str:
|
|
68
|
+
if not hasattr(model, function):
|
|
69
|
+
raise AttributeError(f"The model does not have the method '{function}'.")
|
|
70
|
+
predictions = getattr(model, function)(X_test)
|
|
71
|
+
elif callable(function):
|
|
72
|
+
predictions = function(X_test)
|
|
73
|
+
else:
|
|
74
|
+
raise ValueError("The 'function' parameter must be a string or a callable.")
|
|
75
|
+
|
|
76
|
+
all_predictions.append(predictions)
|
|
77
|
+
all_true_labels.append(y_test)
|
|
78
|
+
|
|
79
|
+
# Concatenate all predictions and labels
|
|
80
|
+
final_predictions = np.vstack(all_predictions) if function == 'predict_proba' else np.concatenate(all_predictions)
|
|
81
|
+
final_true_labels = np.concatenate(all_true_labels)
|
|
82
|
+
|
|
83
|
+
return final_predictions, final_true_labels
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def apply_bootstrap(
|
|
88
|
+
model,
|
|
89
|
+
X: np.ndarray,
|
|
90
|
+
y: np.ndarray = None,
|
|
91
|
+
n_bootstraps: int = 100,
|
|
92
|
+
function: str = 'predict_proba',
|
|
93
|
+
random_state: int = None
|
|
94
|
+
):
|
|
95
|
+
"""
|
|
96
|
+
Perform bootstrap resampling and return predictions with true labels for each bootstrap sample.
|
|
97
|
+
If y is None, bootstrap and fit using only X, and check if model is fitted.
|
|
98
|
+
|
|
99
|
+
Parameters:
|
|
100
|
+
-----------
|
|
101
|
+
model : estimator
|
|
102
|
+
Model with fit and predict/predict_proba methods
|
|
103
|
+
X : np.ndarray
|
|
104
|
+
Feature matrix
|
|
105
|
+
y : np.ndarray or None
|
|
106
|
+
Target vector (optional)
|
|
107
|
+
n_bootstraps : int, default=100
|
|
108
|
+
Number of bootstrap samples
|
|
109
|
+
function : str or callable, default='predict_proba'
|
|
110
|
+
Method to use for predictions ('predict' or 'predict_proba' or any callable)
|
|
111
|
+
random_state : int or None, default=None
|
|
112
|
+
Random state for reproducibility
|
|
113
|
+
"""
|
|
114
|
+
|
|
115
|
+
if random_state is not None:
|
|
116
|
+
np.random.seed(random_state)
|
|
117
|
+
|
|
118
|
+
all_predictions = []
|
|
119
|
+
all_true_labels = [] if y is not None else None
|
|
120
|
+
|
|
121
|
+
for _ in range(n_bootstraps):
|
|
122
|
+
bootstrap_indices = np.random.choice(len(X), size=len(X), replace=True)
|
|
123
|
+
X_bootstrap = X[bootstrap_indices]
|
|
124
|
+
if y is not None:
|
|
125
|
+
y_bootstrap = y[bootstrap_indices]
|
|
126
|
+
model.fit(X_bootstrap, y_bootstrap)
|
|
127
|
+
else:
|
|
128
|
+
model.fit(X_bootstrap)
|
|
129
|
+
|
|
130
|
+
# Check if model is fitted - raise error if not
|
|
131
|
+
if not hasattr(model, "fitted_") or not getattr(model, "fitted_"):
|
|
132
|
+
# Some models have other indicators, as a fallback we could just pass
|
|
133
|
+
# or do other checks. For simplicity, we check fitted_
|
|
134
|
+
# If not fitted, raise exception
|
|
135
|
+
raise ValueError("Model does not appear to be fitted after fit(X).")
|
|
136
|
+
|
|
137
|
+
if type(function) is str:
|
|
138
|
+
if not hasattr(model, function):
|
|
139
|
+
raise AttributeError(f"The model does not have the method '{function}'.")
|
|
140
|
+
predictions = getattr(model, function)(X_bootstrap)
|
|
141
|
+
elif callable(function):
|
|
142
|
+
predictions = function(X_bootstrap)
|
|
143
|
+
else:
|
|
144
|
+
raise ValueError("The 'function' parameter must be a string or a callable.")
|
|
145
|
+
|
|
146
|
+
all_predictions.append(predictions)
|
|
147
|
+
if y is not None:
|
|
148
|
+
all_true_labels.append(y_bootstrap)
|
|
149
|
+
|
|
150
|
+
if function == 'predict_proba':
|
|
151
|
+
final_predictions = np.vstack(all_predictions)
|
|
152
|
+
else:
|
|
153
|
+
final_predictions = np.concatenate(all_predictions)
|
|
154
|
+
|
|
155
|
+
if y is not None:
|
|
156
|
+
final_true_labels = np.concatenate(all_true_labels)
|
|
157
|
+
return final_predictions, final_true_labels
|
|
158
|
+
else:
|
|
159
|
+
return final_predictions
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from joblib import load
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def load_quantifier(path:str):
|
|
5
|
+
"""
|
|
6
|
+
Load a quantifier from a file.
|
|
7
|
+
|
|
8
|
+
Parameters
|
|
9
|
+
----------
|
|
10
|
+
path : str
|
|
11
|
+
Path to the file containing the quantifier.
|
|
12
|
+
|
|
13
|
+
Returns
|
|
14
|
+
-------
|
|
15
|
+
Quantifier
|
|
16
|
+
Loaded quantifier.
|
|
17
|
+
"""
|
|
18
|
+
return load(path)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from numpy.random import RandomState, Generator, default_rng
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def check_random_state(seed=None):
|
|
6
|
+
"""
|
|
7
|
+
Turn seed into a np.random.RandomState or np.random.Generator instance.
|
|
8
|
+
|
|
9
|
+
Parameters
|
|
10
|
+
----------
|
|
11
|
+
seed : None, int, RandomState, Generator
|
|
12
|
+
- If None, return the global RandomState singleton used by np.random.
|
|
13
|
+
- If int, return a new RandomState instance seeded with seed.
|
|
14
|
+
- If RandomState or Generator, return it.
|
|
15
|
+
- Otherwise, raise ValueError.
|
|
16
|
+
|
|
17
|
+
Returns
|
|
18
|
+
-------
|
|
19
|
+
rng : np.random.Generator
|
|
20
|
+
A numpy random generator compatible with modern numpy APIs.
|
|
21
|
+
"""
|
|
22
|
+
if seed is None or seed is np.random:
|
|
23
|
+
return default_rng() # new independent generator each call
|
|
24
|
+
if isinstance(seed, (int, np.integer)):
|
|
25
|
+
return default_rng(seed)
|
|
26
|
+
if isinstance(seed, Generator):
|
|
27
|
+
return seed
|
|
28
|
+
if isinstance(seed, RandomState):
|
|
29
|
+
# Wrap legacy RandomState inside a Generator for uniformity
|
|
30
|
+
bitgen = np.random.MT19937()
|
|
31
|
+
bitgen.state = seed.get_state()
|
|
32
|
+
return Generator(bitgen)
|
|
33
|
+
raise ValueError(
|
|
34
|
+
f"{seed!r} cannot be used to seed a numpy random number generator. "
|
|
35
|
+
"Valid options are None, int, RandomState, or Generator."
|
|
36
|
+
)
|