2019년 7월 14일 일요일

음성인식 메모(kaldi) 14 - feature 변환 Dan's DNN(nnet2)

「原作者へ」

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

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

http://work-in-progress.hatenablog.com/entry/2018/05/26/120212

LDA변환용 파라미터는 supervised data의 통계량을 기반으로 생성된다.

통계 데이터 생성에는 「bin/acc-lda」 커맨드를 사용한다.

「bin/acc-lda」コマンド

Accumulate LDA statistics based on pdf-ids.
Usage:  acc-lda [options] <transition-gmm/model> <features-rspecifier> <posteriors-rspecifier> <lda-acc-out>

input은 아래와 같다.

  • 모델(GMM-HMM)
  • supervised 데이터가 되는 feature (정규화 적용된)
  • supervised 데이터의 alignment 결과로부터 생성한 posterior

posterior (pdf-id)

utterance_id_001 [ 206 1 ] [ 208 1 ] [ 210 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 209 1 ] [ 242 1 ] [ 244 1 ] [ 246 1 ] [ 266 1 ] [ 268 1 ] [ 270 1 ] [ 194 1 ] [ 196 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 195 1 ] [ 198 1 ] [ 218 1 ] [ 220 1 ] [ 222 1 ] [ 221 1 ] [ 221 1 ] [ 221 1 ] [ 221 1 ] [ 221 1 ] [ 221 1 ] [ 221 1 ] [ 221 1 ] [ 221 1 ] [ 221 1 ] [ 221 1 ] [ 221 1 ] [ 221 1 ] [ 221 1 ] [ 221 1 ] [ 221 1 ] [ 221 1 ] [ 221 1 ] [ 221 1 ] [ 221 1 ] [ 242 1 ] [ 244 1 ] [ 246 1 ] [ 266 1 ] [ 268 1 ] [ 270 1 ] [ 188 1 ] [ 190 1 ] [ 192 1 ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] 

[ ]안의 1열째가 pdf-id, 2열째가 posterior(weight)를 나타냄

[ ]안의 blank는 silence를 나타냄(weight가「0.0」)

모델은 「pdf-id」를 「pdf-class」로 치환하여 읽기 위해 사용

「pdf-class」로 치환된 것은 아래와 같음

(참고)posterior(pdf-class)

utterance_id_001
[ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 4 1 ] [ 4 1 ] [ 4 1 ] [ 5 1 ] [ 5 1 ] [ 5 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 3 1 ] [ 4 1 ] [ 4 1 ] [ 4 1 ] [ 5 1 ] [ 5 1 ] [ 5 1 ] [ 2 1 ] [ 2 1 ] [ 2 1 ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] 

[ ]안의 1열째가 pdf-id、2열째가 posterior(weight)를 나타냄

[ ]안의 blank는 silence를 나타냄(weight가「0.0」)

이번엔 feature를 2차원으로만 하여 파라미터의 산출 과정을 추적해보자

feature(198row x 13col의 데이터로부터 1차원째와 2차원째만을 잘라낸 것. 198row x 2col)

utterance_id_001  [
  16.92272 7.178926
  4.827858 0.9412766
  -3.098977 -18.89928
  -3.82908 -10.80018
  5.34936 1.858578
  12.67259 11.39851
  8.422453 -14.75593
  9.636777 -7.864816
  9.636777 -17.51817
  (snip)
  -4.976385 9.013528
  -3.93338 10.29775
  -4.976385 13.56448
  -4.767784 12.44007
  -8.559893 7.545846 ]

플롯

pdf-class의 index는 「0」부터 시작

"X"는 각 pdf-class마다 평균을 나타냄(까만색은 전체 평균)

전체의 covariance 행렬

498.761   96.582
 96.582  166.250

1차원(dim1)의 평균: 0.430 2차원(dim2)의 평균: -3.985

1차원(dim1)의 표준편차: 22.333 2차원(dim2)의 표준편차: 12.894

1차원과 2차원의 상관계수: 0.335

커맨드의 output

  • "VECSIZE" : feature의 차원 수
  • "NUMCLASSES" : pdf-class의 갯수
  • "ZERO_ACCS" : pdf-class마다의 프레임 수 (0차 accumulated?)
  • "FIRST_ACCS" : pdf-class마다의 프레임의 feature 값을 더한 것
  • "SECOND_ACCS" : covariance 행렬의 중도 계산결과(각 차원마다의 분산과 공분산)
  • "SECOND_ACCS"에는 프레임수로 나누기 전의 값, 평균을 빼기 전의 값이 들어있다.

LDA통계량을 기반으로 「nnet2bin/nnet-get-feature-transform」 커맨드를 사용하여 LDA변환 파라미터를 산출한다.

「nnet2bin/nnet-get-feature-transform」 커맨드

Get feature-projection transform using stats obtained with acc-lda.
Usage:  nnet-get-feature-transform [options] <matrix-out> <lda-acc-1> <lda-acc-2> ...

