-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmy_roc_auc.py
48 lines (39 loc) · 1.79 KB
/
my_roc_auc.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import numpy as np
def my_roc_auc(classes : np.ndarray,
predictions : np.ndarray,
weights : np.ndarray = None) -> float:
"""
Calculating ROC AUC score as the probability of correct ordering
"""
if weights is None:
weights = np.ones_like(predictions)
assert len(classes) == len(predictions) == len(weights)
assert classes.ndim == predictions.ndim == weights.ndim == 1
class0, class1 = sorted(np.unique(classes))
data = np.empty(
shape=len(classes),
dtype=[('c', classes.dtype),
('p', predictions.dtype),
('w', weights.dtype)]
)
data['c'], data['p'], data['w'] = classes, predictions, weights
data = data[np.argsort(data['c'])]
data = data[np.argsort(data['p'], kind='mergesort')] # here we're relying on stability as we need class orders preserved
correction = 0.
# mask1 - bool mask to highlight collision areas
# mask2 - bool mask with collision areas' start points
mask1 = np.empty(len(data), dtype=bool)
mask2 = np.empty(len(data), dtype=bool)
mask1[0] = mask2[-1] = False
mask1[1:] = data['p'][1:] == data['p'][:-1]
if mask1.any():
mask2[:-1] = ~mask1[:-1] & mask1[1:]
mask1[:-1] |= mask1[1:]
ids, = mask2.nonzero()
correction = sum([((dsplit['c'] == class0) * dsplit['w'] * msplit).sum() *
((dsplit['c'] == class1) * dsplit['w'] * msplit).sum()
for dsplit, msplit in zip(np.split(data, ids), np.split(mask1, ids))]) * 0.5
weights_0 = data['w'] * (data['c'] == class0)
weights_1 = data['w'] * (data['c'] == class1)
cumsum_0 = weights_0.cumsum()
return ((cumsum_0 * weights_1).sum() - correction) / (weights_1.sum() * cumsum_0[-1])