diff --git a/RELEASE.md b/RELEASE.md index 09ae177..c3ff835 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -3,8 +3,8 @@ ## Release 0.1.1-dev0 ### Includes -- Minor bugfixes. -- 100% line coverage. + - Minor bugfixes. + - 100% line coverage. ## Release 0.1.0-dev0 diff --git a/tests/test_functions.py b/tests/test_functions.py index c129a21..8086b40 100644 --- a/tests/test_functions.py +++ b/tests/test_functions.py @@ -126,6 +126,16 @@ class TestCompetitions(unittest.TestCase): decimal=5) self.assertIsNone(mismatch) + def test_stratified_min_simple(self): + d = torch.tensor([[0., 2., 3.], [8., 0, 1]]) + labels = torch.tensor([0, 1, 2]) + actual = competitions.stratified_min(d, labels) + desired = torch.tensor([[0., 2., 3.], [8., 0., 1.]]) + mismatch = np.testing.assert_array_almost_equal(actual, + desired, + decimal=5) + self.assertIsNone(mismatch) + def test_knnc_k1(self): d = torch.tensor([[2., 3., 1.99, 3.01], [2., 3., 2.01, 3.]]) labels = torch.tensor([0, 1, 2, 3]) @@ -372,7 +382,7 @@ class TestInitializers(unittest.TestCase): def test_stratified_mean_equal1(self): pdist = torch.tensor([1, 1]) - actual, _ = initializers.stratified_mean(self.x, self.y, pdist) + actual, _ = initializers.stratified_mean(self.x, self.y, pdist, False) desired = torch.tensor([[5., 5., 5.], [1., 1., 1.]]) mismatch = np.testing.assert_array_almost_equal(actual, desired, @@ -381,7 +391,8 @@ class TestInitializers(unittest.TestCase): def test_stratified_random_equal1(self): pdist = torch.tensor([1, 1]) - actual, _ = initializers.stratified_random(self.x, self.y, pdist) + actual, _ = initializers.stratified_random(self.x, self.y, pdist, + False) desired = torch.tensor([[0., -1., -2.], [0., 0., 0.]]) mismatch = np.testing.assert_array_almost_equal(actual, desired, @@ -390,7 +401,7 @@ class TestInitializers(unittest.TestCase): def test_stratified_mean_equal2(self): pdist = torch.tensor([2, 2]) - actual, _ = initializers.stratified_mean(self.x, self.y, pdist) + actual, _ = initializers.stratified_mean(self.x, self.y, pdist, False) desired = torch.tensor([[5., 5., 5.], [5., 5., 5.], [1., 1., 1.], [1., 1., 1.]]) mismatch = np.testing.assert_array_almost_equal(actual, @@ -400,7 +411,8 @@ class TestInitializers(unittest.TestCase): def test_stratified_random_equal2(self): pdist = torch.tensor([2, 2]) - actual, _ = initializers.stratified_random(self.x, self.y, pdist) + actual, _ = initializers.stratified_random(self.x, self.y, pdist, + False) desired = torch.tensor([[0., -1., -2.], [0., -1., -2.], [0., 0., 0.], [0., 0., 0.]]) mismatch = np.testing.assert_array_almost_equal(actual, @@ -410,7 +422,7 @@ class TestInitializers(unittest.TestCase): def test_stratified_mean_unequal(self): pdist = torch.tensor([1, 3]) - actual, _ = initializers.stratified_mean(self.x, self.y, pdist) + actual, _ = initializers.stratified_mean(self.x, self.y, pdist, False) desired = torch.tensor([[5., 5., 5.], [1., 1., 1.], [1., 1., 1.], [1., 1., 1.]]) mismatch = np.testing.assert_array_almost_equal(actual, @@ -420,7 +432,8 @@ class TestInitializers(unittest.TestCase): def test_stratified_random_unequal(self): pdist = torch.tensor([1, 3]) - actual, _ = initializers.stratified_random(self.x, self.y, pdist) + actual, _ = initializers.stratified_random(self.x, self.y, pdist, + False) desired = torch.tensor([[0., -1., -2.], [0., 0., 0.], [0., 0., 0.], [0., 0., 0.]]) mismatch = np.testing.assert_array_almost_equal(actual, @@ -428,6 +441,36 @@ class TestInitializers(unittest.TestCase): decimal=5) self.assertIsNone(mismatch) + def test_stratified_mean_unequal_one_hot(self): + pdist = torch.tensor([1, 3]) + y = torch.eye(2)[self.y] + desired1 = torch.tensor([[5., 5., 5.], [1., 1., 1.], [1., 1., 1.], + [1., 1., 1.]]) + actual1, actual2 = initializers.stratified_mean(self.x, y, pdist) + desired2 = torch.tensor([[1, 0], [0, 1], [0, 1], [0, 1]]) + mismatch = np.testing.assert_array_almost_equal(actual1, + desired1, + decimal=5) + mismatch = np.testing.assert_array_almost_equal(actual2, + desired2, + decimal=5) + self.assertIsNone(mismatch) + + def test_stratified_random_unequal_one_hot(self): + pdist = torch.tensor([1, 3]) + y = torch.eye(2)[self.y] + actual1, actual2 = initializers.stratified_random(self.x, y, pdist) + desired1 = torch.tensor([[0., -1., -2.], [0., 0., 0.], [0., 0., 0.], + [0., 0., 0.]]) + desired2 = torch.tensor([[1, 0], [0, 1], [0, 1], [0, 1]]) + mismatch = np.testing.assert_array_almost_equal(actual1, + desired1, + decimal=5) + mismatch = np.testing.assert_array_almost_equal(actual2, + desired2, + decimal=5) + self.assertIsNone(mismatch) + def tearDown(self): del self.x, self.y, self.gen _ = torch.seed() diff --git a/tests/test_modules.py b/tests/test_modules.py index 5a62087..1beb1a0 100644 --- a/tests/test_modules.py +++ b/tests/test_modules.py @@ -5,7 +5,7 @@ import unittest import numpy as np import torch -from prototorch.modules import prototypes, losses +from prototorch.modules import losses, prototypes class TestPrototypes(unittest.TestCase): @@ -18,12 +18,16 @@ class TestPrototypes(unittest.TestCase): def test_prototypes1d_init_without_input_dim(self): with self.assertRaises(NameError): - _ = prototypes.Prototypes1D(nclasses=1) + _ = prototypes.Prototypes1D(nclasses=2) def test_prototypes1d_init_without_nclasses(self): with self.assertRaises(NameError): _ = prototypes.Prototypes1D(input_dim=1) + def test_prototypes1d_init_with_nclasses_1(self): + with self.assertWarns(UserWarning): + _ = prototypes.Prototypes1D(nclasses=1, input_dim=1) + def test_prototypes1d_init_without_pdist(self): p1 = prototypes.Prototypes1D(input_dim=6, nclasses=2, @@ -73,24 +77,72 @@ class TestPrototypes(unittest.TestCase): self.assertIsNone(mismatch) def test_prototypes1d_init_without_inputdim_with_data(self): - _ = prototypes.Prototypes1D(nclasses=1, + _ = prototypes.Prototypes1D(nclasses=2, prototypes_per_class=1, prototype_initializer='stratified_mean', - data=[[[1.]], [1]]) + data=[[[1.], [0.]], [1, 0]]) def test_prototypes1d_init_with_int_data(self): - _ = prototypes.Prototypes1D(nclasses=1, + _ = prototypes.Prototypes1D(nclasses=2, prototypes_per_class=1, prototype_initializer='stratified_mean', - data=[[[1]], [1]]) + data=[[[1], [0]], [1, 0]]) + + def test_prototypes1d_init_one_hot_without_data(self): + _ = prototypes.Prototypes1D(input_dim=1, + nclasses=2, + prototypes_per_class=1, + prototype_initializer='stratified_mean', + data=None, + one_hot_labels=True) + + def test_prototypes1d_init_one_hot_labels_false(self): + """Test if ValueError is raised when `one_hot_labels` is set to `False` + but the provided `data` has one-hot encoded labels. + """ + with self.assertRaises(ValueError): + _ = prototypes.Prototypes1D( + input_dim=1, + nclasses=2, + prototypes_per_class=1, + prototype_initializer='stratified_mean', + data=([[0.], [1.]], [[0, 1], [1, 0]]), + one_hot_labels=False) + + def test_prototypes1d_init_1d_y_data_one_hot_labels_true(self): + """Test if ValueError is raised when `one_hot_labels` is set to `True` + but the provided `data` does not contain one-hot encoded labels. + """ + with self.assertRaises(ValueError): + _ = prototypes.Prototypes1D( + input_dim=1, + nclasses=2, + prototypes_per_class=1, + prototype_initializer='stratified_mean', + data=([[0.], [1.]], [0, 1]), + one_hot_labels=True) + + def test_prototypes1d_init_one_hot_labels_true(self): + """Test if ValueError is raised when `one_hot_labels` is set to `True` + but the provided `data` contains 2D targets but + does not contain one-hot encoded labels. + """ + with self.assertRaises(ValueError): + _ = prototypes.Prototypes1D( + input_dim=1, + nclasses=2, + prototypes_per_class=1, + prototype_initializer='stratified_mean', + data=([[0.], [1.]], [[0], [1]]), + one_hot_labels=True) def test_prototypes1d_init_with_int_dtype(self): with self.assertRaises(RuntimeError): _ = prototypes.Prototypes1D( - nclasses=1, + nclasses=2, prototypes_per_class=1, prototype_initializer='stratified_mean', - data=[[[1]], [1]], + data=[[[1], [0]], [1, 0]], dtype=torch.int32) def test_prototypes1d_inputndim_with_data(self): @@ -104,12 +156,15 @@ class TestPrototypes(unittest.TestCase): with self.assertRaises(ValueError): _ = prototypes.Prototypes1D( input_dim=2, - nclasses=1, + nclasses=2, prototypes_per_class=1, prototype_initializer='stratified_mean', - data=[[[1.]], [1]]) + data=[[[1.], [0.]], [1, 0]]) def test_prototypes1d_nclasses_with_data(self): + """Test ValueError raise if provided `nclasses` is not the same + as the one computed from the provided `data`. + """ with self.assertRaises(ValueError): _ = prototypes.Prototypes1D( input_dim=1, @@ -168,12 +223,12 @@ class TestPrototypes(unittest.TestCase): decimal=5) self.assertIsNone(mismatch) - def test_prototypes1d_dist_check(self): + def test_prototypes1d_dist_validate(self): p1 = prototypes.Prototypes1D(input_dim=0, prototype_distribution=[0]) with self.assertWarns(UserWarning): - _ = p1._check_prototype_distribution() + _ = p1._validate_prototype_distribution() - def test_prototypes1d_check_extra_repr_not_empty(self): + def test_prototypes1d_validate_extra_repr_not_empty(self): p1 = prototypes.Prototypes1D(input_dim=0, prototype_distribution=[0]) rep = p1.extra_repr() self.assertNotEqual(rep, '')