def test_Timeseries3DState2DParam(self): alpha = 0.5 * torch.ones((500, 1)) x = torch.randn(size=(500, 200)) linear = AffineModel((f0, g0), (f, g), (alpha, 1.), (Normal(0., 1.), Normal(0., 1.))) assert np.allclose(linear.mean(x), f(x, alpha, 1.))
def test_Algorithms(self): priors = Exponential(2.), Exponential(2.) # ===== Test for multiple models ===== # hidden1d = AffineModel((f0, g0), (f, g), priors, (self.linear.noise0, self.linear.noise)) oned = LinearGaussianObservations(hidden1d, 1., Exponential(1.)) hidden2d = AffineModel((f0mvn, g0mvn), (fmvn, gmvn), priors, (self.mvn.noise0, self.mvn.noise)) twod = LinearGaussianObservations(hidden2d, self.a, Exponential(1.)) # ====== Run inference ===== # for trumod, model in [(self.model, oned), (self.mvnmodel, twod)]: x, y = trumod.sample(550) algs = [ (NESS, {'particles': 1000, 'filter_': SISR(model.copy(), 200)}), (SMC2, {'particles': 1000, 'filter_': SISR(model.copy(), 200)}), (NESSMC2, {'particles': 1000, 'filter_': SISR(model.copy(), 200)}), (IteratedFilteringV2, {'particles': 1000, 'filter_': SISR(model.copy(), 1000)}) ] for alg, props in algs: alg = alg(**props).initialize() alg = alg.fit(y) parameter = alg.filter.ssm.hidden.theta[-1] kde = parameter.get_kde(transformed=False) tru_val = trumod.hidden.theta[-1] densval = kde.logpdf(tru_val.numpy().reshape(-1, 1)) priorval = parameter.dist.log_prob(tru_val) assert bool(densval > priorval.numpy())
def test_UnscentedTransform1D(self): # ===== 1D model ===== # norm = Normal(0., 1.) linear = AffineModel((f0, g0), (f, g), (1., 1.), (norm, norm)) linearobs = Observable((fo, go), (1., 1.), norm) model = StateSpaceModel(linear, linearobs) # ===== Perform unscented transform ===== # x = model.hidden.i_sample(shape=3000) ut = UnscentedTransform(model).initialize(x).construct(0.) assert isinstance(ut.x_dist, Normal)
def test_ParallelUnscented(self): x, y = self.model.sample(50) shape = 30 linear = AffineModel((f0, g0), (f, g), (1., 1.), (self.norm, self.norm)) self.model.hidden = linear filt = SISR(self.model, 1000, proposal=Unscented()).set_nparallel(shape).initialize().longfilter(y) filtermeans = torch.cat(filt.filtermeans()).reshape(x.shape[0], -1) x = filtermeans[:, 0:1] mape = ((x - filtermeans[:, 1:]) / x).abs() assert mape.median(0)[0].max() < 0.05
def test_ParallellFiltersAndStability(self): x, y = self.model.sample(50) shape = 30 linear = AffineModel((f0, g0), (f, g), (1., 1.), (self.norm, self.norm)) self.model.hidden = linear filt = SISR(self.model, 1000).set_nparallel(shape).initialize().longfilter(y) filtermeans = filt.filtermeans x = filtermeans[:, :1] mape = ((x - filtermeans[:, 1:]) / x).abs() assert mape.median(0)[0].max() < 0.05
def test_UnscentedTransform2D(self): # ===== 2D model ===== # mat = torch.eye(2) scale = torch.diag(mat) norm = Normal(0., 1.) mvn = MultivariateNormal(torch.zeros(2), torch.eye(2)) mvnlinear = AffineModel((f0mvn, g0), (fmvn, g), (mat, scale), (mvn, mvn)) mvnoblinear = Observable((fomvn, gomvn), (1., ), norm) mvnmodel = StateSpaceModel(mvnlinear, mvnoblinear) # ===== Perform unscented transform ===== # x = mvnmodel.hidden.i_sample(shape=3000) ut = UnscentedTransform(mvnmodel).initialize(x).construct(0.) assert isinstance(ut.x_dist, MultivariateNormal) and isinstance( ut.y_dist, Normal) assert isinstance(ut.x_dist_indep, Independent)
class Tests(unittest.TestCase): norm = Normal(0., 1.) linear = AffineModel((f0, g0), (f, g), (1., 1.), (norm, norm)) def test_TimeseriesCreate_1D(self): assert self.linear.mean(torch.tensor(1.)) == 1. and self.linear.scale( torch.tensor(1.)) == 1. def test_Timeseries2DState(self): x = np.random.normal(size=500) assert np.allclose(self.linear.mean(torch.tensor(x)), f(x, 1, 1)) def test_Timeseries3DState2DParam(self): alpha = 0.5 * torch.ones((500, 1)) x = torch.randn(size=(500, 200)) linear = AffineModel((f0, g0), (f, g), (alpha, 1.), (Normal(0., 1.), Normal(0., 1.))) assert np.allclose(linear.mean(x), f(x, alpha, 1.)) def test_SampleInitial(self): x = self.linear.i_sample() assert isinstance(x, torch.Tensor) def test_Propagate(self): out = torch.zeros(500) out[0] = self.linear.i_sample() for i in range(1, out.shape[0]): out[i] = self.linear.propagate(out[i - 1]) assert not all(out == 0.) def test_SampleTrajectory1D(self): sample = self.linear.sample(500) assert sample.shape[0] == 500 def test_SampleTrajectory2D(self): sample = self.linear.sample(500, 250) assert sample.shape == (500, 250, 1) def test_Weight1D(self): sample = self.linear.i_sample() obs = 0. assert np.allclose( self.linear.weight(obs, sample).numpy(), stats.norm.logpdf(obs, loc=sample, scale=1)) def test_Weight2D(self): sample = self.linear.i_sample(shape=(500, 200)) obs = 1 assert np.allclose(self.linear.weight(obs, sample), stats.norm.logpdf(obs, loc=sample, scale=1)) def test_EulerMaruyama(self): mod = EulerMaruyma((lambda: 0., lambda: 1.), (lambda u: 0, lambda u: 1), (), ndim=1) samples = mod.sample(30) assert samples.shape == (30, 1) def test_OrnsteinUhlenbeck(self): mod = OrnsteinUhlenbeck(0.05, 1, 0.15) x = mod.sample(300) assert x.shape == (300, 1)
class Tests(unittest.TestCase): # ===== Simple 1D model ===== # norm = Normal(0., 1.) linear = AffineModel((f0, g0), (f, g), (1., 1.), (norm, norm)) model = LinearGaussianObservations(linear, 1., 1.) # ===== Simple 2D model ===== # mvn = Independent(Normal(torch.zeros(2), torch.ones(2)), 1) mvn = AffineModel((f0mvn, g0mvn), (fmvn, gmvn), (0.5, 1.), (mvn, mvn)) a = torch.Tensor([1., 2.]) mvnmodel = LinearGaussianObservations(mvn, a, 1.) def test_InitializeFilter(self): filt = SISR(self.model, 1000).initialize() assert filt._x_cur.shape == (1000,) def test_Filters(self): for model in [self.model, self.mvnmodel]: x, y = model.sample(500) for filter_, props in [(SISR, {'particles': 500}), (APF, {'particles': 500}), (UKF, {})]: filt = filter_(model, **props).initialize() filt = filt.longfilter(y) assert len(filt.s_mx) > 0 filtmeans = filt.filtermeans.numpy() # ===== Run Kalman ===== # if model is self.model: kf = pykalman.KalmanFilter(transition_matrices=1., observation_matrices=1.) else: kf = pykalman.KalmanFilter(transition_matrices=[[0.5, 1 / 3], [0, 1.]], observation_matrices=[1, 2]) filterestimates = kf.filter(y.numpy()) if filtmeans.ndim < 2: filtmeans = filtmeans[:, None] rel_error = np.median(np.abs((filtmeans - filterestimates[0]) / filterestimates[0])) ll = kf.loglikelihood(y.numpy()) rel_ll_error = np.abs((ll - np.array(filt.s_ll).sum()) / ll) assert rel_error < 0.05 and rel_ll_error < 0.05 def test_ParallellFiltersAndStability(self): x, y = self.model.sample(50) shape = 30 linear = AffineModel((f0, g0), (f, g), (1., 1.), (self.norm, self.norm)) self.model.hidden = linear filt = SISR(self.model, 1000).set_nparallel(shape).initialize().longfilter(y) filtermeans = torch.cat(filt.filtermeans()).reshape(x.shape[0], -1) x = filtermeans[:, 0:1] mape = ((x - filtermeans[:, 1:]) / x).abs() assert mape.median(0)[0].max() < 0.05 def test_ParallelUnscented(self): x, y = self.model.sample(50) shape = 30 linear = AffineModel((f0, g0), (f, g), (1., 1.), (self.norm, self.norm)) self.model.hidden = linear filt = SISR(self.model, 1000, proposal=Unscented()).set_nparallel(shape).initialize().longfilter(y) filtermeans = torch.cat(filt.filtermeans()).reshape(x.shape[0], -1) x = filtermeans[:, 0:1] mape = ((x - filtermeans[:, 1:]) / x).abs() assert mape.median(0)[0].max() < 0.05 def test_Algorithms(self): priors = Exponential(2.), Exponential(2.) # ===== Test for multiple models ===== # hidden1d = AffineModel((f0, g0), (f, g), priors, (self.linear.noise0, self.linear.noise)) oned = LinearGaussianObservations(hidden1d, 1., Exponential(1.)) hidden2d = AffineModel((f0mvn, g0mvn), (fmvn, gmvn), priors, (self.mvn.noise0, self.mvn.noise)) twod = LinearGaussianObservations(hidden2d, self.a, Exponential(1.)) # ====== Run inference ===== # for trumod, model in [(self.model, oned), (self.mvnmodel, twod)]: x, y = trumod.sample(550) algs = [ (NESS, {'particles': 1000, 'filter_': SISR(model.copy(), 200)}), (SMC2, {'particles': 1000, 'filter_': SISR(model.copy(), 200)}), (NESSMC2, {'particles': 1000, 'filter_': SISR(model.copy(), 200)}), (IteratedFilteringV2, {'particles': 1000, 'filter_': SISR(model.copy(), 1000)}) ] for alg, props in algs: alg = alg(**props).initialize() alg = alg.fit(y) parameter = alg.filter.ssm.hidden.theta[-1] kde = parameter.get_kde(transformed=False) tru_val = trumod.hidden.theta[-1] densval = kde.logpdf(tru_val.numpy().reshape(-1, 1)) priorval = parameter.dist.log_prob(tru_val) assert bool(densval > priorval.numpy())
class Tests(unittest.TestCase): # ===== 1D model ===== # norm = Normal(0., 1.) linear = AffineModel((f0, g0), (f, g), (1., 1.), (norm, norm)) linearobs = Observable((fo, go), (1., 1.), norm) model = StateSpaceModel(linear, linearobs) # ===== 2D model ===== # mat = torch.eye(2) scale = torch.diag(mat) mvn = MultivariateNormal(torch.zeros(2), torch.eye(2)) mvnlinear = AffineModel((f0mvn, g0mvn), (fmvn, gmvn), (mat, scale), (mvn, mvn)) mvnoblinear = Observable((fomvn, gomvn), (1., ), norm) mvnmodel = StateSpaceModel(mvnlinear, mvnoblinear) def test_InitializeModel1D(self): sample = self.model.initialize() assert isinstance(sample, torch.Tensor) def test_InitializeModel(self): sample = self.model.initialize(1000) assert sample.shape == (1000, ) def test_Propagate(self): x = self.model.initialize(1000) sample = self.model.propagate(x) assert sample.shape == (1000, ) def test_Sample(self): x, y = self.model.sample(50) assert len(x) == 50 and len(y) == 50 and np.array(x).shape == (50, 1) def test_SampleMultivariate(self): x, y = self.mvnmodel.sample(30) assert len(x) == 30 and x[0].shape == (2, ) def test_SampleMultivariateSamples(self): shape = (100, 100) x, y = self.mvnmodel.sample(30, samples=shape) assert x.shape == (30, 2, *shape) and isinstance( x, torch.Tensor) and isinstance(y, torch.Tensor) assert self.mvnmodel.h_weight(x[1], x[0]).shape == shape if len(shape) > 1: assert self.mvnmodel.h_weight(x[1, :, 0, 0], x[0]).shape == shape assert self.mvnmodel.weight(y[0, 0], x[0]).shape == shape def test_Parameter(self): param = Parameter(Beta(1, 3)).sample_() assert param.values.shape == torch.Size([]) newshape = (3000, 1000) with self.assertRaises(ValueError): param.values = Normal(0., 1.).sample(newshape) newvals = Beta(1, 3).sample(newshape) param.values = newvals assert param.values.shape == newshape param.t_values = Normal(0., 1.).sample(newshape) assert (param.values != newvals).all() def test_LinearGaussianObservations(self): linearmodel = LinearGaussianObservations(self.linear) steps = 30 x, y = linearmodel.sample(steps) assert len(x) == steps and len(y) == steps mat = torch.eye(2) mvn_linearmodel = LinearGaussianObservations(self.mvnlinear, a=mat) x, y = mvn_linearmodel.sample(30) assert len(x) == steps and len(y) == steps
class Tests(unittest.TestCase): norm = Normal(0., 1.) linear = AffineModel((f0, g0), (f, g), (1., 1.), (norm, norm)) def test_TimeseriesCreate_1D(self): assert self.linear.mean(torch.tensor(1.)) == 1. and self.linear.scale( torch.tensor(1.)) == 1. def test_Timeseries2DState(self): x = np.random.normal(size=500) assert np.allclose(self.linear.mean(torch.tensor(x)), f(x, 1, 1)) def test_Timeseries3DState2DParam(self): alpha = 0.5 * torch.ones((500, 1)) x = torch.randn(size=(500, 200)) linear = AffineModel((f0, g0), (f, g), (alpha, 1.), (Normal(0., 1.), Normal(0., 1.))) assert np.allclose(linear.mean(x), f(x, alpha, 1.)) def test_SampleInitial(self): x = self.linear.i_sample() assert isinstance(x, torch.Tensor) def test_Propagate(self): out = torch.zeros(500) out[0] = self.linear.i_sample() for i in range(1, out.shape[0]): out[i] = self.linear.propagate(out[i - 1]) assert not all(out == 0.) def test_SampleTrajectory1D(self): sample = self.linear.sample(500) assert sample.shape[0] == 500 def test_SampleTrajectory2D(self): sample = self.linear.sample(500, 250) assert sample.shape == (500, 250) def test_Weight1D(self): sample = self.linear.i_sample() obs = 0. assert np.allclose( self.linear.weight(obs, sample).numpy(), stats.norm.logpdf(obs, loc=sample, scale=1)) def test_Weight2D(self): sample = self.linear.i_sample(shape=(500, 200)) obs = 1 assert np.allclose(self.linear.weight(obs, sample), stats.norm.logpdf(obs, loc=sample, scale=1)) def test_EulerMaruyama(self): zero = torch.tensor(0.) one = torch.tensor(1.) mod = EulerMaruyma((lambda: zero, lambda: one), (lambda u: zero, lambda u: one), (), ndim=1) samples = mod.sample(30) assert samples.shape == (30, ) def test_OrnsteinUhlenbeck(self): mod = OrnsteinUhlenbeck(0.05, 1, 0.15) x = mod.sample(300) assert x.shape == (300, ) def test_StateVariable(self): # ===== Emulate last value ===== # rands = torch.empty((300, 3)).normal_() rands.requires_grad_(True) # ===== Pass through function ===== # sv = StateVariable(rands) agg = sv.sum(-1) # ===== Get gradient ===== # agg.backward(torch.ones_like(agg)) assert rands.grad is not None def test_Parameter(self): # ===== Start stuff ===== # param = Parameter(Normal(0., 1.)) param.sample_(1000) assert param.shape == torch.Size([1000]) # ===== Construct view ===== # view = param.view(1000, 1) # ===== Change values ===== # param.values = torch.empty_like(param).normal_() assert (view[:, 0] == param).all() # ===== Have in tuple ===== # vals = (param.view(1000, 1, 1), ) param.values = torch.empty_like(param).normal_() assert (vals[0][:, 0, 0] == param).all() # ===== Set t_values ===== # view = param.view(1000, 1) param.t_values = torch.empty_like(param).normal_() assert (view[:, 0] == param.t_values).all() # ===== Check we cannot set different shape ===== # with self.assertRaises(ValueError): param.values = torch.empty(1).normal_() # ===== Check that we cannot set out of bounds values for parameter ===== # positive = Parameter(Exponential(1.)) positive.sample_(1) with self.assertRaises(ValueError): positive.values = -torch.empty_like(positive).normal_().abs() # ===== Check that we can set transformed values ===== # values = torch.empty_like(positive).normal_() positive.t_values = values assert (positive == positive.bijection(values)).all()