2019년 7월 14일 일요일

음성인식 메모(kaldi) 23 - training 시의 모델 업데이트 Dan's DNN(nnet2)

「原作者へ」

連絡先を存じ上げませんでしたので、不本意ながら無断で翻訳しました。 
正式に翻訳を許可されたいです。 
gogyzzz@gmail.comでご連絡ください。

아래 포스트의 번역입니다.

http://work-in-progress.hatenablog.com/entry/2018/08/12/123334


음성인식 메모(kaldi) 20 - Training Dan's DNN(nnet2)의 연장.

mixup 후에 생성된 12개의 모델(14.mdl〜25.mdl)에서 「final.mdl」을 생성하는 과정을 추적해보자.

nnet2에는 결과가 좋은 모델을 하나만 고르지 않고 (여러 모델에?) 스케일을 곱한 다음 더하는 방식을 취한다.

생성은 「nnet2bin/nnet-combine-fast」 커맨드를 사용하여 모델을 combine(합성)한다.

nnet-combine-fast \
    --minibatch-size=129 \ 
    exp/nnet4c/14.mdl \
    exp/nnet4c/15.mdl \
    <snip> \
    exp/nnet4c/25.mdl \
    ark:exp/nnet4c/egs/combine.egs \    #  <valid-examples-in>
    exp/nnet4c/final.mdl

이번 케이스에선 모델의 Component 수가 「9」、Updatable-Component 수가 「3」

info 커맨드(nnet2bin/nnet-am-info exp/nnet4c/14.mdl )

num-components 9
num-updatable-components 3
input-dim 40
output-dim 192
component 0 : SpliceComponent, input-dim=40, output-dim=360, ... 
component 1 : FixedAffineComponent, input-dim=360, output-dim=360, ...
component 2 : AffineComponentPreconditionedOnline, input-dim=360, output-dim=375, ...
component 3 : TanhComponent, input-dim=375, output-dim=375
component 4 : AffineComponentPreconditionedOnline, input-dim=375, output-dim=375, ...
component 5 : TanhComponent, input-dim=375, output-dim=375
component 6 : AffineComponentPreconditionedOnline, input-dim=375, output-dim=453, ...
component 7 : SoftmaxComponent, input-dim=453, output-dim=453
component 8 : SumGroupComponent, input-dim=453, output-dim=192

index이 2、4、6인 「AffineComponentPreconditionedOnline」 컴포넌트 (Updatable-Component에 해당)가 합성 대상이 된다.

결과를 먼저 쓰자면, 각 모델, 각 컴포넌트에 대해 아래와 같은 스케일이 할당된다.

각 모델, 컴포넌트마다의 스케일

스케일을 구하는 과정을 따라가보자.

업데이트에 있어서의 평가 척도는 Propagate의 값(Log값)이 된다.(값이 작을수록 좋다)

같은 데이터(exp/nnet4c/egs/combine.egs)에 대한 모델의 값은 아래와 같이 되어 있다.

14.mdl : -0.0753596
15.mdl : -0.0679429
16.mdl : -0.0373454
17.mdl : -0.0325585
18.mdl : -0.0286209
19.mdl : -0.0237487
20.mdl : -0.0209156
21.mdl : -0.00755152
22.mdl : -0.0101945
23.mdl : -0.00779286
24.mdl : -0.00615664
25.mdl : -0.00456561

이번 케이스에서는 「25.mdl」의 「-0.00456561」가 가장 좋은 값이므로, 그 값을 기준으로 더욱 좋은 값을 얻을 수 있는 스케일을 구해보자.

스케일의 최적해는 뉴턴 메소드 (L-BFGS)를 사용하여 구한다.

소스 코드의 내용(nnet2/combine-nnet-fast.cc)

OptimizeLbfgs<double> lbfgs(params_,
                            lbfgs_options);

// Loop 10 times
for (int32 i = 0; i < config_.num_lbfgs_iters; i++) {

    // 스케일을 세팅
    params_.CopyFromVec(lbfgs.GetProposedValue());

    // Propagate의 값과 gradient를 구한다
    objf = ComputeObjfAndGradient(&gradient, ®ularizer_objf);

    if (i == 0) {
        initial_objf = objf;
        initial_regularizer_objf = regularizer_objf;
    }
    // 판정과 스케일을 업데이트
    lbfgs.DoStep(objf, gradient);

} // end of for(i)

각 루프 단계에서 Propagate의 값과 판정은 아래와 같았다.

(i=0) -0.00456561                  
(i=1) -0.310829      action = decrease 
(i=2) -0.0201834     action = decrease 
(i=3) -0.00512826    action = decrease 
(i=4) -0.00410415    action = accept   
(i=5) -0.00352887    action = accept
(i=6) -0.00315388    action = accept
(i=7) -0.00228854    action = accept
(i=8) -0.000916785   action = accept
(i=9) -0.000539656   action = accept

루프 카운터가 「9」일 때의 값 「-0.000539656」가 가장 좋았기 때문에, 이 때의 스케일이 최적해가 된다.

params_ = lbfgs.GetValue(&objf);

댓글 없음:

댓글 쓰기