Coverage for contextualized/easy/tests.py: 99%
224 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-21 13:49 -0400
« prev ^ index » next coverage.py v7.4.4, created at 2024-04-21 13:49 -0400
1""""
2Unit tests for Easy Networks.
3"""
5import unittest
6import numpy as np
7import torch
8from sklearn.metrics import roc_auc_score
10from contextualized.easy import (
11 ContextualizedMarkovNetworks,
12 ContextualizedCorrelationNetworks,
13 ContextualizedBayesianNetworks,
14 ContextualizedRegressor,
15 ContextualizedClassifier,
16 ContextualGAMClassifier,
17 ContextualGAMRegressor,
18)
19from contextualized.utils import DummyParamPredictor, DummyYPredictor
22class TestEasyNetworks(unittest.TestCase):
23 """
24 Test Easy Network models.
25 """
27 def __init__(self, *args, **kwargs):
28 super().__init__(*args, **kwargs)
30 def _quicktest(self, model, C, X, **kwargs):
31 print(f"{type(model)} quicktest")
32 model.fit(C, X, max_epochs=0)
33 err_init = model.measure_mses(C, X)
34 model.fit(C, X, **kwargs)
35 err_trained = model.measure_mses(C, X)
36 W_pred = model.predict_networks(C)
37 assert W_pred.shape == (C.shape[0], X.shape[1], X.shape[1])
38 assert np.mean(err_trained) < np.mean(err_init)
41class TestContextualizedMarkovNetworks(TestEasyNetworks):
42 """
43 Test Contextualized Markov Network models.
44 """
46 def setUp(self):
47 """
48 Shared unit test setup code.
49 """
50 np.random.seed(0)
51 torch.manual_seed(0)
52 self.n_samples = 100
53 self.c_dim = 4
54 self.x_dim = 5
55 C = torch.rand((self.n_samples, self.c_dim)) - 0.5
56 # TODO: Use graph utils to generate X from a network.
57 X = torch.rand((self.n_samples, self.x_dim)) - 0.5
58 self.C, self.X = C.numpy(), X.numpy()
60 def test_markov(self):
61 """Test Case for ContextualizedMarkovNetworks."""
62 model = ContextualizedMarkovNetworks()
63 self._quicktest(model, self.C, self.X, max_epochs=10, learning_rate=1e-3)
64 self._quicktest(
65 model, self.C, self.X, max_epochs=10, learning_rate=1e-3, val_split=0.5
66 )
68 model = ContextualizedMarkovNetworks(num_archetypes=16)
69 self._quicktest(model, self.C, self.X, max_epochs=10, learning_rate=1e-3)
71 model = ContextualizedMarkovNetworks(encoder_type="ngam", num_archetypes=16)
72 self._quicktest(model, self.C, self.X, max_epochs=10, learning_rate=1e-3)
73 omegas = model.predict_precisions(self.C, individual_preds=False)
74 assert np.shape(omegas) == (self.n_samples, self.x_dim, self.x_dim)
75 omegas = model.predict_precisions(self.C, individual_preds=True)
76 assert np.shape(omegas) == (1, self.n_samples, self.x_dim, self.x_dim)
79class TestContextualizedCorrelationNetworks(TestEasyNetworks):
80 """
81 Test Contextualized Correlation Network models.
82 """
84 def setUp(self):
85 """
86 Shared unit test setup code.
87 """
88 np.random.seed(0)
89 torch.manual_seed(0)
90 self.n_samples = 100
91 self.c_dim = 4
92 self.x_dim = 5
93 C = torch.rand((self.n_samples, self.c_dim)) - 0.5
94 # TODO: Use graph utils to generate X from a network.
95 X = torch.rand((self.n_samples, self.x_dim)) - 0.5
96 self.C, self.X = C.numpy(), X.numpy()
98 def test_correlation(self):
99 """
100 Test Case for ContextualizedCorrelationNetworks.
101 """
103 model = ContextualizedCorrelationNetworks()
104 self._quicktest(model, self.C, self.X, max_epochs=10, learning_rate=1e-3)
105 self._quicktest(
106 model, self.C, self.X, max_epochs=10, learning_rate=1e-3, val_split=0.5
107 )
109 model = ContextualizedCorrelationNetworks(num_archetypes=16)
110 self._quicktest(model, self.C, self.X, max_epochs=10, learning_rate=1e-3)
112 model = ContextualizedCorrelationNetworks(
113 encoder_type="ngam", num_archetypes=16
114 )
115 self._quicktest(model, self.C, self.X, max_epochs=10, learning_rate=1e-3)
116 rho = model.predict_correlation(self.C, squared=False)
117 assert rho.shape == (1, self.n_samples, self.x_dim, self.x_dim)
118 rho = model.predict_correlation(self.C, individual_preds=False, squared=False)
119 assert rho.shape == (self.n_samples, self.x_dim, self.x_dim), rho.shape
120 rho_squared = model.predict_correlation(self.C, squared=True)
121 assert np.min(rho_squared) >= 0
122 assert rho_squared.shape == (1, self.n_samples, self.x_dim, self.x_dim)
125class TestContextualizedBayesianNetworks(TestEasyNetworks):
126 """
127 Test Contextualized Bayesian Network models.
128 """
130 def setUp(self):
131 """
132 Shared unit test setup code.
133 """
134 np.random.seed(0)
135 torch.manual_seed(0)
136 self.n_samples = 100
137 self.c_dim = 4
138 self.x_dim = 5
139 C = torch.rand((self.n_samples, self.c_dim)) - 0.5
140 # TODO: Use graph utils to generate X from a network.
141 X = torch.rand((self.n_samples, self.x_dim)) - 0.5
142 self.C, self.X = C.numpy(), X.numpy()
144 def test_bayesian_factors(self):
145 """Test case for ContextualizedBayesianNetworks."""
146 model = ContextualizedBayesianNetworks(
147 encoder_type="ngam", num_archetypes=16, num_factors=2
148 )
149 model.fit(self.C, self.X, max_epochs=10)
150 networks = model.predict_networks(self.C, individual_preds=False)
151 assert np.shape(networks) == (self.n_samples, self.x_dim, self.x_dim)
152 networks = model.predict_networks(self.C, factors=True)
153 assert np.shape(networks) == (self.n_samples, 2, 2)
154 model = ContextualizedBayesianNetworks(
155 encoder_type="ngam", num_archetypes=16, num_factors=2
156 )
157 self._quicktest(model, self.C, self.X, max_epochs=10, learning_rate=1e-3)
159 def test_bayesian_default(self):
160 model = ContextualizedBayesianNetworks()
161 self._quicktest(model, self.C, self.X, max_epochs=10, learning_rate=1e-3)
163 def test_bayesian_val_split(self):
164 model = ContextualizedBayesianNetworks()
165 self._quicktest(
166 model, self.C, self.X, max_epochs=10, learning_rate=1e-3, val_split=0.5
167 )
169 def test_bayesian_archetypes(self):
170 model = ContextualizedBayesianNetworks(num_archetypes=16)
171 self._quicktest(model, self.C, self.X, max_epochs=10, learning_rate=1e-3)
173 def test_bayesian_encoder(self):
174 model = ContextualizedBayesianNetworks(encoder_type="ngam", num_archetypes=16)
175 self._quicktest(model, self.C, self.X, max_epochs=10, learning_rate=1e-3)
176 networks = model.predict_networks(self.C, individual_preds=False)
177 assert np.shape(networks) == (self.n_samples, self.x_dim, self.x_dim)
179 model = ContextualizedBayesianNetworks(encoder_type="mlp", num_archetypes=16)
180 self._quicktest(model, self.C, self.X, max_epochs=10, learning_rate=1e-3)
181 networks = model.predict_networks(self.C, individual_preds=False)
182 assert np.shape(networks) == (self.n_samples, self.x_dim, self.x_dim)
184 def test_bayesian_acyclicity(self):
185 model = ContextualizedBayesianNetworks(
186 archetype_dag_loss_type="DAGMA", num_archetypes=16
187 )
188 self._quicktest(model, self.C, self.X, max_epochs=10, learning_rate=1e-3)
189 networks = model.predict_networks(self.C, individual_preds=False)
190 assert np.shape(networks) == (self.n_samples, self.x_dim, self.x_dim)
192 model = ContextualizedBayesianNetworks(
193 archetype_dag_loss_type="poly", num_archetypes=16
194 )
195 self._quicktest(model, self.C, self.X, max_epochs=10, learning_rate=1e-3)
196 networks = model.predict_networks(self.C, individual_preds=False)
197 assert np.shape(networks) == (self.n_samples, self.x_dim, self.x_dim)
200class TestEasyClassifiers(unittest.TestCase):
201 """
202 Test Easy Classifier models.
203 """
205 def __init__(self, *args, **kwargs):
206 super().__init__(*args, **kwargs)
208 def _quicktest(self, model, C, X, Y, **kwargs):
209 print(f"{type(model)} quicktest")
210 model.fit(C, X, Y, max_epochs=0)
211 y_preds_init = model.predict(C, X)
212 y_proba_preds_init = model.predict_proba(C, X)[:, :, 1]
213 err_init = (Y != y_preds_init).sum()
214 roc_init = roc_auc_score(Y, y_proba_preds_init)
215 model.fit(C, X, Y, **kwargs)
216 beta_preds, mu_preds = model.predict_params(C)
217 assert beta_preds.shape == (X.shape[0], Y.shape[1], X.shape[1])
218 assert mu_preds.shape == (X.shape[0], Y.shape[1])
219 assert not np.any(np.isnan(beta_preds))
220 assert not np.any(np.isnan(mu_preds))
221 y_preds = model.predict(C, X)
222 y_proba_preds = model.predict_proba(C, X)[:, :, 1]
223 assert y_preds.shape == Y.shape
224 assert y_proba_preds.shape == Y.shape
225 err_trained = (Y != y_preds).sum()
226 roc_trained = roc_auc_score(Y, y_proba_preds)
227 assert err_trained < err_init
228 assert roc_trained > roc_init
229 print(err_trained, err_init)
231 def test_classifier(self):
232 """Test Case for ContextualizedClassifier."""
234 n_samples = 1000
235 c_dim = 100
236 x_dim = 3
237 y_dim = 1
238 C = np.random.uniform(-1, 1, size=(n_samples, c_dim))
239 X = np.random.uniform(-1, 1, size=(n_samples, x_dim))
240 Y = np.random.binomial(1, 0.5, size=(n_samples, y_dim))
242 model = ContextualizedClassifier(alpha=1e-1, encoder_type="mlp")
243 self._quicktest(model, C, X, Y, max_epochs=10, es_patience=float("inf"))
245 def test_gam_classifier(self):
246 """Test Case for ContextualGAMClassifier."""
248 n_samples = 1000
249 c_dim = 100
250 x_dim = 3
251 y_dim = 1
252 C = np.random.uniform(-1, 1, size=(n_samples, c_dim))
253 X = np.random.uniform(-1, 1, size=(n_samples, x_dim))
254 Y = np.random.binomial(1, 0.5, size=(n_samples, y_dim))
256 model = ContextualGAMClassifier(alpha=1e-1, encoder_type="mlp")
257 self._quicktest(model, C, X, Y, max_epochs=10, es_patience=float("inf"))
260class TestEasyRegression(unittest.TestCase):
261 """
262 Test Easy Regression models.
263 """
265 def __init__(self, *args, **kwargs):
266 super().__init__(*args, **kwargs)
268 def _quicktest(self, model, C, X, Y, **kwargs):
269 print(f"{type(model)} quicktest")
270 model.fit(C, X, Y, max_epochs=0)
271 err_init = np.linalg.norm(Y - model.predict(C, X), ord=2)
272 model.fit(C, X, Y, **kwargs)
273 beta_preds, mu_preds = model.predict_params(C)
274 try:
275 y_dim = Y.shape[1]
276 except IndexError:
277 y_dim = 1
278 assert beta_preds.shape == (X.shape[0], y_dim, X.shape[1])
279 assert mu_preds.shape == (X.shape[0], y_dim)
280 y_preds = model.predict(C, X)
281 assert y_preds.shape == (len(Y), y_dim)
282 err_trained = np.linalg.norm(Y - np.squeeze(y_preds), ord=2)
283 assert err_trained < err_init
284 print(err_trained, err_init)
286 def test_regressor(self):
287 """Test Case for ContextualizedRegressor."""
288 n_samples = 1000
289 c_dim = 2
290 x_dim = 3
291 y_dim = 2
292 C = torch.rand((n_samples, c_dim)) - 0.5
293 beta_1 = C.sum(axis=1).unsqueeze(-1) ** 2
294 beta_2 = -C.sum(axis=1).unsqueeze(-1)
295 b_1 = C[:, 0].unsqueeze(-1)
296 b_2 = C[:, 1].unsqueeze(-1)
297 X = torch.rand((n_samples, x_dim)) - 0.5
298 outcome_1 = X[:, 0].unsqueeze(-1) * beta_1 + b_1
299 outcome_2 = X[:, 1].unsqueeze(-1) * beta_2 + b_2
300 Y = torch.cat((outcome_1, outcome_2), axis=1)
302 C, X, Y = C.numpy(), X.numpy(), Y.numpy()
304 # Naive Multivariate
305 parambase = DummyParamPredictor((y_dim, x_dim), (y_dim, 1))
306 ybase = DummyYPredictor((y_dim, 1))
307 model = ContextualizedRegressor(
308 base_param_predictor=parambase, base_y_predictor=ybase
309 )
310 self._quicktest(
311 model, C, X, Y, max_epochs=10, learning_rate=1e-3, es_patience=float("inf")
312 )
314 model = ContextualizedRegressor(num_archetypes=0)
315 self._quicktest(model, C, X, Y, max_epochs=10, es_patience=float("inf"))
317 model = ContextualizedRegressor(num_archetypes=4)
318 self._quicktest(model, C, X, Y, max_epochs=10, es_patience=float("inf"))
320 # With regularization
321 model = ContextualizedRegressor(
322 num_archetypes=4, alpha=1e-1, l1_ratio=0.5, mu_ratio=0.1
323 )
324 self._quicktest(model, C, X, Y, max_epochs=10, es_patience=float("inf"))
326 # With bootstrap
327 model = ContextualizedRegressor(
328 num_archetypes=4, alpha=1e-1, l1_ratio=0.5, mu_ratio=0.1
329 )
330 self._quicktest(
331 model,
332 C,
333 X,
334 Y,
335 max_epochs=10,
336 n_bootstraps=2,
337 learning_rate=1e-3,
338 es_patience=float("inf"),
339 )
341 # Check smaller Y.
342 model = ContextualizedRegressor(
343 num_archetypes=4, alpha=1e-1, l1_ratio=0.5, mu_ratio=0.1
344 )
345 self._quicktest(
346 model,
347 C,
348 X,
349 Y[:, 0],
350 max_epochs=10,
351 n_bootstraps=2,
352 learning_rate=1e-3,
353 es_patience=float("inf"),
354 )
356 def test_gam_regressor(self):
357 """Test Case for ContextualGAMRegressor."""
358 n_samples = 100
359 c_dim = 2
360 x_dim = 3
361 y_dim = 2
362 C = torch.rand((n_samples, c_dim)) - 0.5
363 beta_1 = C.sum(axis=1).unsqueeze(-1) ** 2
364 beta_2 = -C.sum(axis=1).unsqueeze(-1)
365 b_1 = C[:, 0].unsqueeze(-1)
366 b_2 = C[:, 1].unsqueeze(-1)
367 X = torch.rand((n_samples, x_dim)) - 0.5
368 outcome_1 = X[:, 0].unsqueeze(-1) * beta_1 + b_1
369 outcome_2 = X[:, 1].unsqueeze(-1) * beta_2 + b_2
370 Y = torch.cat((outcome_1, outcome_2), axis=1)
372 C, X, Y = C.numpy(), X.numpy(), Y.numpy()
374 model = ContextualGAMRegressor()
375 self._quicktest(
376 model, C, X, Y, max_epochs=10, learning_rate=1e-3, es_patience=float("inf")
377 )
380if __name__ == "__main__":
381 unittest.main()