Skip to content

4 regression tests available device #3335 #3406

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

Closed
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
45af2f9
test_median_absolute_percentage_error.py
BanzaiTokyo May 3, 2025
6c741e1
Merge branch 'master' into 4_regression_tests_available_device
BanzaiTokyo May 4, 2025
5d0f1c1
revert "if torch.isnan(r)" check in pearson_correlation.py
BanzaiTokyo May 4, 2025
89f1149
Merge branch 'master' into 4_regression_tests_available_device
BanzaiTokyo May 5, 2025
731c223
Update tests/ignite/metrics/regression/test_median_absolute_percentag…
BanzaiTokyo May 5, 2025
2203edd
Merge branch 'master' into 4_regression_tests_available_device
BanzaiTokyo May 5, 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
Original file line number Diff line number Diff line change
Expand Up @@ -34,38 +34,42 @@ def test_wrong_input_shapes():
m.update((torch.rand(4), torch.rand(4, 1, 2)))


def test_median_absolute_percentage_error():
def test_median_absolute_percentage_error(available_device):
# See https://github.com/torch/torch7/pull/182
# For even number of elements, PyTorch returns middle element
# NumPy returns average of middle elements
# Size of dataset will be odd for these tests

size = 51
np_y_pred = np.random.rand(size)
np_y = np.random.rand(size)
np_median_absolute_percentage_error = 100.0 * np.median(np.abs(np_y - np_y_pred) / np.abs(np_y))
y_pred = torch.rand(size)
y = torch.rand(size)

m = MedianAbsolutePercentageError()
y_pred = torch.from_numpy(np_y_pred)
y = torch.from_numpy(np_y)
epsilon = 1e-8
expected = torch.median(torch.abs((y - y_pred) / (y + epsilon)).cpu()).item() * 100.0

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

m.reset()
m.update((y_pred, y))

assert np_median_absolute_percentage_error == pytest.approx(m.compute())
assert expected == pytest.approx(m.compute())


def test_median_absolute_percentage_error_2():
np.random.seed(1)
def test_median_absolute_percentage_error_2(available_device):
size = 105
np_y_pred = np.random.rand(size, 1)
np_y = np.random.rand(size, 1)
np.random.shuffle(np_y)
np_median_absolute_percentage_error = 100.0 * np.median(np.abs(np_y - np_y_pred) / np.abs(np_y))
y_pred = torch.rand(size, 1)
y = torch.rand(size, 1)

m = MedianAbsolutePercentageError()
y_pred = torch.from_numpy(np_y_pred)
y = torch.from_numpy(np_y)
indices = torch.randperm(size)
y = y[indices]

epsilon = 1e-8
safe_y = torch.where(y == 0, torch.full_like(y, epsilon), y)
expected = torch.median(torch.abs((y - y_pred) / safe_y).cpu()).item() * 100.0

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

m.reset()
batch_size = 16
Expand All @@ -74,34 +78,37 @@ def test_median_absolute_percentage_error_2():
idx = i * batch_size
m.update((y_pred[idx : idx + batch_size], y[idx : idx + batch_size]))

assert np_median_absolute_percentage_error == pytest.approx(m.compute())
assert expected == pytest.approx(m.compute())


def test_integration_median_absolute_percentage_error():
np.random.seed(1)
def test_integration_median_absolute_percentage_error(available_device):
size = 105
np_y_pred = np.random.rand(size, 1)
np_y = np.random.rand(size, 1)
np.random.shuffle(np_y)
np_median_absolute_percentage_error = 100.0 * np.median(np.abs(np_y - np_y_pred) / np.abs(np_y))
y_pred = torch.rand(size, 1)
y = torch.rand(size, 1)

indices = torch.randperm(size)
y = y[indices]

epsilon = 1e-8
safe_y = torch.where(y == 0, torch.full_like(y, epsilon), y)
expected = torch.median(torch.abs((y - y_pred) / safe_y).cpu()).item() * 100.0

batch_size = 15

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)
return y_pred[idx : idx + batch_size], y[idx : idx + batch_size]

engine = Engine(update_fn)

m = MedianAbsolutePercentageError()
m = MedianAbsolutePercentageError(device=available_device)
assert m._device == torch.device(available_device)
m.attach(engine, "median_absolute_percentage_error")

