다음 링크의 자료를 참고했고 발표해주신 김태훈님께 감사를 표합니다.
김태훈님 발표 영상 https://bit.ly/2uRklOo
김태훈님 발표 슬라이드 https://bit.ly/2mJ6rsZ


네이버 nvoice

배우 유인나해리포터를 읽어준다면?
유인나가 해리포터를 읽어주는 소프트웨어를 만들어보자
로 시작함.

API 사용해보자. (TTS 서비스) NAVER, KAKAO, GOOGLE

목소리 퀄리티가 아쉽다. 

그래서 TENSORFLOW를 이용해 만들었다.


오늘의 발표는 크게 3파트로 나뉜다.
  1. 데이터
  2. 모델
  3. 결과

텍스트 <-> 음성 pair로 있어야한다.
한국어 음성 합성 데이터는 공개 된게 없다. 직접 만들어야한다.

  • 데이터 프로세싱
  1. 음성추출
  2. 문장 별 자르기
  3. 텍스트 <-> 음성 맞추기

노가다 x -> Google Speech API, Text similarity 이용

뉴스 + 유튜브 + 오디오 북 데이터를 이용해서  50+ 시간 데이터를 모음

손석희 15+시간 13,000 문장
박근혜 5+ 시간 6,000 문장
문재인 2+ 시간 2000 문장

  • 모델
딥러닝
  1. 타코트론
  2. 딥 보이스2
타코트론의 핵심
과거의 전통적인 음성 합성 기술
텍스트 -> [토큰화 -> 운율 분석 -> 모델을 만들거나 or 잘게나눠진 음성들을 검색하고 합성 ]-> 음성 

여러 개의 파이프라인을 없애고 모델 하나로 가능하게 했다.
텍스트 -> 모델-> 음성
                    이 모델이 타코트론이다.

모델은 크게 4가지로 구성되어있다.
  1. 인코더 Encoder
  2. 디코더 Decoder
  3. 어텐션 Attention
  4. 보코더 Vocoder

하나씩 소개해본다.

 1. 인코더부터 설명

인코더의 역할?

텍스트 -> Encoder -> 텍스트 정보를 잘 나타내는 숫자

캐릭터 임베딩?
글자를숫자로 변환하는 것
딥러닝 모델이 글자를 계산 할 수 없으므로 숫자로 바꿔주는 것
0.7
0.3
0.1
0.9
0.5
0.0
0.0
0.5
0.9
0.7
0.3
0.1
1.0
0.5
0.2
0.2
...
...
...
...
학습을 하면서 행렬도 바뀜


띵작








명작                                                                                    띵동
















장점 : 띵작을 말하고 싶을 때
학습 데이터에 띵작이라는 단어가 없어도
명작, 띵동 이라는 단어를 캐릭터 임베딩으로 잘 배웠다면
명작을 잘 표현하는 캐릭터 임베딩을 만들 수 있다.

ㄱㄲㄴㄷㄸㄹㅁ ... ㅊㅋㅌㅍㅎ

ㅏㅐㅑㅐㅓㅔ ㅕ ... ㅠ ㅡ ㅢ ㅣ

! ' () , - . : ; ? _ ~

자음, 모음, 특수 문자 총 80개의 임베딩


ex) ㅋㅏㄹㅡㅍㅔ -> pre-net (FC -ReLU-Dropout을 2번 거친다.) -> CBHG -> 텍스트 임베딩 (텍스트를 잘 나타내는 숫자)

카르페라는 문장을 말한다고 했을 때 가장 먼저 pre-net 모듈을 거친다. pre-net은 FC-ReLU-Dropout을 2번 거친 것이다.

그다음 CBHG라는 모듈을 거친다.


CBHG = 1-D Convolution Bank + Highway network + Bidirectional GRU 




요약: 인코더가 하는 일은 다음과 같은데, 텍스트가 Pre-net과 CBHG를 거치면 텍스트 임베딩을 만들어 낸다.



