= c("hot", "cold")
hidden_states
= length(hidden_states)
N
# transition matrix of hidden states
= rbind(
A c(0.7, 0.3),
c(0.4, 0.6)
)
# initial distribution of hidden state
= c(0.571, 0.429)
pi_0
= c("small", "medium", "large")
observed_states
= length(observed_states)
M
# emission matrix: hidden -> observed
= rbind(
B c(0.1, 0.4, 0.5),
c(0.7, 0.2, 0.1)
)
Hidden Markov Models
Simulating HMM
= 100
T
# Note: +1's below because first entries represent initial time 0
= rep(NA, T + 1)
X = rep(NA, T + 1)
O
# initial state
1] = sample(1:N, 1, prob = pi_0)
X[1] = sample(1:M, 1, prob = B[X[1], ])
O[
for (t in 1:T) {
# simulate current hidden state, given previous hidden state
+ 1] = sample(1:N, 1, prob = A[X[t], ])
X[t
# simulate current observed state, given current hidden state
+ 1] = sample(1:M, 1, prob = B[X[t + 1], ])
O[t
}
data.frame(t = 0:T, X_t = hidden_states[X], O_t = observed_states[O]) |>
head(10) |> kbl() |> kable_styling()
t | X_t | O_t |
---|---|---|
0 | hot | large |
1 | hot | large |
2 | hot | large |
3 | hot | large |
4 | hot | large |
5 | cold | large |
6 | cold | medium |
7 | hot | medium |
8 | hot | medium |
9 | hot | small |
plot(0:T, X, type = "o", xlab = "t", ylab = "X_t", col = "blue",
main = "Hidden states (1 = hot, 2 = cold)")
plot(0:T, O, type = "o", xlab = "t", ylab = "O_t", col = "orange",
main = "Observed states (1 = small, 2 = medium, 3 = large)")
Stationary/Marginal at single time
# hidden states
= compute_stationary_distribution(A)
pi_sd
pi_sd
[,1] [,2]
[1,] 0.5714286 0.4285714
# observed states
%*% B pi_sd
[,1] [,2] [,3]
[1,] 0.3571429 0.3142857 0.3285714
HMM package
library(HMM)
# Initialise HMM
= initHMM(States = hidden_states,
hmm Symbols = observed_states,
transProbs = A,
emissionProbs = B,
startProbs = pi_sd)
hmm
$States
[1] "hot" "cold"
$Symbols
[1] "small" "medium" "large"
$startProbs
hot cold
0.5714286 0.4285714
$transProbs
to
from hot cold
hot 0.7 0.3
cold 0.4 0.6
$emissionProbs
symbols
states small medium large
hot 0.1 0.4 0.5
cold 0.7 0.2 0.1
HMM package simulation
simHMM(hmm, 10)
$states
[1] "hot" "cold" "hot" "cold" "hot" "cold" "cold" "cold" "cold" "hot"
$observation
[1] "medium" "small" "large" "small" "medium" "small" "small" "small"
[9] "small" "medium"
Likelihood of observations
# Sequence of observations
= c("small", "medium")
observations
= forward(hmm, observations)
log_forward_probability
= exp(log_forward_probability)
forward_probability
forward_probability
index
states 1 2
hot 0.05714286 0.06400000
cold 0.30000000 0.03942857
colSums(forward_probability)
1 2
0.3571429 0.1034286
# Sequence of observations
= simHMM(hmm, 10)$observation
observations observations
[1] "large" "large" "medium" "small" "medium" "small" "large" "medium"
[9] "small" "medium"
= forward(hmm, observations)
log_forward_probability
= exp(log_forward_probability)
forward_probability
forward_probability
index
states 1 2 3 4 5 6
hot 0.28571429 0.10857143 0.032182857 0.002566857 0.002327680 0.0002173669
cold 0.04285714 0.01114286 0.007851429 0.010056000 0.001360731 0.0010603200
index
states 7 8 9 10
hot 2.881424e-04 9.190230e-05 7.461376e-06 6.904504e-06
cold 7.014021e-05 2.570537e-05 3.009574e-05 4.059171e-06
colSums(forward_probability)
1 2 3 4 5 6
3.285714e-01 1.197143e-01 4.003429e-02 1.262286e-02 3.688411e-03 1.277687e-03
7 8 9 10
3.582826e-04 1.176077e-04 3.755711e-05 1.096367e-05
Decoding
= c("small", "medium")
observations
viterbi(hmm, observations)
[1] "cold" "hot"
# Sequence of observation
= simHMM(hmm, 100)$observation
observations
observations
[1] "large" "medium" "large" "medium" "small" "large" "large" "small"
[9] "small" "small" "medium" "medium" "large" "large" "small" "medium"
[17] "medium" "large" "medium" "small" "large" "medium" "medium" "small"
[25] "large" "small" "medium" "medium" "large" "large" "large" "small"
[33] "large" "small" "small" "small" "medium" "large" "large" "large"
[41] "large" "large" "medium" "large" "medium" "medium" "small" "small"
[49] "large" "small" "small" "medium" "large" "small" "medium" "small"
[57] "large" "medium" "medium" "large" "small" "medium" "medium" "large"
[65] "large" "medium" "large" "small" "small" "large" "small" "medium"
[73] "large" "small" "medium" "small" "medium" "medium" "medium" "medium"
[81] "small" "small" "small" "medium" "medium" "small" "small" "large"
[89] "large" "large" "medium" "small" "large" "small" "small" "medium"
[97] "small" "large" "medium" "large"
viterbi(hmm, observations)
[1] "hot" "hot" "hot" "hot" "cold" "hot" "hot" "cold" "cold" "cold"
[11] "hot" "hot" "hot" "hot" "cold" "hot" "hot" "hot" "hot" "cold"
[21] "hot" "hot" "hot" "cold" "hot" "cold" "hot" "hot" "hot" "hot"
[31] "hot" "cold" "hot" "cold" "cold" "cold" "hot" "hot" "hot" "hot"
[41] "hot" "hot" "hot" "hot" "hot" "hot" "cold" "cold" "hot" "cold"
[51] "cold" "hot" "hot" "cold" "cold" "cold" "hot" "hot" "hot" "hot"
[61] "cold" "hot" "hot" "hot" "hot" "hot" "hot" "cold" "cold" "hot"
[71] "cold" "hot" "hot" "cold" "cold" "cold" "hot" "hot" "hot" "hot"
[81] "cold" "cold" "cold" "hot" "hot" "cold" "cold" "hot" "hot" "hot"
[91] "hot" "cold" "hot" "cold" "cold" "cold" "cold" "hot" "hot" "hot"
Estimation
# Sequence of observation
= simHMM(hmm, 10000)$observation
observation
table(observation) / 10000
observation
large medium small
0.3205 0.3211 0.3584
# Baum-Welch
baumWelch(hmm, observation, maxIterations = 10)
$hmm
$hmm$States
[1] "hot" "cold"
$hmm$Symbols
[1] "small" "medium" "large"
$hmm$startProbs
hot cold
0.5714286 0.4285714
$hmm$transProbs
to
from hot cold
hot 0.6990122 0.3009878
cold 0.4018597 0.5981403
$hmm$emissionProbs
symbols
states small medium large
hot 0.09936791 0.4157953 0.4848368
cold 0.70413347 0.1947090 0.1011575
$difference
[1] 0.018781129 0.002290127 0.002154031 0.002030550 0.001917701 0.001813952
[7] 0.001718117 0.001629262 0.001546632 0.001469609
All or nothing
library(HMM)
= c("learning", "mastery")
hidden_states
= c("incorrect", "correct")
observed_states
= rbind(
A c(0.8, 0.2),
c(0.001, 0.999)
)
= rbind(
B c(0.5, 0.5),
c(0.1, 0.9)
)
= c(0.999, 0.001)
pi_0
# Initialise HMM
= initHMM(States = hidden_states,
hmm Symbols = observed_states,
transProbs = A,
emissionProbs = B,
startProbs = pi_0)
hmm
$States
[1] "learning" "mastery"
$Symbols
[1] "incorrect" "correct"
$startProbs
learning mastery
0.999 0.001
$transProbs
to
from learning mastery
learning 0.800 0.200
mastery 0.001 0.999
$emissionProbs
symbols
states incorrect correct
learning 0.5 0.5
mastery 0.1 0.9
simHMM(hmm, 10)
$states
[1] "learning" "learning" "mastery" "mastery" "mastery" "mastery"
[7] "mastery" "mastery" "mastery" "mastery"
$observation
[1] "correct" "correct" "correct" "correct" "correct" "correct" "correct"
[8] "correct" "correct" "correct"
# Sequence of observation
= simHMM(hmm, 100)$observation
observations
observations
[1] "incorrect" "correct" "correct" "correct" "correct" "correct"
[7] "correct" "correct" "correct" "correct" "correct" "correct"
[13] "correct" "correct" "correct" "correct" "correct" "correct"
[19] "correct" "incorrect" "correct" "correct" "correct" "correct"
[25] "correct" "correct" "correct" "incorrect" "correct" "correct"
[31] "correct" "correct" "correct" "correct" "correct" "correct"
[37] "correct" "correct" "correct" "correct" "correct" "correct"
[43] "correct" "correct" "correct" "incorrect" "correct" "correct"
[49] "correct" "correct" "correct" "correct" "correct" "correct"
[55] "correct" "correct" "correct" "correct" "correct" "correct"
[61] "correct" "correct" "correct" "correct" "correct" "correct"
[67] "correct" "correct" "correct" "correct" "correct" "incorrect"
[73] "correct" "incorrect" "correct" "correct" "incorrect" "correct"
[79] "incorrect" "correct" "correct" "correct" "correct" "incorrect"
[85] "incorrect" "correct" "correct" "incorrect" "incorrect" "incorrect"
[91] "correct" "correct" "correct" "correct" "correct" "correct"
[97] "correct" "correct" "correct" "correct"
viterbi(hmm, observations)
[1] "learning" "mastery" "mastery" "mastery" "mastery" "mastery"
[7] "mastery" "mastery" "mastery" "mastery" "mastery" "mastery"
[13] "mastery" "mastery" "mastery" "mastery" "mastery" "mastery"
[19] "mastery" "mastery" "mastery" "mastery" "mastery" "mastery"
[25] "mastery" "mastery" "mastery" "mastery" "mastery" "mastery"
[31] "mastery" "mastery" "mastery" "mastery" "mastery" "mastery"
[37] "mastery" "mastery" "mastery" "mastery" "mastery" "mastery"
[43] "mastery" "mastery" "mastery" "mastery" "mastery" "mastery"
[49] "mastery" "mastery" "mastery" "mastery" "mastery" "mastery"
[55] "mastery" "mastery" "mastery" "mastery" "mastery" "mastery"
[61] "mastery" "mastery" "mastery" "mastery" "mastery" "mastery"
[67] "mastery" "mastery" "mastery" "mastery" "mastery" "mastery"
[73] "mastery" "mastery" "mastery" "mastery" "mastery" "mastery"
[79] "mastery" "mastery" "mastery" "mastery" "mastery" "mastery"
[85] "mastery" "mastery" "mastery" "mastery" "mastery" "mastery"
[91] "mastery" "mastery" "mastery" "mastery" "mastery" "mastery"
[97] "mastery" "mastery" "mastery" "mastery"
# Sequence of observation
= simHMM(hmm, 10000)$observation
observation table(observation) / 10000
observation
correct incorrect
0.8988 0.1012
# Baum-Welch
baumWelch(hmm, observation, maxIterations = 10)
$hmm
$hmm$States
[1] "learning" "mastery"
$hmm$Symbols
[1] "incorrect" "correct"
$hmm$startProbs
learning mastery
0.999 0.001
$hmm$transProbs
to
from learning mastery
learning 0.895489932 0.1045101
mastery 0.001329809 0.9986702
$hmm$emissionProbs
symbols
states incorrect correct
learning 0.45947571 0.5405243
mastery 0.09629494 0.9037051
$difference
[1] 0.112359065 0.040630020 0.032319113 0.024353848 0.018073108 0.013406443
[7] 0.010007670 0.007541187 0.005744390 0.004425991