# Project: Zeroth


## 0. phone symbol mapping table in Zeroth
Caution: For IPA symbol mappings, it has not been tested if it is proper enough to train or not. I'm trying to change the Zeroth phone symbols into IPA form to design a universal acoustic model, But it is not finialized.

```
CHOSUNG_LIST =  [u'ㄱ', u'ㄲ', u'ㄴ', u'ㄷ', u'ㄸ', u'ㄹ', u'ㅁ', u'ㅂ', u'ㅃ', u'ㅅ',\
                 u'ㅆ', u'ㅇ', u'ㅈ', u'ㅉ', u'ㅊ', u'ㅋ', u'ㅌ', u'ㅍ', u'ㅎ']
JUNGSUNG_LIST = [u'ㅏ', u'ㅐ', u'ㅑ', u'ㅒ', u'ㅓ', u'ㅔ', u'ㅕ', u'ㅖ', u'ㅗ', u'ㅘ',\
                 u'ㅙ', u'ㅚ', u'ㅛ', u'ㅜ', u'ㅝ', u'ㅞ', u'ㅟ', u'ㅠ', u'ㅡ', u'ㅢ', u'ㅣ']
JONGSUNG_LIST = [u'_', u'ㄱ', u'ㄲ', u'ㄳ', u'ㄴ', u'ㄵ', u'ㄶ', u'ㄷ', u'ㄹ', u'ㄺ',\
                 u'ㄻ', u'ㄼ', u'ㄽ', u'ㄾ', u'ㄿ', u'ㅀ', u'ㅁ', u'ㅂ', u'ㅄ', u'ㅅ',\
                 u'ㅆ', u'ㅇ', u'ㅈ', u'ㅊ', u'ㅋ', u'ㅌ', u'ㅍ', u'ㅎ']

CHOSUNG_SYM =  [u'g', u'gg', u'n', u'd', u'dd', u'l', u'm', u'b', u'bb', u's',\
                u'ss', u'', u'j', u'jj', u'ch', u'kh', u't', u'p', u'h']
JUNGSUNG_SYM = [u'a', u'ae', u'ya', u'yae', u'eo', u'e', u'yeo', u'ye', u'o', u'wa',\
                u'wae', u'oe', u'yo', u'u', u'wo', u'we', u'wi', u'yu', u'eu', u'ui', u'i']
JONGSUNG_SYM = [u'', u'g2', u'', u'', u'n2', u'', u'', u'd2', u'l2', u'',\
                u'', u'', u'', u'', u'', u'', u'm2', u'b2', u'', u'',\
                u'', u'ng', u'', u'', u'', u'', u'', u'']

CHOSUNG_SYM_IPA =  [u'k', u'k͈', u'n', u't', u't͈', u'ɾ', u'm', u'p', u'p͈', u'sʰ',\
                    u's͈', u'', u't͡ɕ', u't͡ɕ͈', u't͡ɕʰ', u'kʰ', u'tʰ', u'pʰ', u'h']
JUNGSUNG_SYM_IPA = [u'a', u'ɛ', u'ja̠', u'jɛ̝', u'ʌ̹', u'e', u'jʌ', u'je', u'o', u'wa',\
                    u'wɛ̝', u'we', u'jo', u'u', u'wʌ', u'we', u'y', u'ju', u'ɯ', u'ɰi', u'i']
JONGSUNG_SYM_IPA = [u'', u'k̚', u'', u'', u'n', u'', u'', u't̚', u'ɭ', u'',\
                    u'', u'', u'', u'', u'', u'', u'm', u'p̚', u'', u'',\
                    u'', u'ŋ', u'', u'', u'', u'', u'', u'']
```


## 1. Introduction to Korean ASR
음성인식기를 만들기 위해서는 크게는 음향모델, 언어모델, 발음사전 세 가지가 필요합니다. 

