kaldi筆記(三)train_mono.sh詳解

train_mono.sh 是音素訓練腳本,下面詳細介紹各個功能:

1.首先是初始化GMM,使用的腳本是/kaldi-trunk/src/gmmbin/gmm-init-mono,輸出是0.mdl和tree文件;

2.compile training graphs,使用的腳本是/kaldi-trunk/source/bin/compile-training-graphs,輸入是tree,0.mdl和L.fst

   輸出是fits.JOB.gz,其是在訓練過程中構建graph的過程;

3.接下來是一個對齊的操作,kaldi-trunk/source/bin/align-equal-compiled;

4.然後是基於GMM的聲學模型進行最大似然估計的過程,腳本爲/kaldi-trunk/src/gmmbin/gmm-est;

5.然後進行迭代循環中進行操作,如果本步驟到了對齊的步驟,則調用腳本kaldi-kaldi/src/gmmbin/gmm-align-compiled;

6.重新估計GMM,累計狀態,用腳本/kaldi-trunk/src/gmmbin/gmm-acc-states-ali;調用新生成的參數(高斯數)重新估計GMM,調用腳本/kaldi-trunk/src/gmmbin/gmm-est;

7.對分散在不同處理器上的結果進行合併,生成.mdl結果,調用腳本gmm-acc-sum;

8.增加高斯數,如果沒有超過設定的迭代次數,則跳轉到步驟5重新進行訓練

最後生成的.mdl即爲聲學模型文件

在離線識別階段,即可以調用utils/mkgraph.sh;來對剛剛生成的聲學文件進行構圖之後解碼,得到離線測試的識別率。

以上就完成了聲學模型訓練第一個階段,mono-phone訓練的代碼介紹過程。

這部分是訓練用參數,調用mono.sh時可以通過 –name value的方式改變這些參數.

nj=4   並行個數
cmd=run.pl   處理程序
scale_opts="--transition-scale=1.0 --acoustic-scale=0.1 --self-loop-scale=0.1"
num_iters=40     **  Number of iterations of training  訓練循環次數
max_iter_inc=30  **  Last iter to increase  ** Gauss on.  每個循環裏增加的高斯數
totgauss=1000  **  Target  ** Gaussians.   總高斯數(可能難理解,但可以這麼解釋:比如有3狀態HMM,每個狀態用4組均值方差描述(GMM混合數是4個意思),那總共用了12個高斯,kaldi裏不用具體指定GMM個數,而指定整個系統中總共需要多少個單高斯)
careful=false
boost_silence=1.0  **  Factor by which to boost silence likelihoods in alignment
realign_iters="1 2 3 4 5 6 7 8 9 10 12 14 16 18 20 23 26 29 32 35 38";  循環到這個數時做對其
config=  **  name of config file. 
stage=-4  
power=0.25  **  exponent to determine number of gaussians from occurrence counts
norm_vars=false  **  deprecated, prefer --cmvn-opts "--norm-vars=false"
cmvn_opts=   **  can be used to add extra options to cmvn.
 **  End configuration section.

echo "$0 $@"   **  Print the command line for logging
  •  
    • name value 參數處理
if [ -f path.sh ]; then . ./path.sh; fi
. parse_options.sh || exit 1;
  • 1
  • 2
    • -name 以外的參數必須有3個,否則報錯*
if [ $ **  != 3 ]; then
  echo "Usage: steps/train_mono.sh [options] <data-dir> <lang-dir> <exp-dir>"
  echo " e.g.: steps/train_mono.sh data/train.1k data/lang exp/mono"
  echo "main options (for others, see top of script file)"
  echo "  --config <config-file>                            **  config containing options"
  echo "  --nj <nj>                                         **  number of parallel jobs"
  echo "  --cmd (utils/run.pl|utils/queue.pl <queue opts>)  **  how to run jobs."
  exit 1;
fi

data=$1 * 第一個參數是訓練數據所在的目錄 * 
lang=$2 * 第二個參數是語言模型所在的目錄 * 
dir=$3 * 第一個參數是日誌和最終目標文件輸出目錄 *

oov_sym=cat $lang/oov.int || exit 1;

  • 訓練數據根據–nj 參數分割,用於並行處理 *
mkdir -p $dir/log
echo $nj > $dir/num_jobs
sdata=$data/split$nj;
[[ -d $sdata && $data/feats.scp -ot $sdata ]] || split_data.sh $data $nj || exit 1;

$norm_vars && cmvn_opts="--norm-vars=true $cmvn_opts"
echo $cmvn_opts  > $dir/cmvn_opts  **  keep track of options to CMVN.

**這裏可能第一個難理解的地方,但仔細分析也不難

