2019년 7월 14일 일요일

음성인식 메모(kaldi) 22 - alignment

「原作者へ」

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

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

http://work-in-progress.hatenablog.com/entry/2018/07/29/104925


decode의 과정을 파헤쳐보자.

alignment로 출력되는 수치(input인 MFCC feature 각 프레임에 일대일로 대응한다)는 무엇을 나타내고 있는 것일까?

이번엔 egs/wsj/s5/steps/decode.sh의 내부에서 호출되는 lattice 생성 커맨드의 output을 보도록 하자.

(추가 옵션으로, 「words-wspecifier」와 「alignments-wspecifier」를 지정)

gmm-latgen-faster \
--max-active=7000 \
--beam=13.0 \
--lattice-beam=6.0 \
--acoustic-scale=0.083333 \
--allow-partial=true \
--determinize-lattice=true \
--word-symbol-table=exp/mono/graph/words.txt \
exp/mono/final.mdl \        # model-in
exp/mono/graph/HCLG.fst \   # fst-in
ark:/tmp/utter_053.ark \    # features-rspecifier
ark:/tmp/lat.ark \          # lattice-wspecifier
ark:/tmp/word.ark \         # words-wspecifier
ark:/tmp/ali.ark            # alignments-wspecifier

입력

음성(/tmp/utter_053.ark)

이전 글에서 테스트용으로 사용한 ”禁煙席お願いします(킨넨 세키 오네가이 시 마스: 금연석 부탁합니다)”라는 발화

(프레임 수는 「323」、식별자는 "utteranceid053"、39차원)

아래 커맨드로 생성한다.

apply-cmvn \
--utt2spk=ark:data/test/split1/1/utt2spk \
scp:data/test/split1/1/cmvn.scp \
scp:data/test/split1/1/feats.scp \
ark:- | \
add-deltas \
ark:- \
ark:/tmp/hoge.ark

모델

이전 글에서 생성했던 Monophone 모델(언어 모델은 2-gram으로 생성)

exp/mono/graph/words.txt

<eps> 0
!SIL 1
<UNK> 2
あり(아리) 3 
お(오) 4
お願い(오네가이) 5
し(시) 10
ます(마스) 23
席(세키) 45
禁煙(킨넨) 53
#0 62
<s> 63
</s> 64

exp/mono/graph/phones/align_lexicon.txt

<eps> <eps> sil
禁煙(킨넨) 禁煙(킨넨) k_B i_I N_I e_I N_E
席(세키) 席(세키) s_B e_I k_I i_E
お願い(오네가이) お願い(오네가이) o_B n_I e_I g_I a_I i_E
し(시) し(시) sh_B i_E
ます(마스) ます(마스) m_B a_I s_I u_E

output

words(tmp/word.ark)

utterance_id_053 53 45 5 10 23 

symbol로 바꾸면, 「禁煙(킨넨)(53) 席(세키)(45) お願い(오네가이)(5) し(시)(10) ます(마스)(23)」

lattice (/tmp/lat.ark) ※설명용으로 일부 가공

utterance_id_053                                              
0   1   53  9.81125, 7750.02, 2_1_1_1_8_5_5_5_18_17_17_17_17_17_...
1   2   45  2.38995, 4952.66, 197_197_197_197_197_197_197_197_...
2   3   5   4.61863, 8155.52, 527_527_527_527_527_527_527_527_...
3   4   10  2.22007, 3096.31, 527_926_925_925_925_925_925_925_...
4   5   23  5.81478, 6656.75, 523_526_528_638_637_640_639_639_...
5                 0,       0, 917_917_917_917_917_917_917_917_...

alignment 결과(/tmp/ali.ark)

utterance_id_053 2 1 1 1 8 5 5 5 18 17 17 17 17 17 17 17 17 17 17 ...

MFCC feature 프레임과 같은 수의 「323」개

alignment를 음소로 변환한다.

ali-to-phones \
--write-lengths \
exp/mono/final.mdl \
ark:/tmp/ali.ark \
ark:/tmp/ali2phone.ark

alignment 결과(/tmp/ali2phone.ark) ※설명용으로 음소를 symbol로 치환

utterance_id_053 sil 31 ; k_B 5 ; i_I 12 ; N_I 39 ; e_I 6 ; N_E 3 ; s_B 3 ; e_I 22 ; k_I 3 ; i_E 12 ; o_B 28 ; n_I 14 ; e_I 3 ; g_I 13 ; a_I 4 ; i_E 14 ; sh_B 28 ; i_E 5 ; m_B 38 ; a_I 14 ; s_I 21 ; u_E 5 

symbol의 뒤는 출현 수. 예를 들어 「sil 31」은 "sil"이 31회 이어졌다는 것을 뜻함

다시 오늘의 주제 alignment 시 출력되고 있는 것은 무엇인지 알아보자.

「ali-to-phones」 커맨드에 건넨 input을 봤다면 모델(*.mdl)의 정보로부터 유추 가능하다.

(alignment로부터 음소로 변환하는 것뿐이라면, FST의 그래프는 사용하지 않는다)

모델 생성 시의 input이 되는 「phones.txt」의 내부는 전부 「171」개가 있다.

exp/mono/phones.txt

<eps> 0
sil 1
sil_B 2
sil_E 3
sil_I 4
sil_S 5
spn 6
spn_B 7
spn_E 8
spn_I 9
spn_S 10
N_B 11
N_E 12
N_I 13
N_S 14
a_B 15
a_E 16
a_I 17
a_S 18
...
z_E 164
z_I 165
z_S 166
#0 167
#1 168
#2 169
#3 170

여기에서 모델의 「TopologyEntry」로 정의되는 것은 「166」개.

<ForPhones> 1 2 3 4 5 6 7 8 9 10 </ForPhones> 
<ForPhones> 11 12 13 14 15 16 17 18  ...  164 165 166 </ForPhones> 

phone-id가 1에서 10까지 (silence phone)은 「5」 상태, 11에서 166까지(non silence phone)는 「3」 상태가 된다.

3 state HMM

pdf-class수는 「3」、transition 수는 「6」

5 state HMM

pdf-class수는 「5」、transition 수는 「18」

음소 수 x 상태의 총 수는 「518」(5상태 x 10음소 + 3상태 x 156음소)

이 「518」 개의 하나하나에 pdf를 정의하는 것이 아니라, 닮은 음소 간 상태 pdf를 공유시킨다.

상태 간에 pdf를 공유하여, pdf의 총 수는 「127」이 된다.

<NUMPDFS> 127

상태 transition의 총 수는 「1116」이 된다(18transition x 10음소 + 6transition x 156음소)

(「LogProbs」엔트리와 같은 수)

<LogProbs> 
 [ 0 -0.3281818 -1.378509 -4.027719 -4.60517 ... -1.386294 -0.2876821 -1.386294 ]
</LogProbs> 

alignment로 출력되는 것은 상태 transition의 식별자(transition-id)에 해당한다.

예를 들어, 말하기 시작하는 부분의 「sil」에 대해서는 「2 1 1 1 8 5 5 5 18 17 17 17 17 17 17 17 17 17 17 …」로 나열된다.

번호를 부여하는 방법을 생각해보면, self-loop의 transition을 뒤에서부터 추가하는 것 같다.

이는 어느 state를 봤을 때 self-loop 쪽이 transition-id가 크게 되어있기 때문이다.

댓글 없음:

댓글 쓰기