**음향모델**은 컴퓨터에게 소리를 익히도록 하는 부분입니다. '가다'라는 소리를 음소(phoneme)단위 'ㄱ+ㅏ+ㄷ+ㅏ'로 분리해서 
각각의 음소는 실제로 어떤 소리다라고 매칭해서 알려주는 것이죠. 이것을 통해 특정 소리가 어떤 음소인지 컴퓨터가 
구분할 수 있게 됩니다. 사람이 언어를 배울 때, 새로운 언어를 많이 듣다보면 그 소리에 익숙해지는 것과 같습니다. 

**발음사전**은 우리에게 익숙한 말 그대로 사전입니다. 단어(vocabulary)와 발음(pronunciation)으로
구성됩니다. 예를들면, '덮다'를 [ㄷㅓㅂㄸㅏ]로 표현하는 것이죠. 이렇게 단어를 발음, 즉 음소들로 표현하게 되면
이제 사람이 말하는 소리를 듣게되면 학습된 음향 모델을 통해 
소리를 음소로, 음소를 다시 단어로 인식할 수 있게 됩니다.

**언어모델**은 단어들로 이루어진 실제 언어, 즉 실제 사람들이 사용하는 말을 인식 할 수 있게 해주는 것입니다.
여기에 사용되는 방법을 N-gram 확률언어모델(statistical language model)이라고 하는데, 사람들이 많이
사용하는 수 많은 문장들을 분석해서 어떤 단어가 많이 쓰이는지, 어떤 단어 뒤에, 혹은 앞에는 어떤 단어들이 사용되는지를 
확률적으로 분석해서 기록해 놓습니다. 앞 뒤 상관관계를 최대 n개 까지 확인하기 때문에 n-gram 이라 불립니다.
이런 확률모델까지 준비가 되면 이론적으로, 소리를 음소로, 음소를 모아 단어로, 단어를 모아 문장으로 표현할 수 있고,
실제 사람이 말한 소리와 확률적으로 가장 비슷한 문장을 찾아낼 수 있습니다. 

음성인식기를 만드는 가장 최신 기술에서는 상기 세가지 구성요소를 모두 machine learning,
좀더 정확히 말하면 neural network 를 사용해서 표현하는 End-to-end (DNN) ASR 시스템이 제안되고 있습니다.
최근 어마어마한 관심을 받고 있는 분야이지요. 

사실 지금의 DNN (Deep Neural Network)의 열풍을 가지고 온 것은 DNN을 적용했을 때, 음성인식 성능이 기가막힐 정도로 
좋아진다는 사실을 확인하게 되면서라고 생각합니다. 물론 개인적인 의견이고, 영상부분에서는 다른 방식으로 주목받았습니다. 
오랜 시간, 음성인식기의 성능은 WER(Word Error Rate) 15% 정도(영어기준)의 매우 사용하기 불편한 정도의 수준으로 답보상태에 정체되어 있었습니다. 
하지만 2009~2011 Geoffrey Hinton 이라는 neural network의 아버지 쯤 되는 캐나다의 교수님이 여러층의 신경망을 쌓은 
DNN 형태로 음성인식기의 **음향모델**을 바꾸기만 했는데 WER이 10% 아래로 드라마틱하게 떨어지는 것을 발견하게 되었습니다.
그래서 현재는 음향모델은 DNN으로 구현하는 것이 정설이고, 발음사전과, 언어모델도 NN을 활용하여 구현하려는 시도들이 진행되고 있습니다.

최근 2017년까지의 행보들을 보면 character-level 에서 훈련된 LSTM-LM 언어모델들이 시도되었고 매우 좋은 성능들이 확인되고 있습니다.
현재까지는 wFST 기술에 기반한 전통적인 디코딩 방식이 상용화에 더 유리한 성능을 보이고 있지만,
향후 2~3년 안에는 분명 End-to-End ASR 방식이 주류가 될 것으로 보여집니다.