首先這個是一個feats變量定義,這個變量作爲後續其他命令的參數,這個主要處理特徵數據的。

這裏用到了兩個kaldi函數,apply-cmvn 和 add-deltas

apply-cmvn 的輸入3個文件: 

–utt2spk=ark:sdata/JOB/utt2spk語料和錄音人員關聯文件scp:sdata/JOB/utt2spk 語料和錄音人員關聯文件 
scp:sdata/JOB/cmvn.scp **說話人相關的均值和方差** 

scp:$sdata/JOB/feats.scp 訓練用特徵文件

對feats.scp做歸一化處理

輸出是 ark:-|,利用管道技術把輸出傳遞給下一個函數作爲輸入

add-deltas 輸入是ark:-,表示把上一個函數的輸出作爲輸入(實際上就是整個訓練特徵數據),

輸出  ark:- | 管道技術同上。訓練數據增加差分量,比如13維度mfcc處理後變成39維度
這樣的輸入輸出重定向和管道技術後續使用非常多,所先熟練掌握linux shell的語法。
  • 就變成了 ark,s,cs:特徵數據 這個形式**
eats="ark,s,cs:apply-cmvn $cmvn_opts --utt2spk=ark:$sdata/JOB/utt2spk scp:$sdata/JOB/cmvn.scp scp:$sdata/JOB/feats.scp ark:- | add-deltas ark:- ark:- |"
example_feats="`echo $feats | sed s/JOB/1/g`";
echo "$0: Initializing monophone system."

[ ! -f $lang/phones/sets.int ] && exit 1;
shared_phones_opt="--shared-phones=$lang/phones/sets.int"

if [ $stage -le -3 ]; then
   **  Note: JOB=1 just uses the 1st part of the features-- we only need a subset anyway.
  //特徵維度獲取
  if ! feat_dim=`feat-to-dim "$example_feats" - 2>/dev/null` || [ -z $feat_dim ]; then
    feat-to-dim "$example_feats"  
    echo "error getting feature dimension"
    exit 1;
  fi
//gmm-init-mono 構造第一個模型文件和決策樹
//"--train-feats=$feats subset-feats --n=10 ark:- ark:-|"  這個的意思是特徵數據中取10個特徵用於構造原始模型 
//輸出是    $dir/0.mdl $dir/tree   這兩個文件 
//可以利用 gmm-info $dir/0.mdl 查看這個模型概要信息 
//$cmd 後面的具體命令 gmm-init-mono通過$cmd環境運行的意思,log輸出在$dir/log/init.log這裏
  $cmd JOB=1 $dir/log/init.log \
    gmm-init-mono $shared_phones_opt "--train-feats=$feats subset-feats --n=10 ark:- ark:-|" $lang/topo $feat_dim \
    $dir/0.mdl $dir/tree || exit 1;
fi

//默認高斯數獲取,從模型0.mdl裏讀取的
numgauss=`gmm-info --print-args=false $dir/0.mdl | grep gaussians | awk '{print $NF}'`
//根據參數總高斯計算每個循環增減的具體高斯數
incgauss=$[($totgauss-$numgauss)/$max_iter_inc]  **  per-iter increment for  ** Gauss

**這部分主要調用compile-train-graphs,根據決策樹,模型,lexsionFST,text轉ID這些文件,構造訓練用FST,輸出文本形式後:

S00001

0 25 2 0 0.693359

0 26 3 0 0.693359

0 3 245 419 0.693359

1 27 5 0

1 28 6 0

2 29 7 0

2 30 9 0

3 4 247 0

3 3 244 0

4 5 249 0

4 4 246 0

5 6 251 0

訓練用每句話轉換成一個FST結構,輸入是音素,輸出是整個句子**

if [ $stage -le -2 ]; then
  echo "$0: Compiling training graphs"
  //主要調用compile-train-graphs,輸出 fsts.JOB.gz,JOB是具體分割是數據,比如分割16分(16個並行)
  //fsts.1.gz  fsts.2.gz  ... fsts.16.gz 這些文件
    $cmd JOB=1:$nj $dir/log/compile_graphs.JOB.log \
      compile-train-graphs $dir/tree $dir/0.mdl  $lang/L.fst \
    "ark:sym2int.pl --map-oov $oov_sym -f 2 - $lang/words.txt < $sdata/JOB/text|" \
    "ark:|gzip -c >$dir/fsts.JOB.gz" || exit 1;
fi


align-equal-compiled:對每一個訓練特徵做解碼對其,輸出文本形式爲: 

S00001 3 1 9 8 11 10 245 244 247 246 249 248 251 250 45 44 47 46 49 48 51 50 157 156 159 158 161 160 163 162 149 148 151 150 153 152 155 154 2 1 5 4 9 8 11 10

