def test_discrete_4_2(self): # 4x4 transition matrix n_states = 2 P = np.array([[0.90, 0.10, 0.00, 0.00], [0.10, 0.89, 0.01, 0.00], [0.00, 0.01, 0.89, 0.10], [0.00, 0.00, 0.10, 0.90]]) # generate realization T = 50000 dtrajs = [MarkovStateModel(P).simulate(T)] # estimate initial HMM with 2 states - should be identical to P hmm = initial_guess_discrete_from_data(dtrajs, n_states, lagtime=1, regularize=False) # Test if model fit is close to reference. Note that we do not have an exact reference, so we cannot set the # tolerance in a rigorous way to test statistical significance. These are just sanity checks. Tij = hmm.transition_model.transition_matrix B = hmm.output_model.output_probabilities # Test stochasticity np.testing.assert_(msmana.is_transition_matrix(Tij)) np.testing.assert_allclose(B.sum(axis=1), np.ones(B.shape[0])) Tij_ref = np.array([[0.99, 0.01], [0.01, 0.99]]) Bref = np.array([[0.5, 0.5, 0.0, 0.0], [0.0, 0.0, 0.5, 0.5]]) np.testing.assert_array_almost_equal(Tij, Tij_ref, decimal=2) if np.max(B - Bref) < .05: np.testing.assert_allclose(B, Bref, atol=0.06) else: np.testing.assert_allclose(B[[1, 0]], Bref, atol=0.06)
def test_1state_1obs(self): dtraj = np.array([0, 0, 0, 0, 0]) Aref = np.array([[1.0]]) Bref = np.array([[1.0]]) for rev in [True, False]: # reversibiliy doesn't matter in this example hmm = initial_guess_discrete_from_data(dtraj, 1, 1, reversible=rev) np.testing.assert_allclose(hmm.transition_model.transition_matrix, Aref) np.testing.assert_allclose(hmm.output_model.output_probabilities, Bref)
def setUpClass(cls) -> None: dtraj = DoubleWellDiscrete().dtraj initial_hmm_10 = initial_guess_discrete_from_data(dtraj, n_hidden_states=2, lagtime=10) cls.hmm_lag10 = MaximumLikelihoodHMSM( initial_hmm_10, lagtime=10).fit(dtraj).fetch_model() cls.hmm_lag10_largest = cls.hmm_lag10.submodel_largest(dtrajs=dtraj) cls.msm_lag10 = estimate_markov_model(dtraj, 10, reversible=True) initial_hmm_1 = initial_guess_discrete_from_data(dtraj, n_hidden_states=2, lagtime=1) cls.hmm_lag1 = MaximumLikelihoodHMSM(initial_hmm_1).fit( dtraj).fetch_model() cls.hmm_lag1_largest = cls.hmm_lag1.submodel_largest(dtrajs=dtraj) cls.msm_lag1 = estimate_markov_model(dtraj, 1, reversible=True) cls.dtrajs = dtraj
def test_3state_prev(self): dtraj = np.array([0, 1, 2, 0, 3, 4]) import msmtools.estimation as msmest for rev in [True, False]: hmm = initial_guess_discrete_from_data(dtraj, n_hidden_states=3, lagtime=1, reversible=rev) assert msmana.is_transition_matrix(hmm.transition_model.transition_matrix) if rev: assert msmana.is_reversible(hmm.transition_model.transition_matrix) assert np.allclose(hmm.output_probabilities.sum(axis=1), 1) for rev in [True, False]: C = TransitionCountEstimator(lagtime=1, count_mode="sliding").fit(dtraj).fetch_model().count_matrix C += msmest.prior_neighbor(C, 0.001) hmm = initial_guess_discrete_from_data(dtraj, n_hidden_states=3, lagtime=1, reversible=rev) np.testing.assert_(msmana.is_transition_matrix(hmm.transition_model.transition_matrix)) if rev: np.testing.assert_(msmana.is_reversible(hmm.transition_model.transition_matrix)) np.testing.assert_allclose(hmm.output_model.output_probabilities.sum(axis=1), 1.)
def test_2state_2obs_Pgiven(self): obs = np.array([0, 0, 1, 1, 0]) Aref = np.array([[1.0]]) for rev in [True, False]: # reversibiliy doesn't matter in this example hmm = initial_guess_discrete_from_data(obs, n_hidden_states=1, lagtime=1, reversible=rev) np.testing.assert_(msmana.is_transition_matrix(hmm.transition_model.transition_matrix)) np.testing.assert_allclose(hmm.transition_model.transition_matrix, Aref) # output must be 1 x 2, and no zeros np.testing.assert_equal(hmm.output_model.output_probabilities.shape, (1, 2)) np.testing.assert_(np.all(hmm.output_model.output_probabilities > 0))
def test_2state_2obs_deadend(self): dtraj = np.array([0, 0, 0, 0, 1]) Aref = np.array([[1.0]]) for rev in [True, False]: # reversibiliy doesn't matter in this example hmm = initial_guess_discrete_from_data(dtraj, 1, 1, reversible=rev) np.testing.assert_allclose(hmm.transition_model.transition_matrix, Aref) # output must be 1 x 2, and no zeros B = hmm.output_model.output_probabilities np.testing.assert_equal(B.shape, (1, 2)) np.testing.assert_array_less(0, B)
def test_1state(self): obs = np.array([0, 0, 0, 0, 0], dtype=int) init_hmm = initial_guess_discrete_from_data(obs, n_hidden_states=1, lagtime=1) hmm = MaximumLikelihoodHMSM(init_hmm).fit(obs).fetch_model() # hmm = bhmm.estimate_hmm([obs], n_states=1, lag=1, accuracy=1e-6) p0_ref = np.array([1.0]) A_ref = np.array([[1.0]]) B_ref = np.array([[1.0]]) assert np.allclose(hmm.initial_distribution, p0_ref) assert np.allclose(hmm.transition_model.transition_matrix, A_ref) assert np.allclose(hmm.output_probabilities, B_ref)
def test_state_splitting(self): dtraj = np.array([0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 1, 2, 2, 2, 2, 2, 2]) hmm0 = initial_guess_discrete_from_data(dtraj, n_hidden_states=3, lagtime=1, separate_symbols=np.array([0])) piref = np.array([0.35801876, 0.55535398, 0.08662726]) Aref = np.array([[0.76462978, 0.10261978, 0.13275044], [0.06615566, 0.89464821, 0.03919614], [0.54863966, 0.25128039, 0.20007995]]) Bref = np.array([[0, 1, 0], [0, 0, 1], [1, 0, 0]]) np.testing.assert_array_almost_equal(hmm0.transition_model.transition_matrix, Aref, decimal=2) np.testing.assert_array_almost_equal(hmm0.output_model.output_probabilities, Bref, decimal=2) np.testing.assert_array_almost_equal(hmm0.initial_distribution, piref, decimal=2)
def test_2state_2obs_unidirectional(self): dtraj = np.array([0, 0, 0, 0, 1]) Aref_naked = np.array([[0.75, 0.25], [0, 1]]) Bref_naked = np.array([[1., 0.], [0., 1.]]) perm = [1, 0] # permutation for rev in [True, False]: # reversibiliy doesn't matter in this example hmm = initial_guess_discrete_from_data(dtraj, n_hidden_states=2, lagtime=1, reversible=rev, regularize=False, mode='all') assert np.allclose(hmm.transition_model.transition_matrix, Aref_naked) \ or np.allclose(hmm.transition_model.transition_matrix, Aref_naked[np.ix_(perm, perm)]) # test permutation assert np.allclose(hmm.output_model.output_probabilities, Bref_naked) \ or np.allclose(hmm.output_model.output_probabilities, Bref_naked[perm]) # test permutation
def test_2state_2step(self): obs = np.array([0, 1, 0], dtype=int) init_hmm = initial_guess_discrete_from_data(obs, n_hidden_states=2, lagtime=1) hmm = MaximumLikelihoodHMSM(init_hmm).fit(obs).fetch_model() p0_ref = np.array([1, 0]) A_ref = np.array([[0.0, 1.0], [1.0, 0.0]]) B_ref = np.array([[1, 0], [0, 1]]) perm = [1, 0] # permutation assert np.allclose(hmm.initial_distribution, p0_ref, atol=1e-5) \ or np.allclose(hmm.initial_distribution, p0_ref[perm], atol=1e-5) assert np.allclose(hmm.transition_model.transition_matrix, A_ref, atol=1e-5) \ or np.allclose(hmm.transition_model.transition_matrix, A_ref[np.ix_(perm, perm)], atol=1e-5) assert np.allclose(hmm.output_probabilities, B_ref, atol=1e-5) \ or np.allclose(hmm.output_probabilities, B_ref[[perm]], atol=1e-5)
def test_state_splitting_empty(self): dtraj = np.array([0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, 1, 2, 2, 2, 2, 2, 2]) # create empty labels dtraj += 2 # include an empty label in separate hmm0 = initial_guess_discrete_from_data(dtraj, 3, lagtime=1, separate_symbols=np.array([1, 2]), mode='populous') piref = np.array([0.35801876, 0.55535398, 0.08662726]) Aref = np.array([[0.76462978, 0.10261978, 0.13275044], [0.06615566, 0.89464821, 0.03919614], [0.54863966, 0.25128039, 0.20007995]]) Bref = np.array([[0, 0, 0, 1, 0], [0, 0, 0, 0, 1], [0, 0, 1, 0, 0]]) np.testing.assert_(np.max(np.abs(hmm0.output_model.output_probabilities - Bref)) < 0.01) np.testing.assert_array_almost_equal(hmm0.transition_model.transition_matrix, Aref, decimal=2) np.testing.assert_array_almost_equal(hmm0.initial_distribution, piref, decimal=2)
def test_discrete_2_2(self): # 2x2 transition matrix P = np.array([[0.99, 0.01], [0.01, 0.99]]) # generate realization T = 10000 dtrajs = [MarkovStateModel(P).simulate(T)] # estimate initial HMM with 2 states - should be identical to P init_hmm = initial_guess_discrete_from_data(dtrajs, n_hidden_states=2, lagtime=1) # test A = init_hmm.transition_model.transition_matrix B = init_hmm.output_model.output_probabilities # Test stochasticity np.testing.assert_(msmana.is_transition_matrix(A)) np.testing.assert_allclose(B.sum(axis=1), np.ones(B.shape[0])) # A should be close to P if B[0, 0] < B[1, 0]: B = B[np.array([1, 0]), :] np.testing.assert_array_almost_equal(A, P, decimal=2) np.testing.assert_array_almost_equal(B, np.eye(2), decimal=2)
def test_discrete_6_3(self): # 4x4 transition matrix n_states = 3 P = np.array([[0.90, 0.10, 0.00, 0.00, 0.00, 0.00], [0.20, 0.79, 0.01, 0.00, 0.00, 0.00], [0.00, 0.01, 0.84, 0.15, 0.00, 0.00], [0.00, 0.00, 0.05, 0.94, 0.01, 0.00], [0.00, 0.00, 0.00, 0.02, 0.78, 0.20], [0.00, 0.00, 0.00, 0.00, 0.10, 0.90]]) # generate realization T = 10000 dtrajs = [MarkovStateModel(P).simulate(T)] # estimate initial HMM with 2 states - should be identical to P hmm = initial_guess_discrete_from_data(dtrajs, n_states, 1) # Test stochasticity and reversibility Tij = hmm.transition_model.transition_matrix B = hmm.output_model.output_probabilities np.testing.assert_(msmana.is_transition_matrix(Tij)) np.testing.assert_(msmana.is_reversible(Tij)) np.testing.assert_allclose(B.sum(axis=1), np.ones(B.shape[0]))
def test_separate_states(self): dtrajs = [ np.array([ 0, 1, 1, 1, 1, 1, 0, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1 ]), np.array([ 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2 ]), ] init_hmm = initial_guess_discrete_from_data(dtrajs, n_hidden_states=3, lagtime=1, separate_symbols=[0]) hmm = MaximumLikelihoodHMSM( init_hmm, lagtime=1).fit(dtrajs).fetch_model().submodel_largest( dtrajs=dtrajs) # we expect zeros in all samples at the following indices: pobs_zeros = ((0, 1, 2, 2, 2), (0, 0, 1, 2, 3)) assert np.allclose(hmm.output_probabilities[pobs_zeros], 0)
def test_submodel_simple(self): # sanity check for submodel; dtraj = [ np.array([ 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 2, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 2, 0, 0, 1, 1, 2, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0 ]) ] init_hmm = initial_guess_discrete_from_data(dtraj, n_hidden_states=3, lagtime=2) hmm = MaximumLikelihoodHMSM(init_hmm, lagtime=2).fit(dtraj).fetch_model() hmm_sub = hmm.submodel_largest(connectivity_threshold=5, dtrajs=dtraj) self.assertEqual(hmm_sub.transition_model.timescales().shape[0], 1) self.assertEqual( hmm_sub.transition_model.stationary_distribution.shape[0], 2) self.assertEqual(hmm_sub.transition_model.transition_matrix.shape, (2, 2))
def test_1state_fail(self): obs = np.array([0, 0, 0, 0, 0], dtype=int) with self.assertRaises(ValueError): _ = initial_guess_discrete_from_data(obs, n_hidden_states=2, lagtime=1)
def test_3state_fail(self): dtraj = np.array([0, 1, 0, 0, 1, 1]) # this example doesn't admit more than 2 metastable states. Raise. with self.assertRaises(ValueError): initial_guess_discrete_from_data(dtraj, 3, 1, reversible=False)
def test_state_splitting_fail(self): dtraj = np.array([0, 0, 1, 1]) with self.assertRaises(ValueError): initial_guess_discrete_from_data(dtraj, 2, 1, separate_symbols=np.array([0, 2]))