data = list(range(size // batch_size))
median_absolute_percentage_error = engine.run(data, max_epochs=1).metrics["median_absolute_percentage_error"]

assert np_median_absolute_percentage_error == pytest.approx(median_absolute_percentage_error)
assert expected == pytest.approx(median_absolute_percentage_error)


def _test_distrib_compute(device):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,38 +34,39 @@ def test_wrong_input_shapes():
m.update((torch.rand(4), torch.rand(4, 1, 2)))


def test_median_relative_absolute_error():
def test_median_relative_absolute_error(available_device):
# See https://github.com/torch/torch7/pull/182
# For even number of elements, PyTorch returns middle element
# NumPy returns average of middle elements
# Size of dataset will be odd for these tests

size = 51
np_y_pred = np.random.rand(size)
np_y = np.random.rand(size)
np_median_absolute_relative_error = np.median(np.abs(np_y - np_y_pred) / np.abs(np_y - np_y.mean()))
y_pred = torch.rand(size)
y = torch.rand(size)

m = MedianRelativeAbsoluteError()
y_pred = torch.from_numpy(np_y_pred)
y = torch.from_numpy(np_y)
baseline = torch.abs(y - y.mean())
expected = torch.median((torch.abs(y - y_pred) / baseline).cpu()).item()

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

m.reset()
m.update((y_pred, y))

assert np_median_absolute_relative_error == pytest.approx(m.compute())
assert expected == pytest.approx(m.compute())


def test_median_relative_absolute_error_2():
np.random.seed(1)
def test_median_relative_absolute_error_2(available_device):
size = 105
np_y_pred = np.random.rand(size, 1)
np_y = np.random.rand(size, 1)
np.random.shuffle(np_y)
np_median_absolute_relative_error = np.median(np.abs(np_y - np_y_pred) / np.abs(np_y - np_y.mean()))
y_pred = torch.rand(size, 1)
y = torch.rand(size, 1)
y = y[torch.randperm(size)]

m = MedianRelativeAbsoluteError()
y_pred = torch.from_numpy(np_y_pred)
y = torch.from_numpy(np_y)
baseline = torch.abs(y - y.mean())
expected = torch.median((torch.abs(y - y_pred) / baseline).cpu()).item()

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

m.reset()
batch_size = 16
Expand All @@ -74,34 +75,36 @@ def test_median_relative_absolute_error_2():
idx = i * batch_size
m.update((y_pred[idx : idx + batch_size], y[idx : idx + batch_size]))

assert np_median_absolute_relative_error == pytest.approx(m.compute())
assert expected == pytest.approx(m.compute())


def test_integration_median_relative_absolute_error_with_output_transform():
np.random.seed(1)
def test_integration_median_relative_absolute_error_with_output_transform(available_device):
size = 105
np_y_pred = np.random.rand(size, 1)
np_y = np.random.rand(size, 1)
np.random.shuffle(np_y)
np_median_absolute_relative_error = np.median(np.abs(np_y - np_y_pred) / np.abs(np_y - np_y.mean()))
y_pred = torch.rand(size, 1)
y = torch.rand(size, 1)
y = y[torch.randperm(size)] # shuffle y

baseline = torch.abs(y - y.mean())
expected = torch.median((torch.abs(y - y_pred) / baseline.cpu()).cpu()).item()

batch_size = 15

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)
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)

m = MedianRelativeAbsoluteError()
m = MedianRelativeAbsoluteError(device=available_device)
assert m._device == torch.device(available_device)
m.attach(engine, "median_absolute_relative_error")

