def lbfgs_newton_perf_comparison(T=100, N=15, K=3, D=10, ntrials=5, n_iters=20): np.random.seed(seed=123) true_slds = ssm.SLDS(N, K, D, transitions="recurrent", dynamics="gaussian", emissions="gaussian") z, x, y = true_slds.sample(T) fit_slds = ssm.SLDS(N, K, D, transitions="recurrent", dynamics="gaussian", emissions="gaussian") # Make sure all params are starting at the same value newtons_lds = copy.deepcopy(fit_slds) lbfgs_lds = copy.deepcopy(fit_slds) newton_time = 0 for i in range(ntrials): start = time.time() newtons_lds.fit(y, initialize=False, num_iters=n_iters, continuous_optimizer="newton") end = time.time() newton_time += (end - start) / n_iters newton_time /= ntrials print("Avg time/iter with newton's method: {:.4f}".format(newton_time)) lbfgs_time = 0 for i in range(ntrials): start = time.time() lbfgs_lds.fit(y, initialize=False, num_iters=n_iters, continuous_optimizer="lbfgs") end = time.time() lbfgs_time += (end - start) / n_iters lbfgs_time /= ntrials print("Avg time/iter with lbfgs: {:.4f}".format(lbfgs_time))
def _fit_once(): # fit a model slds = ssm.SLDS(N, Kmax, r, single_subspace=single_subspace, emissions='gaussian') #slds.initialize(X) #q_mf = SLDSMeanFieldVariationalPosterior(slds, X) if laplace_em: elbos, posterior = slds.fit( X, num_iters=num_iters, initialize=True, method="laplace_em", variational_posterior="structured_meanfield") posterior_x = posterior.mean_continuous_states[0] else: # Use blackbox + meanfield elbos, posterior = slds.fit(X, num_iters=num_iters, initialize=True, method="bbvi", variational_posterior="mf") # predict states return slds, elbos, posterior
def test_lds_sample_and_fit(T=100, N=15, K=3, D=10): # method_name --> allowable posteriors methods = { "bbvi": ["mf", "lds"], # "laplace_em": ["structured_meanfield"] } # Test SLDS and RSLDS print("Testing SLDS and RSLDS...") for dynamics in DYNAMICS_NAMES: for emissions in EMISSIONS_NAMES: for transitions in TRANSITIONS_NAMES: for method in methods: for posterior in methods[method]: npr.seed(seed=SEED) print("Fitting: " "transitions = {}," "dynamics = {}, " "emissions = {}, " "method = {}, " "posterior = {}, ".format( transitions, dynamics, emissions, method, posterior)) true_slds = ssm.SLDS(N, K, D, transitions=transitions, dynamics=dynamics, emissions=emissions) z, x, y = true_slds.sample(T) fit_slds = ssm.SLDS(N, K, D, transitions=transitions, dynamics=dynamics, emissions=emissions) fit_slds.fit(y, method=method, variational_posterior=posterior, num_init_iters=2, num_iters=2)
def fit_slds(input: np.ndarray, target: np.ndarray): global K, D_obs, D_latent rslds = ssm.SLDS(D_obs, K, D_latent, transitions="recurrent_only", dynamics="diagonal_gaussian", emissions="gaussian_orthog", single_subspace=True) rslds.initialize(input) q_elbos_lem, q_lem = rslds.fit( input, method="laplace_em", variational_posterior="structured_meanfield", initialize=False, num_iters=50, alpha=0.0) xhat_lem = q_lem.mean_continuous_states[0] zhat_lem = rslds.most_likely_states(xhat_lem, input) # Smooth the data under the variational posterior yhat_lem = rslds.smooth(xhat_lem, input) # compute the posterior over latent and continuous states for the targets target_elbos, target_posterior = rslds.approximate_posterior( target, method="laplace_em", variational_posterior="structured_meanfield", num_iters=10) # Get the posterior mean of the continuous states target_posterior_x = target_posterior.mean_continuous_states[0] target_posterior_y = rslds.smooth(target_posterior_x, target) return { 'training_elbos': q_elbos_lem, 'input_xhat': xhat_lem, 'input_zhat': zhat_lem, 'target_elbos': target_elbos, 'target_posterior': target_posterior_y }
def generate_sample_data(outdim, n_latent_dimensions, n_discrete_states, n_timepoints, dynamics): slds = ssm.SLDS( outdim, n_discrete_states, n_latent_dimensions, transitions="recurrent_only", dynamics="diagonal_gaussian", emissions="gaussian_orthog", single_subspace=True) slds.dynamics.As = dynamics _, _, output_emissions = slds.sample(n_timepoints) return output_emissions
def make_nascar_model(): 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 Rs = np.row_stack((100*w1, 100*w2, 10*w3,10*w4)) r = np.concatenate((100*b1, 100*b2, 10*b3, 10*b4)) true_rslds = ssm.SLDS(D_obs, K, D_latent, transitions="recurrent_only", dynamics="diagonal_gaussian", emissions="gaussian_orthog", single_subspace=True) true_rslds.dynamics.mu_init = np.tile(np.array([[0, 1]]), (K, 1)) true_rslds.dynamics.sigmasq_init = 1e-4 * np.ones((K, D_latent)) true_rslds.dynamics.As = np.array(As) true_rslds.dynamics.bs = np.array(bs) true_rslds.dynamics.sigmasq = 1e-4 * np.ones((K, D_latent)) true_rslds.transitions.Rs = Rs true_rslds.transitions.r = r true_rslds.emissions.inv_etas = np.log(1e-2) * np.ones((1, D_obs)) return true_rslds
from ssm.util import random_rotation, find_permutation # In[2]: # Set the parameters of the HMM T = 1000 # number of time bins K = 5 # number of discrete states D = 2 # number of latent dimensions N = 100 # number of observed dimensions # In[3]: # Make an SLDS with the true parameters true_slds = ssm.SLDS(N, K, D, emissions="poisson_orthog", emission_kwargs=dict(link="softplus")) # Set rotational dynamics for k in range(K): true_slds.dynamics.As[k] = .95 * random_rotation( D, theta=(k + 1) * np.pi / 20) true_slds.dynamics.bs[k] = 3 * npr.randn(D) # Set an offset to make the counts larger # true_slds.emissions.ds += 10 # Sample data z, x, y = true_slds.sample(T)
true_rslds.emissions.inv_etas = np.log(1e-2) * np.ones((1, D_obs)) return true_rslds # Sample from the model true_rslds = make_nascar_model() z, x, y = true_rslds.sample(T=T) # In[4]: # Fit an rSLDS with its default initialization, using Laplace-EM with a structured variational posterior rslds = ssm.SLDS(D_obs, K, D_latent, transitions="recurrent_only", dynamics="diagonal_gaussian", emissions="gaussian_orthog", single_subspace=True) rslds.initialize(y) q_elbos_lem, q_lem = rslds.fit(y, method="laplace_em", variational_posterior="structured_meanfield", initialize=False, num_iters=100, alpha=0.0) xhat_lem = q_lem.mean_continuous_states[0] rslds.permute(find_permutation(z, rslds.most_likely_states(xhat_lem, y))) zhat_lem = rslds.most_likely_states(xhat_lem, y) # store rslds
from ssm.util import random_rotation, find_permutation import seaborn as sns color_names = ["windows blue", "red", "amber", "faded green"] colors = sns.xkcd_palette(color_names) sns.set_style("white") sns.set_context("talk") # Set the parameters of the HMM T = 10000 # number of time bins K = 5 # number of discrete states D = 2 # number of latent dimensions N = 50 # number of observed dimensions # Make an SLDS with the true parameters true_slds = ssm.SLDS(N, K, D, emissions="bernoulli_orthog") for k in range(K): true_slds.dynamics.As[k] = .95 * random_rotation(D, theta=(k+1) * np.pi/20) # true_slds.dynamics.bs[k] = .1 * npr.randn(D) # true_slds.dynamics.Sigmas = np.tile(0.1 * np.eye(D)[None, :, :], (K, 1, 1)) # Sample training and test data from the SLDS z, x, y = true_slds.sample(T) z_test, x_test, y_test = true_slds.sample(T) # Fit an SLDS with mean field posterior print("Fitting SLDS with SVI using structured variational posterior") slds = ssm.SLDS(N, K, D, emissions="bernoulli_orthog") slds.initialize(y) q_mf_elbos, q_mf = slds.fit(y, method="bbvi", variational_posterior="mf",
def test_laplace_em_hessian(N=5, K=3, D=2, T=20): for transitions in ["standard", "recurrent", "recurrent_only"]: for emissions in ["gaussian_orthog", "gaussian"]: print("Checking analytical hessian for transitions={}, " "and emissions={}".format(transitions, emissions)) slds = ssm.SLDS(N, K, D, transitions=transitions, dynamics="gaussian", emissions=emissions) z, x, y = slds.sample(T) new_slds = ssm.SLDS(N, K, D, transitions="standard", dynamics="gaussian", emissions=emissions) inputs = [np.zeros((T, 0))] masks = [np.ones_like(y)] tags = [None] method = "laplace_em" datas = [y] num_samples = 1 def neg_expected_log_joint_wrapper(x_vec, T, D): x = x_vec.reshape(T, D) return new_slds._laplace_neg_expected_log_joint( datas[0], inputs[0], masks[0], tags[0], x, Ez, Ezzp1) variational_posterior = new_slds._make_variational_posterior( "structured_meanfield", datas, inputs, masks, tags, method) new_slds._fit_laplace_em_discrete_state_update( variational_posterior, datas, inputs, masks, tags, num_samples) Ez, Ezzp1, _ = variational_posterior.discrete_expectations[0] x = variational_posterior.mean_continuous_states[0] scale = x.size J_diag, J_lower_diag = new_slds._laplace_hessian_neg_expected_log_joint( datas[0], inputs[0], masks[0], tags[0], x, Ez, Ezzp1) dense_hessian = scipy.linalg.block_diag(*[x for x in J_diag]) dense_hessian[D:, :-D] += scipy.linalg.block_diag( *[x for x in J_lower_diag]) dense_hessian[:-D, D:] += scipy.linalg.block_diag( *[x.T for x in J_lower_diag]) true_hess = hessian(neg_expected_log_joint_wrapper)(x.reshape(-1), T, D) assert np.allclose(true_hess, dense_hessian) print("Hessian passed.") # Also check that computation of H works. h_dense = dense_hessian @ x.reshape(-1) h_dense = h_dense.reshape(T, D) J_ini, J_dyn_11, J_dyn_21, J_dyn_22, J_obs = new_slds._laplace_neg_hessian_params( datas[0], inputs[0], masks[0], tags[0], x, Ez, Ezzp1) h_ini, h_dyn_1, h_dyn_2, h_obs = new_slds._laplace_neg_hessian_params_to_hs( x, J_ini, J_dyn_11, J_dyn_21, J_dyn_22, J_obs) h = h_obs.copy() h[0] += h_ini h[:-1] += h_dyn_1 h[1:] += h_dyn_2 assert np.allclose(h, h_dense)
def test_laplace_em(T=100, N=15, K=3, D=10, num_cases=25): # Check that laplace-em works for each transition and emission model # so long as the dynamics are linear-gaussian. DYNAMICS_NAMES = ["gaussian"] EMISSIONS_NAMES = [ "gaussian", "gaussian_orthog", "poisson", "poisson_orthog", "bernoulli", "bernoulli_orthog" ] TRANSITIONS_NAMES = [ "stationary", "sticky", "inputdriven", "recurrent", "recurrent_only" ] INPUT_DIMS = [0, 1] test_cases = list( it.product(DYNAMICS_NAMES, EMISSIONS_NAMES, TRANSITIONS_NAMES, INPUT_DIMS)) # Choose a random subset of combinations test_case_indices = npr.choice(len(test_cases), size=num_cases) # Test SLDS and RSLDS print("Testing SLDS and RSLDS...") for idx in test_case_indices: dynamics, emissions, transitions, input_dim = test_cases[idx] true_slds = ssm.SLDS(N, K, D, M=input_dim, transitions=transitions, dynamics="gaussian", emissions=emissions) # Test with a random number of data arrays num_datas = npr.randint(1, 5) Ts = T + npr.randint(20, size=num_datas) us = [npr.randn(Ti, input_dim) for Ti in Ts] datas = [true_slds.sample(Ti, input=u) for Ti, u in zip(Ts, us)] zs, xs, ys = list(zip(*datas)) # Fit an SLDS to the data fit_slds = ssm.SLDS(N, K, D, M=input_dim, transitions=transitions, dynamics="gaussian", emissions=emissions) try: fit_slds.fit(ys, inputs=us, initialize=True, num_init_iters=2, num_iters=5) # So that we can still interrupt the test. except KeyboardInterrupt: raise # So that we know which test case fails... except: print("Error during fit with Laplace-EM. Failed with:") print("Emissions = {}".format(emissions)) print("Transitions = {}".format(transitions)) raise
def test_SLDSStructuredMeanField_entropy(): """Test correctness of the entropy calculation for the SLDSStructuredMeanFieldVariationalPosterior class. """ def entropy_mv_gaussian(J, h): mu = np.linalg.solve(J, h) sigma = np.linalg.inv(J) mv_normal = scipy.stats.multivariate_normal(mu, sigma) return mv_normal.entropy() def make_lds_parameters(T, D, N, U): m0 = np.zeros(D) S0 = np.eye(D) As = 0.99 * np.eye(D) Bs = np.zeros((D, U)) Qs = 0.1 * np.eye(D) Cs = npr.randn(N, D) Ds = np.zeros((N, U)) Rs = 0.1 * np.eye(N) us = np.zeros((T, U)) ys = np.sin(2 * np.pi * np.arange(T) / 50)[:, None] * npr.randn(1, N) + 0.1 * npr.randn(T, N) return m0, S0, As, Bs, Qs, Cs, Ds, Rs, us, ys def cumsum(v,strict=False): if not strict: return np.cumsum(v,axis=0) else: out = np.zeros_like(v) out[1:] = np.cumsum(v[:-1],axis=0) return out def bmat(blocks): rowsizes = [row[0].shape[0] for row in blocks] colsizes = [col[0].shape[1] for col in zip(*blocks)] rowstarts = cumsum(rowsizes,strict=True) colstarts = cumsum(colsizes,strict=True) nrows, ncols = sum(rowsizes), sum(colsizes) out = np.zeros((nrows,ncols)) for i, (rstart, rsz) in enumerate(zip(rowstarts, rowsizes)): for j, (cstart, csz) in enumerate(zip(colstarts, colsizes)): out[rstart:rstart+rsz,cstart:cstart+csz] = blocks[i][j] return out def lds_to_dense_infoparams(params): m0, S0, As, Bs, Qs, Cs, Ds, Rs, us, ys = params mu_init = m0 sigma_init = S0 A, B, sigma_states = As, Bs, Qs C, D, sigma_obs = Cs, Ds, Rs data = ys inputs = us # Copied from PYLDS tests/test_dense.py T, n = data.shape[0], D.shape[0] # mu_init, sigma_init = model.mu_init, model.sigma_init # A, B, sigma_states = model.A, model.B, model.sigma_states # C, D, sigma_obs = model.C, model.D, model.sigma_obs ss_inv = np.linalg.inv(sigma_states) h = np.zeros((T,n)) h[0] += np.linalg.solve(sigma_init, mu_init) # Dynamics h[1:] += inputs[:-1].dot(B.T).dot(ss_inv) h[:-1] += -inputs[:-1].dot(B.T).dot(np.linalg.solve(sigma_states, A)) # Emissions h += C.T.dot(np.linalg.solve(sigma_obs, data.T)).T h += -inputs.dot(D.T).dot(np.linalg.solve(sigma_obs, C)) J = np.kron(np.eye(T),C.T.dot(np.linalg.solve(sigma_obs,C))) J[:n,:n] += np.linalg.inv(sigma_init) pairblock = bmat([[A.T.dot(ss_inv).dot(A), -A.T.dot(ss_inv)], [-ss_inv.dot(A), ss_inv]]) for t in range(0,n*(T-1),n): J[t:t+2*n,t:t+2*n] += pairblock return J.reshape(T*n,T*n), h.reshape(T*n) T, D, N, U = 100, 10, 10, 0 params = make_lds_parameters(T, D, N, U) J_full, h_full = lds_to_dense_infoparams(params) ref_entropy = entropy_mv_gaussian(J_full, h_full) # Calculate entropy using kalman filter and posterior's entropy fn info_args = ssm.messages.convert_mean_to_info_args(*params) J_ini, h_ini, _, J_dyn_11,\ J_dyn_21, J_dyn_22, h_dyn_1,\ h_dyn_2, _, J_obs, h_obs, _ = info_args # J_obs[1:] += J_dyn_22 # J_dyn_22[:] = 0 log_Z, smoothed_mus, smoothed_Sigmas, ExxnT = ssm.messages.\ kalman_info_smoother(*info_args) # Model is just a dummy model to simplify # instantiating the posterior object. model = ssm.SLDS(N, 1, D, emissions="gaussian", dynamics="gaussian") datas = params[-1] post = ssm.variational.SLDSStructuredMeanFieldVariationalPosterior(model, datas) # Assign posterior to have info params that are the same as the ones used # in the reference entropy calculation. continuous_state_params = [dict(J_ini=J_ini, J_dyn_11=J_dyn_11, J_dyn_21=J_dyn_21, J_dyn_22=J_dyn_22, J_obs=J_obs, h_ini=h_ini, h_dyn_1=h_dyn_1, h_dyn_2=h_dyn_2, h_obs=h_obs)] post.continuous_state_params = continuous_state_params ssm_entropy = post._continuous_entropy() print("reference entropy: {}".format(ref_entropy)) print("ssm_entropy: {}".format(ssm_entropy)) assert np.allclose(ref_entropy, ssm_entropy)
import matplotlib import matplotlib.pyplot as plt import ssm from ssm.variational import SLDSMeanFieldVariationalPosterior, SLDSTriDiagVariationalPosterior from ssm.util import random_rotation, find_permutation # Set the parameters of the HMM T = 1000 # number of time bins K = 5 # number of discrete states D = 2 # number of latent dimensions N = 10 # number of observed dimensions # Make an SLDS with the true parameters true_slds = ssm.SLDS(N, K, D, emissions="gaussian") for k in range(K): true_slds.dynamics.As[k] = .95 * random_rotation( D, theta=(k + 1) * np.pi / 20) # Sample training and test data from the SLDS z, x, y = true_slds.sample(T) z_test, x_test, y_test = true_slds.sample(T) # Mask off some data mask = npr.rand(T, N) < 0.75 y_masked = y * mask # Fit an SLDS with mean field posterior print("Fitting SLDS with SVI using structured variational posterior") slds = ssm.SLDS(N, K, D, emissions="gaussian")
def test_laplace_em(T=100, N=15, K=3, D=10): # Check that laplace-em works for each transition and emission model # so long as the dynamics are linear-gaussian. for transitions in [ "stationary", "sticky", "inputdriven", "recurrent", "recurrent_only", ]: for emissions in [ "gaussian", "gaussian_orthog", "poisson", "poisson_orthog", "bernoulli", "bernoulli_orthog", ]: for input_dim in [0, 1]: true_slds = ssm.SLDS(N, K, D, M=input_dim, transitions=transitions, dynamics="gaussian", emissions=emissions) # Test with a random number of data arrays num_datas = npr.randint(1, 5) Ts = T + npr.randint(20, size=num_datas) us = [npr.randn(Ti, input_dim) for Ti in Ts] datas = [ true_slds.sample(Ti, input=u) for Ti, u in zip(Ts, us) ] zs, xs, ys = list(zip(*datas)) # Fit an SLDS to the data fit_slds = ssm.SLDS(N, K, D, M=input_dim, transitions=transitions, dynamics="gaussian", emissions=emissions) try: fit_slds.fit(ys, inputs=us, initialize=True, num_init_iters=2, num_iters=5) # So that we can still interrupt the test. except KeyboardInterrupt: raise # So that we know which test case fails... except: print("Error during fit with Laplace-EM. Failed with:") print("Emissions = {}".format(emissions)) print("Transitions = {}".format(transitions)) raise
import ssm from ssm.variational import SLDSMeanFieldVariationalPosterior, SLDSTriDiagVariationalPosterior from ssm.util import random_rotation, find_permutation # In[2]: # Set the parameters of the HMM T = 1000 # number of time bins K = 5 # number of discrete states D = 2 # number of latent dimensions N = 10 # number of observed dimensions # In[3]: # Make an SLDS with the true parameters true_slds = ssm.SLDS(N, K, D, emissions="gaussian_orthog") for k in range(K): true_slds.dynamics.As[k] = .95 * random_rotation( D, theta=(k + 1) * np.pi / 20) z, x, y = true_slds.sample(T) # Mask off some data mask = npr.rand(T, N) < 0.9 y_masked = y * mask # In[4]: print("Fitting SLDS with SVI") # Create the model and initialize its parameters slds = ssm.SLDS(N, K, D, emissions="gaussian_orthog")
def test_lds_sample_and_fit(T=100, N=15, K=3, D=10, num_cases=25): TRANSITIONS_NAMES = [ "stationary", "sticky", "inputdriven", "recurrent", "recurrent_only", # "rbf_recurrent", # "nn_recurrent", ] DYNAMICS_NAMES = [ "none", "gaussian", "diagonal_gaussian", "studentst", "diagonal_t", ] # Exclude the identity emissions (for now) # because they require N == D EMISSIONS_NAMES = [ "gaussian", "gaussian_orthog", "gaussian_nn", "studentst", "studentst_orthog", "studentst_nn", "poisson", "poisson_orthog", "poisson_nn", "bernoulli", "bernoulli_orthog", "bernoulli_nn", # "autoregressive", # "autoregressive_orthog", # "autoregressive_nn", ] METHODS = ["bbvi"] # method_name --> allowable posteriors POSTERIORS = { "bbvi": ["mf", "lds"], # "laplace_em": ["structured_meanfield"] } test_cases = list( it.product(DYNAMICS_NAMES, EMISSIONS_NAMES, TRANSITIONS_NAMES, METHODS)) # Choose a random subset of combinations test_case_indices = npr.choice(len(test_cases), size=num_cases) # Test SLDS and RSLDS print("Testing SLDS and RSLDS...") for idx in test_case_indices: dynamics, emissions, transitions, method = test_cases[idx] for posterior in POSTERIORS[method]: npr.seed(seed=SEED) print("Fitting: " "transitions = {}," "dynamics = {}, " "emissions = {}, " "method = {}, " "posterior = {}, ".format(transitions, dynamics, emissions, method, posterior)) true_slds = ssm.SLDS(N, K, D, transitions=transitions, dynamics=dynamics, emissions=emissions) z, x, y = true_slds.sample(T) fit_slds = ssm.SLDS(N, K, D, transitions=transitions, dynamics=dynamics, emissions=emissions) fit_slds.fit(y, method=method, variational_posterior=posterior, num_init_iters=2, num_iters=2)
def test_lds_sample_and_fit(T=100, N=15, K=3, D=10): transition_names = [ "stationary", "sticky", "inputdriven", "recurrent", "recurrent_only", "rbf_recurrent", "nn_recurrent", ] dynamics_names = [ "none", "gaussian", "diagonal_gaussian", "studentst", "diagonal_t", ] # Exclude the identity emissions (for now) # because they require N == D emission_names = [ "gaussian", "gaussian_orthog", "gaussian_nn", "studentst", "studentst_orthog", "studentst_nn", "poisson", "poisson_orthog", "poisson_nn", "bernoulli", "bernoulli_orthog", "bernoulli_nn", "autoregressive", "autoregressive_orthog", "autoregressive_nn", ] # method_name --> allowable posteriors methods = { "svi": ["mf", "lds"], # "laplace_em": ["structured_meanfield"] } # Test SLDS and RSLDS print("Testing SLDS and RSLDS...") for dynamics in dynamics_names: for emissions in emission_names: for transitions in transition_names: for method in methods: for posterior in methods[method]: npr.seed(seed=SEED) print("Fitting: " "transitions = {}," "dynamics = {}, " "emissions = {}, " "method = {}, " "posterior = {}, ".format( transitions, dynamics, emissions, method, posterior)) true_slds = ssm.SLDS(N, K, D, transitions=transitions, dynamics=dynamics, emissions=emissions) z, x, y = true_slds.sample(T) fit_slds = ssm.SLDS(N, K, D, transitions=transitions, dynamics=dynamics, emissions=emissions) fit_slds.fit(y, method=method, variational_posterior=posterior, num_init_iters=2, num_iters=2)