source: orange/Orange/testing/unit/tests/test_projection_linear.py @ 10710:1083062348a9

Revision 10710:1083062348a9, 7.5 KB checked in by anze <anze.staric@…>, 2 years ago (diff)

Improved pca unittests.

Line 
1try:
2    import unittest2 as unittest
3except:
4    import unittest
5
6import numpy as np
7import random
8
9from Orange import data, feature
10from Orange.projection import linear
11
12random.seed(0)
13
14def normalize(a):
15    a = a if isinstance(a, np.ndarray) else np.array(a)
16    return a / np.linalg.norm(a)
17
18datasets = None
19
20def prepare_dataset(components=((),), n=150):
21    components = components if isinstance(components, np.ndarray) else np.array(components)
22
23    ncomponents, m = components.shape
24    coefficients = np.random.normal(0., 1., (n, ncomponents))
25
26    d = np.dot(coefficients, components)
27
28    domain = data.Domain([feature.Continuous("A%d" % i) for i in range(m)], False)
29    return domain, d
30
31def create_base(ncomponents, m):
32    vector = np.random.randint(0,5,m)
33    while not vector.any():
34        vector = np.random.randint(0,5,m)
35    principal_components = np.zeros((ncomponents, m))
36    k = float(m) / ncomponents
37    to = 0
38    for i in range(1,ncomponents):
39        from_, to = int(k*(i-1)), int(k*i)
40        principal_components[i-1,from_:to] = vector[from_:to]
41    principal_components[ncomponents-1,to:m] = normalize(vector[to:m])
42    return principal_components
43
44
45class TestPca(unittest.TestCase):
46    def create_dataset(self, ncomponents=3, m=10):
47        self.principal_components = create_base(ncomponents, m)
48        self.dataset = data.Table(*prepare_dataset(components=self.principal_components))
49
50    def create_empty_dataset(self):
51        self.dataset = data.Table(*prepare_dataset(components=([0, 0, 0, 0, 0],), n=0))
52
53    def create_constant_dataset(self):
54        self.dataset = data.Table(*prepare_dataset(components=([0, 0, 0, 0, 0],)))
55
56    def create_dataset_with_unknowns(self, percentage=0.05):
57        self.principal_component = normalize([random.randint(0, 5) for _ in range(10)])
58        self.dataset = data.Table(*prepare_dataset(components=[self.principal_component]))
59
60        for ex in self.dataset:
61            for i, _ in enumerate(ex):
62                if random.random() < percentage:
63                    ex[i] = "?"
64
65
66    def test_pca(self):
67        for m in (10, 250):
68            self.create_dataset(m=m)
69
70            pca = linear.Pca(standardize=False)(self.dataset)
71
72            self.assertInCorrectSpace(pca.projection[pca.variances > 0.01, :])
73            for v in pca.projection:
74                # projections vectors should be normalized
75                self.assertAlmostEqual(np.linalg.norm(v), 1.)
76
77            # Components should have decreasing variants
78            self.assertListEqual(pca.variances.tolist(), sorted(pca.variances, reverse=True))
79
80    def test_pca_with_standardization(self):
81        self.create_dataset(ncomponents=1)
82
83        pca = linear.Pca(standardize=True)(self.dataset)
84        projection = pca.projection[0]
85        non_zero_elements = projection[projection.nonzero()]
86
87        # since values in all dimensions are normally distributed, dimensions should be treated as equally important
88        self.assertAlmostEqual(non_zero_elements.min(), non_zero_elements.max())
89
90    def test_pca_with_variance_covered(self):
91        ncomponents = 3
92        self.create_dataset(ncomponents=ncomponents)
93
94        pca = linear.Pca(variance_covered=.99)(self.dataset)
95
96        nvectors, vector_dimension = pca.projection.shape
97        self.assertEqual(nvectors, ncomponents)
98
99    def test_pca_with_max_components(self):
100        max_components = 3
101        self.create_dataset(ncomponents = max_components + 3)
102
103        pca = linear.Pca(max_components=max_components)(self.dataset)
104
105        nvectors, vector_dimension = pca.projection.shape
106        self.assertEqual(nvectors, max_components)
107
108    def test_pca_handles_unknowns(self):
109        self.create_dataset_with_unknowns()
110
111        linear.Pca()(self.dataset)
112
113    def test_total_variance_remains_the_same(self):
114        for m in (10, 250):
115            self.create_dataset(m=m)
116
117            pca = linear.Pca()(self.dataset)
118
119            self.assertAlmostEqual(pca.variance_sum, pca.variances.sum())
120            self.assertAlmostEqual(pca.variance_sum, (self.principal_components != 0).sum())
121
122    def test_pca_on_empty_data(self):
123        self.create_empty_dataset()
124
125        with self.assertRaises(ValueError):
126            linear.Pca()(self.dataset)
127
128    def test_pca_on_only_constant_features(self):
129        self.create_constant_dataset()
130
131        with self.assertRaises(ValueError):
132            linear.Pca()(self.dataset)
133
134    def assertInCorrectSpace(self, vectors):
135        vectors = vectors.copy()
136        for component in self.principal_components:
137            i = component.nonzero()[0][0]
138            coef = vectors[:,i] / component[i]
139            vectors -= np.dot(coef.reshape(-1, 1), component.reshape(1, -1))
140
141        for vector in vectors:
142            for value in vector:
143                self.assertAlmostEqual(value, 0.)
144
145
146class TestProjector(unittest.TestCase):
147    def create_normal_dataset(self):
148        self.principal_component = normalize([random.randint(0, 5) for _ in range(10)])
149        self.dataset = data.Table(*prepare_dataset(components=[self.principal_component]))
150
151    def create_dataset_with_classes(self):
152        domain, features = prepare_dataset(components=[[random.randint(0, 5) for _ in range(10)]])
153        domain = data.Domain(domain.features,
154                             feature.Discrete("C", values=["F", "T"]),
155                             class_vars=[feature.Discrete("MC%i" % i, values=["F", "T"]) for i in range(4)])
156
157        self.dataset = data.Table(domain, np.hstack((features, np.random.random((len(features), 5)))))
158
159
160    def test_projected_domain_can_convert_data_with_class(self):
161        self.create_dataset_with_classes()
162        projector = linear.Pca(variance_covered=.99)(self.dataset)
163
164        projected_data = projector(self.dataset)
165        converted_data = data.Table(projected_data.domain, self.dataset)
166
167        self.assertItemsEqual(projected_data, converted_data)
168
169    def test_projected_domain_can_convert_data_without_class(self):
170        self.create_normal_dataset()
171        projector = linear.Pca(variance_covered=.99)(self.dataset)
172
173        projected_data = projector(self.dataset)
174        converted_data = data.Table(projected_data.domain, self.dataset)
175
176        self.assertItemsEqual(projected_data, converted_data)
177
178    def test_projected_domain_contains_class_vars(self):
179        self.create_dataset_with_classes()
180
181        projector = linear.Pca(variance_covered=.99)(self.dataset)
182        projected_data = projector(self.dataset)
183
184        self.assertIn(self.dataset.domain.class_var, projected_data.domain)
185        for class_ in self.dataset.domain.class_vars:
186            self.assertIn(class_, projected_data.domain)
187        for ex1, ex2 in zip(self.dataset, projected_data):
188            self.assertEqual(ex1.get_class(), ex2.get_class())
189            for v1, v2 in zip(ex1.get_classes(), ex2.get_classes()):
190                self.assertEqual(v2, v2)
191
192
193    def test_projects_example(self):
194        self.create_normal_dataset()
195        projector = linear.Pca(variance_covered=.99)(self.dataset)
196
197        projector(self.dataset[0])
198
199    def test_projects_data_table(self):
200        self.create_normal_dataset()
201        projector = linear.Pca(variance_covered=.99)(self.dataset)
202
203        projector(self.dataset)
204
205    def test_converts_input_domain_if_needed(self):
206        self.create_normal_dataset()
207        projector = linear.Pca(variance_covered=.99)(self.dataset)
208
209        new_examples = data.Table(data.Domain(self.dataset.domain.features[:5]), [[1.,2.,3.,4.,5.]])
210
211        projector(new_examples)
212
213
214class TestFda(unittest.TestCase):
215    pass
216
217if __name__ == '__main__':
218    unittest.main()
219
Note: See TracBrowser for help on using the repository browser.