data = list(range(size // batch_size))
median_absolute_relative_error = engine.run(data, max_epochs=1).metrics["median_absolute_relative_error"]

assert np_median_absolute_relative_error == pytest.approx(median_absolute_relative_error)
assert expected == pytest.approx(median_absolute_relative_error)


def _test_distrib_compute(device):
Expand Down
71 changes: 38 additions & 33 deletions tests/ignite/metrics/regression/test_pearson_correlation.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,54 +43,57 @@ def test_wrong_input_shapes():
m.update((torch.rand(4, 1), torch.rand(4)))


def test_degenerated_sample():
def test_degenerated_sample(available_device):
# one sample
m = PearsonCorrelation()
m = PearsonCorrelation(device=available_device)
assert m._device == torch.device(available_device)
y_pred = torch.tensor([1.0])
y = torch.tensor([1.0])
m.update((y_pred, y))

np_y_pred = y_pred.numpy()
np_y = y_pred.numpy()
np_res = np_corr_eps(np_y_pred, np_y)
assert pytest.approx(np_res) == m.compute()
np_y_pred = y_pred.cpu().numpy()
np_y = y_pred.cpu().numpy()
expected = np_corr_eps(np_y_pred, np_y)
actual = m.compute()

assert pytest.approx(expected) == actual

# constant samples
m.reset()
y_pred = torch.ones(10).float()
y = torch.zeros(10).float()
m.update((y_pred, y))

np_y_pred = y_pred.numpy()
np_y = y_pred.numpy()
np_res = np_corr_eps(np_y_pred, np_y)
assert pytest.approx(np_res) == m.compute()
np_y_pred = y_pred.cpu().numpy()
np_y = y_pred.cpu().numpy()
expected = np_corr_eps(np_y_pred, np_y)
actual = m.compute()

assert pytest.approx(expected) == actual

def test_pearson_correlation():
a = np.random.randn(4).astype(np.float32)
b = np.random.randn(4).astype(np.float32)
c = np.random.randn(4).astype(np.float32)
d = np.random.randn(4).astype(np.float32)
ground_truth = np.random.randn(4).astype(np.float32)

m = PearsonCorrelation()
def test_pearson_correlation(available_device):
torch.manual_seed(1)

m.update((torch.from_numpy(a), torch.from_numpy(ground_truth)))
np_ans = scipy_corr(a, ground_truth)
assert m.compute() == pytest.approx(np_ans, rel=1e-4)
inputs = [torch.randn(4) for _ in range(4)]
ground_truth = torch.randn(4)

m.update((torch.from_numpy(b), torch.from_numpy(ground_truth)))
np_ans = scipy_corr(np.concatenate([a, b]), np.concatenate([ground_truth] * 2))
assert m.compute() == pytest.approx(np_ans, rel=1e-4)
m = PearsonCorrelation(device=available_device)
assert m._device == torch.device(available_device)

m.update((torch.from_numpy(c), torch.from_numpy(ground_truth)))
np_ans = scipy_corr(np.concatenate([a, b, c]), np.concatenate([ground_truth] * 3))
assert m.compute() == pytest.approx(np_ans, rel=1e-4)
all_preds = []
all_targets = []

m.update((torch.from_numpy(d), torch.from_numpy(ground_truth)))
np_ans = scipy_corr(np.concatenate([a, b, c, d]), np.concatenate([ground_truth] * 4))
assert m.compute() == pytest.approx(np_ans, rel=1e-4)
for i, pred in enumerate(inputs, 1):
m.update((pred, ground_truth))
all_preds.append(pred)
all_targets.append(ground_truth)

pred_concat = torch.cat(all_preds).cpu().numpy()
target_concat = torch.cat(all_targets).cpu().numpy()
expected = pearsonr(pred_concat, target_concat)[0]

assert m.compute() == pytest.approx(expected, rel=1e-4)


@pytest.fixture(params=list(range(2)))
Expand All @@ -106,7 +109,7 @@ def test_case(request):


@pytest.mark.parametrize("n_times", range(5))
def test_integration(n_times, test_case: Tuple[Tensor, Tensor, int]):
def test_integration_pearson_correlation(n_times, test_case: Tuple[Tensor, Tensor, int], available_device):
y_pred, y, batch_size = test_case

def update_fn(engine: Engine, batch):
Expand All @@ -117,7 +120,8 @@ def update_fn(engine: Engine, batch):

engine = Engine(update_fn)

m = PearsonCorrelation()
m = PearsonCorrelation(device=available_device)
assert m._device == torch.device(available_device)
m.attach(engine, "corr")

np_y = y.numpy().ravel()
Expand All @@ -131,8 +135,9 @@ def update_fn(engine: Engine, batch):
assert pytest.approx(np_ans, rel=2e-4) == corr


def test_accumulator_detached():
corr = PearsonCorrelation()
def test_accumulator_detached(available_device):
corr = PearsonCorrelation(device=available_device)
assert corr._device == torch.device(available_device)

y_pred = torch.tensor([2.0, 3.0], requires_grad=True)
y = torch.tensor([-2.0, -1.0])
Expand Down
Loading
Loading