unifiedbooster 0.4.2__py3-none-any.whl → 0.6.0__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.
- unifiedbooster/gbdt.py +3 -1
- unifiedbooster/gbdt_classification.py +36 -36
- unifiedbooster/gbdt_regression.py +36 -36
- unifiedbooster/gpoptimization.py +127 -63
- unifiedbooster/nonconformist/__init__.py +30 -0
- unifiedbooster/nonconformist/acp.py +381 -0
- unifiedbooster/nonconformist/base.py +156 -0
- unifiedbooster/nonconformist/cp.py +172 -0
- unifiedbooster/nonconformist/evaluation.py +486 -0
- unifiedbooster/nonconformist/icp.py +442 -0
- unifiedbooster/nonconformist/nc.py +610 -0
- unifiedbooster/nonconformist/util.py +9 -0
- {unifiedbooster-0.4.2.dist-info → unifiedbooster-0.6.0.dist-info}/METADATA +1 -1
- unifiedbooster-0.6.0.dist-info/RECORD +19 -0
- unifiedbooster-0.4.2.dist-info/RECORD +0 -11
- {unifiedbooster-0.4.2.dist-info → unifiedbooster-0.6.0.dist-info}/LICENSE +0 -0
- {unifiedbooster-0.4.2.dist-info → unifiedbooster-0.6.0.dist-info}/WHEEL +0 -0
- {unifiedbooster-0.4.2.dist-info → unifiedbooster-0.6.0.dist-info}/entry_points.txt +0 -0
- {unifiedbooster-0.4.2.dist-info → unifiedbooster-0.6.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,486 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Evaluation of conformal predictors.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
# Authors: Henrik Linusson
|
|
8
|
+
|
|
9
|
+
# TODO: cross_val_score/run_experiment should possibly allow multiple to be evaluated on identical folding
|
|
10
|
+
|
|
11
|
+
from __future__ import division
|
|
12
|
+
|
|
13
|
+
from nonconformist.base import RegressorMixin, ClassifierMixin
|
|
14
|
+
|
|
15
|
+
import sys
|
|
16
|
+
import numpy as np
|
|
17
|
+
import pandas as pd
|
|
18
|
+
|
|
19
|
+
from sklearn.cross_validation import StratifiedShuffleSplit
|
|
20
|
+
from sklearn.cross_validation import KFold
|
|
21
|
+
from sklearn.cross_validation import train_test_split
|
|
22
|
+
from sklearn.base import clone, BaseEstimator
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class BaseIcpCvHelper(BaseEstimator):
|
|
26
|
+
"""Base class for cross validation helpers."""
|
|
27
|
+
|
|
28
|
+
def __init__(self, icp, calibration_portion):
|
|
29
|
+
super(BaseIcpCvHelper, self).__init__()
|
|
30
|
+
self.icp = icp
|
|
31
|
+
self.calibration_portion = calibration_portion
|
|
32
|
+
|
|
33
|
+
def predict(self, x, significance=None):
|
|
34
|
+
return self.icp.predict(x, significance)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class ClassIcpCvHelper(BaseIcpCvHelper, ClassifierMixin):
|
|
38
|
+
"""Helper class for running the ``cross_val_score`` evaluation
|
|
39
|
+
method on IcpClassifiers.
|
|
40
|
+
|
|
41
|
+
See also
|
|
42
|
+
--------
|
|
43
|
+
IcpRegCrossValHelper
|
|
44
|
+
|
|
45
|
+
Examples
|
|
46
|
+
--------
|
|
47
|
+
>>> from sklearn.datasets import load_iris
|
|
48
|
+
>>> from sklearn.ensemble import RandomForestClassifier
|
|
49
|
+
>>> from nonconformist.icp import IcpClassifier
|
|
50
|
+
>>> from nonconformist.nc import ClassifierNc, MarginErrFunc
|
|
51
|
+
>>> from nonconformist.evaluation import ClassIcpCvHelper
|
|
52
|
+
>>> from nonconformist.evaluation import class_mean_errors
|
|
53
|
+
>>> from nonconformist.evaluation import cross_val_score
|
|
54
|
+
>>> data = load_iris()
|
|
55
|
+
>>> nc = ProbEstClassifierNc(RandomForestClassifier(), MarginErrFunc())
|
|
56
|
+
>>> icp = IcpClassifier(nc)
|
|
57
|
+
>>> icp_cv = ClassIcpCvHelper(icp)
|
|
58
|
+
>>> cross_val_score(icp_cv,
|
|
59
|
+
... data.data,
|
|
60
|
+
... data.target,
|
|
61
|
+
... iterations=2,
|
|
62
|
+
... folds=2,
|
|
63
|
+
... scoring_funcs=[class_mean_errors],
|
|
64
|
+
... significance_levels=[0.1])
|
|
65
|
+
... # doctest: +SKIP
|
|
66
|
+
class_mean_errors fold iter significance
|
|
67
|
+
0 0.013333 0 0 0.1
|
|
68
|
+
1 0.080000 1 0 0.1
|
|
69
|
+
2 0.053333 0 1 0.1
|
|
70
|
+
3 0.080000 1 1 0.1
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
def __init__(self, icp, calibration_portion=0.25):
|
|
74
|
+
super(ClassIcpCvHelper, self).__init__(icp, calibration_portion)
|
|
75
|
+
|
|
76
|
+
def fit(self, x, y):
|
|
77
|
+
split = StratifiedShuffleSplit(
|
|
78
|
+
y, n_iter=1, test_size=self.calibration_portion
|
|
79
|
+
)
|
|
80
|
+
for train, cal in split:
|
|
81
|
+
self.icp.fit(x[train, :], y[train])
|
|
82
|
+
self.icp.calibrate(x[cal, :], y[cal])
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class RegIcpCvHelper(BaseIcpCvHelper, RegressorMixin):
|
|
86
|
+
"""Helper class for running the ``cross_val_score`` evaluation
|
|
87
|
+
method on IcpRegressors.
|
|
88
|
+
|
|
89
|
+
See also
|
|
90
|
+
--------
|
|
91
|
+
IcpClassCrossValHelper
|
|
92
|
+
|
|
93
|
+
Examples
|
|
94
|
+
--------
|
|
95
|
+
>>> from sklearn.datasets import load_boston
|
|
96
|
+
>>> from sklearn.ensemble import RandomForestRegressor
|
|
97
|
+
>>> from nonconformist.icp import IcpRegressor
|
|
98
|
+
>>> from nonconformist.nc import RegressorNc, AbsErrorErrFunc
|
|
99
|
+
>>> from nonconformist.evaluation import RegIcpCvHelper
|
|
100
|
+
>>> from nonconformist.evaluation import reg_mean_errors
|
|
101
|
+
>>> from nonconformist.evaluation import cross_val_score
|
|
102
|
+
>>> data = load_boston()
|
|
103
|
+
>>> nc = RegressorNc(RandomForestRegressor(), AbsErrorErrFunc())
|
|
104
|
+
>>> icp = IcpRegressor(nc)
|
|
105
|
+
>>> icp_cv = RegIcpCvHelper(icp)
|
|
106
|
+
>>> cross_val_score(icp_cv,
|
|
107
|
+
... data.data,
|
|
108
|
+
... data.target,
|
|
109
|
+
... iterations=2,
|
|
110
|
+
... folds=2,
|
|
111
|
+
... scoring_funcs=[reg_mean_errors],
|
|
112
|
+
... significance_levels=[0.1])
|
|
113
|
+
... # doctest: +SKIP
|
|
114
|
+
fold iter reg_mean_errors significance
|
|
115
|
+
0 0 0 0.185771 0.1
|
|
116
|
+
1 1 0 0.138340 0.1
|
|
117
|
+
2 0 1 0.071146 0.1
|
|
118
|
+
3 1 1 0.043478 0.1
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
|
+
def __init__(self, icp, calibration_portion=0.25):
|
|
122
|
+
super(RegIcpCvHelper, self).__init__(icp, calibration_portion)
|
|
123
|
+
|
|
124
|
+
def fit(self, x, y):
|
|
125
|
+
split = train_test_split(x, y, test_size=self.calibration_portion)
|
|
126
|
+
x_tr, x_cal, y_tr, y_cal = split[0], split[1], split[2], split[3]
|
|
127
|
+
self.icp.fit(x_tr, y_tr)
|
|
128
|
+
self.icp.calibrate(x_cal, y_cal)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
# -----------------------------------------------------------------------------
|
|
132
|
+
#
|
|
133
|
+
# -----------------------------------------------------------------------------
|
|
134
|
+
def cross_val_score(
|
|
135
|
+
model,
|
|
136
|
+
x,
|
|
137
|
+
y,
|
|
138
|
+
iterations=10,
|
|
139
|
+
folds=10,
|
|
140
|
+
fit_params=None,
|
|
141
|
+
scoring_funcs=None,
|
|
142
|
+
significance_levels=None,
|
|
143
|
+
verbose=False,
|
|
144
|
+
):
|
|
145
|
+
"""Evaluates a conformal predictor using cross-validation.
|
|
146
|
+
|
|
147
|
+
Parameters
|
|
148
|
+
----------
|
|
149
|
+
model : object
|
|
150
|
+
Conformal predictor to evaluate.
|
|
151
|
+
|
|
152
|
+
x : numpy array of shape [n_samples, n_features]
|
|
153
|
+
Inputs of data to use for evaluation.
|
|
154
|
+
|
|
155
|
+
y : numpy array of shape [n_samples]
|
|
156
|
+
Outputs of data to use for evaluation.
|
|
157
|
+
|
|
158
|
+
iterations : int
|
|
159
|
+
Number of iterations to use for evaluation. The data set is randomly
|
|
160
|
+
shuffled before each iteration.
|
|
161
|
+
|
|
162
|
+
folds : int
|
|
163
|
+
Number of folds to use for evaluation.
|
|
164
|
+
|
|
165
|
+
fit_params : dictionary
|
|
166
|
+
Parameters to supply to the conformal prediction object on training.
|
|
167
|
+
|
|
168
|
+
scoring_funcs : iterable
|
|
169
|
+
List of evaluation functions to apply to the conformal predictor in each
|
|
170
|
+
fold. Each evaluation function should have a signature
|
|
171
|
+
``scorer(prediction, y, significance)``.
|
|
172
|
+
|
|
173
|
+
significance_levels : iterable
|
|
174
|
+
List of significance levels at which to evaluate the conformal
|
|
175
|
+
predictor.
|
|
176
|
+
|
|
177
|
+
verbose : boolean
|
|
178
|
+
Indicates whether to output progress information during evaluation.
|
|
179
|
+
|
|
180
|
+
Returns
|
|
181
|
+
-------
|
|
182
|
+
scores : pandas DataFrame
|
|
183
|
+
Tabulated results for each iteration, fold and evaluation function.
|
|
184
|
+
"""
|
|
185
|
+
|
|
186
|
+
fit_params = fit_params if fit_params else {}
|
|
187
|
+
significance_levels = (
|
|
188
|
+
significance_levels
|
|
189
|
+
if significance_levels is not None
|
|
190
|
+
else np.arange(0.01, 1.0, 0.01)
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
df = pd.DataFrame()
|
|
194
|
+
|
|
195
|
+
columns = [
|
|
196
|
+
"iter",
|
|
197
|
+
"fold",
|
|
198
|
+
"significance",
|
|
199
|
+
] + [f.__name__ for f in scoring_funcs]
|
|
200
|
+
for i in range(iterations):
|
|
201
|
+
idx = np.random.permutation(y.size)
|
|
202
|
+
x, y = x[idx, :], y[idx]
|
|
203
|
+
cv = KFold(y.size, folds)
|
|
204
|
+
for j, (train, test) in enumerate(cv):
|
|
205
|
+
if verbose:
|
|
206
|
+
sys.stdout.write(
|
|
207
|
+
"\riter {}/{} fold {}/{}".format(
|
|
208
|
+
i + 1, iterations, j + 1, folds
|
|
209
|
+
)
|
|
210
|
+
)
|
|
211
|
+
m = clone(model)
|
|
212
|
+
m.fit(x[train, :], y[train], **fit_params)
|
|
213
|
+
prediction = m.predict(x[test, :], significance=None)
|
|
214
|
+
for k, s in enumerate(significance_levels):
|
|
215
|
+
scores = [
|
|
216
|
+
scoring_func(prediction, y[test], s)
|
|
217
|
+
for scoring_func in scoring_funcs
|
|
218
|
+
]
|
|
219
|
+
df_score = pd.DataFrame([[i, j, s] + scores], columns=columns)
|
|
220
|
+
df = df.append(df_score, ignore_index=True)
|
|
221
|
+
|
|
222
|
+
return df
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def run_experiment(
|
|
226
|
+
models,
|
|
227
|
+
csv_files,
|
|
228
|
+
iterations=10,
|
|
229
|
+
folds=10,
|
|
230
|
+
fit_params=None,
|
|
231
|
+
scoring_funcs=None,
|
|
232
|
+
significance_levels=None,
|
|
233
|
+
normalize=False,
|
|
234
|
+
verbose=False,
|
|
235
|
+
header=0,
|
|
236
|
+
):
|
|
237
|
+
"""Performs a cross-validation evaluation of one or several conformal
|
|
238
|
+
predictors on a collection of data sets in csv format.
|
|
239
|
+
|
|
240
|
+
Parameters
|
|
241
|
+
----------
|
|
242
|
+
models : object or iterable
|
|
243
|
+
Conformal predictor(s) to evaluate.
|
|
244
|
+
|
|
245
|
+
csv_files : iterable
|
|
246
|
+
List of file names (with absolute paths) containing csv-data, used to
|
|
247
|
+
evaluate the conformal predictor.
|
|
248
|
+
|
|
249
|
+
iterations : int
|
|
250
|
+
Number of iterations to use for evaluation. The data set is randomly
|
|
251
|
+
shuffled before each iteration.
|
|
252
|
+
|
|
253
|
+
folds : int
|
|
254
|
+
Number of folds to use for evaluation.
|
|
255
|
+
|
|
256
|
+
fit_params : dictionary
|
|
257
|
+
Parameters to supply to the conformal prediction object on training.
|
|
258
|
+
|
|
259
|
+
scoring_funcs : iterable
|
|
260
|
+
List of evaluation functions to apply to the conformal predictor in each
|
|
261
|
+
fold. Each evaluation function should have a signature
|
|
262
|
+
``scorer(prediction, y, significance)``.
|
|
263
|
+
|
|
264
|
+
significance_levels : iterable
|
|
265
|
+
List of significance levels at which to evaluate the conformal
|
|
266
|
+
predictor.
|
|
267
|
+
|
|
268
|
+
verbose : boolean
|
|
269
|
+
Indicates whether to output progress information during evaluation.
|
|
270
|
+
|
|
271
|
+
Returns
|
|
272
|
+
-------
|
|
273
|
+
scores : pandas DataFrame
|
|
274
|
+
Tabulated results for each data set, iteration, fold and
|
|
275
|
+
evaluation function.
|
|
276
|
+
"""
|
|
277
|
+
df = pd.DataFrame()
|
|
278
|
+
if not hasattr(models, "__iter__"):
|
|
279
|
+
models = [models]
|
|
280
|
+
|
|
281
|
+
for model in models:
|
|
282
|
+
is_regression = model.get_problem_type() == "regression"
|
|
283
|
+
|
|
284
|
+
n_data_sets = len(csv_files)
|
|
285
|
+
for i, csv_file in enumerate(csv_files):
|
|
286
|
+
if verbose:
|
|
287
|
+
print("\n{} ({} / {})".format(csv_file, i + 1, n_data_sets))
|
|
288
|
+
data = pd.read_csv(csv_file, header=header)
|
|
289
|
+
x, y = data.values[:, :-1], data.values[:, -1]
|
|
290
|
+
x = np.array(x, dtype=np.float64)
|
|
291
|
+
if normalize:
|
|
292
|
+
if is_regression:
|
|
293
|
+
y = y - y.min() / (y.max() - y.min())
|
|
294
|
+
else:
|
|
295
|
+
for j, y_ in enumerate(np.unique(y)):
|
|
296
|
+
y[y == y_] = j
|
|
297
|
+
|
|
298
|
+
scores = cross_val_score(
|
|
299
|
+
model,
|
|
300
|
+
x,
|
|
301
|
+
y,
|
|
302
|
+
iterations,
|
|
303
|
+
folds,
|
|
304
|
+
fit_params,
|
|
305
|
+
scoring_funcs,
|
|
306
|
+
significance_levels,
|
|
307
|
+
verbose,
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
ds_df = pd.DataFrame(scores)
|
|
311
|
+
ds_df["model"] = model.__class__.__name__
|
|
312
|
+
try:
|
|
313
|
+
ds_df["data_set"] = csv_file.split("/")[-1]
|
|
314
|
+
except:
|
|
315
|
+
ds_df["data_set"] = csv_file
|
|
316
|
+
|
|
317
|
+
df = df.append(ds_df)
|
|
318
|
+
|
|
319
|
+
return df
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
# -----------------------------------------------------------------------------
|
|
323
|
+
# Validity measures
|
|
324
|
+
# -----------------------------------------------------------------------------
|
|
325
|
+
def reg_n_correct(prediction, y, significance=None):
|
|
326
|
+
"""Calculates the number of correct predictions made by a conformal
|
|
327
|
+
regression model.
|
|
328
|
+
"""
|
|
329
|
+
if significance is not None:
|
|
330
|
+
idx = int(significance * 100 - 1)
|
|
331
|
+
prediction = prediction[:, :, idx]
|
|
332
|
+
|
|
333
|
+
low = y >= prediction[:, 0]
|
|
334
|
+
high = y <= prediction[:, 1]
|
|
335
|
+
correct = low * high
|
|
336
|
+
|
|
337
|
+
return y[correct].size
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
def reg_mean_errors(prediction, y, significance):
|
|
341
|
+
"""Calculates the average error rate of a conformal regression model."""
|
|
342
|
+
return 1 - reg_n_correct(prediction, y, significance) / y.size
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
def class_n_correct(prediction, y, significance):
|
|
346
|
+
"""Calculates the number of correct predictions made by a conformal
|
|
347
|
+
classification model.
|
|
348
|
+
"""
|
|
349
|
+
labels, y = np.unique(y, return_inverse=True)
|
|
350
|
+
prediction = prediction > significance
|
|
351
|
+
correct = np.zeros((y.size,), dtype=bool)
|
|
352
|
+
for i, y_ in enumerate(y):
|
|
353
|
+
correct[i] = prediction[i, int(y_)]
|
|
354
|
+
return np.sum(correct)
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
def class_mean_errors(prediction, y, significance=None):
|
|
358
|
+
"""Calculates the average error rate of a conformal classification model."""
|
|
359
|
+
return 1 - (class_n_correct(prediction, y, significance) / y.size)
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
def class_one_err(prediction, y, significance=None):
|
|
363
|
+
"""Calculates the error rate of conformal classifier predictions containing
|
|
364
|
+
only a single output label.
|
|
365
|
+
"""
|
|
366
|
+
labels, y = np.unique(y, return_inverse=True)
|
|
367
|
+
prediction = prediction > significance
|
|
368
|
+
idx = np.arange(0, y.size, 1)
|
|
369
|
+
idx = filter(lambda x: np.sum(prediction[x, :]) == 1, idx)
|
|
370
|
+
errors = filter(lambda x: not prediction[x, int(y[x])], idx)
|
|
371
|
+
|
|
372
|
+
if len(idx) > 0:
|
|
373
|
+
return np.size(errors) / np.size(idx)
|
|
374
|
+
else:
|
|
375
|
+
return 0
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
def class_mean_errors_one_class(prediction, y, significance, c=0):
|
|
379
|
+
"""Calculates the average error rate of a conformal classification model,
|
|
380
|
+
considering only test examples belonging to class ``c``. Use
|
|
381
|
+
``functools.partial`` in order to test other classes.
|
|
382
|
+
"""
|
|
383
|
+
labels, y = np.unique(y, return_inverse=True)
|
|
384
|
+
prediction = prediction > significance
|
|
385
|
+
idx = np.arange(0, y.size, 1)[y == c]
|
|
386
|
+
errs = np.sum(1 for _ in filter(lambda x: not prediction[x, c], idx))
|
|
387
|
+
|
|
388
|
+
if idx.size > 0:
|
|
389
|
+
return errs / idx.size
|
|
390
|
+
else:
|
|
391
|
+
return 0
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
def class_one_err_one_class(prediction, y, significance, c=0):
|
|
395
|
+
"""Calculates the error rate of conformal classifier predictions containing
|
|
396
|
+
only a single output label. Considers only test examples belonging to
|
|
397
|
+
class ``c``. Use ``functools.partial`` in order to test other classes.
|
|
398
|
+
"""
|
|
399
|
+
labels, y = np.unique(y, return_inverse=True)
|
|
400
|
+
prediction = prediction > significance
|
|
401
|
+
idx = np.arange(0, y.size, 1)
|
|
402
|
+
idx = filter(lambda x: prediction[x, c], idx)
|
|
403
|
+
idx = filter(lambda x: np.sum(prediction[x, :]) == 1, idx)
|
|
404
|
+
errors = filter(lambda x: int(y[x]) != c, idx)
|
|
405
|
+
|
|
406
|
+
if len(idx) > 0:
|
|
407
|
+
return np.size(errors) / np.size(idx)
|
|
408
|
+
else:
|
|
409
|
+
return 0
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
# -----------------------------------------------------------------------------
|
|
413
|
+
# Efficiency measures
|
|
414
|
+
# -----------------------------------------------------------------------------
|
|
415
|
+
def _reg_interval_size(prediction, y, significance):
|
|
416
|
+
idx = int(significance * 100 - 1)
|
|
417
|
+
prediction = prediction[:, :, idx]
|
|
418
|
+
|
|
419
|
+
return prediction[:, 1] - prediction[:, 0]
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
def reg_min_size(prediction, y, significance):
|
|
423
|
+
return np.min(_reg_interval_size(prediction, y, significance))
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
def reg_q1_size(prediction, y, significance):
|
|
427
|
+
return np.percentile(_reg_interval_size(prediction, y, significance), 25)
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
def reg_median_size(prediction, y, significance):
|
|
431
|
+
return np.median(_reg_interval_size(prediction, y, significance))
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
def reg_q3_size(prediction, y, significance):
|
|
435
|
+
return np.percentile(_reg_interval_size(prediction, y, significance), 75)
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
def reg_max_size(prediction, y, significance):
|
|
439
|
+
return np.max(_reg_interval_size(prediction, y, significance))
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
def reg_mean_size(prediction, y, significance):
|
|
443
|
+
"""Calculates the average prediction interval size of a conformal
|
|
444
|
+
regression model.
|
|
445
|
+
"""
|
|
446
|
+
return np.mean(_reg_interval_size(prediction, y, significance))
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
def class_avg_c(prediction, y, significance):
|
|
450
|
+
"""Calculates the average number of classes per prediction of a conformal
|
|
451
|
+
classification model.
|
|
452
|
+
"""
|
|
453
|
+
prediction = prediction > significance
|
|
454
|
+
return np.sum(prediction) / prediction.shape[0]
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
def class_mean_p_val(prediction, y, significance):
|
|
458
|
+
"""Calculates the mean of the p-values output by a conformal classification
|
|
459
|
+
model.
|
|
460
|
+
"""
|
|
461
|
+
return np.mean(prediction)
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
def class_one_c(prediction, y, significance):
|
|
465
|
+
"""Calculates the rate of singleton predictions (prediction sets containing
|
|
466
|
+
only a single class label) of a conformal classification model.
|
|
467
|
+
"""
|
|
468
|
+
prediction = prediction > significance
|
|
469
|
+
n_singletons = np.sum(
|
|
470
|
+
1 for _ in filter(lambda x: np.sum(x) == 1, prediction)
|
|
471
|
+
)
|
|
472
|
+
return n_singletons / y.size
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
def class_empty(prediction, y, significance):
|
|
476
|
+
"""Calculates the rate of singleton predictions (prediction sets containing
|
|
477
|
+
only a single class label) of a conformal classification model.
|
|
478
|
+
"""
|
|
479
|
+
prediction = prediction > significance
|
|
480
|
+
n_empty = np.sum(1 for _ in filter(lambda x: np.sum(x) == 0, prediction))
|
|
481
|
+
return n_empty / y.size
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
def n_test(prediction, y, significance):
|
|
485
|
+
"""Provides the number of test patters used in the evaluation."""
|
|
486
|
+
return y.size
|