2. Decoder

크게 보면 그냥 RNN


디코더가 하는 역할은?


이전에 만든 스팩트로그램을 입력으로 받고 -> Decoder -> 다음 스팩트로그램 생성한다.


스팩트로그램: 음성을 숫자로 표현하는 여러가지 방법 중 하나이다. 스팩트로그램으로 음성을 만들 수 있다.

디코더는 처음에 입력으로 <GO> frame을 받는데 이것은 학습되는 것이고 어떤 숫자들이다. 


어텐션은 나중에 설명


이후에는 RNN을 한다.

왜 1/N로 줄이냐면 만약 '가'라는 음성이 있으면 파형으로 생각하면 잘게잘게 나눠보면 '가', '가', '가', '가', '가', '가', '가', '가', '가', 이게 반복 될 것이다.

'가ㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏㅏ' 이런식...?

그래서 굳이 똑같은게 여러갠데 많이 예측할 필요없고 n개의 스팩트로그램만 예측한다.






디코더의 결과로 n개의 스팩트로그램의 리스트를 얻게 된다. 스팩트로그램은 음성이 되기 직전의 숫자들이다.



어텐션을 설명하기전에 제일 마지막 모듈인 보코더 부터 설명합니다.

보코더의 역할은 스팩트로그램을 입력으로 받아서 음성을 만들어주는 것이다.




여기서 또 CBHG를 거친다. 


스팩트로그램을 음성으로 만들어주는 방법이 여러가지 있는데 그 중 하나인 그리핀-림(Griffin-Lim)알고리즘을 이용해서 음성으로 만들었다.


그리고 마지막으로 가장 중요한 어텐셜 Attention

왼쪽 초록색 배열은 인코더의 출력으로, 텍스트 임베딩한 결과물이다. 텍스트 임베딩과 디코더를 잘 합쳐주는 모델이 어텐셜이다.


Attention -> 어디에 집중할 것인가?


어디에 집중할 건지는 학습을 통해 알아서 계산한다.


어떻게 만들어지는지 예제를 봅시다




어텐션이 중요한 이유가 뭘까?

일반화 때문이다.

학습하지 않은 것을 얼마나 잘 말 할 수 있는가?


'cs > 데이터사이언스' 카테고리의 다른 글

책 읽어주는 딥러닝  (0) 2018.07.19
나를 괴롭히는 Naive Bayes 정리  (0) 2018.07.04
파이썬 - 변수  (0) 2018.04.30

Naive Bayes를 이용해서 Classifier를 구현하는 중 이론 정리를 해야겠다는 생각이 들어서 글을 쓰게 되었다.


목표: Naive Bayes 이해


많은 Classifier가 있는데 그 중 Naive Bayes Classifier를 이해한다..

참고 https://www.youtube.com/watch?v=ndvZKwZw5tQ



X데이터가 들어오면, 그것이 빨간색에 속하는지, 초록색에 속하는지 분류하는 확률 함수를 생각해본다.

위의 그래프에서 Y축은 확률이고, X축은 데이터이다. X값이 0에 가까운 데이터가 들어오면 Y가 초록색이라고 분류할 것이고. X값이 큰 데이터가 들어오면 Y가 빨간색이라고 분류할 것이다.

P(Y=y | X)는 X라는 조건이 주어졌을 때, 어떤 Y인지 뜻하는 것이다. 조건부 확률.


우리의 목표는 f*을 optimal하게 만드는 것이다.

즉 f* = argmin_f P(f(x) != Y) 를 만족하게 하는 것이다.


f*는 우리의 optimal 함수이다. P(f(x) != Y)가 의미 하는 것은 x라는 데이터로 예측한 결과 f(x)와 정답인 Y의 차이를 말한다. 이것을 argmin하면 흔히 말하는 오차를 줄인다는 말이다.

즉, x라는 데이터가 주어졌을 때, 예측한 y값과 실제 Y값과의 차이를 줄이는 것이 목표이다.


