[Kaldi] Run sample script on Mac – 발췌
발췌 : https://jybaek.tistory.com/772?category=777833
이번 글에는 Kaldi 에서 제공하는 샘플 스크립트를 통해 기본적인 테스트를 진행하는 과정을 살펴봅니다. 테스트를 진행하기 전에 잠깐 Kaldi 의 디렉터리 구조를 살펴볼 필요가 있는데요, 소스코드를 내려받고 살펴보면 아래와 같은 구조를 확인할 수 있습니다.
$ tree -L 1
.
├── COPYING
├── INSTALL
├── README.md
├── egs/
├── misc/
├── scripts/
├── src/
├── tools/
└── windows/
6 directories, 3 files
6개의 디렉터리와 3개의 파일로 구성되어 있군요. 파일은 설치 과정이 메모되어 있는 INSTALL 과 프로젝트 소개가 있는 README.md, 그리고 카피라이트인 COPYING 가 있습니다. 디렉터리는 앞서 살펴본 src, tools 를 제외하고 살펴봅시다. windows 는 윈도우즈 사용자를 위한 설치를 위한 방법과 파일들로 구성되어 있습니다. 넘어가도록 하죠. 이제 scripts 디렉터리와 egs 가 남았는데 egs 가 중요합니다.
egs
egs 는 eg ( 라틴어로 exempli gratia, 영어로는 for example )와 scripts 의 합성어로 예제 스크립트를 모아놓은 디렉터리라는 뜻이겠습니다.
$ ls egs/
README.txt fisher_english sre08
aishell fisher_swbd sre10
aishell2 gale_arabic sre16
ami gale_mandarin svhn
an4 gp swahili
apiai_decode heroico swbd
aspire hkust tedlium
aurora4 hub4_english thchs30
babel hub4_spanish tidigits
babel_multilang iam timit
bentham iban tunisian_msa
bn_music_speech ifnenit uw3
callhome_diarization librispeech voxceleb
callhome_egyptian lre voxforge
chime1 lre07 vystadial_cz
chime2 madcat_ar vystadial_en
chime3 madcat_zh wsj
chime4 mini_librispeech yesno
chime5 multi_en yomdle_fa
cifar ptb yomdle_korean
commonvoice reverb yomdle_russian
csj rimes yomdle_tamil
dihard_2018 rm yomdle_zh
fame sitw zeroth_korean
farsdat sprakbanken
fisher_callhome_spanish sprakbanken_swe
다양한 예제가 보이는데 이중에는 놀랍게도 한글 예제도 존재합니다. 바로 zeroth_korean 인데요, 이쪽을 통해서 해당 프로젝트를 살펴볼 수 있습니다. 하지만 여기서는 더이상 논의하지 않도록 합니다. 왜냐하면 zeroth_korean 은 그쪽 Repo 를 통해 사용법을 쉽게 확인할 수 있기 때문입니다. 우리는 Kaldi 의 일반적인 샘플을 돌려보고 새롭게 프로젝트를 추가해보는 것이 최종 목표입니다. 일단 egs/README.txt 를 통해 egs 를 어떻게 접근해야되는지 들여다봅시다.
$ cat README.txt
This directory contains example scripts that demonstrate how to
use Kaldi. Each subdirectory corresponds to a corpus that we have
example scripts for.
Note: we now have some scripts using free data, including voxforge,
vystadial_{cz,en} and yesno. Most of the others are available from
the Linguistic Data Consortium (LDC), which requires money (unless you
have a membership).
If you have an LDC membership, probably rm/s5 or wsj/s5 should be your first
choice to try out the scripts.
읽어보니 샘플에서 사용하는 모든 데이터가 무료는 아닌걸로 보이네요. 무료 데이터를 제공하는건 voxforge, vystadial_{cz,en}, yesno 가 있습니다. 일단 어떤 샘플로 테스트를 해볼지 안에 디렉터리를 봅시다. ( LDC 멤버라면 Resource Management, 혹은 월스트리트 저널의 말뭉치인 wsj 를 먼저 돌려보는 것이 좋다고 합니다 )
무료 샘플을 살펴보기 위해 각 디렉터리 하위가 어떻게 생겼는지 확인해봅시다.
$ ls voxforge/ vystadial_* yesno/
voxforge/:
gst_demo online_demo s5
vystadial_cz:
README.txt online_demo s5 s5b
vystadial_en:
README.txt online_demo s5
yesno/:
README.txt s5
구성을 보니, online_demo 와 gst_demo 가 있는 voxforge 가 눈에 들어옵니다. voxforge 를 바로 사용해보도록 합니다.
voxforge
디렉터리 안에 있는 {gst, online}_demo 는 일단 무시하고 s5 로 이동합시다. egs 안에 있는 모든 s5 디렉터리는 아래와 유사한 구성을 띄고 있습니다.
$ ls -al
total 48
drwxr-xr-x 10 caley staff 320 1 24 11:50 .
drwxr-xr-x 5 caley staff 160 1 24 11:50 ..
-rw-r--r-- 1 caley staff 904 1 24 11:50 cmd.sh
drwxr-xr-x 4 caley staff 128 1 24 11:50 conf
-rwxr-xr-x 1 caley staff 932 1 24 11:50 getdata.sh
drwxr-xr-x 14 caley staff 448 1 24 11:50 local
-rwxr-xr-x 1 caley staff 841 1 24 11:50 path.sh
-rwxr-xr-x 1 caley staff 9364 1 24 11:50 run.sh
lrwxr-xr-x 1 caley staff 18 1 24 11:50 steps -> ../../wsj/s5/steps
lrwxr-xr-x 1 caley staff 18 1 24 11:50 utils -> ../../wsj/s5/utils
이제 실습 순서는 다음과 같이 진행됩니다. 1) path.sh 의 일부를 수정 할 텐데 후에 데이터를 다운로드 하게 될 디렉터리인 DATA_ROOT 를 지정해주고, 2) getdata.sh 을 실행해서 데이터를 다운로드 합니다. 3) 미리 필요한 환경 구축을 합니다. 이 과정은 run.sh 을 실행할 때 발생되는 각종 예외를 잡는 단계이기 때문에 매우 중요한 과정입니다. 4) 끝으로 run.sh 을 통해 실제 학습을 진행합니다.
1) path.sh
자, 아래 path.sh 의 일부를 가져왔습니다. vim 이나 emacs 등의 편집기로 path.sh 을 열고 export 앞에 있는 셸 스크립트의 주석 기호인 # 을 제거해줍니다.
# VoxForge data will be stored in: # export DATA_ROOT="$KALDI_ROOT/egs/voxforge/s5/voxforge" # e.g. something like /media/secondary/voxforge
편집이 끝났으면 path.sh 을 실행해서 DATA_ROOT 를 적용시켜 줍니다.
$ sh path.sh
2) getdata.sh
다음으로 학습 데이터 다운로드 스크립트를 실행 할 텐데 다운로드 되는 데이터( 대략 20-25GB )를 위해 디스크의 여유공간을 확보하고 getdata.sh 을 실행 시킵니다.
$ ./getdata.sh
--- Starting VoxForge data download (may take some time) ...
--2019-01-31 21:01:44-- http://www.repository.voxforge1.org/downloads/SpeechCorpus/Trunk/Audio/Main/16kHz_16bit
Resolving www.repository.voxforge1.org (www.repository.voxforge1.org)... 74.208.236.70
Connecting to www.repository.voxforge1.org (www.repository.voxforge1.org)|74.208.236.70|:80... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: http://www.repository.voxforge1.org/downloads/SpeechCorpus/Trunk/Audio/Main/16kHz_16bit/ [following]
--2019-01-31 21:01:45-- http://www.repository.voxforge1.org/downloads/SpeechCorpus/Trunk/Audio/Main/16kHz_16bit/
Reusing existing connection to www.repository.voxforge1.org:80.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]
Saving to: '/Users/caley/work/kaldi/egs/voxforge/s5/../../../egs/voxforge/s5/voxforge/tgz/16kHz_16bit.tmp'
16kHz_16bit.tmp [ <=> ] 993.03K 347KB/s in 2.9s
Last-modified header missing -- time-stamps turned off.
2019-01-31 21:01:49 (347 KB/s) - '/Users/caley/work/kaldi/egs/voxforge/s5/../../../egs/voxforge/s5/voxforge/tgz/16kHz_16bit.tmp' saved [1016862]
Removing /Users/caley/work/kaldi/egs/voxforge/s5/../../../egs/voxforge/s5/voxforge/tgz/16kHz_16bit.tmp since it should be rejected.
--2019-01-31 21:01:50-- http://www.repository.voxforge1.org/downloads/SpeechCorpus/Trunk/Audio/Main/16kHz_16bit/?C=N;O=D
Reusing existing connection to www.repository.voxforge1.org:80.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]
...
...
zlp-20100110-wwn.tgz 100%[=======================================================================>] 1.40M 2.34MB/s in 0.6s
2019-01-31 23:12:51 (2.34 MB/s) - '/Users/caley/work/kaldi/egs/voxforge/s5/../../../egs/voxforge/s5/voxforge/tgz/zlp-20100110-wwn.tgz' saved [1464469/1464469]
FINISHED --2019-01-31 23:12:51--
Total wall clock time: 2h 11m 7s
Downloaded: 6250 files, 10G in 1h 45m 21s (1.69 MB/s)
--- Starting VoxForge archives extraction ...
아래 명령어로 전체 데이터 중에 얼마나 다운로드가 완료 되었는지 중간중간 확인이 가능합니다.
$ du -sh voxforge/
25G voxforge/
3) 필요한 환경 구축
다운로드를 기다리는 동안 아래 있는 패키지들을 미리 설치해둡니다. 다른건 에러가 발생하면 그때그때 설치해도 되지만 coreutils 의 경우에는 미리 설치 하지 않으면 여러가지 귀찮은 일이 생깁니다.
$ brew install gawk && brew install coreutils && brew install swig && brew install flac
뒤에서 발생할 에러를 미리 잡아두기 위해 아래와 같이 alias 도 잡아줘야 하는데 우리가 MacOS 환경이기 때문에 필요한 내용입니다. 대부분의 *NIX 시스템에는 readlink 패키지가 기본 설치 되어 있으므로 무시해도 되는 과정입니다만, MacOS 에서 확인되는 readlink 는 kaldi 에 필요한 옵션( -f )이 없습니다.
$ alias readlink=greadlink
자, 다음은 kaldi root 디렉터리로 이동해서 tools 에 있는 install_srilm.sh 을 실행시켜줍니다. 여기서 중요한건 tools 디렉터리에 들어가서 실행시켜줘야 합니다. ( 그렇지 않은 경우 디렉터리를 이동하라는 에러가 발생합니다 )
$ ./install_srilm.sh
Installing libLBFGS library to support MaxEnt LMs
--2019-02-01 09:07:30-- https://github.com/downloads/chokkan/liblbfgs/liblbfgs-1.10.tar.gz
Resolving github.com (github.com)... 192.30.255.112, 192.30.255.113
Connecting to github.com (github.com)|192.30.255.112|:443... connected.
...
...
This script cannot install SRILM in a completely automatic
way because you need to put your address in a download form.
Please download SRILM from http://www.speech.sri.com/projects/srilm/download.html
put it in ./srilm.tgz, then run this script.
뭔가 다운로드 받고 설치 되는 듯 보이더니 마지막 문구가 눈에 띄네요. http://www.speech.sri.com/projects/srilm/download.html 이쪽 사이트에 방문해서 직접 SRILM 을 다운로드 받고 스크립트를 실행시켜야 한답니다. 미리 말씀드리자면 아무리 무료라고하지만 데이터를 다운로드 받기 위해서는 몇 가지 정보를 입력하고 라이선스에 동의해야 하기 때문인데요. 브라우저를 열고 페이지에 방문하면 중간쯤에 아래와 같은 내용이 보입니다.
적절하게 정보를 입력하고 I accept the License 버튼을 클릭하면 데이터 다운로드가 시작됩니다. 다운로드가 완료되면 (이 글을 쓰는 시점에는) 파일명이 install_srilm.sh 에 고정되어 있는 이름과 다르기 때문에 변경해서 tools/ 디렉터리 밑으로 이동시켜줘야 합니다. 아래처럼 진행하도록 합시다.
$ mv ~/Downloads/srilm-1.7.2.tar.gz ./srilm.tgz
그리고나서 다시 install_srilm.sh 을 다시 실행시켜주면 됩니다.
$ ./install_srilm.sh
...
...
Installation of SRILM finished successfully
Please source the tools/env.sh in your path.sh to enable it
설치가 끝나면 install_sequitur.sh 도 미리 실행시켜줍니다. 일반적인 순서로 진행하게 되면 발생하는 에러를 미리 처리하는 과정입니다. 혹시 아래 스크립트를 실행하는데 readlink: illegal option — f 이런 내용이 출력된다면 위에서 alias 했던걸 다시 적용해줍니다. 이전과 다른 셸에서 진행하게 되면 alias가 반영이 안되어 있기 때문에 그럴 수 있습니다. ( .bash_profile 등에 넣어두는 것도 좋은 방법입니다 )
$ ./extras/install_sequitur.sh
...
...
Installation of SEQUITUR finished successfully
Please source tools/env.sh in your path.sh to enable it
이제 egs/voxforge/s5 디렉터리로 돌아와서 ./local/voxforge_prepare_dict.sh 파일을 수정해줘야 합니다. 편집기를 열고 아래와 같은 라인을 찾읍시다.
sequitur=$KALDI_ROOT/tools/sequitur
그리고 다음과 같이 -g2p 를 추가해주도록 합니다. 이부분은, 빠르게 변하는 kaldi 의 업그레이드를 구석에 있는 예제 셸스크립트가 따라가지 못한 겁니다. 이 글이 쓰이는 시점 이후에 kaldi 를 최신으로 받았다면 아래 내용은 이미 반영되어 있을 겁니다. 제가 여러분을 위해 kaldi 프로젝트에 Pull Request 해서 Merge 가 됐거든요.
sequitur=$KALDI_ROOT/tools/sequitur-g2p
이제 끝으로 cmd.sh 을 수정해줄 차례입니다. cmd.sh 안에는 train_cmd, decode_cmd, mkgraph_cmd 가 queue.pl 로 설정되어 있는데 이 부분을 run.pl 로 변경해줍니다. 이는 GridEngine 이 없거나 단일 컴퓨터 안에서 모든 것을 처리하려고 할 때 설정해주는 부분인데 정확히 우리 상황과 일치합니다. GridEngine 를 설치하는 것 조차 MacOS 에서는 쉽지 않으니까요. 아무튼 아래처럼 모든 queue.pl 을 run.pl 로 변경해줍시다.
-export train_cmd="queue.pl --mem 2G"
-export decode_cmd="queue.pl --mem 4G"
-export mkgraph_cmd="queue.pl --mem 8G"
+export train_cmd="run.pl --mem 2G"
+export decode_cmd="run.pl --mem 4G"
+export mkgraph_cmd="run.pl --mem 8G"
4) run.sh
이제 최종단계입니다. path.sh 를 통해 환경변수를 다시 잡아주고 run.sh 스크립트를 실행시켜줍니다.
$ ./path.sh && ./run.sh
이 과정에서 다운로드 받은 데이터를 train 세트로 묶는등의 작업이 이루어집니다. 이제 거의 다 됐습니다
조금 여유를 갖고 기다려줍시다.
$ ./run.sh
=== Starting VoxForge subset selection(accent: ((American)|(British)|(Australia)|(Zealand))) ...
*** VoxForge subset selection finished!
=== Starting to map anonymous users to unique IDs ...
--- Mapping the "anonymous" speakers to unique IDs ...
*** Finished mapping anonymous users!
=== Starting initial VoxForge data preparation ...
--- Making test/train data split ...
2003 data/local/tmp/speakers_all.txt
1983 data/local/tmp/speakers_train.txt
20 data/local/tmp/speakers_test.txt
2003 total
--- Preparing test_wav.scp, test_trans.txt and test.utt2spk ...
--- Preparing test.spk2utt ...
--- Preparing train_wav.scp, train_trans.txt and train.utt2spk ...
Illegal or empty gender (u) for "anonymous0107-20080905-tvm" - assuming m(ale) ...
Illegal or empty gender (p) for "anonymous0354-20091027-coy" - assuming m(ale) ...
Illegal or empty gender (u) for "anonymous0532-20100612-ojf" - assuming m(ale) ...
Illegal or empty gender (p) for "anonymous0728-20110406-opo" - assuming m(ale) ...
Illegal or empty gender (p) for "anonymous0764-20110719-rxx" - assuming m(ale) ...
Illegal or empty gender (p) for "anonymous1208-20140513-nmn" - assuming m(ale) ...
Illegal or empty gender (u) for "guilherme-20080123-pfh" - assuming m(ale) ...
Illegal or empty gender (u) for "ridgey-20080620-zrx" - assuming m(ale) ...
...
...
%WER 52.33 [ 2337 / 4466, 28 ins, 1036 del, 1273 sub ]
%SER 90.00 [ 450 / 500 ]
exp/mono/decode/wer_15
%WER 53.83 [ 2404 / 4466, 25 ins, 1100 del, 1279 sub ]
%SER 90.60 [ 453 / 500 ]
exp/mono/decode/wer_16
%WER 54.88 [ 2451 / 4466, 19 ins, 1152 del, 1280 sub ]
%SER 90.80 [ 454 / 500 ]
...
...
steps/train_deltas.sh: training pass 13
steps/train_deltas.sh: training pass 14
steps/train_deltas.sh: training pass 15
steps/train_deltas.sh: training pass 16
steps/train_deltas.sh: training pass 17
steps/train_deltas.sh: training pass 18
...
...
마무리
Kaldi 는 Speech Recognition Toolkit 의 강자 답게 누구나 쉽게 접근할 수 있습니다. 다만 이번 예제를 진행하면서 아쉬웠던 점은 예제를 진행하기 위한 dependencies 를 체크할 수 있었다면 여러 삽질을 피해갈 수 있지 않았을까 하는 점입니다. 사실 이 부분은 한번 환경을 구축하면 다시 볼 일이 없기 때문에 굉장히 사소한 부분이기도 하지만요. 아무튼 이제 사용자의 데이터를 학습시킬 수 있는 환경 구축은 끝났습니다. 위 스크립트가 실제로 완료되는 것을 기다리려면 시스템의 절전모드 등을 꺼주세요. 대략 며칠 정도 걸립니다.
자, 그럼 다음편에서는 Kaldi 디렉터리와 스크립트의 세부사항을 확인하고 본격적으로 Kaldi 를 다뤄보겠습니다.
(*) 어쩌면 제 환경에는 다른 프로젝트를 진행하며 설치했던 패키지가 사전에 준비되어 있어서 문제가 안됐던 부분이 있을 수도 있습니다. 이를테면 numpy 같은 것들이요. 샘플 스크립트 진행에 어려움이 있다면 주저하지 말고 연락주세요. 도움 드릴 수 있는 부분은 같이 고민하고 해결해보면 재미있을 것 같습니다. 🙂