({{, (RefLink[HiddenMarkovProcess, paclet:ref/HiddenMarkovProcess])[(Subscript[i, 0]),m,em] 
represents a discrete-time, finite-state hidden Markov process with transition matrix m, emission matrix em, and initial hidden state (Subscript[i, 0]).}, {, (RefLink[HiddenMarkovProcess, paclet:ref/HiddenMarkovProcess])[…,m,{(Subscript[dist, 1]),…}]
represents a hidden Markov process with emission distributions (Subscript[dist, i]).}, {, (RefLink[HiddenMarkovProcess, paclet:ref/HiddenMarkovProcess])[(Subscript[p, 0]),m,…]
represents a hidden Markov process with initial hidden state probability vector (Subscript[p, 0]).}})

OpenersNotesSection(Spacer1)Details

(RefLink[HiddenMarkovProcess, paclet:ref/HiddenMarkovProcess]) is also known as a hidden Markov model or HMM.

(RefLink[HiddenMarkovProcess, paclet:ref/HiddenMarkovProcess]) is a discrete-time and discrete-state random process.

A hidden Markov process has (RefLink[DiscreteMarkovProcess, paclet:ref/DiscreteMarkovProcess])[(Subscript[p, 0]),m] as an underlying hidden state transition process. The values observed from a hidden Markov process, called emissions, are random and follow emission distributions (Subscript[dist, i]) at state i. Emissions produced while visiting a given sequence of states are independent.

The hidden states of (RefLink[HiddenMarkovProcess, paclet:ref/HiddenMarkovProcess]) are integers between 1 and n, where n is the length of the transition matrix m.

The transition matrix m specifies conditional hidden state transition probabilities m[[i,j]]==(RefLink[Probability, paclet:ref/Probability])[x[k+1]==j\[Conditioned]x[k]==i], where x[k] is the hidden state of the process at time k.

The emission matrix em specifies the probabilities for emissions at a given hidden state em[[i,r]]==(RefLink[Probability, paclet:ref/Probability])[y[k]==r\[Conditioned]x[k]==i], where x[k] is the hidden state and y[k] is the emission at time k.

The emission distributions (Subscript[dist, i]) must be all univariate or all multivariate, all discrete or all continuous.

The emission distribution (Subscript[dist, i]) specifies that y[k]\[Distributed](Subscript[dist, i]), given that x[k]==i.

A silent state that produces no emissions is represented by a row of zeros in the case of an emission matrix or by (RefLink[None, paclet:ref/None]) for general emissions. Each silent state must have a path to an emitting state.

For a hidden Markov process proc with silent states, (RefLink[HiddenMarkovProcess, paclet:ref/HiddenMarkovProcess])[proc] gives the effective process with silent states removed.

(RefLink[EstimatedProcess, paclet:ref/EstimatedProcess])[data,HiddenMarkovProcess[n,edist]] can be used to estimate an n state process with emission distributions in the family specified by edist.

The following special edist templates can be used:

(RefLink[EstimatedProcess, paclet:ref/EstimatedProcess]) accepts the following settings for (RefLink[ProcessEstimator, paclet:ref/ProcessEstimator]):

The methods "BaumWelch", "ViterbiTraining", and "StateClustering" do not require specifying the hidden state path in the estimation, whereas "SupervisedTraining" relies on having access to the hidden state path data.

Functions that work on data such as (RefLink[LogLikelihood, paclet:ref/LogLikelihood]) accept (RefLink[Missing, paclet:ref/Missing]) values.

(RefLink[RandomFunction, paclet:ref/RandomFunction])[HiddenMarkovProcess[…]] gives only emissions by default. With (RefLink[Method, paclet:ref/Method])->{"IncludeHiddenStates"->(RefLink[True, paclet:ref/True])}, it gives a (RefLink[TemporalData, paclet:ref/TemporalData]) object td with the state sequence included as metadata. The hidden state data can be retrieved using td["HiddenStates"].

(RefLink[HiddenMarkovProcess, paclet:ref/HiddenMarkovProcess]) allows m to be an n×n matrix with non-negative elements and rows that sum to 1, em an n×s matrix with non-negative elements and rows that sum to 0 or 1, (Subscript[i, 0]) an integer between 1 and n, and (Subscript[p, 0]) a vector of length n of non-negative elements that sum to 1.

(RefLink[HiddenMarkovProcess, paclet:ref/HiddenMarkovProcess]) can be used with such functions as (RefLink[LogLikelihood, paclet:ref/LogLikelihood]), (RefLink[FindHiddenMarkovStates, paclet:ref/FindHiddenMarkovStates]), (RefLink[EstimatedProcess, paclet:ref/EstimatedProcess]), (RefLink[PDF, paclet:ref/PDF]), (RefLink[Probability, paclet:ref/Probability]), and (RefLink[RandomFunction, paclet:ref/RandomFunction]).

OpenersPrimaryExamplesSection(Spacer1)Examples  (42)

OpenersExampleSection0(Spacer1)Basic Examples  (2)

Define a hidden Markov process:

𝒫=HiddenMarkovProcess[{0.5,0.5},{{0.7,0.3},{0.25,0.75}},{{0.2,0.6,0.2},{0.4,0.2,0.4}}];