이것을 다르게 표현하면

f(x)* = argmax_Y=y P(Y=y | X=x)로 표현이 가능하다. x가 주어졌을 때 출력한 y값이 Y와 비슷한 정도가 크도록, 해주는 것으로도 생각할 수 있다.



위의 그래프를 보면 X축에 중앙에 Xm이 있다. 이 Xm을 기준으로 X가 왼쪽이면 초록색, 오른쪽이면 빨간색이라고 예측할 것이다.

그래프에서 점선과 실선은 확률 분포인데, 둘 중 어떤 것이 더 좋을지 생각해보자.


우선 실선이 더 좋다. 왜냐하면 


첫 번째, Xm 옆에 있는 Xn데이터를 보자.

Xn 데이터가 주어졌을 때 우리는 초록색이라고 예측할 것이다. 근데 이때 error를 생각해보자.

확률의 합은 항상 1이기 때문에 P(Y=초록색 | x) + P(Y=빨간색 | x) = 1이다.

따라서 둘 중 큰 쪽을 선택하기 때문에 error는 항상 1에서 나머지를 뺀 값이 된다.

실선에서 Xn을 예측했을 때, 초록색이 나오고 그 때 error는 P2가 나온다. (빨간 동그라미)

점선에서 Xn을 예측했을 때, 초록색이 나오고 그 때 error는 P2보다 높게 나온다 (빨간 네모칸)

즉, 실선 일 때 error가 더 작다는 것을 의미한다.


두 번째,

데이터가 Xm에 가까워 질 수록 점선은 선형이라서 빨간색일 확률과 초록색일 확률의 차이가 적지만,

실선은 비선형이라서 그 차이가 더 크게 나타난다.

Xm 근처에서 차이가 더 크게 나타나기 때문에 조금 더 명확하게 예측이 가능하다.

그리고 그래프에서 보면 밑에 색칠된 부분 베이지색으로 색칠된 부분이 error이다.

내가 어떤 점 Xi에서 P(Y=초록 | x)일 확률이 0.75가 나왔다면 P(Y = 빨강 | x)일 확률은 error가 된다. 이때 에러는 0.25이고

1-P(Y=초록 | x)로 표현이 가능하다. 베이지색으로 색칠 된 부분도 그 영역을 의미한다.



그럼 다시 수식으로 돌아와서

우리의 목표는 다음과 같다.

f*(x)  = argmax_Y=y P(Y=y|X=x) 

P(Y=y|X=x)는 bayes 정리를 이용해서 다시 쓸 수 있다.


나이브베이즈


P(Y=y|X=x) = P(X=x|Y=y) * P(Y=y)

이게 좋은점은 우리가 바로 못 구하는 확률을 이미 알고 있는 것을 이용해서 구할 수 있다는 것이다.

이게 무슨말인지 이해하기 위해 수학 문제를 몇개 풀어봤다.


쿠키 문제

쿠키가 들어 있는 그릇 두개가 있다.

첫번째 그릇에는 바닐라 쿠키 30개, 초콜렛 쿠키 10개가 있다.

두번째 그릇에는 바닐라 쿠키 20개, 초콜렛 쿠키 20개가 있다.


어떤 그릇인지 보지 않고 한 그릇에서 임의로 쿠키를 집었는데 바닐라 쿠키였다고 한다.

그렇다면 이 때 '이 바닐라 쿠키가 그릇 1에서 나왔을 가능성'은 얼마인가?


다음과 같이 용어를 정의한다.


P(H=1) : 그릇 1을 골랐을 확률

P(V) : 바닐라 쿠키를 골랐을 확률


그럼 우리가 구하고자 하는 것은 P(H=1 |V)이다.

이것은 

P(H=1)*P(V |H=1)

P(H=1 |V) = --------------------

       P(V)

으로 표현 가능하다.


P(H=1) = 1/2 , 그릇 두개중 첫번째 그릇을 고를 확률

