Skip to content

1 regression tests available device #3335 #3403

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
66755ad
add available device to test_canberra_metric.py
BanzaiTokyo Apr 24, 2025
9229e3b
add _double_dtype ad dtype when transfrring errors to device
BanzaiTokyo Apr 24, 2025
2f6320a
available devices in test_fractional_absolute_error.py, test_fraction…
BanzaiTokyo Apr 24, 2025
557f549
when transferring to device use dtype
BanzaiTokyo Apr 24, 2025
0130773
add available device to tests
BanzaiTokyo Apr 24, 2025
94a002b
use self._double_dtype instead of torch.double
BanzaiTokyo Apr 24, 2025
2631377
use self._double_dtype when moving to device in epoch_metric.py
BanzaiTokyo Apr 24, 2025
d5b9e5a
removes unnecessary tests
BanzaiTokyo Apr 24, 2025
f99b643
rollbacks changes in epoch_metric.py
BanzaiTokyo Apr 24, 2025
e24ce01
redo test_integration
BanzaiTokyo Apr 24, 2025
3dbbe1e
redo test_integration
BanzaiTokyo Apr 24, 2025
1cf59fa
casting of eps in _update
BanzaiTokyo Apr 24, 2025
6f0599d
more conversions to torch
BanzaiTokyo Apr 24, 2025
35527d5
in _torch_median move output to cpu if mps (torch.kthvalue is not sup…
BanzaiTokyo Apr 25, 2025
c13837e
fixing test_degenerated_sample
BanzaiTokyo Apr 25, 2025
c85dab1
fixing test_degenerated_sample
BanzaiTokyo Apr 25, 2025
c662c44
rename upper case variables
BanzaiTokyo Apr 25, 2025
e471064
change range to 3
BanzaiTokyo Apr 25, 2025
37a0469
rewrite test_compute
BanzaiTokyo Apr 25, 2025
71af57e
rewrite test_fractional_bias
BanzaiTokyo Apr 25, 2025
d59cb6f
remove prints
BanzaiTokyo Apr 25, 2025
da2e75d
rollback eps in canberra_metric.py
BanzaiTokyo Apr 25, 2025
0a2f6d4
rollback test_epoch_metric.py because the changes are moved to a sepa…
BanzaiTokyo Apr 25, 2025
d1ef2d4
Merge branch 'master' into regression_tests_add_available_device
BanzaiTokyo Apr 25, 2025
667332d
set sum_of_errors as _double_dtype
BanzaiTokyo Apr 28, 2025
713aab9
Merge branch 'master' into regression_tests_add_available_device
BanzaiTokyo Apr 28, 2025
579d035
use torch instead of numpy where possible in test_canberra_metric.py
BanzaiTokyo Apr 28, 2025
cab29ca
Merge branch 'master' into regression_tests_add_available_device
BanzaiTokyo Apr 29, 2025
e6c96de
remove double_dtype from metrics
BanzaiTokyo Apr 29, 2025
346e0e1
takes into account PR comments
BanzaiTokyo May 2, 2025
ded98cf
refactor integration tests for fractional bias and fractional absolut…
BanzaiTokyo May 2, 2025
63baad6
remove modifications in test
BanzaiTokyo May 3, 2025
151f16b
Merge branch 'master' into regression_metrics_updates_mps
BanzaiTokyo May 3, 2025
7af547f
test_canberra_metric.py test_fractional_absolute_error.py test_fracti…
BanzaiTokyo May 3, 2025
4a47a79
revert "if torch.isnan(r)"
BanzaiTokyo May 4, 2025
82a2733
for loop in test_compute test_canberra_metric.py
BanzaiTokyo May 4, 2025
1f35cca
use torch instead of numpy in test_integration_fractional_absolute_error
BanzaiTokyo May 4, 2025
46dac1f
use loop in test_compute test_geometric_mean_absolute_error.py
BanzaiTokyo May 4, 2025
f00fe0a
Merge branch 'master' into 1_regression_tests_available_device
BanzaiTokyo May 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 55 additions & 65 deletions tests/ignite/metrics/regression/test_canberra_metric.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,83 +20,73 @@ def test_wrong_input_shapes():
m.update((torch.rand(4, 1), torch.rand(4)))


def test_compute():
a = np.random.randn(4)
b = np.random.randn(4)
c = np.random.randn(4)
d = np.random.randn(4)
ground_truth = np.random.randn(4)
def test_compute(available_device):
ground_truth = torch.randn(4)
preds = [torch.randn(4) for _ in range(4)]

m = CanberraMetric()
m = CanberraMetric(device=available_device)
assert m._device == torch.device(available_device)

canberra = DistanceMetric.get_metric("canberra")

m.update((torch.from_numpy(a), torch.from_numpy(ground_truth)))
np_sum = (np.abs(ground_truth - a) / (np.abs(a) + np.abs(ground_truth))).sum()
assert m.compute() == pytest.approx(np_sum)
assert canberra.pairwise([a, ground_truth])[0][1] == pytest.approx(np_sum)

m.update((torch.from_numpy(b), torch.from_numpy(ground_truth)))
np_sum += ((np.abs(ground_truth - b)) / (np.abs(b) + np.abs(ground_truth))).sum()
assert m.compute() == pytest.approx(np_sum)
v1 = np.hstack([a, b])
v2 = np.hstack([ground_truth, ground_truth])
assert canberra.pairwise([v1, v2])[0][1] == pytest.approx(np_sum)

m.update((torch.from_numpy(c), torch.from_numpy(ground_truth)))
np_sum += ((np.abs(ground_truth - c)) / (np.abs(c) + np.abs(ground_truth))).sum()
assert m.compute() == pytest.approx(np_sum)
v1 = np.hstack([v1, c])
v2 = np.hstack([v2, ground_truth])
assert canberra.pairwise([v1, v2])[0][1] == pytest.approx(np_sum)

m.update((torch.from_numpy(d), torch.from_numpy(ground_truth)))
np_sum += (np.abs(ground_truth - d) / (np.abs(d) + np.abs(ground_truth))).sum()
assert m.compute() == pytest.approx(np_sum)
v1 = np.hstack([v1, d])
v2 = np.hstack([v2, ground_truth])
assert canberra.pairwise([v1, v2])[0][1] == pytest.approx(np_sum)


def test_integration():
def _test(y_pred, y, batch_size):
def update_fn(engine, batch):
idx = (engine.state.iteration - 1) * batch_size
y_true_batch = np_y[idx : idx + batch_size]
y_pred_batch = np_y_pred[idx : idx + batch_size]
return torch.from_numpy(y_pred_batch), torch.from_numpy(y_true_batch)

engine = Engine(update_fn)

m = CanberraMetric()
m.attach(engine, "cm")
total_sum = 0.0
v1 = []
v2 = []

np_y = y.numpy().ravel()
np_y_pred = y_pred.numpy().ravel()
for pred in preds:
m.update((pred, ground_truth))
diff = torch.abs(ground_truth - pred)
denom = torch.abs(pred) + torch.abs(ground_truth)
batch_sum = (diff / denom).sum()
total_sum += batch_sum

canberra = DistanceMetric.get_metric("canberra")
assert m.compute() == pytest.approx(total_sum)

data = list(range(y_pred.shape[0] // batch_size))
cm = engine.run(data, max_epochs=1).metrics["cm"]
v1.append(pred.cpu().numpy())
v2.append(ground_truth.cpu().numpy())
v1_cat = np.hstack(v1)
v2_cat = np.hstack(v2)
assert canberra.pairwise([v1_cat, v2_cat])[0][1] == pytest.approx(total_sum)

assert canberra.pairwise([np_y_pred, np_y])[0][1] == pytest.approx(cm)

def get_test_cases():
test_cases = [
(torch.rand(size=(100,)), torch.rand(size=(100,)), 10),
(torch.rand(size=(100, 1)), torch.rand(size=(100, 1)), 20),
]
return test_cases
@pytest.mark.parametrize("n_times", range(3))
@pytest.mark.parametrize(
"test_cases",
[
(torch.rand(size=(100,)), torch.rand(size=(100,)), 10),
(torch.rand(size=(100, 1)), torch.rand(size=(100, 1)), 20),
],
)
def test_integration(n_times, test_cases, available_device):
y_pred, y, batch_size = test_cases

for _ in range(5):
# check multiple random inputs as random exact occurencies are rare
test_cases = get_test_cases()
for y_pred, y, batch_size in test_cases:
_test(y_pred, y, batch_size)
def update_fn(engine, batch):
idx = (engine.state.iteration - 1) * batch_size
y_true_batch = y[idx : idx + batch_size]
y_pred_batch = y_pred[idx : idx + batch_size]
return y_pred_batch, y_true_batch

engine = Engine(update_fn)

def test_error_is_not_nan():
m = CanberraMetric()
m = CanberraMetric(device=available_device)
assert m._device == torch.device(available_device)

m.attach(engine, "cm")

canberra = DistanceMetric.get_metric("canberra")

data = list(range(y_pred.shape[0] // batch_size))
cm = engine.run(data, max_epochs=1).metrics["cm"]

pred_np = y_pred.cpu().numpy().reshape(len(y_pred), -1)
true_np = y.cpu().numpy().reshape(len(y), -1)
expected = np.sum(canberra.pairwise(pred_np, true_np).diagonal())
assert expected == pytest.approx(cm)


def test_error_is_not_nan(available_device):
m = CanberraMetric(device=available_device)
assert m._device == torch.device(available_device)
m.update((torch.zeros(4), torch.zeros(4)))
assert not (torch.isnan(m._sum_of_errors).any() or torch.isinf(m._sum_of_errors).any()), m._sum_of_errors

Expand Down
100 changes: 43 additions & 57 deletions tests/ignite/metrics/regression/test_fractional_absolute_error.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,77 +28,63 @@ def test_wrong_input_shapes():
m.update((torch.rand(4, 1), torch.rand(4)))


def test_compute():
a = np.random.randn(4)
b = np.random.randn(4)
c = np.random.randn(4)
d = np.random.randn(4)
ground_truth = np.random.randn(4)
def test_compute(available_device):
a = torch.randn(4)
b = torch.randn(4)
c = torch.randn(4)
d = torch.randn(4)
ground_truth = torch.randn(4)

m = FractionalAbsoluteError()

m.update((torch.from_numpy(a), torch.from_numpy(ground_truth)))
np_sum = (2 * np.abs((a - ground_truth)) / (np.abs(a) + np.abs(ground_truth))).sum()
np_len = len(a)
np_ans = np_sum / np_len
assert m.compute() == pytest.approx(np_ans)
m = FractionalAbsoluteError(device=available_device)
assert m._device == torch.device(available_device)

m.update((torch.from_numpy(b), torch.from_numpy(ground_truth)))
np_sum += (2 * np.abs((b - ground_truth)) / (np.abs(b) + np.abs(ground_truth))).sum()
np_len += len(b)
np_ans = np_sum / np_len
assert m.compute() == pytest.approx(np_ans)
total_error = 0.0
total_len = 0

m.update((torch.from_numpy(c), torch.from_numpy(ground_truth)))
np_sum += (2 * np.abs((c - ground_truth)) / (np.abs(c) + np.abs(ground_truth))).sum()
np_len += len(c)
np_ans = np_sum / np_len
assert m.compute() == pytest.approx(np_ans)
for pred in [a, b, c, d]:
m.update((pred, ground_truth))

m.update((torch.from_numpy(d), torch.from_numpy(ground_truth)))
np_sum += (2 * np.abs((d - ground_truth)) / (np.abs(d) + np.abs(ground_truth))).sum()
np_len += len(d)
np_ans = np_sum / np_len
assert m.compute() == pytest.approx(np_ans)
# Compute fractional absolute error in PyTorch
error = 2 * torch.abs(pred - ground_truth) / (torch.abs(pred) + torch.abs(ground_truth))
total_error += error.sum().item()
total_len += len(pred)

expected = total_error / total_len
assert m.compute() == pytest.approx(expected)

def test_integration():
def _test(y_pred, y, batch_size):
def update_fn(engine, batch):
idx = (engine.state.iteration - 1) * batch_size
y_true_batch = np_y[idx : idx + batch_size]
y_pred_batch = np_y_pred[idx : idx + batch_size]
return torch.from_numpy(y_pred_batch), torch.from_numpy(y_true_batch)

engine = Engine(update_fn)
@pytest.mark.parametrize("n_times", range(5))
@pytest.mark.parametrize(
"test_cases",
[
(torch.rand(size=(100,)), torch.rand(size=(100,)), 10),
(torch.rand(size=(100, 1)), torch.rand(size=(100, 1)), 20),
],
)
def test_integration_fractional_absolute_error(n_times, test_cases, available_device):
y_pred, y, batch_size = test_cases

m = FractionalAbsoluteError()
m.attach(engine, "fab")
def update_fn(engine, batch):
idx = (engine.state.iteration - 1) * batch_size
y_true_batch = y[idx : idx + batch_size]
y_pred_batch = y_pred[idx : idx + batch_size]
return y_pred_batch, y_true_batch

np_y = y.numpy().ravel()
np_y_pred = y_pred.numpy().ravel()
engine = Engine(update_fn)

data = list(range(y_pred.shape[0] // batch_size))
fab = engine.run(data, max_epochs=1).metrics["fab"]
metric = FractionalAbsoluteError(device=available_device)
assert metric._device == torch.device(available_device)

np_sum = (2 * np.abs((np_y_pred - np_y)) / (np.abs(np_y_pred) + np.abs(np_y))).sum()
np_len = len(y_pred)
np_ans = np_sum / np_len
metric.attach(engine, "fab")

assert np_ans == pytest.approx(fab)
data = list(range(y_pred.shape[0] // batch_size))
fab = engine.run(data, max_epochs=1).metrics["fab"]

def get_test_cases():
test_cases = [
(torch.rand(size=(100,)), torch.rand(size=(100,)), 10),
(torch.rand(size=(100, 1)), torch.rand(size=(100, 1)), 20),
]
return test_cases
abs_diff = torch.abs(y_pred - y)
denom = torch.abs(y_pred) + torch.abs(y)
expected = (2 * abs_diff / denom).sum().item() / y.numel()

for _ in range(5):
# check multiple random inputs as random exact occurencies are rare
test_cases = get_test_cases()
for y_pred, y, batch_size in test_cases:
_test(y_pred, y, batch_size)
assert pytest.approx(expected) == fab


def _test_distrib_compute(device):
Expand Down
Loading
Loading