Kaldi Tutorial for Korean Model Part 3
Image source
칼디로 한국어 음성인식 구현하기 파트 3
- 본 튜토리얼은 칼디를 막 시작하는 초보자들을 대상으로 하고 있으므로 칼디를 어느정도 공부하신 분들에게는 적합하지 않을 수 있습니다. 모든 설명은 다음 깃헙에 올려진 run.sh 스크립트를 기준으로 진행되면 추가적으로 궁금한 사항은 칼디 공식 홈페이지나 칼디 구글 헬프를 이용하길 바랍니다.
- 본 튜토리얼에서 사용하는 스크립트는 맥과 리눅스(우분투) 환경에서 준비해왔기 때문에 그 외에 환경 (예: 윈도우)에서는 제대로 진행되지 않을수도 있습니다. 따라서 다소 불편하시더라도 이 부분은 최대한 맞춰주시고 튜토리얼을 진행하여 주시기 바랍니다.
- 튜토리얼에 사용되는 튜토리얼용 서울말 낭독체 코퍼스는 다음 링크를 통해 받으실 수 있으며, 튜토리얼 진행 도중 훈련에 필수적인 파일들이 제대로 생성되지 않을 상황에 대비해서 몇개의 파일을 미리 생성하여 준비하였으니 필요한 데이터는 그때마다 다운 받으시고 계속해서 진행해 나가시면 되겠습니다.
- 궁금한 사항이 있으실 경우 개인적인 메일을 보내시기 보다는 아래에 댓글을 다셔서 대부분의 질문이 이 튜토리얼을 보는 모든 분들과 공유되게 해주시기 바랍니다.
데이터 준비 - Data Preparation
-
krs_prep_data.sh
파트 2에서 여러가지 변수들을 셋팅하고 run.sh 훈련을 진행한다면 처음으로 data preparation 단계를 진행하게 된다. 본 단계에서는 krs_prep_data.sh를 실행하고 text, utt2spk, spk2utt, wav.scp, 와 segments 파일을 생성하는데, 이 파일들에 대해서는 파트 1에서 자세히 다루었기 때문에 여기서는 이에 대한 설명을 생략하겠다.
언어 모델 생성 - Language Modeling
-
krs_prep_dict.sh
-
데이터 준비가 끝났다면 다음은 언어모델 단계를 거치게 된다. 언어모델에서는 먼저 krs_prep_dict.sh을 통해 lexicon, lexiconp, silence, nonsilence, optional_silence, 와 extra_questions를 생성하게 되는데 이 부분 역시 파트 1에서 다루었기 때문에 자세한 설명을 생략하겠다.
-
krs_prep_dict.sh을 통해 생성되는 lexicon과 lexiconp의 경우 본 튜토리얼에서 제공하는 small_krs 데이터에 존재하는 단어들에 대해서만 음소열(혹은 발음열) 정보를 담고 있다. 그러므로 추가로 모은 데이터에 대한 단어들의 음소열 정보는 한국어 g2p(grapheme to phoneme) 프로그램을 통해 생성해야 하며, 본인이 생각하기에 적절하다고 생각하는 g2p 시스템을 찾아서 적용하면 된다.
-
-
utils/prepare_lang.sh
- krs_prep_dict.sh을 통해 생성된 데이터를 기반으로 L.fst와 그와 관련된 파일들을 생성한다.
- L.fst
- lexicon을 finite state transducer(fst)의 형태로 만든 결과물이며 이는 나중에 최종 결과물인 HCLG.fst을 만들기 위해 사용된다.
- kaldi에서는 openfst 툴을 이용해서 fst 결합을 진행하는데, 이에 대해 궁금하다면 openfst 사이트를 참조하여 공부하는것을 추천한다. 하지만 조금 많이 어려울 수도 있다.
- L_disambig.fst
- 이 파일은 L(lexicon)을 생성할 때, 구별할 수 있는 표식자를 추가로 붙인 결과물이다.
- 단어를 발음열로 나타내는 과정에서 단어는 비록 다르지만 그 발음열들이 같아서 그 둘을 구별하기 힘들 때 이들을 구분해주는 표식자를 붙이는 것이다.
- 예를들어, write와 right라는 단어가 있을 때, 이 둘의 단어 생김새는 다르지만 발음은 /rait/로 동일하다. 이럴 경우 #1같은 disambig 기호를 사용해서 둘을 구분짓는다. 방금 언급한 예시를 fst로 표현하자면 다음과 같다고 할 수 있다. 참고로 아래의 예시는 정확한 L_disambig.fst를 표현한 것은 아니며 오직 다음과 같은 순서로 발음열과 disambig 기호가 연결되었다는것을 보여주고자 단순화 한 것이다. 정확한 그림은 이 사이트를 참고하길 바란다.
- oov.txt & oov.int
- oov는 out of vocabulary의 약자로 사전에 없는 단어들을 처리할 때 사용할 특정 기호를 의미한다. prepare_lang.sh를 실행할 때, 두번째 인자로 들어가는 기호가 oov.txt에 담기며 본 튜토리얼에서는 <UNK>를 사용하고 이는 unknown의 앞 3글자를 따온것이다.
- 이 oov 기호는 lexicon(사전)이 보지못한 단어들을 처리할 때 사용한다고 했는데 예를들어, 내가 가진 lexicon은 1만개의 단어를 담고 있고, 내가 언어모델로 훈련할 텍스트 파일은 1만 5천개의 단어를 가지고 있다고 해보자. 이 때 lexicon에 담고 있는 1만개의 단어가 텍스트 파일에 존재하는 1만개의 단어를 포함한다고 할 때 나머지 5천개에 대해서는 포함하지 못하게 된다. 즉 텍스트 파일에 존재하는 5천개의 단어는 어떻게 발음할지를 모르므로 최종 fst 결합에 사용할 수 없기에 이러한 단어들을 oov 기호를 사용해 일괄 처리한다.
- oov.int는 oov.txt에 정의된 oov 기호를 숫자로 정의한 것으로 실제 fst 단에서는 글자가 아닌 이 oov.int에 적힌 숫자를 참고한다.
- phones (폴더)
- phones 폴더에는 훈련에 사용할 다양한 음소정보를 세밀하게 여러 파일로 분리하여 정리해 놓았다.
- *.txt는 실제 사용하는 음소 기호를 적어놨으며, *.int는 그 기호를 숫자로 정의한 것이고, *.csl은 colon-separated list로 콜론(:)을 이용하여 그 기호 숫자들을 정리하였다.
- phones.txt
- 각 음소와 그 음소를 연결해주는 숫자를 적은 파일로 훈련에 사용할 모든 음소에 대한 정보를 담고 있다.
- words.txt
- 각 단어와 그 단어를 연결해주는 숫자를 적은 파일로 훈련에 사용할 모든 단어에 대한 정보를 담고 있다.
- topo
- 모든 음소에 대한 음향모델 훈련을 진행할 때, 특정 음소들을 그룹짓고 그 그룹에 대한 훈련 state 개수와 초기 확률 값을 정의한 파일로, 본 튜토리얼에서는 silence 음소와 nonsilence 음소, 2가지 그룹으로 나누고 각 그룹에 대한 훈련 state 개수 및 초기 확률값을 다르게 설정하였다. 물론 이는 prepare_lang.sh에서 지정하는 기본 값이기도 하다.
- topo에서 정의한 한가지 음소 그룹에 대한 state 개수 및 초기확률 값에 대해서 알아보자. topo 파일 상위에 보면 첫번째로 정의된 음소 그룹이 보이는데, 이들은 사이에 정의된 11 ~ 194까지의 음소들이다. (phones.txt 적힌 숫자들을 역추적해보면 실제 어떤 음소인지 알 수 있다) 이들에 대해서는 총 3개의 state가 정의되어 있으며(실제로 시작과 끝 state까지 포함하면 총 5개다) 각 state로 넘어가는 transition 확률값이 적혀있다.
<State> 0 <PdfClass> 0 <Transition> 0 0.75 <Transition> 1 0.25 </State>
- topo 6번째 줄에 대해서 설명하자면 0번 째 state가 0번째 state로 이동(transition)할 확률은 0.75이며 1번째 state로 이동할 확률은 0.25라는 의미이다. 이를 풀어 말하자면 현재 state에서 75%의 확률은 현재 자리에 그대로 있거나 25%의 확률로 그 다음 state로 넘어간다는 의미이다. 본 값들은 초기 값이므로 추후 훈련을 통해 변해나가게 되며, 위 topo 라인에 대해서 그래프로 표현하면 다음과 같다.
- L.fst
- krs_prep_dict.sh을 통해 생성된 데이터를 기반으로 L.fst와 그와 관련된 파일들을 생성한다.
-
ngram-count
- kaldi에서는 언어모델 훈련을 위해 srilm 툴을 이용하는데 이 때 ngram-count를 이용하여 훈련을 한다. ngram-count에서 제공하는 다양한 학습방식에 대해서는 다음의 사이트를 참고하도록 하고 사이트상에서 언급된 언어모델 학습방식은 따로 시간을 들여 공부를 해야한다. 참고로 언어모델에 대해 공부하고자 한다면 Stanford 대학에서 Dan Jurafsky 교수님과 Chris Manning교수님이 제공하는 NLP 강의를 추천한다. 물론 이것 또한 쉽지 않겠지만 오랜 시간(대략 1년?) 공부하겠다는 마음을 갖고 시작한다면 해볼만하다.
- 본 튜토리얼에서는 기본적인 훈련 방식인 good-turing 방식을 이용하여 언어모델 학습을 진행하며 이를 통해 lm.arpa 파일을 얻게된다.
- arpa 포맷으로 저장된 이 언어모델은 \data\ 영역과 각 \n-gram\ 영역의 정보를 담고 있으며 언어모델 훈련중 따로 옵션을 주지 않았다면 3-gram까지 훈련을 진행하기 때문에 \data\에는 1-gram, 2-gram, 3-gram 훈련에 사용된 단어 연쇄 개수와 각 \1-gram\, \2-gram\, \3-gram\ 에 대한 단어 연쇄들과 확률값이 담겨있다.
- 이렇게 lm.arpa를 생성하였다면 이를 fst 형태로 변환하는 과정을 거쳐서 G.fst를 생성한다면 최종적으로 언어모델 훈련이 끝난다.
음성 특징 추출 - Acoustic Feature Extraction
훈련에 사용할 음성데이터를 바로 사용하기보단 적절한 작업을 거쳐 훈련에 좀 더 유리한 상태로 만들어 주는 작업이 필요하다. 이러한 작업을 음성 특징 추출 이라고 하는데, 본 튜토리얼에서는 다양한 음성관련 분야에서 사용하는 대표적인 음성특징 기법인 mfcc를 사용할 것이며 추가적으로 plp 방식에 대해서는 옵션으로 제공한다.
- steps/make_mfcc.sh
- mfcc를 추출할 때 다양한 변수값을 설정할 수 있는데, 이 중 2가지 값만 미리 설정할 것이며 그 외에 변수값을 변경하고자 한다면 featbin/compute-mfcc-feats를 실행하여 설정가능한 변수명들을 확인하면 된다.
- --use-energy
- 이 값을 false로 진행하여 mel filterbank 들의 평균 log값을 이용할 것이다.
- --sampling-frequency
- 오디오 자료를 저장할 때 초당 몇개의 샘플을 이용하느냐에 따라 sampling rate(또는 sampling frequency)가 결정되는데, 본 튜토리얼에서 사용하는 small_krs에 경우 초당 16000 샘플을 이용하므로 변수에 16000 정보를 넣어 준다.
- 혹시라도 따로 준비한 데이터를 추가로 훈련에 넣고 싶을 경우 오디오 데이터의 sampling rate를 16000으로 조정한 뒤에 사용해야 한다.
- --use-energy
- 훈련 데이터와 테스트 데이터에 대해 각각 mfcc를 추출한뒤에 cmvn(cepstral mean and variance normalization) 작업을 진행하여 최종적으로 특징 표준화 작업을 해줌으로써 특징 추출을 마무리 짓는다.
- mfcc에 대해 자세히 알고싶다면 다음 사이트를 참조하길 바란다.
- mfcc를 추출할 때 다양한 변수값을 설정할 수 있는데, 이 중 2가지 값만 미리 설정할 것이며 그 외에 변수값을 변경하고자 한다면 featbin/compute-mfcc-feats를 실행하여 설정가능한 변수명들을 확인하면 된다.
댓글
댓글 쓰기