P(V| H=1) = 3/4, 첫번째그릇을 골랐을 때 바닐라 쿠키를 고를 확률, (40개의 쿠키중 30개를 고를 확률이므로)

P(v) = 5/8,바닐라 쿠키를 고를 확률, (전체 80개의 쿠키중 첫번째 그릇에 30개, 2번째 그릇에 20개 총 50개의 바닐라 쿠키를 고를 확률이므로 50/80)


이렇게 우리는 우리가 이미 알고있는 것으로 우리가 원하는 것을 구할 수 있다.


P(H=1)*P(V |H=1)

P(H=1 |V) = --------------------

       P(V)


미리 말하자면 P(V)를 evidence (그릇에 상관없이 바닐라가 나올 확률 / H에 상관없음)

P(H=1)를 prior probability 사전 확률(x에 상관없음)

P(V|H=1)를 likelihood라고 한다.



우리는 bayes 이론 덕분에 우리가 알고 있는 것을 이용해 모르는 값을 구할 수 있게 되었다.



우리의 목표인


f*(x)  = argmax_Y=y P(Y=y|X=x) 이것을

P(Y=y|X=x) = P(X=x|Y=y) * P(Y=y)로 바꾼다.

그런데, 여기서 문제가 생겼다. 위의 표 처럼 고려해야 할 x가 너무 많다는 것이다.

Sky, temp, Humid, 등등 고려해야할 feature가 있는데 이에 따라 P(X=x|Y=y) , P(Y=y)를 계산할 때 생기는 문제에 대해 알아보자.


우선 P(Y=y)는 쉽다. x에 관계 없이 모든 y에대해 구해주면 된다. 여기서는 EnjoySpt 전체가 4개, yes가 3개 이므로 3/4이 된다.

이렇게 하나만 구하면 나머지하나는 1-3/4으로 1/4인 것을 알 수 있다.

그래서 클래스 갯수가 k개 일 때 k-1번만 계산하면 된다.

문제는 P(X=x|Y=y)이다. 고려해야할 대상이 Sky 하나만 있을 때 경우의수는 2가지이다.


Sky, Temp가 있을 때는 경우의 수가 3가지이다. 


sunny warm

sunny cold

rainy warm


rainy cold는 1 - 이미 위에서 구한 3개의 확률 로 계산하면 된다.


이렇게 feature가 d개이면 2^d -1 개를 계산해야하고 (2의 제곱인 경우는 아마 feature도 확률로 생각해서 맞다 아니다 식으로 계산하기 때문인것같다.)

그때 EnjoySpt가 가능한지 안한지도 곱해줘야한다.

그래서 (2^d-1)*k 가 된다.


2의 제곱 형식으로 증가하기 때문에 상당히 계산량이 많아져서 좋지 않다.

그럼 이제 어떻게 해야할까?

데이터를 표현하는 d(dimension)를 줄여 볼까? Sky 정보 빼고, Temp 정보 빼고... 그렇게 해야할까?

근데 어렵게 구한 데이터에서 d를 빼고 싶지는 않을 것이다.

그래서 우리는 Conditional Independence라는 가정을 한다.


여러 X feature(Sky, Temp 등)들이 있는데, 이것들이 모두 독립적이라고 가정하는 것이다. 확률에서 독립이라고 하면 P(X,Y) = P(X)*P(Y)를 의미한다.

그런데 실제로 독립적일까?


혹시 여자친구 있으세요?

여자친구의 유무는 키, 몸무게, 피시방 방문 빈도수에 비례한다고 가정해보자.

근데 피시방에 자주 가면 컵라면을 먹어서 몸무게가 증가하는 상관관계가 있다.

하지만 우리는 순진하게 상관관계가 없다고 가정한다.


순진하게. Naive하게.


ex)

P(Thunder | Rain, Lightning) = P(Thunder | Lightning)


비가내리고 번개(Lightning)가 칠 때 천둥이 칠 확률은