전체의 covariance 행렬(total_covar)

498.761   96.582
 96.582  166.250

이어서, 클래스 간(between-class)covariance 행렬을 구한다.

여기서 클래스란 차원을 말함

각 pdf-class의 평균을 기준으로 1차원(dim1)과 2차원(dim2)에 관한 covariance 행렬을 구하여, 전체 데이터에서 차지하는 비율을 곱한 것을 더한다.

클래스 간 covariance 행렬(bc_covar)

14.524   26.249
26.249   59.821

이것을 SVD하여, 기저 벡터 u1, u2방향의 축으로 플롯

특이값은 「71.842」、「2.503」

svd_u= 
 0.416  0.909
 0.909 -0.416

u1 = (0.416, 0.909) L2 norm: 1

u2 = (0.909, -0.416) L2 norm: 1

이어서, 클래스 내 (within-class)covariance 행렬을 구한다.

전체의 covariance 행렬(totalcovar)로부터, 클래스 간 covariance 행렬(bccovar)을 뺀다.

클래스 내의 covariance 행렬(wc_covar)

484.237   70.333
 70.333  106.430

이것을 LU분해 한다.

대칭행렬이므로, Cholesky factorization을 사용한다.

분해 후 Lower Triangular Matrix

22.005  0  
 3.196  9.809

L의 역행렬(L^(-1))을 구하자.

 0.045  0
-0.015  0.102

이것을 클래스 간 (between-class)covariance 행렬에 곱한다. (왼쪽에서 L^(-1),오른쪽에서 LT^(-1))。

L.inverse() * bc_covar * LT.inverse()= 
0.030  0.112
0.112  0.546

이것을 SVD하여, 기저 벡터 u1, u2방향의 축으로 플롯

특이값은 「0.569」、「0.007」

기저 벡터

svd_u= 
 0.203  0.979
 0.979 -0.203

u1 = (0.203, 0.979) L2 norm: 1

u2 = (0.979, -0.203) L2 norm: 1

여기서, 특이값이 큰 순서대로 기저 벡터를 정렬한다.

이어서, 기저 벡터를 transpose한 것에 L^(-1)을 곱한다.

svd_u= 
 0.203  0.979
 0.979 -0.203

svd_u.transpose() * L.inverse()= 
-0.005   0.100
 0.048  -0.021

u1 = (-0.005, 0.100) L2 norm: 0.1001

u2 = ( 0.048, -0.021) L2 norm: 0.0524

이어서, Scale을 곱한다.

파라미터 「--within-class-factor」가 "0.0001"(디폴트)이라면, 기저 벡터 u1의 Scale은 아래와 같이 계산된다.(특이값은 「0.569」)

sqrt (( 0.0001 + 0.569 ) / ( 1.0 + 0.569 ) )
= sqrt ( 0.569 / 1.569)
= sqrt (0.367)
= 0.602

u1 = (-0.003, 0.060) L2 norm: 0.060

(보충)소수점 여섯째 자리에서 반올림

u1 = (-0.003170, 0.060114)

같은 방식으로, 기저 벡터 u2의 Scale을 계산한다.(특이값은 「0.00678」)

sqrt (( 0.0001 + 0.007 ) / ( 1.0 + 0.007 ) )
= sqrt ( 0.007 / 1.007)
= sqrt (0.007)
= 0.083

u2 = (0.004, -0.002) L2 norm: 0.004

(보충)소수점 여섯째 자리에서 반올림

u2 = (0.003984, -0.001743)

이어서, 전체 평균(0.4296, -3.9851)에 대해, u1, u2위에 projection한 것을 구한다.

평균 벡터와 u1의 inner product

( 0.4296 * -0.003170 ) +  ( -3.9851 * 0.060114 ) = -0.240922

평균 벡터와 u2의 inner product

( 0.4296 * 0.003984 ) +  ( -3.9851 * -0.001743 ) = 0.008658

평균을 u1위에 projection한 좌표

(0.000763, -0.014482)

평균을 u2위에 projection한 좌표

(3.4e-05, -1.5e-05)

평균을 u1, u2위에 projection한 좌표를 플롯

평균을 u1, u2위에 projection한 좌표를 플롯 (확대)

평균을 u1, u2위에 projection한 좌표를 플롯(한층 더 확대)

아래가 최종 출력 결과로, LDA변환의 파라미터가 된다.

출력결과

[  -0.003  0.060  0.241 
    0.004 -0.002 -0.009 ]

1행째는 기저 벡터 u1(제 1성분과 제 2성분)과 전체 평균을 u1위에 projection한 값에 -1을 곱한 것

2행째는 기저 벡터 u2(제 1성분과 제 2성분)과 전체 평균을 u2위에 projection한 값에 -1을 곱한 것

댓글 없음:

댓글 쓰기