def setUp(self): self.args = (2, 2) self.dummy_source = sources.Constant(1) self.arma = make_random_arma(*self.args, rng=np.random.default_rng(0)) self.arma_alt = make_random_arma(*self.args, rng=np.random.default_rng(0), default_source=self.dummy_source)
def test_generated_ma_has_correct_orders(self): q = 2 ar = make_random_arma(0, q, self.rng) self.assertEqual(ar.p, 0) self.assertEqual(ar.q, q) self.assertEqual(len(ar.a), ar.p) self.assertEqual(len(ar.b), ar.q)
def make_bio_wta_with_stable_initial(*args, **kwargs) -> BioWTARegressor: """ Call the BioWTARegressor constructor, ensuring that the initial coefficients are chosen to correspond to stable AR processes. """ weights = [ make_random_arma(kwargs["n_features"], 0, rng=kwargs["rng"]).a for _ in range(kwargs["n_models"]) ] return BioWTARegressor(*args, weights=weights, **kwargs)
def test_generated_ar_has_correct_orders(self): p = 3 ar = make_random_arma(p, 0, self.rng) self.assertEqual(ar.p, p) self.assertEqual(ar.q, 0) self.assertEqual(len(ar.a), ar.p) self.assertEqual(len(ar.b), ar.q)
def test_generated_process_has_random_biases_when_bias_range_given(self): n = 20 bias_range = (-0.5, 0.7) biases = [] for i in range(n): arma = make_random_arma(5, 3, self.rng, bias_range=bias_range) biases.append(arma.bias) self.assertGreater(np.std(biases), 0.0)
def test_generated_process_has_bias_in_given_range(self): n = 20 bias_range = (-0.5, 0.7) biases = [] for i in range(n): arma = make_random_arma(5, 3, self.rng, bias_range=bias_range) biases.append(arma.bias) np.testing.assert_array_less(bias_range[0], biases) np.testing.assert_array_less(biases, bias_range[1])
def test_fix_source_scale_returns_final_scale(self): seed = 10 src = sources.GaussianNoise(seed) rng = np.random.default_rng(30) arma = make_random_arma(2, 0, rng, default_source=src) scale = sources.fix_source_scale(arma) self.assertAlmostEqual(scale, src.scale)
def test_ar1_output_variance_is_fixed_to_one_by_default(self): seed = 10 src = sources.GaussianNoise(seed) rng = np.random.default_rng(30) arma = make_random_arma(1, 0, rng, default_source=src) sources.fix_source_scale(arma, n_samples=5000) ma_var = src.scale**2 arma_var = ma_var / (1 - arma.a[0]**2) self.assertAlmostEqual(arma_var, 1, places=2)
def test_ar2_output_variance_is_fixed_to_one_by_default(self): seed = 10 src = sources.GaussianNoise(seed) rng = np.random.default_rng(30) arma = make_random_arma(2, 0, rng, default_source=src) sources.fix_source_scale(arma, n_samples=10000) ma_var = src.scale**2 a_diff = 1 - arma.a[1] a_sum = 1 + arma.a[1] arma_var = a_diff * ma_var / (a_sum * (a_diff**2 - arma.a[0]**2)) self.assertAlmostEqual(arma_var, 1, places=2)
def test_scale_varies_in_proportion_to_output_variance(self): seed = 10 src = sources.GaussianNoise(seed) rng = np.random.default_rng(30) arma = make_random_arma(2, 0, rng, default_source=src) var1 = 0.5 sources.fix_source_scale(arma, output_std=var1) scale1 = src.scale var2 = 1.5 sources.fix_source_scale(arma, output_std=var2) scale2 = src.scale self.assertAlmostEqual(var1 / var2, scale1 / scale2, places=2)
def test_fix_source_scale_does_not_affect_sources_rng_by_default(self): seed = 123 src1 = sources.GaussianNoise(seed) n = 12 u1 = src1(size=n) rng = np.random.default_rng(30) src2 = sources.GaussianNoise(seed) arma = make_random_arma(3, 2, rng, default_source=src2) sources.fix_source_scale(arma) # reset scale src2.scale = 1 u2 = src2(size=n) np.testing.assert_allclose(u1, u2)
def test_fix_source_scale_affects_sources_rng_when_use_copy_is_false(self): seed = 123 src1 = sources.GaussianNoise(seed) n = 12 u1 = src1(size=n) rng = np.random.default_rng(30) src2 = sources.GaussianNoise(seed) arma = make_random_arma(3, 2, rng, default_source=src2) sources.fix_source_scale(arma, use_copy=False) # reset scale src2.scale = 1 u2 = src2(size=n) self.assertGreater(np.max(np.abs(u1 - u2)), 1e-3)
def assert_if_poles_or_zeros_not_within_given_radius( self, n: int, kind: str, order: int, radius: float): """ Generate many AR or MA processes and check that their poles or zeros are within the given radius. Parameters ---------- n Number of processes to generate. kind Kind of process, either "ar" or "ma". order Order of the AR or MA processes. radius Radius to request (and check) for the poles / zeros. """ if kind == "ar": p = order q = 0 elif kind == "ma": p = 0 q = order else: raise NotImplementedError("Unknown kind.") all_roots = [] for i in range(n): arma = make_random_arma(p, q, self.rng, max_pole_radius=radius, max_zero_radius=radius) coeffs = np.ones(order + 1) if q == 0: coeffs[1:] = -arma.a else: coeffs[1:] = arma.b roots = np.roots(coeffs) all_roots.extend(roots) np.testing.assert_array_less(np.abs(all_roots), radius)
def _generate_armas( self, rng: Union[np.random.RandomState, np.random.Generator], arma_orders: Optional[Sequence] = None, arma_kws: Optional[dict] = None, ): """ Generate the ARMA processes to use for each signal. """ # handle None arma_kws if arma_kws is None: arma_kws = {} armas = [] for i in range(self.n_signals): crt_armas = [] for crt_order in arma_orders: crt_arma = make_random_arma(*crt_order, rng=rng, **arma_kws) crt_armas.append(crt_arma) armas.append(crt_armas) self.armas = armas
def test_raises_if_both_bias_range_and_bias_keyword(self): with self.assertRaises(TypeError): make_random_arma(3, 2, default_rng(1), bias_range=(2, 3), bias=2.5)
def test_generated_process_has_zero_bias_by_default(self): arma = make_random_arma(5, 3, self.rng) self.assertEqual(arma.bias, 0)
def test_generated_arma_ma_coeffs_are_random(self): arma1 = make_random_arma(3, 4, self.rng) arma2 = make_random_arma(3, 4, self.rng) self.assertFalse(np.allclose(arma1.b, arma2.b))
def test_additional_kws_passed_to_arma_init(self): kws = {"bias": 5, "default_source": lambda size: np.zeros(size)} with mock.patch("bioslds.arma.Arma") as MockInit: make_random_arma(2, 3, self.rng, **kws) self.assertEqual(MockInit.call_args_list[0][1], kws)