<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Viterbi on M1KE BL0G</title><link>https://www.m1ke.org/tags/viterbi/</link><description>Recent content in Viterbi on M1KE BL0G</description><generator>Hugo -- gohugo.io</generator><language>ja-jp</language><copyright>mike</copyright><lastBuildDate>Tue, 08 Sep 2026 13:00:00 +0900</lastBuildDate><atom:link href="https://www.m1ke.org/tags/viterbi/index.xml" rel="self" type="application/rss+xml"/><item><title>ビタビアルゴリズム</title><link>https://www.m1ke.org/p/%E3%83%93%E3%82%BF%E3%83%93%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0/</link><pubDate>Tue, 08 Sep 2026 13:00:00 +0900</pubDate><guid>https://www.m1ke.org/p/%E3%83%93%E3%82%BF%E3%83%93%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0/</guid><description>&lt;img src="https://www.m1ke.org/p/%E3%83%93%E3%82%BF%E3%83%93%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0/Viterbi_algorithm.png" alt="Featured image of post ビタビアルゴリズム" /&gt;&lt;h2 id="背景"&gt;背景&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;「pyopenjtalkの仕組み」という記事で、MeCabの形態素解析に使われているビタビアルゴリズムに触れた&lt;/li&gt;
&lt;li&gt;ここでは、ビタビアルゴリズムそのものを掘り下げて整理する&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ビタビアルゴリズムの起源"&gt;ビタビアルゴリズムの起源&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Andrew J. Viterbiが1967年に発表した論文&lt;code&gt;Error bounds for convolutional codes and an asymptotically optimum decoding algorithm&lt;/code&gt;（&lt;code&gt;IEEE Transactions on Information Theory&lt;/code&gt;, vol. 13, pp. 260-269）が出典&lt;/li&gt;
&lt;li&gt;元々は、通信における畳み込み符号の復号のために考案されたアルゴリズム&lt;/li&gt;
&lt;li&gt;その後、隠れマルコフモデル（HMM）のデコーディング、音声認識、そしてMeCabのような形態素解析まで、幅広い分野に応用されるようになった&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="マルコフ連鎖と隠れマルコフモデル"&gt;マルコフ連鎖と隠れマルコフモデル&lt;/h2&gt;
&lt;p&gt;ビタビアルゴリズムの背景には、マルコフ連鎖と隠れマルコフモデル（HMM）という考え方がある。&lt;/p&gt;
&lt;h3 id="マルコフ連鎖markov-chain"&gt;マルコフ連鎖（Markov Chain）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;ある時点の状態が、直前の状態だけに依存し、それ以前の履歴には依存しないという性質（マルコフ性）を持つ確率過程&lt;/li&gt;
&lt;li&gt;状態の集合と、状態間の遷移確率によって定義される&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="隠れマルコフモデルhmm"&gt;隠れマルコフモデル（HMM）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;マルコフ連鎖に従って遷移する状態の系列が、直接には観測できない（隠れている）というモデル&lt;/li&gt;
&lt;li&gt;代わりに、各状態から確率的に出力される観測値だけが観測できる&lt;/li&gt;
&lt;li&gt;HMMは、以下の3つの要素で定義される
&lt;ul&gt;
&lt;li&gt;初期状態確率（Initial probabilities, $\pi$）: 最初にどの状態から始まるかの確率分布&lt;/li&gt;
&lt;li&gt;状態遷移確率行列（Transition matrix, $A$）: ある状態から別の状態へ遷移する確率&lt;/li&gt;
&lt;li&gt;出力確率（Emission probabilities, $B$）: ある状態にいるときに、特定の観測値が出力される確率&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;MeCabの形態素解析に当てはめると、品詞や単語といった裏の系列（状態）が直接には観測できず、実際に書かれた表層文字列（観測値）だけが見えている、という構造に対応する&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ブルートフォース法との比較"&gt;ブルートフォース法との比較&lt;/h2&gt;
&lt;p&gt;観測系列$O$が与えられたとき、それを生み出した可能性が最も高い状態系列$Q$を求める問題を、デコーディング問題と呼ぶ。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;最も素朴な解法は、あり得る全ての状態系列を列挙し、それぞれの尤度を計算して比較するブルートフォース法（総当たり法）&lt;/li&gt;
&lt;li&gt;状態数を$N$、系列の長さを$T$とすると、あり得る状態系列の数は$N^T$通りになり、系列が長くなるほど組み合わせが指数的に爆発する&lt;/li&gt;
&lt;li&gt;例えば$N=10$、$T=20$でも$10^{20}$通りという非現実的な数になり、実用上は計算できない&lt;/li&gt;
&lt;li&gt;ビタビアルゴリズムは、この組み合わせ爆発を避けながら、ブルートフォース法と同じ最適解を多項式時間で求める方法&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="動的計画法としてのビタビアルゴリズム"&gt;動的計画法としてのビタビアルゴリズム&lt;/h2&gt;
&lt;p&gt;ビタビアルゴリズムの核心は、「未来を全部見る」のではなく「ここまでで一番いい過去だけを持って進む」という考え方。これは動的計画法（Dynamic Programming, DP）の典型例になる。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ある地点に複数の経路で到達できる場合、そこから先の話には、その地点までの累積コストが最小の経路だけが関係する&lt;/li&gt;
&lt;li&gt;つまり、同じ地点に到達した経路のうち、負けている経路はその時点で切り捨ててよい&lt;/li&gt;
&lt;li&gt;全ての分割パターンを総当たりする代わりに、各地点で最良の経路だけを覚えておくことで、計算量を大きく減らせる&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="mecabでの具体例"&gt;MeCabでの具体例&lt;/h2&gt;
&lt;p&gt;MeCabの形態素解析を例に、ビタビアルゴリズムの動きを追ってみる。&lt;/p&gt;
&lt;p&gt;例えば「東京都」という文があったとき、辞書から複数の分割候補が出てくる。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;「東京」＋「都」&lt;/li&gt;
&lt;li&gt;「東」＋「京都」&lt;/li&gt;
&lt;li&gt;「東京都」&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;MeCabはまず、文の各位置から始まる単語候補を全て並べて、ラティスと呼ばれる網目状のグラフを作る。ラティスの各ノードには、以下2種類のコストが割り当てられる。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;単語そのもののコスト（辞書に登録された、その単語らしさを表すコスト）&lt;/li&gt;
&lt;li&gt;直前の単語との接続コスト（品詞の並びとしての自然さを表すコスト）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;イメージとして、以下のようなラティスができる。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;BOS
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├─ 東京 (100)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ └─ 都 (+50)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├─ 東 (200)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ └─ 京都 (+300)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └─ 東京都 (80)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; EOS
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;ビタビアルゴリズムは、文の先頭（BOS）から順番に、各ノードまでの最小累積コストを計算していく。&lt;/p&gt;
$$
C(v) = \min_{u} \{ C(u) + \mathrm{connectionCost}(u,v) + \mathrm{wordCost}(v) \}
$$&lt;p&gt;$C(v)$はノード$v$までの最小累積コスト、$u$は$v$の直前になりうる各ノード。重要なのは、同じ地点に複数の経路で到達したとき、一番安かった経路だけを覚えておけばよいという点。&lt;/p&gt;
&lt;p&gt;上の例で言えば、以下のようになる。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;「東京」→「都」: 累積コスト150&lt;/li&gt;
&lt;li&gt;「東」→「京都」: 累積コスト500&lt;/li&gt;
&lt;li&gt;「東京都」: 累積コスト80&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;このうち「東京都」1語だけの経路が最も安いため、これが採用される。文末（EOS）まで計算した後、EOSから「どのノードから来たか」を逆向きに辿る（バックトラック）ことで、最適な形態素列が得られる。&lt;/p&gt;
&lt;p&gt;MeCabの処理の流れをまとめると、以下のようになる。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;辞書から形態素候補を出す&lt;/li&gt;
&lt;li&gt;ラティスを作る&lt;/li&gt;
&lt;li&gt;各ノードについて最小累積コストを計算する&lt;/li&gt;
&lt;li&gt;各ノードについて、最良の直前ノードを記録する&lt;/li&gt;
&lt;li&gt;文末から先頭へバックトラックする&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="hmmにおける一般的な定式化"&gt;HMMにおける一般的な定式化&lt;/h2&gt;
&lt;p&gt;MeCabのラティスでの定式化は、コストの最小化という形だったが、隠れマルコフモデル（HMM）の文脈では、前述の初期状態確率$\pi$・遷移確率行列$A$・出力確率$B$を使った確率の最大化という形で、同じアルゴリズムが使われる。&lt;/p&gt;
&lt;p&gt;まず、時刻1（最初の観測）における各状態の確率は、初期状態確率と出力確率から以下のように求まる。&lt;/p&gt;
$$
\delta_1(j) = \pi_j \cdot b_j(o_1)
$$&lt;p&gt;時刻$t$、状態$j$における最良経路の確率$\delta_t(j)$は、以下の漸化式で計算できる。&lt;/p&gt;
$$
\delta_t(j) = \max_{i} \left[ \delta_{t-1}(i) \cdot a_{ij} \right] \cdot b_j(o_t)
$$&lt;p&gt;$a_{ij}$は遷移確率行列$A$の要素（状態$i$から状態$j$への遷移確率）、$b_j(o_t)$は出力確率$B$の要素（状態$j$で観測値$o_t$が出力される確率）。MeCabのコスト最小化は、確率の対数を取って符号を反転させたもの（負の対数尤度）とみなせば、この確率最大化の定式化と本質的に同じ計算になる。ブルートフォース法が全ての状態系列について愚直に尤度を計算するのに対し、この漸化式は各時刻・各状態について直前までの最良値だけを使い回すことで、同じ最適解を効率的に求めている。&lt;/p&gt;
&lt;h2 id="計算量のメリット"&gt;計算量のメリット&lt;/h2&gt;
&lt;p&gt;文の長さが$n$、各位置での候補数を$k$とすると、全ての分割パターンを総当たりで比較する場合、組み合わせの数は指数的に増えていく。一方ビタビアルゴリズムでは、各地点で最良の経路だけを保持しながら進むため、計算量は文の長さと候補数にほぼ比例する程度に収まる。全探索を避けながら、最終的には全体最適な経路を見つけられるというのが、動的計画法としてのビタビアルゴリズムの強み。&lt;/p&gt;
&lt;h2 id="まとめ"&gt;まとめ&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;ビタビアルゴリズムは、1967年にAndrew Viterbiが畳み込み符号の復号のために考案した動的計画法&lt;/li&gt;
&lt;li&gt;背景には、初期状態確率$\pi$・遷移確率行列$A$・出力確率$B$で定義される隠れマルコフモデル（HMM）がある&lt;/li&gt;
&lt;li&gt;素朴なブルートフォース法では状態数$N$・系列長$T$に対し$N^T$通りの組み合わせを比較する必要があるが、「ここまでの最良の経路だけを残しながら進む」ことで、同じ最適解を効率的に求められる&lt;/li&gt;
&lt;li&gt;MeCabの形態素解析では、単語コストと接続コストの和を最小化する経路探索として使われている&lt;/li&gt;
&lt;li&gt;HMMの文脈では、確率の最大化という形で同じアルゴリズムが使われ、コスト最小化と数学的に対応している&lt;/li&gt;
&lt;li&gt;音声認識・通信・形態素解析など、系列の背後にある最適な経路を求める問題に広く応用されている&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考文献"&gt;参考文献&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Viterbi, A.J. (1967). &amp;ldquo;Error bounds for convolutional codes and an asymptotically optimum decoding algorithm.&amp;rdquo; IEEE Transactions on Information Theory, Vol. 13, pp. 260-269.&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://cs.rice.edu/~ogilvie/comp571/viterbi-algorithm/" target="_blank" rel="noopener"
&gt;Viterbi algorithm - Species and Gene Evolution&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>