Simulate it:

data=RandomFunction[𝒫,{0,20}]

Visualize the emissions:

ListPlot[data,Filling->Axis,Ticks->{Automatic,{1,2,3}}]

Find the most likely hidden state sequence (Viterbi decode) from the given emissions:

𝒫=HiddenMarkovProcess[{0.5,0.5},{{0.7,0.3},{0.25,0.75}},{{0.2,0.6,0.2},{0.4,0.2,0.4}}];

FindHiddenMarkovStates[{1,1,1,1,1,2,3,3,1,2,2},𝒫]

OpenersExampleSection1(Spacer1)Scope  (17)

OpenersExampleSubsection0(Spacer1)Basic Usage  (8)

Define a hidden Markov process with discrete emissions:

hmm=HiddenMarkovProcess[{0.3,0.7},{{0.5,0.5},{0.3,0.7}},{GeometricDistribution[1/2],GeometricDistribution[1/4]}];

Generate a sample path:

RandomFunction[hmm,{0,10}]

Define a hidden Markov process with continuous emissions:

hmm=HiddenMarkovProcess[{0.3,0.7},{{0.5,0.5},{0.3,0.7}},{NormalDistribution[-1,1],NormalDistribution[1,1]}];

Compute (RefLink[LogLikelihood, paclet:ref/LogLikelihood]) of a sequence of emissions:

LogLikelihood[hmm,{{-0.1,0.3,0.9,0.1}}]

Define a hidden Markov process with continuous multivariate emissions:

hmm=HiddenMarkovProcess[{0.3,0.7},{{0.5,0.5},{0.3,0.7}},{BinormalDistribution[{-1,1},{2,3},1/2],BinormalDistribution[{1,-1},{3,2},-1/2]}];

Plot the probability density function of emission at time t==2:

Plot3D[PDF[hmm[2],{x,y}],{x,-7,7},{y,-7,7}]

Define a hidden Markov process with silent states and discrete emissions:

tm=SparseArray[{{1,2}->0.2,{1,3}->0.8,{2,3}->0.8,{2,4}->0.1,{2,2}->0.1,{3,2}->0.3,{3,4}->0.7,{4,2}->0.9,{4,5}->0.1,{5,5}->1.},{5,5}];

Use (RefLink[None, paclet:ref/None]) or a zero vector to denote silent states:

hmm=HiddenMarkovProcess[1,tm,{None,{0.4,0.6,0},{0,0,0},None,{0,0,1}}];

Find the most likely sequence of hidden states from the given emissions:

FindHiddenMarkovStates[{1,2,1,2,2,1,3},hmm]

Highlight emitting states:

%/.{es:(2|5):>Framed[es,Background->Yellow]}

Find the effective hidden Markov process with silent states eliminated:

HiddenMarkovProcess[hmm]

Define a hidden Markov process with silent states and continuous emissions:

tm={{0,1/2,1/2},{1/4,1/4,1/2},{1/2,1/4,1/4}};

Use (RefLink[None, paclet:ref/None]) to denote silent states:

hmm=HiddenMarkovProcess[{1/3,1/3,1/3},tm,{None,NormalDistribution[-2,1],NormalDistribution[2,1]}];

Find the mean of the process:

Mean[hmm[t]]//Simplify

Find the effective hidden Markov process with silent states eliminated:

HiddenMarkovProcess[hmm]

Estimate a hidden Markov process from data:

data=TemporalData[];

{Min[data],Max[data]}

Specify a two-state process with three possible emission values:

𝒫=EstimatedProcess[data,HiddenMarkovProcess[2,3]]

Compute the covariance of a process:

proc=HiddenMarkovProcess[{0.3,0.7},{{0.95,0.05},{0.1,0.9}},{NormalDistribution[-0.1,0.03],NormalDistribution[0.4,0.05]}];

