-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconfusion.py
More file actions
87 lines (73 loc) · 2.78 KB
/
confusion.py
File metadata and controls
87 lines (73 loc) · 2.78 KB
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
from typing import List, Tuple
from statistics import NormalDist
import numpy as np
from models import Response, Participant
class ConfusionMatrix:
def __init__(self, matrix: np.ndarray, labels=None):
assert matrix.shape[0] == matrix.shape[1]
if labels is None:
labels = list(range(0, matrix.shape[0]))
self._matrix = matrix
self._labels = labels
def _normalize(self, axis: int):
with np.errstate(divide="ignore", invalid="ignore"):
return np.nan_to_num(self.totals / self.totals.sum(axis=axis, keepdims=1), 0)
@property
def denom(self):
return np.nan_to_num(self.totals.sum(axis=0, keepdims=1), 0)
@property
def reported_values_sum_to_unity(self):
return self._normalize(0)
@property
def true_values_sum_to_unity(self):
return self._normalize(1)
@property
def size(self):
return self._matrix.shape[0]
@property
def totals(self):
return self._matrix
@property
def labels(self):
return self._labels
@staticmethod
def from_true_reported_pairs(true_reported_pairs: List[Tuple[int, int]], provided_labels=None):
if provided_labels:
labels = provided_labels
else:
extracted_labels = set()
for (true, reported) in true_reported_pairs:
extracted_labels.add(true)
extracted_labels.add(reported)
labels = list(sorted(extracted_labels))
size = len(labels)
matrix = np.zeros((size, size))
for (true, reported) in true_reported_pairs:
true_index = labels.index(true)
reported_index = labels.index(reported)
matrix[true_index, reported_index] += 1
return ConfusionMatrix(matrix, labels)
@staticmethod
def of_azimuths(responses: List[Response]):
min_azimuth = float("inf")
max_azimuth = float("-inf")
for resp in responses:
for az in (resp.true_azimuth, resp.response_azimuth):
min_azimuth = min(min_azimuth, az)
max_azimuth = max(max_azimuth, az)
labels = list(range(min_azimuth, max_azimuth + 10, 10))
return ConfusionMatrix.from_true_reported_pairs(
[(r.true_azimuth, r.response_azimuth) for r in responses], labels
)
@staticmethod
def of_indices(responses: List[Response]):
return ConfusionMatrix.from_true_reported_pairs(
[(r.true_index, r.response_index) for r in responses]
)
@staticmethod
def of_participants(participants: List[Participant], sector=None):
mats = [
ConfusionMatrix.of_azimuths(participant.get_responses(sector)).normalized
for participant in participants
]
return np.mean(mats)