번개가 칠 때 천둥이 칠 확률과 같다면


천둥과 비가오는 것은 conditional independence하다.


이제 우리는 모든 x feature들 끼리는 독립이라고 가정하자.



저기 식에 보면 ㅠ P(Xi= xi | Y =y) 이렇게 되있는데 이건 확률 곱을 의미한다. 즉



이 확률을 P(X1=sunny |Y=y) * P(X2 = warm | Y=y) * ... P(X6=same | Y=y)로 나타낸 것이다.

이렇게 계산량이 줄어든다.

feature의 갯수를 d라고 하고 d가 2가지 경우만 존재할 때, x1이 sunny일 확률을 구하고, x2가 warm일 확률을 구하고 등등...

을 하면 총 d번 연산을 하면 된다. 여기에 Y가 yes인지, no인지 Y의 클래스 갯수 k를 곱해주면 되므로 계산량은

dk로 줄어든다. 그림에서 (2-1)dk라고 표현한 이유는 x1에서 d가 sunny, rainy처럼 2가지 가 존재하는데 한가지만 구하면 나머지 확률은 1-이미 알고 있는 것을 하면 되므로 (2-1)이라고 했다.

그림에서 보면 물결표시가 있는데 어느정도 오차가 있다는 말이다. 당연히 conditional independence를 만족하지 않은데 만족한다고 가정했기 때문이다. 



'cs > 데이터사이언스' 카테고리의 다른 글

책 읽어주는 딥러닝  (0) 2018.07.19
나를 괴롭히는 Naive Bayes 정리  (0) 2018.07.04
파이썬 - 변수  (0) 2018.04.30

디자이너 없이 보기 괜찮은 웹 사이트를 만들어보자.


친절하게도, 웹사이트를 쉽게 만들 수 있게 도와주는 HTML, CSS, JS 프레임워크인 부트스트랩(링크)이란 것이 있다.


부트스트랩을 3.3.7 버전을 여기 링크에서 다운받고 압축을 풀어줍시다.


그리고 이제 Django 폴더에 필요한 파일들을 복사 붙여넣기 해줍시다.


이쯤에서 정리해보는 폴더 구조


윈도우 cmd 창에서 Django 폴더가 있는 곳으로 접근해서 폴더의 구조를 봅시다.


cd 명령어를 통해 장고 프로젝트를 만든 최상위 폴더까지 가고


tree /F 명령어를 통해 해당폴더의 하위에 어떤 파일, 폴더가 있는지 확인해봅시다.


저는 다음과 같이 나왔네요


└─src
    │  db.sqlite3
    │  manage.py
    │
    ├─blog
    │  │  admin.py
    │  │  apps.py
    │  │  models.py
    │  │  tests.py
    │  │  urls.py
    │  │  views.py
    │  │  __init__.py
    │  │
    │  ├─migrations
    │  │  │  0001_initial.py
    │  │  │  __init__.py
    │  │  │
    │  │  └─__pycache__
    │  │          0001_initial.cpython-36.pyc
    │  │          __init__.cpython-36.pyc
    │  │
    │  └─__pycache__
    │          admin.cpython-36.pyc
    │          models.cpython-36.pyc
    │          urls.cpython-36.pyc
    │          views.cpython-36.pyc
    │          __init__.cpython-36.pyc
    │
    ├─sample
    │  │  settings.py
    │  │  urls.py
    │  │  wsgi.py
    │  │  __init__.py
    │  │
    │  └─__pycache__
    │          settings.cpython-36.pyc
    │          urls.cpython-36.pyc
    │          wsgi.cpython-36.pyc
    │          __init__.cpython-36.pyc
    │
    ├─static
    │  ├─css
    │  │  │  base.css
    │  │  │
    │  │  └─lib
    │  │          bootstrap.css
    │  │          bootstrap.min.css
    │  │
    │  └─js
    │      └─lib
    │              bootstrap.js
    │              bootstrap.min.js
    │
    └─templates
            base.html
            index.html


