def DefaultLDS(D_obs, D_latent, D_input=0, mu_init=None, sigma_init=None, A=None, B=None, sigma_states=None, C=None, D=None, sigma_obs=None): model = LDS( dynamics_distn=Regression( nu_0=D_latent + 1, S_0=D_latent * np.eye(D_latent), M_0=np.zeros((D_latent, D_latent + D_input)), K_0=D_latent * np.eye(D_latent + D_input)), emission_distn=Regression( nu_0=D_obs + 1, S_0=D_obs * np.eye(D_obs), M_0=np.zeros((D_obs, D_latent + D_input)), K_0=D_obs * np.eye(D_latent + D_input))) set_default = \ lambda prm, val, default: \ model.__setattr__(prm, val if val is not None else default) set_default("mu_init", mu_init, np.zeros(D_latent)) set_default("sigma_init", sigma_init, np.eye(D_latent)) set_default("A", A, 0.99 * random_rotation(D_latent)) set_default("B", B, 0.1 * np.random.randn(D_latent, D_input)) set_default("sigma_states", sigma_states, 0.1 * np.eye(D_latent)) set_default("C", C, np.random.randn(D_obs, D_latent)) set_default("D", D, 0.1 * np.random.randn(D_obs, D_input)) set_default("sigma_obs", sigma_obs, 0.1 * np.eye(D_obs)) return model
def DefaultBernoulliLDS(D_obs, D_latent, D_input=0, mu_init=None, sigma_init=None, A=None, B=None, sigma_states=None, C=None, D=None ): model = LaplaceApproxBernoulliLDS( init_dynamics_distn= Gaussian(mu_0=np.zeros(D_latent), sigma_0=np.eye(D_latent), kappa_0=1.0, nu_0=D_latent + 1), dynamics_distn=Regression( nu_0=D_latent + 1, S_0=D_latent * np.eye(D_latent), M_0=np.zeros((D_latent, D_latent + D_input)), K_0=D_latent * np.eye(D_latent + D_input)), emission_distn= BernoulliRegression(D_obs, D_latent + D_input, verbose=False)) set_default = \ lambda prm, val, default: \ model.__setattr__(prm, val if val is not None else default) set_default("mu_init", mu_init, np.zeros(D_latent)) set_default("sigma_init", sigma_init, np.eye(D_latent)) set_default("A", A, 0.99 * random_rotation(D_latent)) set_default("B", B, 0.1 * np.random.randn(D_latent, D_input)) set_default("sigma_states", sigma_states, 0.1 * np.eye(D_latent)) set_default("C", C, np.random.randn(D_obs, D_latent)) set_default("D", D, 0.1 * np.random.randn(D_obs, D_input)) return model
def make_rslds_parameters(C_init): init_dynamics_distns = [ Gaussian( mu=np.zeros(D_latent), sigma=np.eye(D_latent), nu_0=D_latent + 2, sigma_0=3. * np.eye(D_latent), mu_0=np.zeros(D_latent), kappa_0=1.0, ) for _ in range(args.K)] dynamics_distns = [ Regression( nu_0=D_latent + 2, S_0=1e-4 * np.eye(D_latent), M_0=np.hstack((np.eye(D_latent), np.zeros((D_latent, 1)))), K_0=np.eye(D_latent + 1), ) for _ in range(args.K)] emission_distns = \ DiagonalRegression(args.D_obs, D_latent + 1, A=C_init.copy(), sigmasq=np.ones(args.D_obs), alpha_0=2.0, beta_0=2.0) return init_dynamics_distns, dynamics_distns, emission_distns
def sample_slds_model(): mu_init = np.zeros(D_latent) mu_init[0] = 2.0 sigma_init = 0.01 * np.eye(D_latent) def random_rotation(n, theta): rot = 0.99 * np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]]) out = np.zeros((n, n)) out[:2, :2] = rot q = np.linalg.qr(np.random.randn(n, n))[0] return q.dot(out).dot(q.T) def random_dynamics(n): A = np.random.randn(n,n) A = A.dot(A.T) U,S,V = np.linalg.svd(A) A_stable = U.dot(np.diag(S/(1.1*np.max(S)))).dot(V.T) # A_stable = U.dot(0.99 * np.eye(n)).dot(V.T) return A_stable ths = np.linspace(0, np.pi/8., K) As = [random_rotation(D_latent, ths[k]) for k in range(K)] # As = [random_dynamics(D_latent) for k in range(K)] bs = [np.zeros((D_latent, 1))] + [.25 * np.random.randn(D_latent, 1) for k in range(K-1)] C = np.random.randn(D_obs, D_latent) d = np.zeros((D_obs, 1)) sigma_obs = 0.5 * np.ones(D_obs) ################### # generate data # ################### init_dynamics_distns = [Gaussian(mu=mu_init, sigma=sigma_init) for _ in range(K)] dynamics_distns = [Regression(A=np.hstack((A, b)), sigma=0.01 * np.eye(D_latent)) for A,b in zip(As, bs)] emission_distns = DiagonalRegression(D_obs, D_latent+1, A=np.hstack((C, d)), sigmasq=sigma_obs) slds = HMMSLDS( dynamics_distns=dynamics_distns, emission_distns=emission_distns, init_dynamics_distns=init_dynamics_distns, alpha=3., init_state_distn='uniform') #### MANUALLY CREATE DATA P = np.ones((K,K)) + 1 * np.eye(K) P = P / np.sum(P,1,keepdims=True) z = np.zeros(T//D, dtype=np.int32) for t in range(1,T//D): z[t] = np.random.choice(np.arange(K), p=P[z[t-1]]) z = np.repeat(z, D) statesobj = slds._states_class(model=slds, T=z.size, stateseq=z, inputs=np.ones((z.size, 1))) statesobj.generate_gaussian_states() y = statesobj.data = statesobj.generate_obs() x = statesobj.gaussian_states slds.states_list.append(statesobj) return z,x,y,slds
def fit_gaussian_lds_model(Xs, Xtest, D_gauss_lds, N_samples=100): Nx = len(Xs) assert len(Xtest) == Nx print("Fitting Gaussian (Raw) LDS with %d states" % D_gauss_lds) models = [NonstationaryLDS( init_dynamics_distn=GaussianFixed(mu=np.zeros(D), sigma=1*np.eye(D)), dynamics_distn=AutoRegression(nu_0=D+1,S_0=1*np.eye(D),M_0=np.zeros((D,D)),K_0=1*np.eye(D)), emission_distn=Regression(nu_0=K+1,S_0=K*np.eye(K),M_0=np.zeros((K,D)),K_0=K*np.eye(D))) for _ in xrange(Nx)] Xs_centered = [X - np.mean(X, axis=0)[None,:] + 1e-3*np.random.randn(*X.shape) for X in Xs] for X, model in zip(Xs_centered, models): model.add_data(X) def compute_pred_ll(): pred_ll = 0 for Xtr, Xte, model in zip(Xs_centered, Xtest, models): # Monte Carlo sample to get pi density implied by Gaussian LDS Npred = 10 Tpred = Xte.shape[0] preds = model.sample_predictions(Xtr, Tpred, Npred=Npred) # Convert predictions to a distribution by finding the # largest dimension for each predicted Gaussian. # Preds is T x K x Npred, inds is TxNpred inds = np.argmax(preds, axis=1) pi = np.array([np.bincount(inds[t], minlength=K) for t in xrange(Tpred)]) / float(Npred) assert np.allclose(pi.sum(axis=1), 1.0) pi = np.clip(pi, 1e-8, 1.0) pi /= pi.sum(axis=1)[:,None] # Compute the log likelihood under pi pred_ll += np.sum([Multinomial(weights=pi[t], K=K).log_likelihood(Xte[t][None,:]) for t in xrange(Tpred)]) return pred_ll # TODO: Get initial pred ll init_results = (0, None, np.nan, np.nan, compute_pred_ll()) def resample(): tic = time.time() [model.resample_model() for model in models] toc = time.time() - tic return toc, None, np.nan, np.nan, compute_pred_ll() times, samples, lls, test_lls, pred_lls = \ map(np.array, zip(*([init_results] + [resample() for _ in progprint_xrange(N_samples, perline=5)]))) timestamps = np.cumsum(times) return Results(lls, test_lls, pred_lls, samples, timestamps)
def fit_lds_model_with_pmcmc(Xs, Xtest, D, N_samples=100): """ Fit a logistic normal LDS model with pMCMC """ Nx = len(Xs) assert len(Xtest) == Nx print("Fitting SBM-LDS with %d states using pMCMC" % D) models = [ ParticleSBMultinomialLDS( init_dynamics_distn=GaussianFixed(mu=np.zeros(D), sigma=1 * np.eye(D)), dynamics_distn=AutoRegression(nu_0=D + 1, S_0=D * np.eye(D), M_0=np.zeros((D, D)), K_0=D * np.eye(D)), emission_distn=Regression(nu_0=K + 1, S_0=K * np.eye(K), M_0=np.zeros((K, D)), K_0=K * np.eye(D)), mu=pi_to_psi(np.ones(K) / K), sigma_C=1.0) for _ in xrange(Nx) ] for model in models: model.A = 0.5 * np.eye(D) model.sigma_states = np.eye(D) model.C = np.random.randn(K - 1, D) model.sigma_obs = 0.1 * np.eye(K) for X, model in zip(Xs, models): model.add_data(X) def compute_pred_ll(): pred_ll = 0 for Xte, model in zip(Xtest, models): pred_ll += model.predictive_log_likelihood(Xte, Npred=100)[0] return pred_ll init_results = (0, None, np.nan, np.nan, compute_pred_ll()) def resample(): tic = time.time() [model.resample_model() for model in models] toc = time.time() - tic return toc, None, np.nan, np.nan, compute_pred_ll() times, samples, lls, test_lls, pred_lls = \ map(np.array, zip(*([init_results] + [resample() for _ in progprint_xrange(N_samples, perline=5)]))) timestamps = np.cumsum(times) return Results(lls, test_lls, pred_lls, samples, timestamps)
def DefaultLDS(n, p): model = LDS( dynamics_distn=AutoRegression( nu_0=n+1, S_0=n*np.eye(n), M_0=np.zeros((n, n)), K_0=n*np.eye(n)), emission_distn=Regression( nu_0=p+1, S_0=p*np.eye(p), M_0=np.zeros((p, n)), K_0=p*np.eye(n))) model.A = 0.99*np.eye(n) model.sigma_states = np.eye(n) model.C = np.random.randn(p, n) model.sigma_obs = 0.1*np.eye(p) return model
def fit_lds_model_with_pmcmc(Xs, Xtest, D, N_samples=100): """ Fit a logistic normal LDS model with pMCMC """ print("Fitting SBM-LDS with %d states using pMCMC" % D) model = ParticleSBMultinomialLDS( init_dynamics_distn=GaussianFixed(mu=np.zeros(D), sigma=1 * np.eye(D)), dynamics_distn=AutoRegression(nu_0=D + 1, S_0=D * np.eye(D), M_0=np.zeros((D, D)), K_0=D * np.eye(D)), emission_distn=Regression(nu_0=K + 1, S_0=K * np.eye(K), M_0=np.zeros((K, D)), K_0=K * np.eye(D)), mu=pi_to_psi(np.ones(K) / K)) model.A = 0.5 * np.eye(D) model.sigma_states = np.eye(D) model.C = np.random.randn(K - 1, D) model.sigma_obs = 0.1 * np.eye(K) for X in Xs: model.add_data(X) compute_pred_ll = lambda: sum([ model.predictive_log_likelihood(Xt, data_index=i, Npred=10)[0] for i, Xt in enumerate(Xtest) ]) init_results = (0, None, model.log_likelihood(), np.nan, compute_pred_ll()) def resample(): tic = time.time() model.resample_model() toc = time.time() - tic # pred_ll = model.predictive_log_likelihood(Xtest, Npred=1000) return toc, None, model.log_likelihood(), \ np.nan, \ compute_pred_ll() times, samples, lls, test_lls, pred_lls = \ list(map(np.array, list(zip(*([init_results] + [resample() for _ in progprint_xrange(N_samples)]))))) timestamps = np.cumsum(times) return Results(lls, test_lls, pred_lls, samples, timestamps)
def fit_ln_lds_model(Xs, Xtest, D, N_samples=100): """ Fit a logistic normal LDS model with pMCMC """ Nx = len(Xs) assert len(Xtest) == Nx print("Fitting Logistic Normal LDS with %d states" % D) mus = [X.sum(0) + 0.1 for X in Xs] mus = [np.log(mu / mu.sum()) for mu in mus] models = [LogisticNormalMultinomialLDS( init_dynamics_distn=GaussianFixed(mu=np.zeros(D), sigma=1*np.eye(D)), dynamics_distn=AutoRegression(nu_0=D+1,S_0=D*np.eye(D),M_0=np.zeros((D,D)),K_0=D*np.eye(D)), emission_distn=Regression(nu_0=K+1,S_0=K*np.eye(K),M_0=np.zeros((K,D)),K_0=K*np.eye(D)), sigma_C=1.0, mu=mu) \ for mu in mus] for model in models: model.A = 0.5 * np.eye(D) model.sigma_states = np.eye(D) model.C = 1.0 * np.random.randn(K, D) model.sigma_obs = 0.1 * np.eye(K) for X, model in zip(Xs, models): model.add_data(X) def compute_pred_ll(): pred_ll = 0 for Xte, model in zip(Xtest, models): pred_ll += model.predictive_log_likelihood(Xte, Npred=1)[0] return pred_ll init_results = (0, None, np.nan, np.nan, compute_pred_ll()) def resample(): tic = time.time() [model.resample_model() for model in models] toc = time.time() - tic return toc, None, np.nan, np.nan, compute_pred_ll() times, samples, lls, test_lls, pred_lls = \ list(map(np.array, list(zip(*([init_results] + [resample() for _ in progprint_xrange(N_samples, perline=5)]))))) timestamps = np.cumsum(times) return Results(lls, test_lls, pred_lls, samples, timestamps)
def fit_ln_lds_model(Xs, Xtest, D, N_samples=100): """ Fit a logistic normal LDS model with pMCMC """ print("Fitting Logistic Normal LDS with %d states" % D) model = LogisticNormalMultinomialLDS( init_dynamics_distn=GaussianFixed(mu=np.zeros(D), sigma=1 * np.eye(D)), dynamics_distn=AutoRegression(nu_0=D + 1, S_0=D * np.eye(D), M_0=np.zeros((D, D)), K_0=D * np.eye(D)), emission_distn=Regression(nu_0=K + 1, S_0=K * np.eye(K), M_0=np.zeros((K, D)), K_0=K * np.eye(D)), sigma_C=0.1) model.A = 0.5 * np.eye(D) model.sigma_states = np.eye(D) model.C = 0.33 * np.random.randn(K, D) model.sigma_obs = 0.1 * np.eye(K) for X in Xs: model.add_data(X) init_results = (0, None, model.log_likelihood(), np.nan, model.predictive_log_likelihood(Xtest, Npred=1000)) def resample(): tic = time.time() model.resample_model() toc = time.time() - tic pred_ll = model.predictive_log_likelihood(Xtest, Npred=1000) return toc, None, model.log_likelihood(), \ np.nan, \ pred_ll times, samples, lls, test_lls, pred_lls = \ map(np.array, zip(*([init_results] + [resample() for _ in progprint_xrange(N_samples)]))) timestamps = np.cumsum(times) return Results(lls, test_lls, pred_lls, samples, timestamps)
def DefaultPoissonLDS( D_obs, D_latent, D_input=0, mu_init=None, sigma_init=None, A=None, B=None, sigma_states=None, C=None, d=None, ): assert D_input == 0, "Inputs are not yet supported for Poisson LDS" model = LaplaceApproxPoissonLDS( init_dynamics_distn=Gaussian(mu_0=np.zeros(D_latent), sigma_0=np.eye(D_latent), kappa_0=1.0, nu_0=D_latent + 1), dynamics_distn=Regression(A=0.9 * np.eye(D_latent), sigma=np.eye(D_latent), nu_0=D_latent + 1, S_0=D_latent * np.eye(D_latent), M_0=np.zeros((D_latent, D_latent)), K_0=D_latent * np.eye(D_latent)), emission_distn=PoissonRegression(D_obs, D_latent, verbose=False)) set_default = \ lambda prm, val, default: \ model.__setattr__(prm, val if val is not None else default) set_default("mu_init", mu_init, np.zeros(D_latent)) set_default("sigma_init", sigma_init, np.eye(D_latent)) set_default("A", A, 0.99 * random_rotation(D_latent)) set_default("B", B, 0.1 * np.random.randn(D_latent, D_input)) set_default("sigma_states", sigma_states, 0.1 * np.eye(D_latent)) set_default("C", C, np.random.randn(D_obs, D_latent)) set_default("d", d, np.zeros((D_obs, 1))) return model
def make_rslds_parameters(C_init): init_dynamics_distns = [ Gaussian( mu=np.zeros(D_latent), sigma=3 * np.eye(D_latent), nu_0=D_latent + 2, sigma_0=3. * np.eye(D_latent), mu_0=np.zeros(D_latent), kappa_0=1.0, ) for _ in range(K) ] ths = np.random.uniform(np.pi / 30., 1.0, size=K) As = [random_rotation(D_latent, th) for th in ths] As = [np.hstack((A, np.ones((D_latent, 1)))) for A in As] dynamics_distns = [ Regression( A=As[k], sigma=np.eye(D_latent), nu_0=D_latent + 1000, S_0=np.eye(D_latent), M_0=np.hstack((np.eye(D_latent), np.zeros((D_latent, 1)))), K_0=np.eye(D_latent + 1), ) for k in range(K) ] if C_init is not None: emission_distns = \ DiagonalRegression(D_obs, D_latent + 1, A=C_init.copy(), sigmasq=np.ones(D_obs), alpha_0=2.0, beta_0=2.0) else: emission_distns = \ DiagonalRegression(D_obs, D_latent + 1, alpha_0=2.0, beta_0=2.0) return init_dynamics_distns, dynamics_distns, emission_distns
def make_dynamics_distns(): # Sample the fixed points on the unit disc # ths = 2 * np.pi * np.random.rand(K) ths = np.linspace(0, 2 * np.pi, K + 1)[:K] # ths = np.pi + np.array([np.pi/2., 0., 3*np.pi/2, 3*np.pi/2]) # rs = 1 + np.random.rand(K) rs = 3 * np.ones(K) xs = rs * np.cos(ths) ys = rs * np.sin(ths) xstars = np.column_stack((xs, ys)) # Sample stable dynamics matrices def _stable_dynamics(): eigs = npr.rand(D_latent) X = np.random.randn(D_latent, D_latent) Q, _ = np.linalg.qr(X) A = Q.dot(np.diag(eigs)).dot(Q.T) return A As = [_stable_dynamics() for _ in range(K)] bs = [(A - np.eye(D_latent)).dot(x) for A, x in zip(As, xstars)] # Slow down the dynamics tau = 1. / 0.05 As = [1. / tau * A + (1 - 1. / tau) * np.eye(D_latent) for A in As] bs = [1. / tau * b for b in bs] # Abs = [0.01 * Ab for Ab in Abs] Abs = [np.column_stack((A, b)) for A, b in zip(As, bs)] # Make a recurrent SLDS with these params # dynamics_distns = [ Regression(A=Ab, sigma=0.001 * np.eye(D_latent)) for Ab in Abs ] return dynamics_distns
# Parameters D_obs = 1 D_latent = 2 D_input = 0 T = 2000 # Simulate from an LDS with diagonal observation noise truemodel = DefaultLDS(D_obs, D_latent, D_input, sigma_obs=0.1 * np.eye(D_obs)) inputs = np.random.randn(T, D_input) data, stateseq = truemodel.generate(T, inputs=inputs) # Fit with an LDS with diagonal observation noise diag_model = LDS(dynamics_distn=Regression( nu_0=D_latent + 2, S_0=D_latent * np.eye(D_latent), M_0=np.zeros((D_latent, D_latent + D_input)), K_0=(D_latent + D_input) * np.eye(D_latent + D_input)), emission_distn=DiagonalRegression(D_obs, D_latent + D_input)) diag_model.add_data(data, inputs=inputs) # Also fit a model with a full covariance matrix full_model = DefaultLDS(D_obs, D_latent, D_input) full_model.add_data(data, inputs=inputs) # Fit with Gibbs sampling def update(model): model.resample_model() return model.log_likelihood()
truemodel = DefaultLDS(D_obs, D_latent) data, stateseq = truemodel.generate(T) # Mask off a chunk of data mask = np.ones_like(data, dtype=bool) chunksz = 100 for i, offset in enumerate(range(0, T, chunksz)): j = i % (D_obs + 1) if j < D_obs: mask[offset:min(offset + chunksz, T), j] = False if j == D_obs: mask[offset:min(offset + chunksz, T), :] = False # Fit with another LDS model = LDS(dynamics_distn=Regression(nu_0=D_latent + 3, S_0=D_latent * np.eye(D_latent), M_0=np.zeros((D_latent, D_latent)), K_0=D_latent * np.eye(D_latent)), emission_distn=DiagonalRegression(D_obs, D_latent, alpha_0=2.0, beta_0=1.0)) model.add_data(data=data, mask=mask) # Fit the model N_samples = 500 sigma_obs_smpls = [] def gibbs_update(model): model.resample_model() sigma_obs_smpls.append(model.sigma_obs_flat)
def trainModel(fileName, unit_trial, K=8, xDim=5): # unit_trial -- training data # randomization np.random.seed() numTrial, numUnit, numTime = unit_trial.shape # factor analysis for initialization factor_unit_trial = unit_trial.transpose([0, 2, 1]) factor_unit_trial = factor_unit_trial.reshape([-1, factor_unit_trial.shape[2]]) yDim = numUnit inputDim = 1 # some constants inputs = np.ones((numTime, inputDim)) estimator = factan(n_components=xDim, tol=0.00001, copy=True, max_iter=10000, noise_variance_init=None, svd_method='randomized', iterated_power=3, random_state=None) estimator.fit(factor_unit_trial) C_init = estimator.components_.T D_init = estimator.mean_.reshape([-1, 1]) # SLDS fit init_dynamics_distns = [Gaussian(nu_0=xDim+3, sigma_0=3.*np.eye(xDim), mu_0=np.zeros(xDim), kappa_0=0.01) for _ in range(K)] dynamics_distns = [Regression(nu_0=xDim + 1, S_0=xDim * np.eye(xDim), M_0=np.hstack((.99 * np.eye(xDim), np.zeros((xDim, inputDim)))), K_0=xDim * np.eye(xDim + inputDim)) for _ in range(K)] As = [np.eye(xDim) for _ in range(K)] if inputDim > 0: As = [np.hstack((A, np.zeros((xDim, inputDim)))) for A in As] for dd, A in zip(dynamics_distns, As): dd.A = A sigma_statess = [np.eye(xDim) for _ in range(K)] for dd, sigma in zip(dynamics_distns, sigma_statess): dd.sigma = sigma emission_distns = [DiagonalRegression(yDim, xDim + inputDim, mu_0=None, Sigma_0=None, alpha_0=3.0, beta_0=2.0, A=np.hstack((C_init.copy(), D_init.copy())), sigmasq=None, niter=1) for _ in range(K)] train_model = HMMSLDS( init_dynamics_distns= init_dynamics_distns, dynamics_distns= dynamics_distns, emission_distns= emission_distns, alpha=3., init_state_distn='uniform') # Adding training data for trial in range(numTrial): train_model.add_data(unit_trial[trial].T, inputs=inputs) print("Initializing with Gibbs") N_gibbs_samples = 2000 def initialize(model): model.resample_model() return model.log_likelihood() gibbs_lls = [initialize(train_model) for _ in progprint_xrange(N_gibbs_samples)] print("Fitting with VBEM") N_vbem_iters = 100 def update(model): model.VBEM_step() return model.log_likelihood() train_model._init_mf_from_gibbs() vbem_lls = [update(train_model) for _ in progprint_xrange(N_vbem_iters)] np.save(fileName + '_gibbs_lls', gibbs_lls) np.save(fileName + '_vbem_lls', vbem_lls) np.save(fileName + '_train_model', train_model) return train_model
def __init__(self, tree, Q, S, affine=True, S_scale=1.5): """ :param Q: diagonal of the inverse covariance matrix for observations :param S: diagonal of the inverse covariance matrix for the prior """ self.tree = tree self.affine = affine self.Q = Q self.P = Q.shape[0] assert Q.shape == (self.P, self.P) self.Q_inv = np.linalg.inv(self.Q) self.S = S self.D = S.shape[0] - affine assert S.shape == (self.D + affine, self.D + affine) # Get the precision matrix from the tree-structured prior self.adj = adjacency(tree) self.N = self.adj.shape[0] self.L = (self.N + 1) // 2 # self.J_0 = np.kron(self.adj, -self.S) # self.J_0 += np.kron(np.diag(self.adj.sum(1)), self.S) # self.J_0[:self.D, :self.D] += self.S # Get the indices of the leaves self._ids = ids(tree) self.depths = depths(tree) self.leaves = np.array([self._ids[l] for l in range(self.L)]) # Make the prior precision for the regression matrices J_0 = np.zeros((self.N, self.N)) J_0[0, 0] = 1 def _prior(node, depth): if np.isscalar(node): return elif isinstance(node, tuple) and len(node) == 2: J_0[self._ids[node], self._ids[node]] += S_scale**depth J_0[self._ids[node], self._ids[node[0]]] -= S_scale**depth J_0[self._ids[node[0]], self._ids[node]] -= S_scale**depth J_0[self._ids[node[0]], self._ids[node[0]]] += S_scale**depth _prior(node[0], depth + 1) J_0[self._ids[node], self._ids[node]] += S_scale**depth J_0[self._ids[node], self._ids[node[1]]] -= S_scale**depth J_0[self._ids[node[1]], self._ids[node]] -= S_scale**depth J_0[self._ids[node[1]], self._ids[node[1]]] += S_scale**depth _prior(node[1], depth + 1) _prior(tree, 0) self.J_0 = np.kron(J_0, self.S) self.As = np.zeros((self.N, self.P, self.D)) self.regressions = [ Regression(A=self.As[l], sigma=self.Q_inv, affine=self.affine) for l in self.leaves ] # Resample to populate with a draw from the prior self.resample()
# True LDS Parameters mu_init = np.array([0., 1.]) sigma_init = 0.01 * np.eye(2) A = 0.99 * np.array([[np.cos(np.pi / 24), -np.sin(np.pi / 24)], [np.sin(np.pi / 24), np.cos(np.pi / 24)]]) B = np.zeros((D_latent, D_input)) sigma_states = 0.01 * np.eye(2) C = np.random.randn(D_obs, D_latent) D = np.zeros((D_obs, D_input)) b = -2.0 * np.ones((D_obs, 1)) # Simulate from a Bernoulli LDS truemodel = CountLDS(dynamics_distn=Regression(A=np.hstack((A, B)), sigma=sigma_states), emission_distn=BernoulliRegression(D_out=D_obs, D_in=D_latent + D_input, A=np.hstack((C, D)), b=b)) inputs = np.random.randn(T, D_input) data, stateseq = truemodel.generate(T, inputs=inputs) # Make a model model = CountLDS(dynamics_distn=Regression( nu_0=D_latent + 2, S_0=D_latent * np.eye(D_latent), M_0=np.zeros((D_latent, D_latent + D_input)), K_0=(D_latent + D_input) * np.eye(D_latent + D_input)),
def make_roslds(V, I_inj_values, not_noisy=True, K=6, D_latent=2, sigmasq_value=1e-4, penalty=.05): """ :param V: the (T,) array of voltage observations :param K: the number of discrete states (integer) :param D_latent: the dimension of the continuous latent states """ assert V.ndim == 1, "V must be a shape (T,) array of voltage observations" T = V.shape[0] D_obs = 2 ''' # initialization w1, b1 = np.array([+1.0, 0.0]), np.array([0.0]) # x >0 w2, b2 = np.array([0.0, +1.0]), np.array([0.0]) # y > 0 reg_W = np.row_stack((w1, w2)) reg_b = np.row_stack((b1, b2)) ''' reg_W, reg_b = make_initial_plane(K) # Scale the weights to make the transition boundary sharper reg_scale = 100. reg_b *= reg_scale reg_W *= reg_scale # Create the model components # (initial state dist, dynamics dist, emissions dist) init_dynamics_distns = [Gaussian(mu=np.zeros(D_latent), sigma=np.eye(D_latent), nu_0=D_latent + 2, sigma_0=3 * np.eye(D_latent), mu_0=np.zeros(D_latent), kappa_0=1.0, ) for _ in range(K)] dynamics_distns = [Regression( nu_0=D_latent + 4, S_0=1e-4 * np.eye(D_latent), M_0=np.hstack((np.eye(D_latent), np.zeros((D_latent, 2)))), K_0=np.eye(D_latent + 2), affine=False ) for _ in range(K)] # Constrain the emission matrix to have C = [[1, 0, ..., 0]] # and small sigmasq # C = np.hstack((np.eye(D_obs), np.zeros((D_obs, 2)))) C = np.hstack((np.eye(D_obs), np.zeros((D_latent, 2)))) #sigmasq = np.concatenate((np.array([1e-4]), np.ones(D_obs-1))) sigmasq = np.array([sigmasq_value, penalty]) emission_distns = DiagonalRegression(D_obs, D_latent+2, A=C, sigmasq=sigmasq) # Construct the full model if K == 1: rslds = PGRecurrentOnlySLDS(trans_params=dict(sigmasq_A=10000., sigmasq_b=10000.), init_state_distn='uniform', init_dynamics_distns=init_dynamics_distns, dynamics_distns=dynamics_distns, emission_distns=emission_distns, fixed_emission=True) else: rslds = PGRecurrentOnlySLDS(trans_params=dict(A=np.hstack((np.zeros((K-1, K)), reg_W)), b=reg_b, sigmasq_A=10000., sigmasq_b=10000.), init_state_distn='uniform', init_dynamics_distns=init_dynamics_distns, dynamics_distns=dynamics_distns, emission_distns=emission_distns, fixed_emission=True) # Initialize the continuous states to be V and its gradient assert D_latent == 2 if not_noisy: dV = gaussian_filter1d(np.gradient(V), 1) else: nconvolve =10000 dV =np.convolve(np.gradient(V), np.ones((nconvolve,))/nconvolve, mode='same') x_init = np.column_stack((V, dV)) x_init = (x_init - np.mean(x_init, axis=0)) / np.std(x_init, axis=0) # Initialize the discrete states by clustering x_init km = KMeans(K).fit(x_init) z_init = km.labels_ # Provide an array of ones for the bias (affine term) assert I_inj_values.shape == (T,) data = np.column_stack((V, np.zeros(T,))) # pseudo obs inputs = np.column_stack((np.ones((T, 1)), I_inj_values)) mask = np.ones((T, D_obs), dtype=bool) rslds.add_data(data, mask=mask, inputs=inputs, stateseq=z_init, gaussian_states=x_init) return rslds
for _ in range(Kmax)] # Emission noise covariances model = HMMSLDS(init_dynamics_distns=[ Gaussian(nu_0=5, sigma_0=3. * np.eye(D_latent), mu_0=np.zeros(D_latent), kappa_0=0.01, mu=np.zeros(D_latent), sigma=np.eye(D_latent)) for _ in range(Kmax) ], dynamics_distns=[ Regression( A=np.hstack( (np.eye(D_latent), np.zeros((D_latent, D_input)))), sigma=np.eye(D_latent), nu_0=D_latent + 3, S_0=D_latent * np.eye(D_latent), M_0=np.hstack( (np.eye(D_latent), np.zeros((D_latent, D_input)))), K_0=D_latent * np.eye(D_latent + D_input), ) for _ in range(Kmax) ], emission_distns=DiagonalRegression( D_obs, D_latent + D_input, alpha_0=2.0, beta_0=1.0, ), alpha=3., init_state_distn='uniform') model.add_data(data, inputs=np.ones((T, D_input)))
def _default_model(model_class, K, D_obs, D_latent, D_input=0, mu_inits=None, sigma_inits=None, As=None, Bs=None, sigma_statess=None, Cs=None, Ds=None, sigma_obss=None, alpha=3.0, init_state_distn='uniform', **kwargs): # Initialize init_dynamics_distns init_dynamics_distns = \ [Gaussian(nu_0=D_latent+3, sigma_0=3.*np.eye(D_latent), mu_0=np.zeros(D_latent), kappa_0=0.01) for _ in range(K)] if mu_inits is not None: assert isinstance(mu_inits, list) and len(mu_inits) == K for id, mu in zip(init_dynamics_distns, mu_inits): id.mu = mu if sigma_inits is not None: assert isinstance(sigma_inits, list) and len(sigma_inits) == K for id, sigma in zip(init_dynamics_distns, sigma_inits): id.sigma = sigma # Initialize dynamics distributions dynamics_distns = [ Regression(nu_0=D_latent + 1, S_0=D_latent * np.eye(D_latent), M_0=np.hstack( (.99 * np.eye(D_latent), np.zeros( (D_latent, D_input)))), K_0=D_latent * np.eye(D_latent + D_input)) for _ in range(K) ] if As is not None: assert isinstance(As, list) and len(As) == K if D_input > 0: assert isinstance(Bs, list) and len(Bs) == K As = [np.hstack((A, B)) for A, B in zip(As, Bs)] else: # As = [random_rotation(D_latent) for _ in range(K)] As = [np.eye(D_latent) for _ in range(K)] if D_input > 0: As = [np.hstack((A, np.zeros((D_latent, D_input)))) for A in As] for dd, A in zip(dynamics_distns, As): dd.A = A if sigma_statess is not None: assert isinstance(sigma_statess, list) and len(sigma_statess) == K else: sigma_statess = [np.eye(D_latent) for _ in range(K)] for dd, sigma in zip(dynamics_distns, sigma_statess): dd.sigma = sigma # Initialize emission distributions _single_emission = (Cs is not None) and (not isinstance(Cs, list)) if _single_emission: if D_input > 0: assert Ds is not None and not isinstance(Ds, list) Cs = np.hstack((Cs, Ds)) if sigma_obss is None: sigma_obss = np.eye(D_obs) emission_distns = Regression(nu_0=D_obs + 3, S_0=D_obs * np.eye(D_obs), M_0=np.zeros((D_obs, D_latent + D_input)), K_0=D_obs * np.eye(D_latent + D_input), A=Cs, sigma=sigma_obss) else: emission_distns = [ Regression(nu_0=D_obs + 1, S_0=D_obs * np.eye(D_obs), M_0=np.zeros((D_obs, D_latent + D_input)), K_0=D_obs * np.eye(D_latent + D_input)) for _ in range(K) ] if Cs is not None and sigma_obss is not None: assert isinstance(Cs, list) and len(Cs) == K assert isinstance(sigma_obss, list) and len(sigma_obss) == K if D_input > 0: assert isinstance(Ds, list) and len(Ds) == K Cs = [np.hstack((C, D)) for C, D in zip(Cs, Ds)] else: Cs = [np.zeros((D_obs, D_latent + D_input)) for _ in range(K)] sigma_obss = [0.05 * np.eye(D_obs) for _ in range(K)] for ed, C, sigma in zip(emission_distns, Cs, sigma_obss): ed.A = C ed.sigma = sigma model = model_class(init_dynamics_distns=init_dynamics_distns, dynamics_distns=dynamics_distns, emission_distns=emission_distns, init_state_distn=init_state_distn, alpha=alpha, **kwargs) return model
T = 2000 # True LDS Parameters mu_init = np.array([0., 1.]) sigma_init = 0.01 * np.eye(2) A = 0.99 * np.array([[np.cos(np.pi / 24), -np.sin(np.pi / 24)], [np.sin(np.pi / 24), np.cos(np.pi / 24)]]) sigma_states = 0.01 * np.eye(2) C = np.random.randn(D_obs, D_latent) b = -2.0 * np.ones((D_obs, 1)) # Simulate from a Bernoulli LDS truemodel = LDS(dynamics_distn=Regression(A=A, sigma=sigma_states), emission_distn=BernoulliRegression(D_out=D_obs, D_in=D_latent, A=C, b=b)) data, stateseq = truemodel.generate(T) # Fit with a Poisson LDS model = DefaultPoissonLDS(D_obs, D_latent) model.add_data(data, verbose=False) N_iters = 50 def em_update(model): model.EM_step()
sigma_init = 0.01 * np.eye(2) A = 0.99 * np.array([[np.cos(np.pi / 24), -np.sin(np.pi / 24)], [np.sin(np.pi / 24), np.cos(np.pi / 24)]]) sigma_states = 0.01 * np.eye(2) C = np.array([[10., 0.]]) sigma_obs = 0.01 * np.eye(1) ################### # generate data # ################### truemodel = LDS(dynamics_distn=AutoRegression(A=A, sigma=sigma_states), emission_distn=Regression(A=C, sigma=sigma_obs)) data, stateseq = truemodel.generate(2000) ############### # fit model # ############### def update(model): model.resample_model() return model.log_likelihood() model = DefaultLDS(n=2, p=data.shape[1]).add_data(data) vlbs = [update(model) for _ in progprint_xrange(100)]
def simulate_nascar(): assert K_true == 4 As = [ random_rotation(D_latent, np.pi / 24.), random_rotation(D_latent, np.pi / 48.) ] # Set the center points for each system centers = [np.array([+2.0, 0.]), np.array([-2.0, 0.])] bs = [ -(A - np.eye(D_latent)).dot(center) for A, center in zip(As, centers) ] # Add a "right" state As.append(np.eye(D_latent)) bs.append(np.array([+0.1, 0.])) # Add a "right" state As.append(np.eye(D_latent)) bs.append(np.array([-0.25, 0.])) # Construct multinomial regression to divvy up the space w1, b1 = np.array([+1.0, 0.0]), np.array([-2.0]) # x + b > 0 -> x > -b w2, b2 = np.array([-1.0, 0.0]), np.array([-2.0]) # -x + b > 0 -> x < b w3, b3 = np.array([0.0, +1.0]), np.array([0.0]) # y > 0 w4, b4 = np.array([0.0, -1.0]), np.array([0.0]) # y < 0 reg_W = np.column_stack((100 * w1, 100 * w2, 10 * w3, 10 * w4)) reg_b = np.concatenate((100 * b1, 100 * b2, 10 * b3, 10 * b4)) # Make a recurrent SLDS with these params # dynamics_distns = [ Regression( A=np.column_stack((A, b)), sigma=1e-4 * np.eye(D_latent), nu_0=D_latent + 2, S_0=1e-4 * np.eye(D_latent), M_0=np.zeros((D_latent, D_latent + 1)), K_0=np.eye(D_latent + 1), ) for A, b in zip(As, bs) ] init_dynamics_distns = [ Gaussian(mu=np.array([0.0, 1.0]), sigma=1e-3 * np.eye(D_latent)) for _ in range(K) ] C = np.hstack((npr.randn(D_obs, D_latent), np.zeros((D_obs, 1)))) emission_distns = \ DiagonalRegression(D_obs, D_latent+1, A=C, sigmasq=1e-5 *np.ones(D_obs), alpha_0=2.0, beta_0=2.0) model = SoftmaxRecurrentOnlySLDS(trans_params=dict(W=reg_W, b=reg_b), init_state_distn='uniform', init_dynamics_distns=init_dynamics_distns, dynamics_distns=dynamics_distns, emission_distns=emission_distns, alpha=3.) ######################### # Sample from the model # ######################### inputs = np.ones((T, 1)) y, x, z = model.generate(T=T, inputs=inputs) # Maks off some data if mask_start == mask_stop: mask = None else: mask = np.ones((T, D_obs), dtype=bool) mask[mask_start:mask_stop] = False # Print the true parameters np.set_printoptions(precision=2) print("True W:\n{}".format(model.trans_distn.W)) print("True logpi:\n{}".format(model.trans_distn.logpi)) return model, inputs, z, x, y, mask
def simulate_nascar(): assert K_true == 4 def random_rotation(n, theta): rot = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]]) out = np.zeros((n,n)) out[:2,:2] = rot q = np.linalg.qr(np.random.randn(n,n))[0] # q = np.eye(n) return q.dot(out).dot(q.T) As = [random_rotation(D_latent, np.pi/24.), random_rotation(D_latent, np.pi/48.)] # Set the center points for each system centers = [np.array([+2.0, 0.]), np.array([-2.0, 0.])] bs = [-(A - np.eye(D_latent)).dot(center) for A, center in zip(As, centers)] # Add a "right" state As.append(np.eye(D_latent)) bs.append(np.array([+0.1, 0.])) # Add a "right" state As.append(np.eye(D_latent)) bs.append(np.array([-0.35, 0.])) # Construct multinomial regression to divvy up the space # w1, b1 = np.array([+1.0, 0.0]), np.array([-2.0]) # x + b > 0 -> x > -b w2, b2 = np.array([-1.0, 0.0]), np.array([-2.0]) # -x + b > 0 -> x < b w3, b3 = np.array([0.0, +1.0]), np.array([0.0]) # y > 0 reg_W = np.row_stack((w1, w2, w3)) reg_b = np.row_stack((b1, b2, b3)) # Scale the weights to make the transition boundary sharper reg_scale = 100. reg_b *= reg_scale reg_W *= reg_scale # Account for stick breaking asymmetry mu_b, _ = compute_psi_cmoments(np.ones(K_true)) reg_b += mu_b[:,None] # Make a recurrent SLDS with these params # dynamics_distns = [ Regression( A=np.column_stack((A,b)), sigma=1e-4 * np.eye(D_latent), nu_0=D_latent + 2, S_0=1e-4 * np.eye(D_latent), M_0=np.zeros((D_latent, D_latent + 1)), K_0=np.eye(D_latent + 1), ) for A,b in zip(As, bs)] init_dynamics_distns = [ Gaussian( mu=np.array([0.0, 1.0]), sigma=1e-3 * np.eye(D_latent)) for _ in range(K_true)] C = np.hstack((npr.randn(args.D_obs, D_latent), np.zeros((args.D_obs, 1)))) emission_distns = \ DiagonalRegression(args.D_obs, D_latent+1, A=C, sigmasq=1e-5 *np.ones(args.D_obs), alpha_0=2.0, beta_0=2.0) model = PGRecurrentSLDS( trans_params=dict(A=np.hstack((np.zeros((K_true-1, K_true)), reg_W)), b=reg_b, sigmasq_A=100., sigmasq_b=100.), init_state_distn='uniform', init_dynamics_distns=init_dynamics_distns, dynamics_distns=dynamics_distns, emission_distns=emission_distns) # Sample from the model inputs = np.ones((args.T, 1)) y, x, z = model.generate(T=args.T, inputs=inputs) # Maks off some data mask = np.ones((args.T, args.D_obs), dtype=bool) mask[args.mask_start:args.mask_stop] = False return model, inputs, z, x, y, mask
return q.dot(out).dot(q.T) As = [ random_rotation(D_latent, np.pi / 24.), random_rotation(D_latent, np.pi / 8.) ] # Start with a random emission matrix C = np.random.randn(D_obs, D_latent) b = -2.0 * np.ones((D_obs, 1)) init_dynamics_distns = [ Gaussian(mu=mu_init, sigma=sigma_init) for _ in range(K) ] dynamics_distns = [Regression(A=A, sigma=0.01 * np.eye(D_latent)) for A in As] emission_distns = BernoulliRegression(D_obs, D_latent, A=C, b=b) truemodel = HMMCountSLDS(dynamics_distns=dynamics_distns, emission_distns=emission_distns, init_dynamics_distns=init_dynamics_distns, alpha=3., init_state_distn='uniform') #%% ### Generate data from an SLDS # Manually create the states object with the mask T = 1000 stateseq = np.repeat(np.arange(T // 100) % 2, 100).astype(np.int32) statesobj = truemodel._states_class(model=truemodel, T=stateseq.size,
import seaborn as sns sns.set_style("white") from pybasicbayes.util.text import progprint_xrange from pybasicbayes.distributions import Regression, RobustRegression D_out = 1 D_in = 2 N = 100 # Make a regression model and simulate data A = npr.randn(D_out, D_in) b = npr.randn(D_out) Sigma = 0.1 * np.eye(D_out) true_reg = Regression(A=np.column_stack((A, b)), sigma=Sigma, affine=True) X = npr.randn(N, D_in) y = true_reg.rvs(x=X, return_xy=False) # Corrupt a fraction of the data inds = npr.rand(N) < 0.1 y[inds] = 3 * npr.randn(inds.sum(), D_out) # Make a test regression and fit it std_reg = Regression(nu_0=D_out + 2, S_0=np.eye(D_out), M_0=np.zeros((D_out, D_in + 1)), K_0=np.eye(D_in + 1), affine=True) robust_reg = RobustRegression(nu_0=D_out + 2,
def make_roslds_mtpl(V, I_inj_values, V_compartment, K=3, D_latent=2, sigmasq_value=1e-4, penalty=.05): """ :param V: the (T,) array of voltage observations :param K: the number of discrete states (integer) :param D_latent: the dimension of the continuous latent states """ assert V.ndim == 1, "V must be a shape (T,) array of voltage observations" T = V.shape[0] D_obs = 2 directory = './results/' # set initial plane if K > 1: reg_W, reg_b = make_initial_plane(K) # Scale the weights to make the transition boundary sharper reg_scale = 100. reg_b *= reg_scale reg_W *= reg_scale # Create the model components # (initial state dist, dynamics dist, emissions dist) init_dynamics_distns = [ Gaussian( mu=np.zeros(D_latent), sigma=np.eye(D_latent), nu_0=D_latent + 2, sigma_0=3 * np.eye(D_latent), mu_0=np.zeros(D_latent), kappa_0=1.0, ) for _ in range(K)] dynamics_distns = [ Regression( nu_0=D_latent + 6,#4, S_0=1e-4 * np.eye(D_latent), M_0=np.hstack((np.eye(D_latent), np.zeros((D_latent, 3)))),#2)))), K_0=np.eye(D_latent + 3),#2), affine=False ) for _ in range(K)] # Constrain the emission matrix to have C = [[1, 0, ..., 0]] # and small sigmasq # C = np.hstack((np.eye(D_obs), np.zeros((D_obs, 2)))) C = np.hstack((np.eye(D_obs), np.zeros((D_latent, 3))))#2)))) #sigmasq = np.concatenate((np.array([1e-4]), np.ones(D_obs-1))) sigmasq = np.array([sigmasq_value, penalty]) emission_distns = \ DiagonalRegression(D_obs, D_latent+3,#+2, A=C, sigmasq=sigmasq) # Construct the full model if K == 1: rslds = PGRecurrentOnlySLDS( trans_params=dict(sigmasq_A=10000., sigmasq_b=10000.), init_state_distn='uniform', init_dynamics_distns=init_dynamics_distns, dynamics_distns=dynamics_distns, emission_distns=emission_distns, fixed_emission=True) else: rslds = PGRecurrentOnlySLDS( trans_params=dict(A=np.hstack((np.zeros((K-1, K)), reg_W)), b=reg_b, sigmasq_A=10000., sigmasq_b=10000.), init_state_distn='uniform', init_dynamics_distns=init_dynamics_distns, dynamics_distns=dynamics_distns, emission_distns=emission_distns, fixed_emission=True) # Initialize the continuous states to be V and its gradient assert D_latent == 2 from scipy.ndimage import gaussian_filter1d from sklearn.cluster import KMeans #dV = gaussian_filter1d(np.gradient(V), 1) #nconvolve = 0 #nconvolve =500#100 #dV =np.convolve(np.gradient(V), np.ones((nconvolve,))/nconvolve, mode='same') V_tmp = V.copy() v_thre = 0#3.3 (good)#3#3.5#4#3.5#3#2.5#2.2 V_tmp[V_tmp<v_thre] = 0 print('NEW INITIALIZATION!', v_thre) #dV = gaussian_filter1d(np.gradient(V_tmp), 1) dV = gaussian_filter1d(np.gradient(V_tmp), 10) print('convolue dV') #x_init = np.column_stack((V, dV)) x_init = np.column_stack((V_tmp, dV)) x_init = (x_init - np.mean(x_init, axis=0)) / np.std(x_init, axis=0) # Initialize the discrete states by clustering x_init km = KMeans(K).fit(x_init) z_init = km.labels_ # Plot the #''' plt.close('all') plt.figure() plt.subplot(211) plt.plot(x_init[:10000,:]) # plt.plot(Vs_true[:,j],'r') plt.subplot(212) plt.plot(z_init[:10000]) #plt.show() plt.savefig(directory+'-init-penalized.png') #plt.savefig('nconvolve'+str(nconvolve)+'-init-penalized.png') #''' # Provide an array of ones for the bias (affine term) assert I_inj_values.shape == (T,) data = np.column_stack((V, np.zeros(T,))) # pseudo obs # add voltage effect on rslds (V_compartments) inputs = np.column_stack((np.ones((T, 1)), I_inj_values, V_compartment)) #inputs = np.column_stack((np.ones((T, 1)), I_inj_values)) mask = np.ones((T, D_obs), dtype=bool) rslds.add_data(data, mask=mask, inputs=inputs, stateseq=z_init, gaussian_states=x_init) return rslds