From fa78cc5a93239c5479eedc8ba39082a96b525747 Mon Sep 17 00:00:00 2001 From: ilan-gold Date: Tue, 29 Mar 2022 11:56:04 -0400 Subject: [PATCH 1/3] Starting shape tests --- .vscode/launch.json | 16 +++++++++++++ tests/numpy/test_shape.py | 48 +++++++++++++++++++++++++++++++++++++++ tests/numpy/utils.py | 7 +++--- 3 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 tests/numpy/test_shape.py diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..306f58eb --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Current File", + "type": "python", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal", + "justMyCode": true + } + ] +} \ No newline at end of file diff --git a/tests/numpy/test_shape.py b/tests/numpy/test_shape.py new file mode 100644 index 00000000..c79177d7 --- /dev/null +++ b/tests/numpy/test_shape.py @@ -0,0 +1,48 @@ +import logging +import unittest + +from utils import get_estimator, get_generated_model + +from batchglm.train.numpy.base_glm import BaseModelContainer + +logger = logging.getLogger("batchglm") + +n_obs = 2000 +n_vars = 100 +num_batches = 4 +num_conditions = 2 + +class TestShape(unittest.TestCase): + + def _test_shape(self, model_container: BaseModelContainer) -> bool: + """Runs the estimator to fit the model and evaluates with respect to the simulated parameters.""" + assert model_container.theta_scale.shape == (model_container.model.num_scale_params, n_vars) + assert model_container.theta_location.shape == (model_container.model.num_loc_params, n_vars) + + +class TestShapeNB(TestShape): + def test_shape(self) -> bool: + """ + This tests randTheta simulated data with 2 conditions and 4 batches sparse and dense. + """ + dense_model = get_generated_model( + noise_model="nb", num_conditions=num_conditions, num_batches=num_batches, sparse=False, + n_obs=n_obs, n_vars=n_vars + ) + sparse_model = get_generated_model( + noise_model="nb", num_conditions=num_conditions, num_batches=num_batches, sparse=True, + n_obs=n_obs, n_vars=n_vars + ) + dense_estimator = get_estimator( + noise_model="nb", model=dense_model, init_location="standard", init_scale="standard" + ) + sparse_estimator = get_estimator( + noise_model="nb", model=sparse_model, init_location="standard", init_scale="standard" + ) + model_container_dense = dense_estimator.model_container + model_container_sparse = sparse_estimator.model_container + self._test_shape(model_container_dense) + self._test_shape(model_container_sparse) + +if __name__ == "__main__": + unittest.main() diff --git a/tests/numpy/utils.py b/tests/numpy/utils.py index f89bcdb5..af41a7bc 100644 --- a/tests/numpy/utils.py +++ b/tests/numpy/utils.py @@ -39,7 +39,8 @@ def get_model(noise_model: str) -> _ModelGLM: def get_generated_model( - noise_model: str, num_conditions: int, num_batches: int, sparse: bool, mode: Optional[str] = None + noise_model: str, num_conditions: int, num_batches: int, sparse: bool, mode: Optional[str] = None, + n_obs: Optional[int] = 2000, n_vars: Optional[int] = 100, ) -> _ModelGLM: model = get_model(noise_model=noise_model) @@ -85,8 +86,8 @@ def const(offset: float): raise ValueError(f"Mode {mode} not recognized.") model.generate_artificial_data( - n_obs=2000, - n_vars=100, + n_obs=n_obs, + n_vars=n_vars, num_conditions=num_conditions, num_batches=num_batches, intercept_scale=True, From 89569d6005c2bb3da63fbdb82f1dfa2974dd54b4 Mon Sep 17 00:00:00 2001 From: ilan-gold Date: Tue, 29 Mar 2022 11:56:21 -0400 Subject: [PATCH 2/3] oops --- .vscode/launch.json | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 306f58eb..00000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Python: Current File", - "type": "python", - "request": "launch", - "program": "${file}", - "console": "integratedTerminal", - "justMyCode": true - } - ] -} \ No newline at end of file From 25e44da6107dc817405a0bf4e0a4aeeec52d32a2 Mon Sep 17 00:00:00 2001 From: ilan-gold Date: Tue, 29 Mar 2022 19:38:50 -0400 Subject: [PATCH 3/3] [WIP] Add normal tests. --- .../train/numpy/glm_norm/model_container.py | 9 ++- tests/numpy/test_shape.py | 58 ++++++++++++++----- 2 files changed, 50 insertions(+), 17 deletions(-) diff --git a/batchglm/train/numpy/glm_norm/model_container.py b/batchglm/train/numpy/glm_norm/model_container.py index d9c964d8..ca99a5a5 100644 --- a/batchglm/train/numpy/glm_norm/model_container.py +++ b/batchglm/train/numpy/glm_norm/model_container.py @@ -26,7 +26,7 @@ def jac_weight_scale_j(self, j) -> Union[np.ndarray, dask.array.core.Array]: @property def fim_location_location(self): return np.power(self.location / self.scale, 2) - + @property def fim_location_scale(self) -> np.ndarray: # Unfinished in manuscript? @@ -75,3 +75,10 @@ def ll_j(self, j) -> Union[np.ndarray, dask.array.core.Array]: var = np.power(sd, 2) ll = -.5 * loc.shape[0] * np.log(2 * math.pi * var) - .5 * np.linalg.norm(resid, axis=0) / np.power(sd, 2) return ll + + @property + def ybar(self) -> Union[np.ndarray, dask.array.core.Array]: + """ + :return: observations x features + """ + return np.asarray(self.x - self.location) / self.location diff --git a/tests/numpy/test_shape.py b/tests/numpy/test_shape.py index c79177d7..a0421498 100644 --- a/tests/numpy/test_shape.py +++ b/tests/numpy/test_shape.py @@ -12,37 +12,63 @@ num_batches = 4 num_conditions = 2 -class TestShape(unittest.TestCase): - def _test_shape(self, model_container: BaseModelContainer) -> bool: - """Runs the estimator to fit the model and evaluates with respect to the simulated parameters.""" - assert model_container.theta_scale.shape == (model_container.model.num_scale_params, n_vars) - assert model_container.theta_location.shape == (model_container.model.num_loc_params, n_vars) +def _test_shape_of_model(model_container: BaseModelContainer) -> bool: + """Check the shape of different fitted/parametrized values against what is epected""" + assert model_container.theta_scale.shape == (model_container.model.num_scale_params, n_vars) + assert model_container.theta_location.shape == (model_container.model.num_loc_params, n_vars) + assert model_container.fim_weight_location_location.shape == (n_obs, n_vars) -class TestShapeNB(TestShape): - def test_shape(self) -> bool: - """ - This tests randTheta simulated data with 2 conditions and 4 batches sparse and dense. - """ + assert model_container.hessian_weight_location_location.shape == (n_obs, n_vars) + assert model_container.hessian_weight_location_scale.shape == (n_obs, n_vars) + assert model_container.hessian_weight_scale_scale.shape == (n_obs, n_vars) + + assert model_container.jac_scale.shape == (n_vars, model_container.model.num_scale_params) + assert model_container.jac_location.shape == (n_vars, model_container.model.num_loc_params) + + +class TestShape(unittest.TestCase): + + def _test_shape(self) -> bool: dense_model = get_generated_model( - noise_model="nb", num_conditions=num_conditions, num_batches=num_batches, sparse=False, + noise_model=self._model_name, num_conditions=num_conditions, num_batches=num_batches, sparse=False, n_obs=n_obs, n_vars=n_vars ) sparse_model = get_generated_model( - noise_model="nb", num_conditions=num_conditions, num_batches=num_batches, sparse=True, + noise_model=self._model_name, num_conditions=num_conditions, num_batches=num_batches, sparse=True, n_obs=n_obs, n_vars=n_vars ) dense_estimator = get_estimator( - noise_model="nb", model=dense_model, init_location="standard", init_scale="standard" + noise_model=self._model_name, model=dense_model, init_location="standard", init_scale="standard" ) sparse_estimator = get_estimator( - noise_model="nb", model=sparse_model, init_location="standard", init_scale="standard" + noise_model=self._model_name, model=sparse_model, init_location="standard", init_scale="standard" ) model_container_dense = dense_estimator.model_container model_container_sparse = sparse_estimator.model_container - self._test_shape(model_container_dense) - self._test_shape(model_container_sparse) + _test_shape_of_model(model_container_dense) + _test_shape_of_model(model_container_sparse) + return True + + +class TestShapeNB(TestShape): + + def __init__(self, *args, **kwargs): + self._model_name = "nb" + super(TestShapeNB, self).__init__(*args, **kwargs) + + def test_shape(self) -> bool: + return self._test_shape() + +class TestShapeNorm(TestShape): + + def __init__(self, *args, **kwargs): + self._model_name = "norm" + super(TestShapeNorm, self).__init__(*args, **kwargs) + + def test_shape(self) -> bool: + return self._test_shape() if __name__ == "__main__": unittest.main()