音声認識メモ(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」

f:id:ichou1:20180729094226p:plain
f:id:ichou1:20180729095443p:plain

5 state HMM

pdf-class数は「5」、遷移数は「18」

f:id:ichou1:20180729094210p:plain

素数 x 状態の総数は「518」(5状態 x 10音素 + 3状態 x 156音素)
この「518」個の1つ1つにpdfを定義するわけではなく、似たような音素x状態はpdfを共有する。

f:id:ichou1:20180729100930p:plain

状態間で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が大きくなる。