티스토리 뷰

http://kaldi-asr.org/


이번 글에는 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_demogst_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 에서 확인되는 readlinkkaldi 에 필요한 옵션( -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.plrun.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 같은 것들이요. 샘플 스크립트 진행에 어려움이 있다면 주저하지 말고 연락주세요. 도움 드릴 수 있는 부분은 같이 고민하고 해결해보면 재미있을 것 같습니다. :-) 


댓글
  • 프로필사진 집가는중 감사합니다. kaldi는 실습용 데이터를 준다는 점이 정말정말 감사하네요 ^^
    설치하면 디렉토리에 떡하니 따라와 있기까지 하니 ㅎㅎ
    2019.02.11 11:08
  • 프로필사진 BlogIcon Jaeyeon Baek 네, 맞습니다. 흩어져있는 데이터가 칼디 자체에 대부분 명시돼 있어 좋죠 :-) 2019.02.11 17:53 신고
  • 프로필사진 솔로임 안녕하세요.
    올려주신 자료를 보면서 개념을 익히고 있습니다.
    예제를 따라하던 중에
    ./extras/install_sequitur.sh
    명령어 부분에서
    error: bad install directory or PYTHONPATH
    라는 오류가 생기는데
    검색해서 PYTHONPATH 부분을 site-packages 로 바꿔봐도 계속 같은 에러나 나는데
    그부분에 대해서 혹시 아시는게 있으신지요?
    2019.03.25 14:58
  • 프로필사진 BlogIcon Jaeyeon Baek 1)에서 path.sh을 다시 작용해서 시도해보면 좋을 것 같습니다. :) 2019.03.25 16:11 신고
  • 프로필사진 yhsang2@naver.com ./extras/install_sequitur.sh을 실행하면서 아래와 같은 에러가 발생하였는데요

    No module named setuptools
    > sudo apt-get install -y python-setuptools

    No module named numpy
    > apt install python-numpy

    입력하니까 해결이 되네요. 한참 헤메었네요 ㅠ
    제 환경은 python 2.7, ubuntu 18.04입니다. ^ ^
    좋은 포스팅 감사합니다. 마지막 ./run.sh까지 잘 실행되고 있는 것 같네요.
    2019.06.14 19:01
  • 프로필사진 BlogIcon Jaeyeon Baek 도움이 되셨다면 감사합니다. :) 2019.06.14 23:49 신고
댓글쓰기 폼