ichou1のブログ

主に音声認識、時々、データ分析のことを書く

音声認識メモ(Kaldi)その5(学習 その2)

前回の続き。

学習用グラフを作成したら、アライメントを作成する。
初期モデルに対しては「bin/align-equal-compiled」コマンドを使用する。

bin/align-equal-compiled ark:fsts.0 ark:mosimosi.ark ark:equal.align.0

均等分割アライメントの出力結果は以下のとおり。
インプットとして渡したMFCCファイルの198フレームがtransition-idに置き換わる。
尚、右側のコロン以降は説明用に付加したもの。

均等分割アライメント(加工)
utterance_id_001
  2   1   1   1   1   1		:sil(state0)                 
  8   5   5   5   5   5		:sil(state1)                    
 18  17  17  17  17  17		:sil(state4)              
206 205 205 205 205 205		:M_B(state0)        
208 207 207 207 207 207		:M_B(state1)        
210 209 209 209 209 209		:M_B(state2)        
242 241 241 241 241 241		:O_I(state0)        
244 243 243 243 243 243		:O_I(state1)        
246 245 245 245 245 245		:O_I(state2)        
266 265 265 265 265 265		:S_I(state0)        
268 267 267 267 267 267		:S_I(state1)        
270 269 269 269 269 269		:S_I(state2)        
194 193 193 193 193 193		:I_I(state0)        
196 195 195 195 195    		:I_I(state1) 
198 197 197 197 197    		:I_I(state2) 
218 217 217 217 217    		:M_I(state0)
220 219 219 219 219    		:M_I(state1)
222 221 221 221 221    		:M_I(state2)
242 241 241 241 241    		:O_I(state0)
244 243 243 243 243    		:O_I(state1)
246 245 245 245 245    		:O_I(state2)
266 265 265 265 265    		:S_I(state0)
268 267 267 267 267    		:S_I(state1)
270 269 269 269 269    		:S_I(state2)
188 187 187 187 187    		:I_E(state0)
190 189 189 189 189    		:I_E(state1)
192 191 191 191 191    		:I_E(state2)
  2   1   1   1   1    		:sil(state0)
  6   5   5   5   5    		:sil(state1)
 11  10  10  10  10    		:sil(state2)
 13  15  15  15  15    		:sil(state3)
  7   5   5   5   5    		:sil(state1)
 14  15  15  15  15    		:sil(state3)
 11  10  10  10  10    		:sil(state2)
 14  15  15  15  15    		:sil(state3)
 12  10  10  10  10    		:sil(state2)
 18  17  17  17  17    		:sil(state4)  

状態遷移(PATH)は、学習用グラフをもとに生成される。

(gdb) p path
$25 = std::vector of length 49, capacity 64 = {0, 35, 1, 40, 33, 34, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 47, 28, 50, 29, 54, 30, 56, 28, 51, 30, 57, 29, 54, 30, 57, 29, 55, 31, 32}

数値はFSTにおけるState-Id

    // First select path through ifst.
    vector<StateId> path;

結果はランダムになると思ったが、10回やっても同じ。
ソースを見たら、kaldi::RandIntの呼び出しで第3引数を渡していない。

fstext/fstext-utils-inl.h
size_t arc_offset = static_cast<size_t>(kaldi::RandInt(0, num_arcs_tot-1));

省略時のデフォルトはNULLだから、Rand()のインプットは同じ値(初期値)が使われ、実行結果は同じになる。

base/kaldi-math.h
// Returns a random integer between first and last inclusive.
int32 RandInt(int32 first, int32 last, struct RandomState* state = NULL);
base/kaldi-math.cc
int32 RandInt(int32 min_val, int32 max_val, struct RandomState* state) {

均等分割アライメントができたら、これを元に統計量を求める。

gmmbin/gmm-acc-stats-ali 0.mdl ark:mosimosi.ark ark:equal.align.0 0.acc

統計量の出力フォーマットは以下の通り。
最初のカッコ内は、transition-idごとのカウント、その後ろはpdf-id(phone、HMM-stateで識別できるようにしたもの)に関するもので、専有数(OCCUPANCY)などが分かる。

 [ 0 9 2 0 0 13 1 1 1 0 12 2 1 1 2 12 0 9 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 1 4 1 4 1 5 1 4 1 4 1 0 0 0 0 0 0 5 1 5 1 5 1 0 0 0 0 0 0 4 1 4 1 4 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9 2 9 2 9 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 9 2 9 2 9 2 0 0 0 0 0 0 ]
<NUMPDFS> 98
<GMMACCS> <VECSIZE> 13 <NUMCOMPONENTS> 1 <FLAGS> 15 <OCCUPANCY>  [ 11 ]
<MEANACCS>  [
  583.025 -77.64178 -50.17585 77.67705 1.827717 -98.23819 141.6106 68.02332 -25.67511 138.0809 -28.37501 51.49424 -60.51704 ]
<DIAGVARACCS>  [
  31450.12 980.6454 1569.188 971.1459 888.6505 4001.74 2254.043 769.4111 1730.576 2365.113 1063.856 679.8729 789.1522 ]
</GMMACCS>
(途中省略、残りのPDF-ID 97個分が続く)
<total_like> -678789.2 <total_frames> 198 

続けて学習を行う。

gmmbin/gmm-est --min-gaussian-occupancy=3 0.mdl 0.acc 1.mdl

学習用サンプルが少ないので、オプションを追加している。
これを付けないと、出現数の少ないpdf-idに関するモデルが更新されない。
一部のモデルが初期値のままだと、後続のアライメントに失敗する。

 --min-gaussian-occupancy    : MleDiagGmmOptions: Minimum occupancy to update a Gaussian.(float, default = 10)

続けてアライメントを行う。

gmmbin/gmm-align-compiled 1.mdl ark:fsts.0 ark:mosimosi.ark ark:1.ali

続けて統計量を作成し、学習する。これはインプットが変わっただけで、前項でやっていることと同じ。

gmmbin/gmm-acc-stats-ali 1.mdl ark:mosimosi.ark ark:1.ali 1.acc
gmmbin/gmm-est --min-gaussian-occupancy=3 1.mdl 1.acc 2.mdl
(参考)1.acc
 [ 0 8 2 0 0 8 1 0 1 0 24 1 1 0 1 12 0 5 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 1 4 1 6 1 5 1 4 1 5 1 0 0 0 0 0 0 3 1 7 1 5 1 0 0 0 0 0 0 3 1 4 1 4 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 2 6 2 14 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 2 4 2 17 2 0 0 0 0 0 0 ]
<NUMPDFS> 98 

<GMMACCS> <VECSIZE> 13 <NUMCOMPONENTS> 1 <FLAGS> 15 <OCCUPANCY>  [ 10 ]
<MEANACCS>  [
  -115.1633 37.34524 52.23244 40.05222 16.03667 8.719225 85.01067 68.30832 11.52509 34.59558 62.21133 -23.4759 -52.60085 ]
<DIAGVARACCS>  [
  1822.415 538.1805 1578.469 610.5429 804.1371 3180.515 1147.177 790.0551 1260.287 790.6093 1341.816 235.106 707.7091 ]
</GMMACCS> 
(途中省略、残りのPDF-ID 97個分が続く)
<total_like> -8444.121 <total_frames> 198 

最下部に着目するとスコアが更新されていることが分かる。