S00002 3 1 7 8 5 4 9 8 11 10 29 28 31 30 33 32 35 34 117 116 119 118 121 120 123 122 69 68 71 70 73 72 75 74 77 76 79 78 81 80 83 82 21 20 23 22 25 24 27 26 37 39 41 43 2 6 11 

編號是對應: transition-ids

gmm-acc-stats-ali:根據對其信息,計算每個高斯分佈的均值和方差,文本輸出形式是:

[ 0 1251 780 747 1127 763 789 772 1097 738 1100 1527 455 344 441 344 434 344 417 344 861 900 834 900 798 900 767 900 367 336 350 3 36 337 336 332 336 238 322 225 322 213 322 201 322 310 323 301 323 290 323 277 323 46 39 44 39 42 39 41 39 160 190 156 190 152 190 144 190 133 134 128 134 123 134 118 134 389 387 380 387 370 387 358 387 232 225 230 225 222 225 218 225 115 173 100 173 92 173 83 1 73 162 160 154 160 149 160 146 160 30 21 26 21 26 21 25 21 57 58 56 58 55 58 53 58 141 159 134 159 131 159 127 159 155 154 151 154 149 154 142 154 718 658 698 658 682 658 657 658 154 198 139 198 131 198 120 198 173 181 167 181 159 181 155 181 43 116 40 116 36 11 6 36 116 14 16 14 16 12 16 12 16 50 94 46 94 39 94 34 94 95 146 87 146 82 146 78 146 68 93 65 93 59 93 52 93 197 173 191 173 185 17 3 175 173 18 20 17 20 17 20 13 20 104 89 100 89 97 89 95 89 22 27 20 27 19 27 19 27 71 79 68 79 65 79 62 79 180 184 175 184 168 184 166 184 50 55 46 55 40 55 39 55 81 89 78 89 74 89 72 89 32 27 31 27 29 27 29 27 6 9 6 9 6 9 5 9 130 113 126 113 123 113 116 113 52 56 51 56 51 56 50 56 152 120 148 120 147 120 145 120 45 28 45 28 44 28 44 28 27 22 26 22 26 22 26 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 31 26 29 26 28 26 28 26 160 119 158 119 153 119 152 119 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]

96 1 15 [ 2778 ]

[

131.1602 -122.5539 34.99217 -58.83603 -41.43925 13.44948 463.3047 -57.9593 -18.75538 75.6356 -19.41969 104.4369 -124.7882 10.0328 6 192.8238 17.50561 30.52075 -186.307 -103.0168 -182.8055 -93.31313 274.8601 -134.9286 -20.74373 292.326 -139.4371 -76.76163 125.10 22 176.4698 -73.94184 671.5715 320.7724 187.5074 20.53596 -39.48004 0.9577144 -17.36876 98.11237 -74.94476 -6.995347 -24.19745 12.9 314 -11.86463 24.64146 -4.998218 16.60446 54.21263 7.680242 80.09453 -1.158172 12.43884 -21.7555 8.72164 -82.95818 30.4046 77.66879 -147.196 37.55052 -9.052818 169.3757 25.53467 -29.35383 -9.141276 -163.5246 -0.5642087 -4.418148 7.150371 1.227273 1.874714 -5.212 431 -35.17178 3.145967 -9.014412 5.978422 4.867862 24.94123 4.603298 9.424832 4.24349 11.20849 -4.842735 4.014105 -4.744929 5.26339 6 2.670479 2.020237 2.857623 -11.47297 6.608553 3.21471 -13.41074 -4.644363 0.2190919 -2.052493 -27.65508 8.728714 ]

[

302.8793 96.91061 50.14678 32.40083 62.61554 127.9802 427.8968 59.14513 97.06206 45.82985 51.53176 124.2855 36.80134 57.89008 169 .3976 79.1737 140.4388 50.01487 68.45477 115.8913 41.76318 151.5989 36.88505 87.20601 204.4366 56.90768 203.9601 228.5459 130.8333 52.88366 559.3757 200.2088 59.71447 11.39293 9.831112 5.036578 8.143344 25.86716 35.48496 8.004593 9.955203 7.049322 7.714571 22.01 161 4.823307 8.744013 22.8913 12.14625 22.91733 6.248809 7.172078 16.7681 4.72665 21.95807 6.282173 16.24944 35.32213 9.839767 18.3 4587 44.31969 12.50674 5.586533 45.20058 31.49718 7.654399 2.389589 1.18734 1.046883 1.593502 3.394817 5.20261 1.703343 1.964516 1. 464402 1.537351 4.471569 0.8961765 1.717167 3.762137 2.311954 4.111099 1.202704 1.794535 3.404304 1.064913 2.071092 1.182136 2.2995 83 2.488608 1.465976 4.587708 5.893738 2.384184 0.8646237 6.272319 1.73957 ]

