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_LoadModule(self): def f(x_, alpha, sigma): return alpha * x_ def g(x_, alpha, sigma): return sigma norm = DistributionWrapper(Normal, loc=0.0, scale=1.0) linear = AffineProcess((f, g), (1.0, 1.0), norm, norm) model = LinearGaussianObservations(linear, 1.0, 1.0) x, y = model.sample_path(100) filt = SISR(model, 200) res = filt.longfilter(y) filt2 = SISR(model, 300) filt2.load_state_dict(filt.state_dict()) self.assertTrue(filt2.particles[0] == 200) res2 = FilterResult(filt2.initialize()) res2.load_state_dict(res.state_dict()) self.assertTrue((res2.filter_means == res.filter_means).all())
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_path(50) shape = 3000 linear = AffineProcess((f, g), (1.0, 1.0), self.norm, self.norm) self.model.hidden = linear filt = SISR(self.model, 1000).set_nparallel(shape) result = filt.longfilter(y) filtermeans = result.filter_means x = filtermeans[:, :1] mape = ((x - filtermeans[:, 1:]) / x).abs() assert mape.median(0)[0].max() < 0.05
def test_SDE(self): def f(x, a, s): return -a * x def g(x, a, s): return s em = AffineEulerMaruyama((f, g), (0.02, 0.15), Normal(0., 1.), Normal(0., 1.), dt=1e-2, num_steps=10) model = LinearGaussianObservations(em, scale=1e-3) x, y = model.sample_path(500) with self.assertRaises(NotImplementedError): SISR(model, 200) for filt in [SISR(model, 500, proposal=Bootstrap()), UKF(model)]: filt = filt.initialize().longfilter(y) means = filt.filtermeans if isinstance(filt, UKF): means = means[:, 0] self.assertLess(torch.std(x - means), 5e-2)
def test_StateDict(self): # ===== Define model ===== # norm = Normal(0., 1.) linear = AffineProcess((f, g), (1., 1.), norm, norm) linearobs = AffineObservations((fo, go), (1., 1.), norm) model = StateSpaceModel(linear, linearobs) # ===== Define filter ===== # filt = SISR(model, 100).initialize() # ===== Get statedict ===== # sd = filt.state_dict() # ===== Verify that we don't save multiple instances ===== # assert '_model' in sd and '_model' not in sd['_proposal'] newfilt = SISR(model, 1000).load_state_dict(sd) assert newfilt._w_old is not None and newfilt.ssm is newfilt._proposal._model # ===== Test same with UKF and verify that we save UT ===== # ukf = UKF(model).initialize() sd = ukf.state_dict() assert '_model' in sd and '_model' not in sd['_ut']
def test_ParallelUnscented(self): x, y = self.model.sample_path(50) shape = 30 linear = AffineProcess((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 = filt.filtermeans x = filtermeans[:, :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_SDE(self): def f(x, a, s): return -a * x def g(x, a, s): return s dt = 1e-2 norm = DistributionWrapper(Normal, loc=0.0, scale=sqrt(dt)) em = AffineEulerMaruyama((f, g), (0.02, 0.15), norm, norm, dt=1e-2, num_steps=10) model = LinearGaussianObservations(em, scale=1e-3) x, y = model.sample_path(500) for filt in [SISR(model, 500, proposal=prop.Bootstrap()), UKF(model)]: result = filt.longfilter(y) means = result.filter_means if isinstance(filt, UKF): means = means[:, 0] self.assertLess(torch.std(x - means), 5e-2)
def test_InitializeFilter(self): filt = SISR(self.model, 1000).initialize() assert filt._x_cur.shape == torch.Size([1000])
def test_Inference(self): # ===== Distributions ===== # dist = Normal(0., 1.) mvn = Independent(Normal(torch.zeros(2), torch.ones(2)), 1) # ===== Define model ===== # linear = AffineProcess((f, g), (1., 0.25), dist, dist) model = LinearGaussianObservations(linear, scale=0.1) mv_linear = AffineProcess((fmvn, gmvn), (0.5, 0.25), mvn, mvn) mvnmodel = LinearGaussianObservations(mv_linear, torch.tensor([1., 2.]), scale=0.1) # ===== Test for multiple models ===== # priors = Exponential(1.), make_invgamma(2., 1.) hidden1d = AffineProcess((f, g), priors, dist, dist) oned = LinearGaussianObservations(hidden1d, 1., make_invgamma(2., 1.)) hidden2d = AffineProcess((fmvn, gmvn), priors, mvn, mvn) twod = LinearGaussianObservations(hidden2d, torch.tensor([1., 2.]), make_invgamma(2., 1.)) particles = 1000 # ====== Run inference ===== # for trumod, model in [(model, oned), (mvnmodel, twod)]: x, y = trumod.sample_path(1000) algs = [(NESS, { 'particles': particles, 'filter_': SISR(model.copy(), 200) }), (NESS, { 'particles': particles, 'filter_': UKF(model.copy()) }), (SMC2, { 'particles': particles, 'filter_': APF(model.copy(), 200) }), (SMC2FW, { 'particles': particles, 'filter_': APF(model.copy(), 200) }), (NESSMC2, { 'particles': particles, 'filter_': APF(model.copy(), 200) }), (IteratedFilteringV2, { 'filter_': SISR(model.copy(), particles) })] for alg, props in algs: alg = alg(**props).initialize() alg = alg.fit(y) w = normalize(alg._w_rec if hasattr(alg, '_w_rec') else torch. ones(particles)) tru_params = trumod.hidden.theta + trumod.observable.theta inf_params = alg.filter.ssm.hidden.theta + alg.filter.ssm.observable.theta for trup, p in zip(tru_params, inf_params): if not p.trainable: continue kde = p.get_kde(weights=w) transed = p.bijection.inv(trup) densval = kde.logpdf(transed.numpy().reshape(-1, 1)) priorval = p.distr.log_prob(trup) assert (densval > priorval.numpy()).all()
def test_InitializeFilter(self): state = SISR(self.model, 1000).initialize() assert state.x.shape == torch.Size([1000])