def test_result_does_not_depend_on_position_in_feature_dimension(self): norms1 = self.variance.transform(X=self.x) variance2 = OnlineVariance(self.n_features, rate=self.rate) norms2 = variance2.transform(X=np.fliplr(self.x)) np.testing.assert_allclose(norms1, np.fliplr(norms2))
def setUp(self): self.n_features = 3 self.rate = 0.02 self.variance = OnlineVariance(self.n_features, rate=self.rate) self.rng = np.random.default_rng(33) self.n_samples = 500 self.x = self.rng.normal(size=(self.n_samples, self.n_features))
def test_result_in_one_seq_independent_of_other_seqs(self): X1 = self.x norms1 = self.variance.transform(X=X1) X2 = np.copy(self.x) X2[:, 1] = self.x[:, 2] variance2 = OnlineVariance(self.n_features, rate=self.rate) norms2 = variance2.transform(X=X2) np.testing.assert_allclose(norms1[:, 0], norms2[:, 0])
def setUp(self): self.n_features = 4 self.order = 4 self.rate = 0.01 self.variance = OnlineVariance(self.n_features, rate=self.rate) self.rng = np.random.default_rng(33) self.n_samples = 500 self.x = self.rng.normal(size=(self.n_samples, self.n_features)) self.norms = self.variance.transform(X=self.x)
def test_repeated_transform_same_as_single_transform_on_combined_input(self): norms = self.variance.transform(X=self.x) n1 = self.n_samples // 2 x1 = self.x[:n1] x2 = self.x[n1:] variance_alt = OnlineVariance(self.n_features, rate=self.rate) norms1 = variance_alt.transform(X=x1) norms2 = variance_alt.transform(X=x2) norms_exp = np.row_stack((norms1, norms2)) np.testing.assert_allclose(norms, norms_exp)
def __init__( self, weights: Optional[Sequence] = None, n_models: Optional[int] = None, n_features: Optional[int] = None, rng: Union[int, np.random.Generator] = 0, variance_kws: Optional[dict] = None, ): """ Initialize the variance-based regressor. This chains together a `PredictionError` instance with an `OnlineVariance`. Parameters ---------- weights Regression coefficients for each model, shape `(n_models, n_features)`. If this is provided, `n_models` and `n_features` need not be provided. If `weights` is not provided, it will be initialized randomly, using a standard normal distribution. See `rng`. n_models Number of models. If `weights` is provided, `n_models` need not be. However, if both are provided, then `n_models` should be equal to the number of rows in `weights`. n_features Number of predictor variables (features). If `weights` is provided, `n_features` need not be. However, if both are provided, then `n_features` should be equal to the number of columns in `weights`. rng Random number generator or seed to use for generating initial weight values. If seed, a random number generator is created using `np.random.default_rng`. If not provided, a seed of 0 is used. The random number generator is not used at all if `weights` is provided. variance_kws Additional keywords to pass to `OnlineVariance`. By default `negative` is set to true. """ if weights is None: if not hasattr(rng, "normal"): rng = np.random.default_rng(rng) weights = rng.normal(size=(n_models, n_features)) else: if n_models is not None and n_models != np.shape(weights)[0]: raise ValueError("n_models does not match shape(weights)[0]") if n_features is not None and n_features != np.shape(weights)[1]: raise ValueError("n_features does not match shape(weights)[1]") self.n_models = len(weights) self.prediction_error = PredictionError(weights) if variance_kws is None: variance_kws = {} variance_kws.setdefault("negative", True) self.variance_norm = OnlineVariance(self.n_models, **variance_kws) super().__init__(["prediction_error", "variance_norm"])
class TestOnlineVarianceNegative(unittest.TestCase): def setUp(self): self.n_features = 4 self.order = 4 self.rate = 0.01 self.variance = OnlineVariance(self.n_features, rate=self.rate) self.rng = np.random.default_rng(33) self.n_samples = 500 self.x = self.rng.normal(size=(self.n_samples, self.n_features)) self.norms = self.variance.transform(X=self.x) def test_negative_returned_when_asked_for(self): variance_neg = OnlineVariance(self.n_features, rate=self.rate, negative=True) norms_neg = variance_neg.transform(X=self.x) np.testing.assert_allclose(norms_neg, -self.norms)
def setUp(self): self.n_features = 3 self.rate = 0.02 self.variance = OnlineVariance(self.n_features, rate=self.rate)
class TestOnlineVarianceTransform(unittest.TestCase): def setUp(self): self.n_features = 3 self.rate = 0.02 self.variance = OnlineVariance(self.n_features, rate=self.rate) self.rng = np.random.default_rng(33) self.n_samples = 500 self.x = self.rng.normal(size=(self.n_samples, self.n_features)) def test_all_outputs_are_non_negative(self): norms = self.variance.transform(X=self.x) self.assertGreaterEqual(np.min(norms), 0) def test_result_does_not_depend_on_position_in_feature_dimension(self): norms1 = self.variance.transform(X=self.x) variance2 = OnlineVariance(self.n_features, rate=self.rate) norms2 = variance2.transform(X=np.fliplr(self.x)) np.testing.assert_allclose(norms1, np.fliplr(norms2)) def test_result_in_one_seq_independent_of_other_seqs(self): X1 = self.x norms1 = self.variance.transform(X=X1) X2 = np.copy(self.x) X2[:, 1] = self.x[:, 2] variance2 = OnlineVariance(self.n_features, rate=self.rate) norms2 = variance2.transform(X=X2) np.testing.assert_allclose(norms1[:, 0], norms2[:, 0]) def test_initial_estimate_is_zero(self): norms = self.variance.transform(X=self.x) np.testing.assert_allclose(norms[0], self.rate * self.x[0] ** 2) def test_one_step_update_end(self): norms = self.variance.transform(X=self.x) diffs = np.diff(norms, axis=0) expected_last_diff = self.rate * (self.x[-1] ** 2 - norms[-2]) np.testing.assert_allclose(diffs[-1], expected_last_diff) def test_shape_of_output_correct(self): norms = self.variance.transform(X=self.x) self.assertEqual(norms.shape, self.x.shape) def test_repeated_transform_same_as_single_transform_on_combined_input(self): norms = self.variance.transform(X=self.x) n1 = self.n_samples // 2 x1 = self.x[:n1] x2 = self.x[n1:] variance_alt = OnlineVariance(self.n_features, rate=self.rate) norms1 = variance_alt.transform(X=x1) norms2 = variance_alt.transform(X=x2) norms_exp = np.row_stack((norms1, norms2)) np.testing.assert_allclose(norms, norms_exp) def test_output_is_set_properly(self): norms = self.variance.transform(X=self.x) np.testing.assert_allclose(self.variance.output_, norms[-1]) def test_monitor_output(self): monitor = AttributeMonitor(["output_"]) norms = self.variance.transform(X=self.x, monitor=monitor) np.testing.assert_allclose(monitor.history_.output_, norms)
def test_negative_returned_when_asked_for(self): variance_neg = OnlineVariance(self.n_features, rate=self.rate, negative=True) norms_neg = variance_neg.transform(X=self.x) np.testing.assert_allclose(norms_neg, -self.norms)