這個信息最後保存在 0.JOB.acc 裏。JOB同上。

if [ $stage -le -1 ]; then
  echo "$0: Aligning data equally (pass 0)"
  $cmd JOB=1:$nj $dir/log/align.0.JOB.log \
    align-equal-compiled "ark:gunzip -c $dir/fsts.JOB.gz|" "$feats" ark,t:-  \| \
    gmm-acc-stats-ali --binary=true $dir/0.mdl "$feats" ark:- \
    $dir/0.JOB.acc || exit 1;
fi

 **  In the following steps, the --min-gaussian-occupancy=3 option is important, otherwise
 **  we fail to est "rare" phones and later on, they never align properly.

gmm-est:模型重建,根據原始模型0.mdl 所有0.*.acc文件合併輸出 1.mdl

gmm-sum-accs:完成多個文件的統計合併

if [ $stage -le 0 ]; then
  gmm-est --min-gaussian-occupancy=3  --mix-up=$numgauss --power=$power \
    $dir/0.mdl "gmm-sum-accs - $dir/0.*.acc|" $dir/1.mdl 2> $dir/log/update.0.log || exit 1;
  rm $dir/0.*.acc
fi

下面代碼根據循環次數做模型訓練

主要用下面三個函數:

$x變量就是目前的循環次數

gmm-align-compiled:和上面講的“align-equal-compiled”類似,做特徵數據的對其,對其信息輸出到ali.JOB.gz裏。對其不是每次都做,realign_iters=”1 2 3 4 5 6 7 8 9 10 12 14 16 18 20 23 26 29 32 35 38”; x再x 再 realign_iters 是才做對其。

gmm-acc-stats-ali:根據對其信息,計算每個高斯分佈的均值和方差(看有介紹),輸出$x.JOB.acc文件

gmm-est:根據上一次的模型,構建新模型 [[x+1].mdl

beam=6  **  will change to 10 below after 1st pass
 **  note: using slightly wider beams for WSJ vs. RM.
x=1
while [ $x -lt $num_iters ]; do
  echo "$0: Pass $x"
  if [ $stage -le $x ]; then
    if echo $realign_iters | grep -w $x >/dev/null; then
      echo "$0: Aligning data"
      //sil模型調整
      mdl="gmm-boost-silence --boost=$boost_silence `cat $lang/phones/optional_silence.csl` $dir/$x.mdl - |"
      $cmd JOB=1:$nj $dir/log/align.$x.JOB.log \
        gmm-align-compiled $scale_opts --beam=$beam --retry-beam=$[$beam*4] --careful=$careful "$mdl" \
        "ark:gunzip -c $dir/fsts.JOB.gz|" "$feats" "ark,t:|gzip -c >$dir/ali.JOB.gz" \
        || exit 1;
    fi
    $cmd JOB=1:$nj $dir/log/acc.$x.JOB.log \
      gmm-acc-stats-ali  $dir/$x.mdl "$feats" "ark:gunzip -c $dir/ali.JOB.gz|" \
      $dir/$x.JOB.acc || exit 1;

    $cmd $dir/log/update.$x.log \
      gmm-est --write-occs=$dir/$[$x+1].occs --mix-up=$numgauss --power=$power $dir/$x.mdl \
      "gmm-sum-accs - $dir/$x.*.acc|" $dir/$[$x+1].mdl || exit 1;
    rm $dir/$x.mdl $dir/$x.*.acc $dir/$x.occs 2>/dev/null
  fi
  if [ $x -le $max_iter_inc ]; then
     numgauss=$[$numgauss+$incgauss];
  fi
  beam=10
  x=$[$x+1] 循環變量+1
done

最後模型就是final.mdl文件,他是對最後一個訓練模型的link

( cd $dir; rm final.{mdl,occs} 2>/dev/null; ln -s $x.mdl final.mdl; ln -s $x.occs final.occs )

utils/summarize_warnings.pl $dir/log

echo Done

 **  example of showing the alignments:
 **  show-alignments data/lang/phones.txt $dir/30.mdl "ark:gunzip -c $dir/ali.0.gz|" | head -4

以上就是對train_mono.sh的詳細解釋。

理解train_mono.sh對後續三音素, LDM MLLT, MMI ,MPE,DNN等都有很大幫助。

更多細節自行閱讀http://kaldi.sourceforge.net/。 
**kaldi主要運行思路是:

1.準備數據

2.訓練單因素模型

3.訓練三音素模型 train_deltas.sh

  1. 調整三音素模型(LDM MLLT, MMI ,MPE)等

  2. 訓練DNN

  3. GMM模型和DNN模型綁定**

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章