Kaldi-dnn 學習01
1. Kaldi 中實現的 dnn 共 4 種:
a. nnet1 - 基於 Karel's 的實現,特點:簡單,僅支援單 GPU, 由 Karel 維護
b. nnet2 - 基於 Daniel Povey p-norm 的實現,特點:靈活,支援多 GPU、CPU,由 Daniel 維護
c. nnet3 - nnet2 的改進,由 Daniel 維護
d. (nnet3 + chain) - Daniel Povey 改進的 nnet3, 特點:可以實現實時解碼,解碼速率為 nnet3 的 3~5 倍
目前來看:minibatch Stochastic Gradient Descent 用於 DNN 梯度下降的效果最好
從一個小樣本含 (τ個樣本) 估計出一個 avarage gradient , 這個小樣本就叫做 minibatch
2. 先從 nnet2 說起
a. nnet2 最頂層的訓練指令碼:steps/nnet2/train_pnorm_fast.sh
通過多計算節點,完成並行化訓練
b. 輸入神經網路的特徵
輸入神經網路的特徵是可配置的,通常為MFCC+LDA+MLLT+fMLLR, 40-維的特徵,從網路上看到的是由7幀(從中間幀到左右幀都是3幀)組成的一個幀窗。由於神經網路很難從相關輸入的資料中學習,因此,以 40*7 維特徵作為一個不相關的固定變換形式,通過 step/nnet2/get_lda.sh 完成該工作,實際中並非使用準確的 LDA,而是用 non-dimension-reducing 形式的 LDA,然後減少輸出特徵方差的維度。
c. dumping 訓練樣本到磁碟
第一步,呼叫 step/nnet2/get_egs.sh:拷貝大量資料至 /exp/nnet5d/egs/;便於隨機梯度下降訓練。對輸入做“幀-級別”的隨機初始化(僅做一次)。也就是說:能始終以相同的序列化 access 資料,對於 disk 和 network, disk access 序列化是很好的。
/exp/nnet5d/egs/中包含很多 class 例項(稱為NnetTrainingExample) (如egs.1.1.ark,egs.1.2.ark...),這些 class 包含每幀的 label 資訊,和該幀用於神經網路計算的一個充足的特徵(40維特徵)的輸入時間窗。(從表面上看來)並非為神經網路做 frame-splicing,神經網路有“時間觀念”,並知道“需要多長時間的上下文”(即看函式 RightContext() 和 LeftContext())。egs.1.1.ark 中的第 1 個數字 1 代表 job-index,第 2 個數字 1 代表 iteration index。
有檔案中包含 job-index 和 the iteration index,如共有16個 CPU/GPU 可用,則 job-index 取值範圍 [1, 16],而 the iteration index 的範圍則根據資料量、及有多少個 job 來定。每個 archive 大約需要 200,000 個 samples。需要訓練很多個 epochs, 每個 epoch 做很多次迭代。設定引數為 iters_per_epoch, num_jobs_nnet 和 sample_per_iter。
具體 iters_per_epoch, num_jobs_nnet 和 sample_per_iter 設定值,見 exp/nnet5d/egs/ 對應名字檔案。
d. 神經網路初始化
第一步,初始含一個隱藏層的神經網路,隨後在訓練中逐漸增加 (2~5 ) 隱藏層。配置隱藏層的檔案類似 /exp/nnet4d/nnet.config。即通過 nnet-am-init 建立初始化模型。類似如下的配置檔案
SpliceComponent input-dim=40 left-context=4 right-context=4 const-component-dim=0
FixedAffineComponent matrix=exp/nnet4d/lda.mat
AffineComponentPreconditionedOnline input-dim=360 output-dim=1000 alpha=4.0 num-samples-history=2000 update-period=4 rank-in=20 rank-out=80 max-change-per-sample=0.075 learning-rate=0.02 param-stddev=0.0316227766016838 bias-stddev=0.5
PnormComponent input-dim=1000 output-dim=200 p=2
NormalizeComponent dim=200
AffineComponentPreconditionedOnline input-dim=200 output-dim=1475 alpha=4.0 num-samples-history=2000 update-period=4 rank-in=20 rank-out=80 max-change-per-sample=0.075 learning-rate=0.02 param-stddev=0 bias-stddev=0
SoftmaxComponent dim=1475
SpliceComponent: 定義了完成 feature-frame-splicing 的視窗尺寸
FixedAffineComponent:類 LDA-like 的非相關轉換,由標準的 weight matrix plus bias 組成,通過標準的 stochastic gradient descent 訓練而來,使用 global learning rate
AffineComponentPreconditionedOnline:為 FixedAffineComponent 的一種提煉,訓練過程中不僅使用global learning rate,還使用 matrix-valued learning rate 來預處理梯度下降。參見 dnn2_preconditioning。
PnormComponent:為非線性,傳統的神經網路模型中使用 TanhComponent
NormalizeComponent:用於穩定訓練 p-norm 網路,它是固定的,非可訓練,非線性的。它不是在個別 individual activations 上起作用,而是對單幀的整個 vetor 起作用,重新使它們單位標準化。
SoftmaxComponent:為最終的非線性特徵,便於輸出標準概率
同時,上述指令碼也會產生 hidden.config, 用於新的隱藏層,在最開始的兩次迭代中不會使用,如
AffineComponentPreconditionedOnline input-dim=200 output-dim=1000 alpha=4.0 num-samples-history=2000 update-period=4 rank-in=20 rank-out=80 max-change-per-sample=0.075 learning-rate=0.02 param-stddev=0.0316227766016838 bias-stddev=0.5
PnormComponent input-dim=1000 output-dim=200 p=2
NormalizeComponent dim=200
第二步,做 nnet-train-transitions ,完成轉移概率的計算,該步驟計算的概率在 decoding 時 HMMs 中使用(神經網路中是不需要該概率的)。並計算 “targets(幾千個 context-dependent 狀態)” 的先驗概率。接下來進行解碼,分割這些通過網路計算得到的先驗概率,得到pseudo-likelihoods。
d. 神經網路訓練
本階段進行關鍵步驟:神經網路訓練。實際上就是 0 - num_iters-1 次的迴圈,迭代次數 num_iters 就是 每個 epoch 的迭代次數。訓練 epochs 的次數 = num_pochs(eg 15) + num_epochs_extra(eg 5)。每個 epoch 的迭代次數儲存在 egs/nnet5d/egs/iters_per_epoch 中,具體大小依賴於併發的 job 個數和訓練的資料量。一般的策略是:learning rate 從初始的 0.04,decrease rete 為 0.004,迭代15個epoch,最後5個 epoch 使用固定的 final_learning_rate 0.004。
在每個迭代中,首要任務是計算一些 diagnostics:即 訓練與驗證資料的目標函式(如,iteration 10, 可以檢視對應的 egs/nnet5d/log/compute_prob_valid.10.log 和 egs/nnet5d/log/compute_prob_train.10.log)。在檔案(eg: egs/nnet5d/log/progress.10.log)即可看到 iteration 10 對應的 diagnostics [表示每層有多少個 parameters 變化,以及有多少訓練資料目標函式的變化對每一層的變化有作用]。
基本的並行方法:對數百個 samples 使用隨機梯度下降來訓練,在不同 job 中使用不同的資料,然後 average models。在引數中,目標函式不是凸函式。實踐證明對於並行方法, "preconditioned update" 是非常重要的,而 average model 是沒有作用的。
g. Final model combination
檢視 exp/nnet4d/log/combine.log 檔案可看到,final.mdl 是如何合成的。基本方法:減少方差估計的平均迭代次數。實際中,combine.log 不僅僅只利用引數的平均值,而使用 training-data examples 的 subset 來優化 weight set(不限制必需為正)。對於 subset 的目標函式為常用函式(eg: log-probability),優化方法為 L-BFGS 和 特殊的預處理方法。each component and each iteration 含各自的 weilght。實踐證明:使用 隨機訓練資料的 subset 效果會更好。
#> cat exp/nnet4d/log/combine.log
<snip>
Scale parameters are [
-0.109349 -0.365521 -0.760345
0.124764 -0.142875 -1.02651
0.117608 0.334453 -0.762045
-0.186654 -0.286753 -0.522608
-0.697463 0.0842729 -0.274787
-0.0995975 -0.102453 -0.154562
-0.141524 -0.445594 -0.134846
-0.429088 -1.86144 -0.165885
0.152729 0.380491 0.212379
0.178501 -0.0663124 0.183646
0.111049 0.223023 0.51741
0.34404 0.437391 0.666507
0.710299 0.737166 1.0455
0.859282 1.9126 1.97164 ]
LOG <snip> Combining nnets, objf per frame changed from -1.05681 to -0.989872
LOG <snip> Finished combining neural nets, wrote model to exp/nnet4a2/final.mdl
如上所求,combination weights 被列印為矩陣格式,行:代表 iteration,列:代表相關 layer。combination weights 剛開始 negative,隨後 postive,可以解釋為趨於一次嘗試模型進一步的方向。使用 training data 而不是 validation data,因為這樣效果更好。
f. Mixing-up
可以使用如下工具列印 final.mdl 來分析
#> nnet-am-info exp/nnet4d/final.mdl
num-components 11
num-updatable-components 3
left-context 4
right-context 4
input-dim 40
output-dim 1483
parameter-dim 1366000
component 0 : SpliceComponent, input-dim=40, output-dim=360, context=4/4
component 1 : FixedAffineComponent, input-dim=360, output-dim=360, linear-params-stddev=0.0386901, bias-params-stddev=0.0315842
component 2 : AffineComponentPreconditioned, input-dim=360, output-dim=1000, linear-params-stddev=0.988958, bias-params-stddev=2.98569, learning-rate=0.004, alpha=4, max-change=10
component 3 : PnormComponent, input-dim = 1000, output-dim = 200, p = 2
component 4 : NormalizeComponent, input-dim=200, output-dim=200
component 5 : AffineComponentPreconditioned, input-dim=200, output-dim=1000, linear-params-stddev=0.998705, bias-params-stddev=1.23249, learning-rate=0.004, alpha=4, max-change=10
component 6 : PnormComponent, input-dim = 1000, output-dim = 200, p = 2
component 7 : NormalizeComponent, input-dim=200, output-dim=200
component 8 : AffineComponentPreconditioned, input-dim=200, output-dim=4000, linear-params-stddev=0.719869, bias-params-stddev=1.69202, learning-rate=0.004, alpha=4, max-change=10
component 9 : SoftmaxComponent, input-dim=4000, output-dim=4000
component 10 : SumGroupComponent, input-dim=4000, output-dim=1483
prior dimension: 1483, prior sum: 1, prior min: 7.96841e-05
LOG (nnet-am-info:main():nnet-am-info.cc:60) Printed info about baseline/exp/nnet4d/final.mdl
可以看到,在 outlayer 層之前有一層網路層(神經元節點數為4000),而它的實際大小為 1483,因為決策樹含有1483個葉子。
通過 SumGroupComponent,softmax層維度由4000減少到1483,可以使用如下命令檢視
#> nnet-am-copy --binary=false baseline/exp/nnet4d/final.mdl - | grep SumGroup
nnet-am-copy --binary=false baseline/exp/nnet4d/final.mdl -
<SumGroupComponent> <Sizes> [ 6 3 3 3 2 3 3 3 2 3 2 2 3 3 3 3 2 3 3 3 3 \
3 3 4 2 1 2 3 3 3 2 2 2 3 2 2 3 3 3 3 2 4 2 3 2 3 3 3 4 2 2 3 3 2 4 3 3 \
<snip>
4 3 3 2 3 3 2 2 2 3 3 3 3 3 1 2 3 1 3 2 ]
g. Tuning the number of jobs
通常,最有效的 minibatch size = threads 的倍數。learning rate 與相關 jobs 的數量有關係,一般地,如果增加 jobs 的數量,同時應該增加相同倍數的 learning rate 。原因如下:
由於並行化方法是基於平行SGD執行的神經網路的平均,我們認為“有效學習率”
整個學習過程的每個樣本等於學習率除以工作數。 所以當工作量增加一倍時,
如果我們將學習率提高一倍,我們就會保持“有效學習率”不變
h. Tuning the neural network training
h.1 Number of parameters(hidden layers and layer size)
對於 p-norm 網路,一般要求 -pnorm-input-dim 是 -pnorm-output-dim 的整數倍
h.2 Learning rates
h.3 Minibatch size
minibatch size 一般取 2 的次冪,eg: 128,256,512。
h.4 Max-change
用於限制,在每個 minibatch 允許多少個 parameters 能變化,-max-change 會使訓練減慢
h.5 Number of epochs,etc
epochs 由 -num-epochs (default: 15) 和 -num-epochs-extra(default:5) 組成,-num-epochs 用於 learning rate 從 -initial-learning-rate 梯度下降到 -final-learning-rate 階段,-num-epochs-extra 用於固定的 -final-learning-rate 階段,
-num-iters-final 引數很重要,它決定了 final model combination 階段的迭代次數。
h.6 Feature splicing width
用於控制將多少幀的特徵組合成輸入特徵,該操作會影響到神經網路層的初始化,以及 examples 的產生。一般預設值為 4,表示的含義:以中間 frame 為軸,左右各四個 frame,共9幀為單位組合後做為輸入(通常由 MFCC+splice+LDA+MLLT+fMLLR 組成的 40 維特徵,splicing width = 4 是最優的,注意:LDA+MLLT特徵基於 splice frame 左右兩側各4幀,也就是說從神經網路上看 splice frame 兩側的 7 、8 幀均影響 acoustic context )
40 維的由來:
MFCC/幀:13維
9幀:13*9維
再LDA:40 維
h.7 Configuration values relating to the LDA transform
正如上面所說,此 LDA 並非標準的 LDA。傳統的 LDA 中,資料需要經過 normalize,使得 within-class variance 為單位矩陣,經過變換後,總 variance (within plus between-class) 第 i 個的對角值為 1.0+b(i),b(i) 具有資料依賴特性,根據 i 減少,between-class variance 為對角矩陣,而現在的 LDA 矩陣中每行乘以,其中,預設的 within-class-factor 為 0.0001,即 0.0001+b(i),而非原來的 1.0+b(i)。
h.8 Other miscellaneous configuration values
對於 train_tanh.sh,有一個優化選項 -shrink-interval(預設為 5),含義為:多久做一次 model “shrinking”,就是說用一個小子集訓練資料來優化一組尺度不同層的引數。
原文:https://blog.csdn.net/dearwind153/article/details/62044689
Kaldi中如何使用已經訓練好的模型進行語音識別ASR呢?
Kaldi中有兩個版本的online、online2分別是第一代、第二代,現在已經不維護online,轉到online2了,但作為我們入門的,我建議還是選擇online,由簡入深嘛!!!
預設kaldi是不會編譯online模組的,怎麼讓她理解我的意圖呢?
[[email protected] ~]$ cd ~/kaldi-master/src
[[email protected] src]$ make ext -j 6
順利編譯出來~~~~
語音識別就看egs/voxforge檢視下面的run.sh
指令碼自動去下載預訓練模型:http://sourceforge.net/projects/kaldi/files/online-data.tar.bz2
我們輸入:./run.sh --test-mode simulated就可以直接識別wav音訊檔案了!!!
深度學習專案:https://blog.csdn.net/chinatelecom08/article/details/83654602
原文:https://blog.csdn.net/houwenbin1986/article/details/78658102
!