Skip to content

Commit

Permalink
build based on 284189f
Browse files Browse the repository at this point in the history
  • Loading branch information
Documenter.jl committed Sep 30, 2024
1 parent f0082f1 commit fdd7a5e
Show file tree
Hide file tree
Showing 13 changed files with 55 additions and 55 deletions.
2 changes: 1 addition & 1 deletion dev/.documenter-siteinfo.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"documenter":{"julia_version":"1.10.5","generation_timestamp":"2024-09-29T19:05:07","documenter_version":"1.7.0"}}
{"documenter":{"julia_version":"1.10.5","generation_timestamp":"2024-09-30T07:55:59","documenter_version":"1.7.0"}}
2 changes: 1 addition & 1 deletion dev/alternatives/index.html

Large diffs are not rendered by default.

50 changes: 25 additions & 25 deletions dev/api/index.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dev/debugging/index.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dev/examples/autodiff/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,4 @@
Enzyme.Duplicated(obs_seq, ∇obs_enzyme),
Enzyme.Duplicated(control_seq, ∇control_enzyme),
Enzyme.Const(seq_ends),
)</code></pre><pre class="documenter-example-output"><code class="nohighlight hljs ansi">((nothing, nothing, nothing, nothing),)</code></pre><p>Once again we can check the results.</p><pre><code class="language-julia hljs">∇parameters_enzyme ≈ ∇parameters_forwarddiff</code></pre><pre class="documenter-example-output"><code class="nohighlight hljs ansi">true</code></pre><pre><code class="language-julia hljs">∇obs_enzyme ≈ ∇obs_forwarddiff</code></pre><pre class="documenter-example-output"><code class="nohighlight hljs ansi">true</code></pre><pre><code class="language-julia hljs">∇control_enzyme ≈ ∇control_forwarddiff</code></pre><pre class="documenter-example-output"><code class="nohighlight hljs ansi">true</code></pre><p>For increased efficiency, we could provide temporary storage to Enzyme.jl in order to avoid allocations. This requires going one level deeper and leveraging the in-place <a href="../../api/#HiddenMarkovModels.forward!"><code>HiddenMarkovModels.forward!</code></a> function.</p><h2 id="Gradient-methods"><a class="docs-heading-anchor" href="#Gradient-methods">Gradient methods</a><a id="Gradient-methods-1"></a><a class="docs-heading-anchor-permalink" href="#Gradient-methods" title="Permalink"></a></h2><p>Once we have gradients of the loglikelihood, it is a natural idea to perform gradient descent in order to fit the parameters of a custom HMM. However, there are two caveats we must keep in mind.</p><p>First, computing a gradient essentially requires running the forward-backward algorithm, which means it is expensive. Given the output of forward-backward, if there is a way to perform a more accurate parameter update (like going straight to the maximum likelihood value), it is probably worth it. That is what we show in the other tutorials with the reimplementation of the <code>fit!</code> method.</p><p>Second, HMM parameters live in a constrained space, which calls for a projected gradient descent. Most notably, the transition matrix must be stochastic, and the orthogonal projection onto this set (the Birkhoff polytope) is not easy to obtain.</p><p>Still, first order optimization can be relevant when we lack explicit formulas for maximum likelihood.</p><hr/><p><em>This page was generated using <a href="https://github.com/fredrikekre/Literate.jl">Literate.jl</a>.</em></p></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../controlled/">« Control dependency</a><a class="docs-footer-nextpage" href="../../api/">API reference »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Sunday 29 September 2024 19:05">Sunday 29 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
)</code></pre><pre class="documenter-example-output"><code class="nohighlight hljs ansi">((nothing, nothing, nothing, nothing),)</code></pre><p>Once again we can check the results.</p><pre><code class="language-julia hljs">∇parameters_enzyme ≈ ∇parameters_forwarddiff</code></pre><pre class="documenter-example-output"><code class="nohighlight hljs ansi">true</code></pre><pre><code class="language-julia hljs">∇obs_enzyme ≈ ∇obs_forwarddiff</code></pre><pre class="documenter-example-output"><code class="nohighlight hljs ansi">true</code></pre><pre><code class="language-julia hljs">∇control_enzyme ≈ ∇control_forwarddiff</code></pre><pre class="documenter-example-output"><code class="nohighlight hljs ansi">true</code></pre><p>For increased efficiency, we could provide temporary storage to Enzyme.jl in order to avoid allocations. This requires going one level deeper and leveraging the in-place <a href="../../api/#HiddenMarkovModels.forward!"><code>HiddenMarkovModels.forward!</code></a> function.</p><h2 id="Gradient-methods"><a class="docs-heading-anchor" href="#Gradient-methods">Gradient methods</a><a id="Gradient-methods-1"></a><a class="docs-heading-anchor-permalink" href="#Gradient-methods" title="Permalink"></a></h2><p>Once we have gradients of the loglikelihood, it is a natural idea to perform gradient descent in order to fit the parameters of a custom HMM. However, there are two caveats we must keep in mind.</p><p>First, computing a gradient essentially requires running the forward-backward algorithm, which means it is expensive. Given the output of forward-backward, if there is a way to perform a more accurate parameter update (like going straight to the maximum likelihood value), it is probably worth it. That is what we show in the other tutorials with the reimplementation of the <code>fit!</code> method.</p><p>Second, HMM parameters live in a constrained space, which calls for a projected gradient descent. Most notably, the transition matrix must be stochastic, and the orthogonal projection onto this set (the Birkhoff polytope) is not easy to obtain.</p><p>Still, first order optimization can be relevant when we lack explicit formulas for maximum likelihood.</p><hr/><p><em>This page was generated using <a href="https://github.com/fredrikekre/Literate.jl">Literate.jl</a>.</em></p></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../controlled/">« Control dependency</a><a class="docs-footer-nextpage" href="../../api/">API reference »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Monday 30 September 2024 07:55">Monday 30 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
18 changes: 9 additions & 9 deletions dev/examples/basics/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,22 +47,22 @@
[-0.256414, -0.563875] [-0.5, -0.8]
[0.652218, 0.841332] [0.5, 0.8]</code></pre><p>On the other hand, the initialization is concentrated on one state. This effect can be mitigated by learning from several independent sequences.</p><pre><code class="language-julia hljs">hcat(initialization(hmm_est), initialization(hmm))</code></pre><pre class="documenter-example-output"><code class="nohighlight hljs ansi">2×2 Matrix{Float64}:
1.91765e-19 0.6
1.0 0.4</code></pre><p>Since HMMs are not identifiable up to a permutation of the states, there is no guarantee that state <span>$i$</span> in the true model will correspond to state <span>$i$</span> in the estimated model. This is important to keep in mind when testing new models.</p><h2 id="Multiple-sequences"><a class="docs-heading-anchor" href="#Multiple-sequences">Multiple sequences</a><a id="Multiple-sequences-1"></a><a class="docs-heading-anchor-permalink" href="#Multiple-sequences" title="Permalink"></a></h2><p>In many applications, we have access to various observation sequences of different lengths.</p><pre><code class="language-julia hljs">nb_seqs = 300
1.0 0.4</code></pre><p>Since HMMs are not identifiable up to a permutation of the states, there is no guarantee that state <span>$i$</span> in the true model will correspond to state <span>$i$</span> in the estimated model. This is important to keep in mind when testing new models.</p><h2 id="Multiple-sequences"><a class="docs-heading-anchor" href="#Multiple-sequences">Multiple sequences</a><a id="Multiple-sequences-1"></a><a class="docs-heading-anchor-permalink" href="#Multiple-sequences" title="Permalink"></a></h2><p>In many applications, we have access to various observation sequences of different lengths.</p><pre><code class="language-julia hljs">nb_seqs = 1000
long_obs_seqs = [last(rand(rng, hmm, rand(rng, 100:200))) for k in 1:nb_seqs];
typeof(long_obs_seqs)</code></pre><pre class="documenter-example-output"><code class="nohighlight hljs ansi">Vector{Vector{Vector{Float64}}}<span class="sgr90"> (alias for Array{Array{Array{Float64, 1}, 1}, 1})</span></code></pre><p>Every algorithm in the package accepts multiple sequences in a concatenated form. The user must also specify where each sequence ends in the concatenated vector, by passing <code>seq_ends</code> as a keyword argument. Otherwise, the input will be treated as a unique observation sequence, which is mathematically incorrect.</p><pre><code class="language-julia hljs">long_obs_seq_concat = reduce(vcat, long_obs_seqs)
typeof(long_obs_seq_concat)</code></pre><pre class="documenter-example-output"><code class="nohighlight hljs ansi">Vector{Vector{Float64}}<span class="sgr90"> (alias for Array{Array{Float64, 1}, 1})</span></code></pre><pre><code class="language-julia hljs">seq_ends = cumsum(length.(long_obs_seqs))
seq_ends&#39;</code></pre><pre class="documenter-example-output"><code class="nohighlight hljs ansi">300 adjoint(::Vector{Int64}) with eltype Int64:
174 279 388 539 737 894 1007 … 44408 44557 44737 44855 45032</code></pre><p>The outputs of inference algorithms are then concatenated, and the associated loglikelihoods are split by sequence (in a vector of size <code>length(seq_ends)</code>).</p><pre><code class="language-julia hljs">best_state_seq_concat, best_joint_loglikelihood_concat = viterbi(
seq_ends&#39;</code></pre><pre class="documenter-example-output"><code class="nohighlight hljs ansi">1000 adjoint(::Vector{Int64}) with eltype Int64:
174 279 388 539 737 894 1007 1161 … 148712 148826 148945 149138</code></pre><p>The outputs of inference algorithms are then concatenated, and the associated loglikelihoods are split by sequence (in a vector of size <code>length(seq_ends)</code>).</p><pre><code class="language-julia hljs">best_state_seq_concat, best_joint_loglikelihood_concat = viterbi(
hmm, long_obs_seq_concat; seq_ends
);</code></pre><pre><code class="language-julia hljs">length(best_joint_loglikelihood_concat) == length(seq_ends)</code></pre><pre class="documenter-example-output"><code class="nohighlight hljs ansi">true</code></pre><pre><code class="language-julia hljs">length(best_state_seq_concat) == last(seq_ends)</code></pre><pre class="documenter-example-output"><code class="nohighlight hljs ansi">true</code></pre><p>The function <a href="../../api/#HiddenMarkovModels.seq_limits"><code>seq_limits</code></a> returns the begin and end of a given sequence in the concatenated vector. It can be used to untangle the results.</p><pre><code class="language-julia hljs">start2, stop2 = seq_limits(seq_ends, 2)</code></pre><pre class="documenter-example-output"><code class="nohighlight hljs ansi">(175, 279)</code></pre><pre><code class="language-julia hljs">best_state_seq_concat[start2:stop2] == first(viterbi(hmm, long_obs_seqs[2]))</code></pre><pre class="documenter-example-output"><code class="nohighlight hljs ansi">true</code></pre><p>While inference algorithms can also be run separately on each sequence without changing the results, considering multiple sequences together is nontrivial for Baum-Welch. That is why the package takes care of it automatically.</p><pre><code class="language-julia hljs">hmm_est_concat, _ = baum_welch(hmm_guess, long_obs_seq_concat; seq_ends);</code></pre><p>Our estimate should be a little better.</p><pre><code class="language-julia hljs">cat(transition_matrix(hmm_est_concat), transition_matrix(hmm); dims=3)</code></pre><pre class="documenter-example-output"><code class="nohighlight hljs ansi">2×2×2 Array{Float64, 3}:
[:, :, 1] =
0.69677 0.30323
0.207515 0.792485
0.700421 0.299579
0.203473 0.796527

[:, :, 2] =
0.7 0.3
0.2 0.8</code></pre><pre><code class="language-julia hljs">map(mean, hcat(obs_distributions(hmm_est_concat), obs_distributions(hmm)))</code></pre><pre class="documenter-example-output"><code class="nohighlight hljs ansi">2×2 Matrix{Vector{Float64}}:
[-0.503771, -0.796337] [-0.5, -0.8]
[0.509728, 0.805274] [0.5, 0.8]</code></pre><pre><code class="language-julia hljs">hcat(initialization(hmm_est_concat), initialization(hmm))</code></pre><pre class="documenter-example-output"><code class="nohighlight hljs ansi">2×2 Matrix{Float64}:
0.629082 0.6
0.370918 0.4</code></pre><hr/><p><em>This page was generated using <a href="https://github.com/fredrikekre/Literate.jl">Literate.jl</a>.</em></p></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../../">« Home</a><a class="docs-footer-nextpage" href="../types/">Types »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Sunday 29 September 2024 19:05">Sunday 29 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
[-0.502073, -0.800874] [-0.5, -0.8]
[0.504019, 0.801399] [0.5, 0.8]</code></pre><pre><code class="language-julia hljs">hcat(initialization(hmm_est_concat), initialization(hmm))</code></pre><pre class="documenter-example-output"><code class="nohighlight hljs ansi">2×2 Matrix{Float64}:
0.605645 0.6
0.394355 0.4</code></pre><hr/><p><em>This page was generated using <a href="https://github.com/fredrikekre/Literate.jl">Literate.jl</a>.</em></p></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../../">« Home</a><a class="docs-footer-nextpage" href="../types/">Types »</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Monday 30 September 2024 07:55">Monday 30 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
Loading

0 comments on commit fdd7a5e

Please sign in to comment.