Skip to content

Commit f96b466

Browse files
Merge pull request #122 from Continvvm/fix_metrics
Fix metrics
2 parents 16ec9e5 + aaea3d2 commit f96b466

File tree

6 files changed

+42
-34
lines changed

6 files changed

+42
-34
lines changed

continuum/metrics/base_logger.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ def __init__(self, root_log=None, list_keywords=["performance"], list_subsets=["
4343
self._update_dict_architecture(update_task=True)
4444

4545
def add(self, value, keyword="performance", subset="train"):
46-
4746
assert keyword in self.list_keywords, f"Keyword {keyword} is not declared in list_keywords {self.list_keywords}"
4847
assert subset in self.list_subsets, f"Field {subset} is not declared in list_keywords {self.list_subsets}"
4948

@@ -89,7 +88,7 @@ def _add_perf(self, predictions, targets, task_ids=None, subset="train"):
8988
targets = np.concatenate([self._get_current_targets(subset), targets])
9089
self.logger_dict[subset]["performance"][self.current_task][self.current_epoch]["targets"] = targets
9190

92-
if (task_ids is not None) and self._get_current_task_ids(subset).size > 0:
91+
if task_ids is not None:
9392
task_ids = np.concatenate([self._get_current_task_ids(subset), task_ids])
9493
self.logger_dict[subset]["performance"][self.current_task][self.current_epoch]["task_ids"] = task_ids
9594

continuum/metrics/logger.py

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import statistics
2+
13
import numpy as np
24

35
from continuum.metrics.base_logger import _BaseLogger
@@ -37,7 +39,7 @@ def _get_best_epochs_perf(self, subset):
3739
last_epoch_pred = []
3840
last_epoch_targets = []
3941
last_epoch_task_ids = []
40-
for task_id in range(self.current_task):
42+
for task_id in range(len(self.logger_dict[subset]["performance"])):
4143
predictions = self.logger_dict[subset]["performance"][task_id][-1]["predictions"]
4244
targets = self.logger_dict[subset]["performance"][task_id][-1]["targets"]
4345
task_id = self.logger_dict[subset]["performance"][task_id][-1]["task_ids"]
@@ -48,20 +50,15 @@ def _get_best_epochs_perf(self, subset):
4850

4951
return last_epoch_pred, last_epoch_targets, last_epoch_task_ids
5052

51-
5253
def _get_best_epochs_data(self, keyword, subset):
53-
5454
assert keyword != "performance", f"this method is not mode for performance keyword use _get_best_epochs_perf"
5555
list_values = []
5656
for task_id in range(self.current_task):
5757
list_values.append(self.logger_dict[subset][keyword][task_id][-1])
5858
return list_values
5959

60-
61-
6260
def _get_best_epochs(self, keyword="performance", subset="train"):
63-
64-
if keyword=="performance":
61+
if keyword == "performance":
6562
values = self._get_best_epochs_perf(subset)
6663
else:
6764
values = self._get_best_epochs_data(keyword, subset)
@@ -84,7 +81,6 @@ def online_accuracy(self):
8481
return accuracy(predictions, targets)
8582

8683
@property
87-
@cache
8884
@require_subset("test")
8985
def accuracy(self):
9086
return accuracy(
@@ -93,7 +89,6 @@ def accuracy(self):
9389
)
9490

9591
@property
96-
@cache
9792
@require_subset("test")
9893
def accuracy_per_task(self):
9994
"""Returns all task accuracy individually."""
@@ -104,7 +99,6 @@ def accuracy_per_task(self):
10499
]
105100

106101
@property
107-
@cache
108102
@require_subset("train")
109103
def online_cumulative_performance(self):
110104
"""Computes the accuracy of last task on the train set.
@@ -122,7 +116,6 @@ def online_cumulative_performance(self):
122116
return accuracy(preds, targets)
123117

124118
@property
125-
@cache
126119
@require_subset("test")
127120
def average_incremental_accuracy(self):
128121
"""Computes the average of the accuracies computed after each task.
@@ -132,56 +125,48 @@ def average_incremental_accuracy(self):
132125
Rebuffi et al. CVPR 2017
133126
"""
134127
all_preds, all_targets, _ = self._get_best_epochs(subset="test")
135-
136128
return statistics.mean([
137129
accuracy(all_preds[t], all_targets[t])
138130
for t in range(len(all_preds))
139131
])
140132

141133
@property
142-
@cache
143134
@require_subset("test")
144135
def backward_transfer(self):
145136
all_preds, all_targets, task_ids = self._get_best_epochs(subset="test")
146137
return backward_transfer(all_preds, all_targets, task_ids)
147138

148139
@property
149-
@cache
150140
@require_subset("test")
151141
def forward_transfer(self):
152142
all_preds, all_targets, task_ids = self._get_best_epochs(subset="test")
153143
return forward_transfer(all_preds, all_targets, task_ids)
154144

155145
@property
156-
@cache
157146
@require_subset("test")
158147
def positive_backward_transfer(self):
159148
all_preds, all_targets, task_ids = self._get_best_epochs(subset="test")
160149
return positive_backward_transfer(all_preds, all_targets, task_ids)
161150

162151
@property
163-
@cache
164152
@require_subset("test")
165153
def remembering(self):
166154
all_preds, all_targets, task_ids = self._get_best_epochs(subset="test")
167155
return remembering(all_preds, all_targets, task_ids)
168156

169157
@property
170-
@cache
171158
@require_subset("test")
172159
def accuracy_A(self):
173160
all_preds, all_targets, task_ids = self._get_best_epochs(subset="test")
174161
return accuracy_A(all_preds, all_targets, task_ids)
175162

176163
@property
177-
@cache
178164
@require_subset("test")
179165
def forgetting(self):
180166
all_preds, all_targets, task_ids = self._get_best_epochs(subset="test")
181167
return forgetting(all_preds, all_targets, task_ids)
182168

183169
@property
184-
@cache
185170
def model_size_growth(self):
186171
assert "model_size" in self.list_keywords
187172
sizes = self._get_best_epochs("model_size")

continuum/metrics/metrics.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from functools import reduce
22

3+
import numpy as np
4+
35

46
def accuracy(task_preds, task_targets):
57
"""Computes the accuracy of a given task.
@@ -14,7 +16,7 @@ def accuracy(task_preds, task_targets):
1416
assert task_targets.size == task_preds.size, f"{task_targets.size} vs {task_preds.size}"
1517

1618
metric = (task_preds == task_targets).mean()
17-
assert 0. <= metric <= 1.0
19+
assert 0. <= metric <= 1.0, metric
1820
return metric
1921

2022

@@ -48,7 +50,7 @@ def accuracy_A(all_preds, all_targets, all_tasks):
4850
A += _get_R_ij(i, j, all_preds, all_targets, all_tasks)
4951

5052
metric = A / (T * (T + 1) / 2)
51-
assert 0. <= metric <= 1.0
53+
assert 0. <= metric <= 1.0, metric
5254
return metric
5355

5456

@@ -78,7 +80,7 @@ def backward_transfer(all_preds, all_targets, all_tasks):
7880
bwt += (r_ij - r_jj)
7981

8082
metric = bwt / (T * (T - 1) / 2)
81-
assert -1. <= metric <= 1.0
83+
assert -1. <= metric <= 1.0, metric
8284
return metric
8385

8486

@@ -96,7 +98,7 @@ def positive_backward_transfer(all_preds, all_targets, all_tasks):
9698
"""
9799
bwt = backward_transfer(all_preds, all_targets, all_tasks)
98100
metric = 1 - abs(min(bwt, 0.))
99-
assert 0. <= metric <= 1.0
101+
assert 0. <= metric <= 1.0, metric
100102
return metric
101103

102104

@@ -114,7 +116,7 @@ def remembering(all_preds, all_targets, all_tasks):
114116
"""
115117
bwt = backward_transfer(all_preds, all_targets, all_tasks)
116118
metric = max(bwt, 0.)
117-
assert 0. <= metric <= 1.0
119+
assert 0. <= metric <= 1.0, metric
118120
return metric
119121

120122

@@ -141,7 +143,7 @@ def forward_transfer(all_preds, all_targets, all_tasks):
141143
fwt += _get_R_ij(i, j, all_preds, all_targets, all_tasks)
142144

143145
metric = fwt / (T * (T - 1) / 2)
144-
assert -1. <= metric <= 1.0
146+
assert -1. <= metric <= 1.0, metric
145147
return metric
146148

147149

@@ -164,7 +166,7 @@ def forgetting(all_preds, all_targets, all_tasks):
164166
f += (r_lj - r_kj)
165167

166168
metric = f / (T - 1)
167-
assert 0. <= metric <= 1.0
169+
assert 0. <= metric <= 1.0, metric
168170
return metric
169171

170172

@@ -241,5 +243,5 @@ def get_model_size_growth(model_sizes):
241243
ms += (model_sizes[0][0] / model_sizes[i][-1])
242244

243245
metric = min(1., ms / T)
244-
assert 0. <= metric <= 1.0
246+
assert 0. <= metric <= 1.0, metric
245247
return metric

continuum/metrics/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@ def wrapper(self):
2121
v = func(self)
2222
self.__dict__[name] = v
2323
return v
24-
return wrapper
24+
return wrapper

continuum/scenarios/base.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,12 @@ def _select_data_by_task(
115115
x, y, t = self.dataset # type: ignore
116116

117117
if isinstance(task_index, slice):
118-
start = task_index.start or 0
119-
stop = task_index.stop or len(self) + 1
120-
step = task_index.step or 1
118+
start = task_index.start if task_index.start is not None else 0
119+
stop = task_index.stop if task_index.stop is not None else len(self) + 1
120+
step = task_index.step if task_index.step is not None else 1
121121
task_index = list(range(start, stop, step))
122+
if len(task_index) == 0:
123+
raise ValueError(f"Invalid slicing resulting in no data (start={start}, end={stop}, step={step}).")
122124
task_index = [
123125
t if t >= 0 else _handle_negative_indexes(t, len(self)) for t in task_index
124126
]

tests/test_slicing.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ def test_slicing_nc(index, classes):
4949
(0, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
5050
(3, [6, 7, 8, 9]),
5151
(4, [8, 9]),
52-
(12, [])
5352
])
5453
def test_slicing_nc_no_end(start_index, classes):
5554
train, test = gen_data()
@@ -61,6 +60,25 @@ def test_slicing_nc_no_end(start_index, classes):
6160
assert (targets == np.array(classes)).all(), (targets, classes)
6261

6362

63+
@pytest.mark.parametrize("start,end", [
64+
(12, 100),
65+
(0, 0),
66+
(3, 3)
67+
])
68+
def test_slicing_empty(start, end):
69+
train, test = gen_data()
70+
dummy = InMemoryDataset(*train)
71+
scenario = ClassIncremental(dummy, increment=2)
72+
73+
has_failed = False
74+
try:
75+
taskset = scenario[start_index:]
76+
except:
77+
has_failed = True
78+
79+
assert has_failed
80+
81+
6482
def test_slicing_nc_no_index():
6583
train, test = gen_data()
6684
dummy = InMemoryDataset(*train)
@@ -72,3 +90,5 @@ def test_slicing_nc_no_index():
7290

7391
assert len(targets) == len(classes)
7492
assert (targets == np.array(classes)).all(), (targets, classes)
93+
94+

0 commit comments

Comments
 (0)