처음에 sample 이란 이름으로 프로젝트를 생성하면 sample 폴더가 생기고 그 밑에 여러 파일들이 생깁니다. 근데 sample안에 sample이 있으니 최상위 폴더 sample을 src로 이름을 바꿨습니다. 


blog 폴더는 처음으로 만든 앱이고


migrations은 모델을 관리하는 정보가 담긴 폴더입니다


sample폴더는 처음에 생긴 폴더인데 여기에 settings.py와 urls.py 많은 설정들을 해줬습니다.


static은 css, js등을 저장하는 용도이고요


templates는 MTV 패턴에서 T에 해당하는 사용자에게 보여지는 html 부분입니다.


이제 bootstrap의 css, js를 사용하기 위해 설정해봅시다. 


├─static
    │  ├─css
    │  │  │  base.css
    │  │  │
    │  │  └─lib
    │  │          bootstrap.css
    │  │          bootstrap.min.css
    │  │
    │  └─js
    │      └─lib
    │              bootstrap.js
    │              bootstrap.min.js


다운받은 파일을 압축해제 해주시고 static폴더밑에 css폴더를 생성해주고


css 폴더 밑에 lib 폴더를 생성해줍니다.


그리고 lib 폴더에 bootstrap.css, bootstrap.min.css 파일을 넣어줍니다.


js 폴더도 마찬가지로 해줍니다.




*.css VS *.min.css


파일을 열어보면 *.css는 보기 편하게 되어있고


*.min.css는 한줄로 되어있는 것을 알 수 있다.


이는 웹사이트에서 css를 사용할 때 더 빨리 읽어오기 위해 한줄로 저장해놓은 것이다. 줄바꿈도, 공백도 없다 한줄로 쭉


이게 웹 사이트에서 css파일 적용하는데에 얼마나 성능 향상을 미칠지 궁금하군요


그리고 이제 링크의 Basic template처럼 html코드에 css, js파일을 사용하겠다고 적어줍시다.


base.html 파일입니다.

<!DOCTYPE html>
{% load static %}
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=11; IE=10; IE=8; IE=7; IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">
    <title>{% block title %}sample{% endblock %}</title>
    <!-- <title /> -->
    <link rel="stylesheet" href='{% static "css/base.css" %}'>
    <link rel="stylesheet" href='{% static "css/lib/bootstrap.css" %}'>
</head>
<body>
    {% block body %}{% endblock %}
    <script src='{% static "js/lib/bootstap.js" %}'></script>
</body>
</html>


base.html파일에 이렇게 적어주고


우리는 index.html 파일을 다시 보면


{% extends "base.html" %} {% block body %} <div style="color:red; font-size:2em;">hello world, {{ myname }} </div> <div style="color:#123456;">hello world, Joe </div> <div style="color:blue;">hello world, Tom </div> {% endblock %}


맨 윗줄에 {% extends "base.html" %}


를 통해 index.html 파일이 base.html파일을 상속받는 것을 알 수 있다.


솔직히 상속이 맞는 표현인지 모르겠다. 처음에 html 배웠을 때는 상속이란게 html에도 있는지 모르겠다 이거 질문해봐야겠네 아무튼 저런 허접한 div style을 주지말고 base.html에서 bootstrap의 css, js를 사용하겠다고 선언해놨으니 이제 이쁘게 만들어보면된다.


이쁘게 만드는 예제는 여기에 있다. 여기서 css, js등에 들어가서 해보고 싶은대로 해보시면 됩니다.



'cs > ' 카테고리의 다른 글

부트스트랩  (0) 2018.06.20
Django models  (1) 2018.06.19
pycharm에서 html autocomplete랑 syntax highlighting이 안되잖아요  (0) 2018.06.18
깃에서 필요없는 걸 빼주고 싶을 때 gitignore  (0) 2018.06.18
장고 설치, 파이참 연동  (0) 2018.06.11

+ Recent posts

티스토리 툴바