제로스 프로젝트에서는 먼저 전통적인 방식으로 한국어 음성인식기를 개발하고 추후에 End-to-end DNN 방식까지 진행할 예정입니다.
물론 현재 kaldi 에 적용된 음향모델인 TDNN-LSTM + chain 모델 역시 전통적인 ASR 방식에서는 매우 진보된 형태입니다. 
다만 전통적인 방식으로 발음사전과 N-gram 언어모델을 한국어에 맞게 이용하겠다는 면에서 End-to-End ASR 이 아니기 때문에 
전통적인 방식이라는 표현을 사용하였습니다. 

### 한국어 인식 단위(형태소)
앞서 발음사전을 설명할 때, 단어(word)라는 표현을 사용했는데, 사실 영어에서는 맞는 말이지만 한국어에서는 조금
다른 표현이 필요합니다. 영어의 경우 단어사전은 띄어쓰기 단위와 일치하는 말그대로 단어(word)를 사용할 수 있지만 한국어는
그렇게 하면 많은 어려움이 있기 때문에 띄어쓰기 단위보다 조금 더 작은 형태소(morpheme) 단위에서 단어장을
만듭니다. 왜냐햐면 언어를 유형론적으로 분류(Toypological Classification)했을 대, 영어는 굴절어(inflective Language) 
한국어는 교착어(agglutinative language)로 분류되기 때문입니다. 갑자기 머리가 아픈데, 사실 어려운 단어들은
언어학자들의 몫이고, 사실은 언어학자가 아니더라도 영어와 한국어는 매우 다르다는 것을 쉽게 알 수 있습니다. 

영어는 일단 단어의 변화가 크지 않습니다.
```
want / wanted / wants / wanting 
```
하지만 한국어는 어근에 접사, 어미가 결합되면서 다양한 의미를 가지게 되지요.
``` 
가+다/ 가+고 / 가+시+다/ 가+시+었다 / ...
```
문제는 한국어와 같은 교착어는 위와 같은 변화가 너무 다양하다는데 있습니다. 예를 들어 한국어 음성인식에
사용될 단어장을 만든다고 생각해보겠습니다. 과연 특정 말뭉치(corpus)에서 독립적인 단어가 몇 개쯤 나올까요?
독립적인 단어라는 뜻이 애매함으로 단순히 띄어쓰기 단위로 나눈 어절들 중에서 독립적인 어절을 찾는다고
가정해보겠습니다. 앞서 말한 것 처럼, 한국어는 하나의 동사 '가다' 에도 수많은 변화형이 가능하기 때문에 
말뭉치의 크기가 커지면 고유한 어절만 모아 단어장을 만들더라도 그 크기가 무한정 늘어나게됩니다.
혹시나 유한하게 만든다 하더라도 그걸 분석하는데는 sparsity 라는 수학적인 문제가 생깁니다. 

그래서 보통은 띄어쓰기 단위보다 좀 더 세분화된 형태소(morpheme) 단위에서 분석을 합니다. 
형태소 분석을 통해 말뭉치를 분석하고 형태소 단위에서 고유한 어절을 모아 단어장을 만듭니다.
많은 NLP 관련 프로젝트들에서는 그래서 형태소 분석기를 사용하지요. 하지만 사실 언어라는 것은 시간에 따라
바뀌고, 늘 새로운 단어들이 출현하고 없어지기 때문에, 새롭게 만들어지고 쓰이는 단어들에 대해서 형태소 분석을 
하는 것은 어려운 일입니다. 그래서 음성인식을 위해서는 조금 다른 접근을 생각해 볼 수 있습니다.