DiscretePlot3D[CovarianceFunction[proc,s,t]//Evaluate,{s,0,10},{t,0,10},ExtentSize->1/2,ColorFunction->"Rainbow"]

Use a (RefLink[Graph, paclet:ref/Graph]) annotated by (RefLink[Property, paclet:ref/Property]) to define (RefLink[HiddenMarkovProcess, paclet:ref/HiddenMarkovProcess]):

v1=Property[ℬ,{"p0"->1,"EmissionData"->None}];
v2=Property[(Subscript[G, 1]),{"p0"->0,"EmissionData"->{0.4,0.6,0}}];
v3=Property[(Subscript[𝒟, 1]),{"p0"->0,"EmissionData"->None}];
v4=Property[(Subscript[𝒟, 2]),{"p0"->0,"EmissionData"->None}];
v5=Property[ℰ,{"p0"->0,"EmissionData"->{0,0,1}}];

gr2=Graph[{v1,v2,v3,v4,v5},{Property[ℬ\[DirectedEdge](Subscript[G, 1]),"Probability"->0.2],Property[ℬ\[DirectedEdge](Subscript[𝒟, 1]),"Probability"->0.8],Property[(Subscript[G, 1])\[DirectedEdge](Subscript[𝒟, 1]),"Probability"->0.8],Property[(Subscript[G, 1])\[DirectedEdge](Subscript[𝒟, 2]),"Probability"->0.1],Property[(Subscript[G, 1])\[DirectedEdge](Subscript[G, 1]),"Probability"->0.1],Property[(Subscript[𝒟, 1])\[DirectedEdge](Subscript[G, 1]),"Probability"->0.3],Property[(Subscript[𝒟, 1])\[DirectedEdge](Subscript[𝒟, 2]),"Probability"->0.7],Property[(Subscript[𝒟, 2])\[DirectedEdge](Subscript[G, 1]),"Probability"->0.9],Property[(Subscript[𝒟, 2])\[DirectedEdge]ℰ,"Probability"->0.1],Property[ℰ\[DirectedEdge]ℰ,"Probability"->1.0]}]

hmm=HiddenMarkovProcess[Table[PropertyValue[{gr2,v},"p0"],{v,VertexList[gr2]}],
WeightedAdjacencyMatrix[gr2,EdgeWeight->"Probability"]//Normal,Table[PropertyValue[{gr2,v},"EmissionData"],{v,VertexList[gr2]}]]

Compute effective HMM with only emitting underlying states:

HiddenMarkovProcess[hmm]

OpenersExampleSubsection1(Spacer1)Estimation  (5)

Estimate a two-state process with normally distributed emissions:

data=TemporalData[];

Overlay the histograms for the 100 paths:

Histogram[data,Automatic,"PDF"]

Use the template form to specify the class of process to estimate:

class=HiddenMarkovProcess[2,"Gaussian"];

EstimatedProcess[data,class]

Estimate a two-state model with exponential emissions:

data=TemporalData[];

class=HiddenMarkovProcess[2,ExponentialDistribution[λ]];

Provide a starting value for the process estimate:

sv𝒫=HiddenMarkovProcess[{1/4,3/4},{{0.2,0.8},{0.7,0.3}},{ExponentialDistribution[2],ExponentialDistribution[3]}];

Estimate the process using sv𝒫 as an initial model:

EstimatedProcess[data,class,sv𝒫]

Specify different estimation methods:

data=TemporalData[];

class=HiddenMarkovProcess[2,"Gaussian"];

"BaumWelch" is the default estimator that iteratively maximizes the likelihood of given emissions:

𝒫1=EstimatedProcess[data,class,ProcessEstimator->"BaumWelch"];//AbsoluteTiming

"ViterbiTraining" is an iterative estimator that maximizes the joint likelihood of given emissions and their unknown underlying states:

𝒫2=EstimatedProcess[data,class,ProcessEstimator->"ViterbiTraining"];//AbsoluteTiming

"StateClustering" is commonly used to make a fast heuristic non-iterative estimate:

𝒫3=EstimatedProcess[data,class,ProcessEstimator->"StateClustering"];//AbsoluteTiming

Compare log-likelihoods of estimated processes:

Table[LogLikelihood[pr,data],{pr,{𝒫1,𝒫2,𝒫3}}]

"SupervisedTraining" is an estimator that maximizes the joint likelihood of given emissions and given states:

proc=HiddenMarkovProcess[{0.3,0.7},{{0.95,0.05},{0.1,0.9}},{{0.9,0.1},{0.5,0.5}}];

ems={{1,1,1,1,2,2,2,1,2,2},{2,2,2,1,1,1,2,1,1,1},{1,2,1,2,2,2,1,2,1,2},{2,1,1,1,2,1,1,1,2,1},{1,1,1,1,2,2,1,2,1,2},{2,2,2,1,1,2,1,2,1,2},{1,1,1,1,1,1,1,2,2,2}};

states={{2,2,2,2,2,2,2,2,2,2},{2,2,2,2,2,2,2,2,2,2},{2,2,2,2,2,2,2,2,2,2},{2,2,2,2,2,2,2,2,2,1},{2,2,1,1,1,1,1,2,2,2},{2,2,2,2,2,2,2,2,1,1},{1,1,1,1,1,2,2,2,2,2}};

Use the template form to specify the class of process to estimate:

class=HiddenMarkovProcess[2,2];

Use the "StateData" suboption to specify data about underlying states for given emissions:

ps=EstimatedProcess[ems,class,ProcessEstimator->{"SupervisedTraining","StateData"->states}]

Estimate a three-state model with two emissions and a silent state:

data=TemporalData[];

{Min[data],Max[data]}

Estimate the model using a starting value process:

sv𝒫=HiddenMarkovProcess[{0.5,0.3,0.2},{{1/4,0,3/4},{0,1/3,2/3},{1/4,1/3,5/12}},{{3/4,1/4},{0,0},{1/3,2/3}}];

e𝒫1=EstimatedProcess[data,HiddenMarkovProcess[3,2],sv𝒫]

If no initial process is given, specify which states are silent in the template:

e𝒫2=EstimatedProcess[data,HiddenMarkovProcess[3,2,{2}]]

Compare log-likelihoods of resulting processes:

LogLikelihood[#,data]&/@{e𝒫1,e𝒫2}

OpenersExampleSubsection2(Spacer1)Process Slice Properties  (4)

Find the (RefLink[PDF, paclet:ref/PDF]) of the emission distribution at a fixed time:

𝒫=HiddenMarkovProcess[1,{{0,1/2,1/2},{1/2,0,1/2},{1/2,1/2,0}},{BernoulliDistribution[1/4],BernoulliDistribution[2/3],BernoulliDistribution[1/2]}];

PDF[𝒫[2],e]

Compute the mean and the covariance for symbolic times for multivariate emissions:

𝒫=HiddenMarkovProcess[{2/5,3/5},{{1/2,1/2},{2/5,3/5}},{BinormalDistribution[1/3],BinormalDistribution[2/3]}];

Mean[𝒫[t]]

Covariance[𝒫[t]]//FullSimplify

Sample emissions of the hidden Markov process at specified times:

hmm=HiddenMarkovProcess[{0.5,0.5},{{0.9,0.1},{0.1,0.9}},{{0.5,0.5},{0.8,0.2}}];

ems16=RandomVariate[hmm[{1,6}],10^4];

Visualize frequencies and compare to theoretical results:

Histogram3D[ems16,Automatic,"Probability"]

Table[{{e1,e6},Probability[x[1]==e1&&x[6]==e6,x\[Distributed]hmm]},{e1,{1,2}},{e6,{1,2}}]

Find stationary distribution of emissions following a hidden Markov process:

hmm=HiddenMarkovProcess[{0.5,0.5},{{0.7,0.3},{0.25,0.75}},{{0.2,0.6,0.2},{0.4,0.2,0.4}}];

Probability[e[Infinity]==k,e\[Distributed]hmm]

OpenersExampleSection2(Spacer1)Generalizations & Extensions  (1)

Specify that (RefLink[RandomFunction, paclet:ref/RandomFunction]) should include the hidden state path:

𝒫=HiddenMarkovProcess[{0.3,0.7},{{0.95,0.05},{0.1,0.9}},{ExponentialDistribution[2],ErlangDistribution[2,3]}];

data=RandomFunction[𝒫,{0,50},Method->{Automatic,"IncludeHiddenStates"->True}]

The hidden states are stored as metadata in the produced (RefLink[TemporalData, paclet:ref/TemporalData]) object:

data["HiddenStates"]

Visualize the state path:

ListPlot[data["HiddenStates"],Ticks->{Automatic,{1,2}},Filling->Axis]

OpenersExampleSection3(Spacer1)Applications  (11)

OpenersExampleSubsection3(Spacer1)Games  (3)

An occasionally dishonest casino offers a coin betting game and uses an unfair practice of using a biased coin for which the head is three times more likely than the tail. The casino dealer is known to secretly switch between the fair and biased coins with probability 10%:

{fair,biased}={1,2};
tm=SparseArray[{{fair,fair}->9/10,{fair,biased}->1/10,{biased,fair}->1/10,{biased,biased}->9/10}];

The probabilities of getting heads or tails:

fairCoin={1/2,1/2};
biasedCoin={3/4,1/4};

The resulting hidden Markov process, assuming equal probabilities of starting with either coin:

UnfairCasinoHMM=HiddenMarkovProcess[{1/2,1/2},tm,{fairCoin,biasedCoin}];
FairCasinoHMM=HiddenMarkovProcess[1,{{1}},{fairCoin}];

The probability of getting a head, given that the previous roll was a head:

NProbability[x[1]==1\[Conditioned]x[0]==1,x\[Distributed]UnfairCasinoHMM]

NProbability[x[1]==1\[Conditioned]x[0]==1,x\[Distributed]FairCasinoHMM]

If you intend to play six games, compute the probability that at least three tails will be tossed:

AtLeastK[k_,v_]:=BooleanCountingFunction[{k,Length[v]},Length[v]]@@v

NProbability[AtLeastK[3,Table[o[t]==2,{t,0,5}]],o\[Distributed]UnfairCasinoHMM]

The probability if the casino is fair at all times:

NProbability[AtLeastK[3,Table[o[t]==2,{t,0,5}]],o\[Distributed]FairCasinoHMM]

Given a sequence of tosses, guess on which occasions the dealer used the biased coin:

tosses=RandomFunction[UnfairCasinoHMM,{0,100}]

probableCoinTypes=FindHiddenMarkovStates[tosses,UnfairCasinoHMM];

ListPlot[probableCoinTypes,Ticks->{Automatic,{{1,"Fair"},{2,"Biased"}}},AxesOrigin->{0,0}]

There are three urns, each containing a large number of balls colored red, blue, and green:

{urn1,urn2,urn3}={1,2,3};
{red,blue,green}={1,2,3};

Each time a person randomly selects an urn, selects a ball, announces the color, and returns the ball to one of the urns. The process is repeated four times. The probabilities of moving to the next urn are as follows:

tm=SparseArray[{{urn3,urn3}->1,{{urn2,urn2},{urn2,urn3}}->{0.8,0.2},{{urn1,urn1},{urn1,urn2},{urn1,urn3}}->{0.5,0.3,0.2}}];

The probabilities of picking a certain color from each urn correspond to the fraction of different balls for each urn:

em={{0.3,0.5,0.2},{0.4,0.4,0.2},{0.6,0.3,0.1}};

Construct the hidden Markov process for the given probabilities of choosing the first urn:

hmm=HiddenMarkovProcess[{0.9,0.1,0},tm,em];

The probability of getting the color sequence {red,blue,green,green}:

Likelihood[hmm,{red,blue,green,green}]

Given the color sequence, find the most likely sequence of urns that were picked:

FindHiddenMarkovStates[{red,blue,green,green},hmm]

In a first-person shooter game, an agent is hiding inside a level and waiting to jump out at the player. The agent cannot see the player but can hear what they are doing and can then match that against its knowledge of the layout to estimate the player’s position. Consider a layout with 27 regions of four types—grass, metal grates, water, and door portals:

grass=Alternatives[1,2,4,5,11,12,13,14,15,16,17,18,19,20];
metal=Alternatives[3,6,21,22,24,25];
water=Alternatives[7,8,9,10];
door=Alternatives[23,26,27];

Assign colors to the different types of regions:

colors=Transpose[{{grass,Green},{metal,Gray},{water,Blue},{door,Brown}}];

Walking on the different terrain types produces different kinds of noises:

{none,footsteps,splashing,creaking,unclear}=Range[5];

Probabilities of giving out noises depends on the terrain type:

em=SparseArray[{
{{grass,none},{grass,unclear}}->{0.9,0.1},
{{metal,none},{metal,footsteps}}->{0.1,0.9},
{{water,splashing},{water,unclear}}->{0.9,0.1},
{{door,creaking},{door,unclear}}->{0.9,0.1}},{27,5}];

Visualize the layout of the level:

edges={27\[UndirectedEdge]1,1\[UndirectedEdge]2,2\[UndirectedEdge]3,3\[UndirectedEdge]4,3\[UndirectedEdge]7,4\[UndirectedEdge]5,5\[UndirectedEdge]25,25\[UndirectedEdge]24,24\[UndirectedEdge]22,22\[UndirectedEdge]21,21\[UndirectedEdge]23,21\[UndirectedEdge]20,20\[UndirectedEdge]19,19\[UndirectedEdge]18,18\[UndirectedEdge]17,17\[UndirectedEdge]7,17\[UndirectedEdge]8,18\[UndirectedEdge]9,19\[UndirectedEdge]10,10\[UndirectedEdge]9,9\[UndirectedEdge]8,8\[UndirectedEdge]7,10\[UndirectedEdge]26,10\[UndirectedEdge]14,9\[UndirectedEdge]14,8\[UndirectedEdge]13,8\[UndirectedEdge]12,14\[UndirectedEdge]15,15\[UndirectedEdge]16,14\[UndirectedEdge]13,13\[UndirectedEdge]12,13\[UndirectedEdge]11,12\[UndirectedEdge]11,11\[UndirectedEdge]6,6\[UndirectedEdge]1};

regions=Range[27]/.MapThread[vert:#1:>Style[vert,#2]&,colors];

gr=Graph[regions,edges,VertexSize->Large,VertexLabels->Placed["Name",Above],VertexShapeFunction->"Square"]

Assume the player enters through one of the doors with equal probability:

p0=SparseArray[{door->1/Length[door]},27];

The player remains in their current region with probability 10%, and otherwise is equally likely to move to any of the neighboring regions, giving the following transition probability matrix:

adjm=AdjacencyMatrix[gr];
tm=0.9adjm/Total[adjm,{2}]+0.1 IdentityMatrix[27];

hmm=HiddenMarkovProcess[p0,tm,em];

The agent hears the following sequence of noises:

obs={creaking,none,footsteps,none,none,splashing,splashing,footsteps,splashing};

This shows that most likely the player entered through the door marked 27 and is currently in region 7:

FindHiddenMarkovStates[obs,hmm]/.MapThread[v:#1:>Framed[v,FrameStyle->#2]&,colors]

OpenersExampleSubsection4(Spacer1)Genetics  (3)

A DNA sequence consists of letters A, C, G, and T. Subsequences, called nucleotide sequences, are characterized by the frequency with which different letters occur. One important task is to split the sequences into their different nucleotide subsequences. Suppose you are given a sequence that begins in an exon, contains a 5' splice site, and ends in an intron. If the exons have a uniform base composition, the introns are deficient in C and G, and the splice site consensus nucleotide is a G with probability 0.95, the nucleotide frequency distributions are the following:

exon={0.25,0.25,0.25,0.25};
intron={0.4,0.1,0.1,0.4};splice={0.05,0,0.95,0};

dnaSeq=Characters["CTTCATGTGAAAGCAGACGTAAGTCA"]/.{"A"->1,"C"->2,"G"->3,"T"->4}

The state machine has states for exon (1), splice (2), intron (3), and end (4), with the following transition probabilities between states:

tm={{0.9,0.1,0,0},{0,0,1,0},{0,0,0.9,0.1},{0,0,0,1}};

The emissions are nucleotides A (1), C (2), G (3), T (4), or end (5):

em=PadRight[{exon,splice,intron,UnitVector[5,5]}];

hmm=HiddenMarkovProcess[1,tm,em];

Find the most probable current nucleotide sequence (exon, splice, intron, or end):

sites=FindHiddenMarkovStates[Append[dnaSeq,5],hmm]

The joint probability of the above nucleotide sequence and the DNA sequence:

Fold[Times,Likelihood[DiscreteMarkovProcess[hmm],sites],MapThread[Part[em,#1,#2]&,{sites,Append[dnaSeq,5]}]]

Model breast cancer risk transmitted via a damaged allele B of the BRCA1 gene, with each parent contributing one of their alleles with probability 1/2 for each allele:

states={"BB","bB","bb"};

If the mother has a functional allele pair "bb", the probabilities of their son having each allele combination are:

sm={{0,1,0},{0,(1/2),(1/2)},{0,0,1}};

The emission probabilities for the son are the same as for the father, since they are both male. The emission is 1 for cancer and 2 for no cancer:

em={{0.2,0.8},{0.2,0.8},{0,1}};

Suppose you know the priors for the father:

p0={0.3,0.3,0.4};

hmm=HiddenMarkovProcess[p0,sm,em];

Find the probability of both the father and the son developing breast cancer:

cancer=1;
Probability[health[0]==cancer&&health[1]==cancer,health\[Distributed]hmm]

Two genes of a diploid plant are being investigated, having the following alleles:

alleles={{"a","A"},{"b","B"}};

There are nine distinct genotypes:

genotypes=gene@@@Tuples[Select[Tuples[{#,#}],OrderedQ]&/@alleles]

The plant is self-pollinating, i.e. the genotype of its offspring depends on the genotype of the parent only:

offspring[g_]:=Tuples[Map[Sort,Tuples[{#,#}]]&/@g]

Frequencies[data_]:=Block[{fr=Tally[data]},fr[[All,2]]/=Total[fr[[All,2]]];fr]

Graph of genotype transitions between generations that encodes transition probabilities:

gr=Graph[genotypes,Property[#1,"Probability"->#2]&@@@Join@@Table[Frequencies[DirectedEdge[gi,#]&/@offspring[gi]],{gi,genotypes}],VertexLabels->Placed["Name",Tooltip]]

Model generational genotype changes using (RefLink[DiscreteMarkovProcess, paclet:ref/DiscreteMarkovProcess]):

gene𝒫=DiscreteMarkovProcess[Normalize[Table[1,{VertexCount[gr]}],Total],WeightedAdjacencyMatrix[gr,EdgeWeight->"Probability"]];

Alleles control the plant's phenotypes, i.e. visible features. Assuming complete dominance of capital letter alleles over respective lowercase letter alleles:

toTrait[{___,"A",___}]:="purple"
toTrait[{"a","a"}]:="white"
toTrait[{___,"B",___}]:="tall"
toTrait[{"b","b"}]:="short"

toTrait[gene[p1_,p2_]]:=traits[toTrait[p1],toTrait[p2]]

The genotypes control four distinct phenotypes:

ind=Union[phenotypes=toTrait/@genotypes];
ind=Thread[ind->Range[Length[ind]]]

The plant's phenotypes (indexed by an integer) are modeled by a hidden Markov process:

hmm=HiddenMarkovProcess[gene𝒫,SparseArray[Table[{VertexIndex[gr,gi],toTrait[gi]/.ind}->1,{gi,genotypes}]]];

Simulate Mendel's observations, which he collected for 2734 plants over four generations:

data=RandomFunction[hmm,{0,3},2734]

Estimate genotype transition probabilities from these observations:

class=HiddenMarkovProcess[Length[genotypes],Length[ind]]

estPr=EstimatedProcess[data,class,hmm]

LogLikelihood[estPr,data]

OpenersExampleSubsection5(Spacer1)Linguistics  (1)

Classify the characters from sample text into vowels and consonants using a two-state HMM:

text=ExampleData[{"Text","DeclarationOfIndependence"}];

chars=Append[CharacterRange["a","z"]," "];

data=Cases[ToLowerCase[Flatten[Characters[text]]],Alternatives@@chars]/.Thread[chars->Range[27]];

Find the best parameter estimate:

proc=EstimatedProcess[data,HiddenMarkovProcess[2,27],PrecisionGoal->MachinePrecision,AccuracyGoal->MachinePrecision];

For each character, pick the state with highest probability from the emission matrix:

ArrayPlot[em=Last[proc]]

res={chars,Cases[Transpose[em],{pv_,pc_}:>If[pv≥pc,"vowel","consonant"]]}//Transpose;

GroupBy[res,Extract[2]->Extract[1]]

OpenersExampleSubsection6(Spacer1)Weather  (2)

Tree ring sizes are well correlated with average annual temperatures. Using two temperature states (hot and cold) and three tree ring sizes (small, medium, and large), and given a four-year sequence of tree ring sizes {s,m,s,l}, estimate the average annual temperature for those years. The transition probabilities for temperature switching:

{hot,cold}={1,2};

sm=SparseArray[{{{hot,hot},{hot,cold}}->{0.7,0.3},{{cold,hot},{cold,cold}}->{0.4,0.6}}];

The emission probabilities:

{s,m,l}={1,2,3};

em=SparseArray[{{{hot,s},{hot,m},{hot,l}}->{0.1,0.4,0.5},
{{cold,s},{cold,m},{cold,l}}->{0.7,0.2,0.1}}];

The hidden Markov process model for tree ring sizes:

hmm=HiddenMarkovProcess[{0.6,0.4},sm,em];

Find the most likely temperature sequence for the specific tree ring observations:

Part[{"hot","cold"},FindHiddenMarkovStates[{s,m,s,l},hmm]]

Find the sequence of the most likely individual temperatures:

Part[{"hot","cold"},FindHiddenMarkovStates[{s,m,s,l},hmm,"PosteriorDecoding"]]

Suppose you are locked in a room and your only clue as to the weather outside is whether or not the person bringing you your meals has an umbrella. The weather could be in one of three states—sunny, rainy, or foggy—with the following transition probabilities:

{sunny,rainy,foggy}={1,2,3};
tm=SparseArray[{{{sunny,sunny},{sunny,rainy},{sunny,foggy}}->{0.8,0.05,0.15},{{rainy,sunny},{rainy,rainy},{rainy,foggy}}->{0.2,0.6,0.2},
{{foggy,sunny},{foggy,rainy},{foggy,foggy}}->{0.2,0.3,0.5}}];

The probabilities of carrying an umbrella depending on the weather:

{umbrella,noumbrella}={1,2};
em=SparseArray[{
{{sunny,umbrella},{sunny,noumbrella}}->{0.1,0.9},{{rainy,umbrella},{rainy,noumbrella}}->{0.8,0.2},{{foggy,umbrella},{foggy,noumbrella}}->{0.3,0.7}}];

Model presence of umbrella by a hidden Markov process:

hmm=HiddenMarkovProcess[foggy,tm,em];

Inferences of the weather outside based on the pattern of clues:

clueHistory={noumbrella,umbrella,noumbrella,noumbrella,noumbrella,umbrella,noumbrella};

The most likely weather pattern:

Part[{"sunny","rainy","foggy"},FindHiddenMarkovStates[clueHistory,hmm,"ViterbiDecoding"]]

The sequence of most likely conditions on each day:

Part[{"sunny","rainy","foggy"},FindHiddenMarkovStates[clueHistory,hmm,"PosteriorDecoding"]]

OpenersExampleSubsection7(Spacer1)Other  (2)

A production process is in either in a good state or a poor state. When in a good state it remains so with probability 90%, and once it goes into a poor state it remains in that state forever:

{good,poor}={1,2};
tm=SparseArray[{{{good,good},{good,poor}}->{0.9,0.1},{poor,poor}->1}];

When in a good state, the product quality is acceptable with probability 99%, and when in a poor state, the probability of acceptable quality product is 96%:

{accept,unaccept}={1,2};
em=SparseArray[{{{good,accept},{good,unaccept}}->{0.99,0.01},{{poor,accept},{poor,unaccept}}->{0.96,0.04}}];

If the process starts in a good state with probability 80% and the first item was acceptable, find the probability of the next two produced items being of acceptable quality:

p0=SparseArray[{good->0.8,poor->0.2}];
hmm=HiddenMarkovProcess[p0,tm,em];

Probability[x[2]==1&&x[1]==1\[Conditioned]x[0]==1,x\[Distributed]hmm]

Consider a two-bit register with four possible states: 00, 01, 10, and 11. The register is initially in one of these four states with equal probabilities:

ind[{0,0}]=1;ind[{0,1}]=2;ind[{1,0}]=3;ind[{1,1}]=4;

p0={1/4,1/4,1/4,1/4};

At each time step, the register is randomly manipulated. The register is left unchanged with probability 1/2, the two bits of the register are exchanged with probability 1/4, and the right bit is flipped with probability 1/4:

tm=Table[0,{4},{4}];
Do[tm[[ind[r],ind[r]]]+=1/2;
tm[[ind[r],ind[Reverse[r]]]]+=1/4;tm[[ind[r],ind[MapAt[1-#&,r,2]]]]+=1/4,{r,{{0,0},{0,1},{1,0},{1,1}}}];

After the register has been manipulated in this fashion, the left bit is observed:

em=Table[0,{4},{2}];
Do[em[[ind[r],First[r]+1]]+=1,{r,{{0,0},{0,1},{1,0},{1,1}}}];

hmm=HiddenMarkovProcess[p0,tm,em];

Given the first three observations to be 0, 0, and 1, find the most likely sequence of states:

Part[{"00","01","10","11"},FindHiddenMarkovStates[{0,0,1}+1,hmm]]

OpenersExampleSection4(Spacer1)Properties & Relations  (6)

(RefLink[SliceDistribution, paclet:ref/SliceDistribution]) of (RefLink[HiddenMarkovProcess, paclet:ref/HiddenMarkovProcess]) with discrete emissions evaluates to an empirical (RefLink[DataDistribution, paclet:ref/DataDistribution]):

hmm=HiddenMarkovProcess[{1/3,2/3},{{1/4,3/4},{3/5,2/5}},{{1/2,1/2},{3/7,4/7}}];

Find distribution of emissions at time t==2:

SliceDistribution[hmm,2]

Find the (RefLink[PDF, paclet:ref/PDF]) of the joint distribution of emissions at times t==2 and t==6:

PDF[SliceDistribution[hmm,{2,6}],{e2,e6}]//Expand

Emissions of (RefLink[HiddenMarkovProcess, paclet:ref/HiddenMarkovProcess]) with exponential emissions at any single time follow (RefLink[HyperexponentialDistribution, paclet:ref/HyperexponentialDistribution]):

hmm=HiddenMarkovProcess[{1/3,2/3},{{1/4,3/4},{3/5,2/5}},{ExponentialDistribution[(Subscript[λ, 1])],ExponentialDistribution[(Subscript[λ, 2])]}];

sdist=SliceDistribution[hmm,t]//Simplify

Emissions of (RefLink[HiddenMarkovProcess, paclet:ref/HiddenMarkovProcess]) with generic emission distributions evaluate to (RefLink[MixtureDistribution, paclet:ref/MixtureDistribution]):

hmm=HiddenMarkovProcess[{1/3,2/3},{{1/4,3/4},{3/5,2/5}},{NormalDistribution[m1,s1],NormalDistribution[m2,s2]}];

SliceDistribution[hmm,2]

An HMM with the identity as the emission matrix is equivalent to a discrete Markov process:

𝒫=HiddenMarkovProcess[{1/2,1/2},{{2/3,1/3},{1/4,3/4}},{{1,0},{0,1}}];

PDF[𝒫[t],x]//Simplify

PDF[DiscreteMarkovProcess[𝒫][t],x]//Simplify

(RefLink[HiddenMarkovProcess, paclet:ref/HiddenMarkovProcess]) is defined up to relabeling of hidden states:

p0={0.3,0.7};
tm={{0.8,0.2},{0.4,0.6}};
em={{0.4,0.6},{0.7,0.3}};

hmm1=HiddenMarkovProcess[p0,tm,em];

perm={2,1};

hmm2=HiddenMarkovProcess[p0[[perm]],tm[[perm,perm]],em[[perm]]];

Likelihoods of short emission sequences are the same for both processes:

emseq=Array[Tuples[{1,2},#]&,6,1,Join];

Table[Likelihood[hmm1,obs],{obs,emseq}]==Table[Likelihood[hmm2,obs],{obs,emseq}]

Different hidden Markov models with silent states may assign identical likelihoods for all sequence emissions:

hmm1=HiddenMarkovProcess[{(1/2),(1/3),(1/6)},{{(1/3),(1/3),(1/3)},{(1/4),(1/2),(1/4)},{(1/5),(1/5),(3/5)}},{{(1/2),(1/2)},{(1/4),(3/4)},None}];

hmm2=HiddenMarkovProcess[{(7/12),(5/12),0},{{(1/4),(1/4),(1/2)},{(3/8),(5/8),0},{(1/5),(1/5),(3/5)}},{{(1/2),(1/2)},{(1/4),(3/4)},None}];

Verify that their effective hidden Markov processes are the same:

HiddenMarkovProcess[hmm1]

HiddenMarkovProcess[hmm2]==%

Check that likelihoods of all short emissions sequences in both models are the same:

emissions=Array[Tuples[{1,2},#]&,5,1,Join];

Table[Likelihood[hmm1,p],{p,emissions}]==Table[Likelihood[hmm2,p],{p,emissions}]

OpenersExampleSection5(Spacer1)Possible Issues  (5)

The emission distributions must all have the same dimensionality:

hmm=HiddenMarkovProcess[{0.3,0.7},{{0.5,0.5},{0.3,0.7}},{NormalDistribution[],BinormalDistribution[1/4]}];

ProcessParameterQ[hmm]

The emission distributions must be either all discrete or all continuous:

hmm=HiddenMarkovProcess[{0.8,0.2},{{0.6,0.4},{0.45,0.55}},{NormalDistribution[],BinomialDistribution[4,1/4]}];

ProcessParameterQ[hmm]

The set of emitting states must be reachable from every silent state, i.e. no recurrent class may be entirely silent:

hmm=HiddenMarkovProcess[{0.5,0.5},{{0.75,0.25},{0,1}},{NormalDistribution[],None}];

ProcessParameterQ[hmm]

Modifying the transition probabilities makes the emitting state 1 accessible from silent state 2:

hmm=HiddenMarkovProcess[{0.5,0.5},{{0.75,0.25},{0.01,0.99}},{NormalDistribution[],None}];

ProcessParameterQ[hmm]

If the rows of the transition matrix do not sum to 1, they are automatically normalized:

HiddenMarkovProcess[1,{{1,2},{4,3}},{NormalDistribution[-0.1,0.3],NormalDistribution[0.4,0.1]}]

If the initial probabilities do not sum to 1, they are normalized:

HiddenMarkovProcess[{1,2},{{1/2,1/2},{2/3,1/3}},{UniformDistribution[],BetaDistribution[2,3]}]

({{DocumentationFooterIconsRelatedFunction.png, ({{See Also}, {(RefLink[DiscreteMarkovProcess, paclet:ref/DiscreteMarkovProcess])  ▪  (RefLink[FindHiddenMarkovStates, paclet:ref/FindHiddenMarkovStates])  ▪  (RefLink[EstimatedProcess, paclet:ref/EstimatedProcess])  ▪  (RefLink[LogLikelihood, paclet:ref/LogLikelihood])}})}})

({{DocumentationFooterIconsRelatedGuide.png, ({{Related Guides}, {▪(RefLinkPlain[Finite Markov Processes, paclet:guide/MarkovProcesses])}, {▪(RefLinkPlain[Scientific Models, paclet:guide/ScientificModels])}})}})