Package: mchmm
mchmmis a Python package implementing Markov chains and Hidden Markov models in pure NumPy and SciPy.
It can also visualize Markov chains (see below).DependenciesNumPySciPyInstallationInstall from PyPi:$pipinstallmchmmClone a GitHub repository:$gitclonehttps://github.com/maximtrp/mchmm.git$cdmchmm$pipinstall.--userFeaturesDiscrete Markov chainsInitializing a Markov chain using some data.>>>importmchmmasmc>>>a=mc.MarkovChain().from_data('AABCABCBAAAACBCBACBABCABCBACBACBABABCBACBBCBBCBCBCBACBABABCBCBAAACABABCBBCBCBCBCBCBAABCBBCBCBCCCBABCBCBBABCBABCABCCABABCBABC')Now, we can look at the observed transitionfrequencymatrix:>>>a.observed_matrixarray([[7.,18.,7.],[19.,5.,29.],[5.,30.,3.]])And the observed transitionprobabilitymatrix:>>>a.observed_p_matrixarray([[0.21875,0.5625,0.21875],[0.35849057,0.09433962,0.54716981],[0.13157895,0.78947368,0.07894737]])You can visualize your Markov chain. First, build a directed graph withgraph_make()method ofMarkovChainobject.
Thenrender()it.>>>graph=a.graph_make(format="png",graph_attr=[("rankdir","LR")],node_attr=[("fontname","Roboto bold"),("fontsize","20")],edge_attr=[("fontname","Iosevka"),("fontsize","12")])>>>graph.render()Here is the result:Pandas can help us annotate columns and rows:>>>importpandasaspd>>>pd.DataFrame(a.observed_matrix,index=a.states,columns=a.states,dtype=int)ABCA7187B19529C5303Viewing the expected transition frequency matrix:>>>a.expected_matrixarray([[8.06504065,13.78861789,10.14634146],[13.35772358,22.83739837,16.80487805],[9.57723577,16.37398374,12.04878049]])Calculating Nth order transition probability matrix:>>>a.n_order_matrix(a.observed_p_matrix,order=2)array([[0.2782854,0.34881028,0.37290432],[0.1842357,0.64252707,0.17323722],[0.32218957,0.21081868,0.46699175]])Carrying out a chi-squared test:>>>a.chisquare(a.observed_matrix,a.expected_matrix,axis=None)Power_divergenceResult(statistic=47.89038802624337,pvalue=1.0367838347591701e-07)Finally, let’s simulate a Markov chain given our data.>>>ids,states=a.simulate(10,start='A',seed=np.random.randint(0,10,10))>>>idsarray([0,2,1,0,2,1,0,2,1,0])>>>statesarray(['A','C','B','A','C','B','A','C','B','A'],dtype='<U1')>>>"".join(states)'ACBACBACBA'Hidden Markov modelsWe will use a fragment of DNA sequence with TATA box as an example. Initializing a hidden Markov model with sequences of observations and states:>>>importmchmmasmc>>>obs_seq='AGACTGCATATATAAGGGGCAGGCTG'>>>sts_seq='00000000111111100000000000'>>>a=mc.HiddenMarkovModel().from_seq(obs_seq,sts_seq)Unique states and observations are automatically inferred:>>>a.states['0''1']>>>a.observations['A''C''G''T']The transition probability matrix for all states can be accessed usingtpattribute:>>>a.tp[[0.944444440.05555556][0.142857140.85714286]]There is alsoepattribute for the emission probability matrix for all states and observations.>>>a.ep[[0.210526320.210526320.473684210.10526316][0.571428570.0.0.42857143]]Converting the emission matrix to Pandas DataFrame:>>>importpandasaspd>>>pd.DataFrame(a.ep,index=a.states,columns=a.observations)ACGT00.2105260.2105260.4736840.10526310.5714290.0000000.0000000.428571Directed graph of the hidden Markov model:Graph can be visualized usinggraph_makemethod ofHiddenMarkovModelobject:>>>graph=a.graph_make(format="png",graph_attr=[("rankdir","LR"),("ranksep","1"),("rank","same")])>>>graph.render()Viterbi algorithmRunning Viterbi algorithm on new observations.>>>new_obs="GGCATTGGGCTATAAGAGGAGCTTG">>>vs,vsi=a.viterbi(new_obs)>>># states sequence>>>print("VI","".join(vs))>>># observations>>>print("NO",new_obs)VI 0000000001111100000000000
NO GGCATTGGGCTATAAGAGGAGCTTGBaum-Welch algorithmUsing Baum-Welch algorithm to infer the parameters of a Hidden Markov model:>>>obs_seq='AGACTGCATATATAAGGGGCAGGCTG'>>>a=hmm.HiddenMarkovModel().from_baum_welch(obs_seq,states=['0','1'])>>># training log: KL divergence values for all iterations>>>a.log{
  'tp': [0.008646969455670256, 0.0012397829805491124, 0.0003950986109761759],
  'ep': [0.09078874423746826, 0.0022734816599056084, 0.0010118204023946836],
  'pi': [0.009030829793043593, 0.016658391248503462, 0.0038894983546756065]
}The inferred transition (tp), emission (ep) probability matrices and
initial state distribution (pi) can be accessed as shown:>>>a.ep,a.tp,a.piThis model can be decoded using Viterbi algorithm:>>>new_obs="GGCATTGGGCTATAAGAGGAGCTTG">>>vs,vsi=a.viterbi(new_obs)>>>print("VI","".join(vs))>>>print("NO",new_obs)VI 0011100001111100000001100
NO GGCATTGGGCTATAAGAGGAGCTTG