그것은 data-driven 방식으로 한국어를 표현하는 기본 인식단위, 즉 형태소를 찾는 것인데요. 
[Morfessor](https://github.com/aalto-speech/morfessor) 라는 툴이 그 일을 하는데 가장 적합합니다.
Morfessor가 형태소를 찾는 방식은 기본적으로 주어진 말뭉치에서 띄어쓰기 단위 단어들을 더 세부적으로 쪼개보면서 
해당 말뭉치를 가장 잘 표현할 수 있는 최소 개수의 형태소(morpheme)들을 찾는 것입니다. 

제로스 프로젝트에서는 morfessor 분석을 통해 나온 morpheme 들을 기본적인 인식 단위로 사용하여
말뭉치를 분석하고, 발음사전을 구축합니다.


## 2. Work Flow
아래 스크립트 `run.sh` 에는 아래 모든 과정을 담고 있습니다.
```
zeroth/s5/data/local/lm/run.sh
```

### 2.1 Text Normalization
발음사전과 언어모델을 만들기위해서는 먼저 큰 말뭉치(corpus)가 필요합니다. 
말뭉치를 구하는 방법은 여러가지가 있지만 주로 웹크롤링(web-crawling)을 통해 사람들이 많이 사용하는
문장들을 모아볼 수 있습니다. 

제로스 프로젝트에는 다방면의 주제에 걸쳐 약 13GB 정도의 텍스트가 웹크롤링을 통해 준비되었고,
발음사전과 언어모델을 만드는데 사용되었습니다. 하지만 세부적인 크롤링 결과는 저작권과 관련된 문제가 있기때문에
오픈소스에 포함되지 않을 예정입니다. 다만 크롤링 텍스트를 사용하여 진행되는 모든 과정에 필요한 코드는 공개될 것입니다.

말뭉치가 준비되었다면 이 말뭉치들은 먼저 적당한 방법으로 normalization 되어야 합니다. 
보통 이과정을 text normalization 이라고 부릅니다. 
한글로 적당한 번역을 찾기가 어렵지만 text normalization 이란 
말뭉치에 포함된 특수기호, 숫자, 알파벳등을 음성 인식에 사용하기 편한 방식으로 바꿔주는 것을 의미합니다.

여기서 수행되는 text normalization에는 다음과 같은 것들이 있습니다.
- 특수문자 제거
- 단위 문자 한글 전환, 예) ㎞ -->  키로미터
- 숫자 변환, 예) -11.05 --> 마이너스 십 일 쩜 영 오 
- 기수, 서수에 따른 숫자 변환, 예) 계란 1 판  --> 계란 한 판
- ... 

### 2.2 Building Lexicon 
제로스 프로젝트의 한국어 발음 사전을 구축하는 방법은 아래와 같습니다.

- 2.1 에서 설명된 text normalization 이 적용된 말뭉치에서 Morfessor를 사용하여 고유한(unique) 형태소들을 추출
- 찾아진 형태소들로 단어장을 구축
- 단어장을 [한국어 표준 발음법](https://www.korean.go.kr/front/page/pageView.do?page_id=P000097&mn_id=95)에 맞추어 발음열로 변환

한국어의 발음은 띄어쓰기 단위 내에서는 어미의 변화에 따라서 달라지고 띄어 쓰기 단위에서 앞, 뒤 단어에 따라서도 변합니다. 
현재 제로스 프로젝트에서는 Morfessor 분석을 통해서 찾아진 단어 내의 형태소(morpheme) 변화에 따른 발음 변화만이 고려되었습니다.
추후 문장 단위에서 발음열(pronunciation string)을 생성하면 고유한 형태소들이 더 다양한 발음을 갖는 것을 파악할 수 있을 것입니다.

예) 
- 가난+이     /가나ㄴ+ 이/
- 가난+하다   /가난+ 하다/
- --> 가난 /가난/ or /가나ㄴ/ 


### 2.3 Language Model Training
2.2 과정 중,  Morfessor를 사용하여 data-driven 방식으로 형태소를 추출하면, 그 결과물로 우리는 주어진 말뭉치를 형태소 단위로
분리(segment)하는데 사용할 수 있는 segment 모델을 얻게됩니다. 이 segment 모델을 사용하여 언어모델에 사용될 말뭉치를 
형태소 단위로 나눕니다. 그리고 형태소 단위로 구분된 말뭉치를 [SRILM](http://www.speech.sri.com/projects/srilm/) 툴을 
사용하여 n-gram 언어모델로 표현합니다. N-gram 언어모델을 표현하는 방식은 [ARPA](http://www.speech.sri.com/projects/srilm/manpages/ngram-format.5.html) 포맷을 활용합니다.
