音声認識メモ(Kaldi)その22(アライメント)
decodeの過程を掘り下げてみる。
アライメントで出力される数値(インプットであるMFCC特徴量の各フレームに1対1で紐付けられる)は何を示しているか。
今回は、デコードシェル(egs/wsj/s5/steps/decode.sh)の内部でコールしているlattice生成コマンドのアウトプットを見てみる。
(追加オプションとして、「words-wspecifier」と「alignments-wspecifier」を指定)
gmm-latgen-faster \ --max-active=7000 \ --beam=13.0 \ --lattice-beam=6.0 \ --acoustic-scale=0.083333 \ --allow-partial=true \ --determinize-lattice=true \ --word-symbol-table=exp/mono/graph/words.txt \ exp/mono/final.mdl \ # model-in exp/mono/graph/HCLG.fst \ # fst-in ark:/tmp/utter_053.ark \ # features-rspecifier ark:/tmp/lat.ark \ # lattice-wspecifier ark:/tmp/word.ark \ # words-wspecifier ark:/tmp/ali.ark # alignments-wspecifier
インプット
音声(/tmp/utter_053.ark)
前回、検証用に使った、”禁煙席お願いします”という発話。
(フレーム数は「323」、識別子は"utterance_id_053"、39次元)
以下のコマンドで生成。
apply-cmvn \ --utt2spk=ark:data/test/split1/1/utt2spk \ scp:data/test/split1/1/cmvn.scp \ scp:data/test/split1/1/feats.scp \ ark:- | \ add-deltas \ ark:- \ ark:/tmp/hoge.ark
モデル
前回、作成したモノフォンのモデル(言語モデルは2-gramで作成)
exp/mono/graph/words.txt(抜粋)
<eps> 0 !SIL 1 <UNK> 2 あり 3 お 4 お願い 5 し 10 ます 23 席 45 禁煙 53 #0 62 <s> 63 </s> 64
exp/mono/graph/phones/align_lexicon.txt (抜粋)
<eps> <eps> sil 禁煙 禁煙 k_B i_I N_I e_I N_E 席 席 s_B e_I k_I i_E お願い お願い o_B n_I e_I g_I a_I i_E し し sh_B i_E ます ます m_B a_I s_I u_E
アウトプット
words(tmp/word.ark)
utterance_id_053 53 45 5 10 23
symbolに直すと、「禁煙(53) 席(45) お願い(5) し(10) ます(23)」
lattice (/tmp/lat.ark) ※説明用に一部加工
utterance_id_053 0 1 53 9.81125, 7750.02, 2_1_1_1_8_5_5_5_18_17_17_17_17_17_... 1 2 45 2.38995, 4952.66, 197_197_197_197_197_197_197_197_... 2 3 5 4.61863, 8155.52, 527_527_527_527_527_527_527_527_... 3 4 10 2.22007, 3096.31, 527_926_925_925_925_925_925_925_... 4 5 23 5.81478, 6656.75, 523_526_528_638_637_640_639_639_... 5 0, 0, 917_917_917_917_917_917_917_917_...
アライメント結果(/tmp/ali.ark)
utterance_id_053 2 1 1 1 8 5 5 5 18 17 17 17 17 17 17 17 17 17 17 ...
MFCC特徴量フレームと同数の「323」個ある
アライメントを音素に変換する。
ali-to-phones \ --write-lengths \ exp/mono/final.mdl \ ark:/tmp/ali.ark \ ark:/tmp/ali2phone.ark
アライメント結果(/tmp/ali2phone.ark) ※説明用に音素をsymbolに置き換え
utterance_id_053 sil 31 ; k_B 5 ; i_I 12 ; N_I 39 ; e_I 6 ; N_E 3 ; s_B 3 ; e_I 22 ; k_I 3 ; i_E 12 ; o_B 28 ; n_I 14 ; e_I 3 ; g_I 13 ; a_I 4 ; i_E 14 ; sh_B 28 ; i_E 5 ; m_B 38 ; a_I 14 ; s_I 21 ; u_E 5
symbolの後ろは出現数。例えば「sil 31」は"sil"が31回続いたことを示す
改めて今回のテーマ、アライメント時に出力されているものは何か。
「ali-to-phones」コマンドに渡しているインプットを見る限り、モデル(*.mdl)の情報から導出できる。
(アライメントから音素への変換だけなら、FSTのグラフは使わない)
モデル生成時のインプットとなる「phones.txt」の中身は全部で「171」個あり、
exp/mono/phones.txt
<eps> 0 sil 1 sil_B 2 sil_E 3 sil_I 4 sil_S 5 spn 6 spn_B 7 spn_E 8 spn_I 9 spn_S 10 N_B 11 N_E 12 N_I 13 N_S 14 a_B 15 a_E 16 a_I 17 a_S 18 ... z_E 164 z_I 165 z_S 166 #0 167 #1 168 #2 169 #3 170
この内、モデルの「TopologyEntry」として定義されるのは「166」個。
<ForPhones> 1 2 3 4 5 6 7 8 9 10 </ForPhones> <ForPhones> 11 12 13 14 15 16 17 18 ... 164 165 166 </ForPhones>
phone-idが1から10まで(silence phone)は「5」状態、11から166まで(non silence phone)は「3」状態となる。
3 state HMM
pdf-class数は「3」、遷移数は「6」
5 state HMM
pdf-class数は「5」、遷移数は「18」
音素数 x 状態の総数は「518」(5状態 x 10音素 + 3状態 x 156音素)
この「518」個の1つ1つにpdfを定義するわけではなく、似たような音素x状態はpdfを共有する。
状態間でpdfを共有し、pdfの総数は「127」になる。
<NUMPDFS> 127
状態遷移については、総数は「1116」になる(18遷移 x 10音素 + 6遷移 x 156音素)
(「LogProbs」エントリと同数)
<LogProbs> [ 0 -0.3281818 -1.378509 -4.027719 -4.60517 ... -1.386294 -0.2876821 -1.386294 ] </LogProbs>
アライメントで出力されているのは、状態遷移の識別子(transition-id)にあたる。
例えば、話し始め部分の「sil」については「2 1 1 1 8 5 5 5 18 17 17 17 17 17 17 17 17 17 17 ...」と並ぶ。
番号の振り方については、self-loopの遷移を後から追加するらしく、あるstateを見た時、self-loopの方がtransition-idが大きくなる。