이제부터 Multi Speaker Tacotron에 대해 설명하도록 하겠다. 필자인 나는 공부하는 입장이니까 내가 이해하는 한으로 최대한 자세하게 설명하도록 하겠다. 하지만 공부하는 입장이기 때문에 틀리는 부분도 있을 거라는걸 명심해 주길 바란다... RNN은 정말 너무 어렵다 ㅠ_ㅠ...

 

 

Tacotron 구조

 

위의 이미지가 구글의 Tactoron 구조이다. 이미지의 출처는 논문이기 때문에 참고하길 바란다. 참고로 논문 처음의 참여자들의 이름에 * 표시가 있는 분들은 타코를 좋아하고 † 표시가 있는 분들은 초밥을 더 좋아한다고 한다. 타코를 좋아하는 사람들이 더 많아서 타코트론이 되었다는 멋진 녀석.... 공대생들의 찐광기를 느낄 수 있는 부분

 

Tactron 구조 세부적으로 보기

 

 

 


 

 

 

Encoder

Tacotron Encoder

 

위의 이미지가 타코트론의 Encoder의 세부적인 내용이다. 우선 첫번째로 Character embeddings를 보도록 하겠다.

 

Character embeddings

사실 Character embeddings에 대해 아주 완벽하게 이해를 하지는 못했다. 내가 책으로 공부하기로는 단어의 one-hot encodding과 가중치의 matmul 연산의 불필요함을 줄이기 위해 한번에 단어 ID로 단어의 분산표현을 만들어내는 것이 Embedding이라고 이해했는데 Tacotron의 논문에서는 입력 인코더는 각 문자가 원-핫 벡터로 표현되고 연속 벡터에 포함되는 문자 시퀀스라고 설명되어 있어서 나의 지식과 혼동되고 있다.(ㅠㅠ) 뭐 아무튼 이래나 저래나 Character embeddings의 핵심은 단어의 분산표현을 나타낸다는 것이고, 결론적으로 이것을 쉽게 말하자면 단어를 숫자 데이터로 변환해준다는 뜻이다.

 

 

Pre-net

pre-net 세부 구조

 

Pre-net은 별거 없어 보인다. Fully Connected layer - ReLU - Dropout을 2번 반복하는 구조이다. 사실 처음 타코트론을 공부할 때 이 Pre-net은 단순히 오버피팅을 억제하는 정도로만 이해했었다. 근데 논문을 자세히 살펴보니 이 pre-net의 Dropout이 상당히 중요한 역할을 한다.

 

Pre-net의 Dropout은 크게 2가지 역할을 하는데 우선 첫번째로 일반화를 해준다는 점에서 매우 중요하다. 일반화란, 학습 데이터와 Input data가 달라져도 출력에 대한 성능 차이가 나지 않도록 하는 것을 의미한다. 즉, training data로 나오는 학습 결과만큼 새로운 입력 데이터에 대해서도 좋은 결과가 나올 수 있도록 돕는 역할이라는 것이다. 뭐, 한마디로 그냥 오버피팅을 억제한다고 생각해도 되겠다.

 

Pre-net의 Dropout은 bottleneck layer, 즉 병목 layer라는 점에서 중요하다. 병목 layer라고 하면 마치 이 계층이 병목현상을 유발한다는 것처럼 읽히지만 사실 이 계층은 병목 현상을 방지한다고 보면 되겠다. Dropout의 구조는 여기의 이미지를 참고하면 되는데, 쉽게 말하자면 모든 신경망을 사용하지 않고 일부만을 사용하여 학습을 진행하고 이 과정을 여러번 반복해 평균을 내 모든 신경망을 사용한것과 비슷한 효과를 내면서 overfitting, 즉 과적합을 방지한다. 이런 과정을 거치면, 여기서 설명하는 것과 같이 학습에 필요한 계산 비용이 크게 줄어들게 된다.

 

 

CBHG

크게 보면 CNN과 RNN으로 구성된 신경망이다.
CBHG 세부 구조

 

CBHG란 convolutional 1-D filters, bank, highway networks, gated recurrent unit bidirectional의 첫글자를 따서 지어진 이름이다. CBHG는 크게 보자면 CNN과 RNN으로 구성된 신경망으로, 층이 깊어질수록 복잡하고 추상화된 특징을 추출할 수 있는 CNN의 장점과 시계열 데이터의 전체적인 특징을 파악할 수 있는 RNN의 장점을 모두 합친 모델이다.

 

CNN 모델을 자세히 살펴보자면 Convolution, Max pooling, Convolution 계층을 지나면서 데이터 특징을 잡을 준비를 한다. (혹은 이미 데이터의 특징을 거의 잡아놨다.) 이 과정에서 바로 Highway Layers로 넘어가지 않고 Residual Connection을 하는데, 이는 ResNet을 사용하는 이유와 같은 맥락이라고 보면 된다. 기존의 데이터에 대한 정보를 잃지 않기 위해 우리는 단순 합산을 통해 학습된 데이터와 기존의 데이터의 모든 정보를 갖고 Highway Layers를 통해 특징만을 추출해 낸다.

 

그 후, Bidirectional RNN으로 데이터를 보내 전체에 대한 흐름의 특징을 파악한다. 여기서 Bidirectional은 양방향이라는 뜻으로, Bidrectional RNN을 사용하는 이유는 시계열 데이터는 순방향 못지 않게 역방향으로도 맥락의 흐름을 유추할 수 있기 때문이다. 따라서 Bidrectional RNN을 사용하여 우리는 과거 시점에서도 미래 시점에 대한 데이터를 받고, 미래 시점에서 과거 시점에 대한 데이터를 받아 맥락의 전체적인 흐름에 대해 파악한다.

 

 

 

 

Attention 

어텐션에 대한 자세한 내용은 링크동영상, PPT p.121 부터를 참고하길 바란다. 여기서 간단히 핵심만 다시 언급하자면 Attention이란 시계열 데이터에서 어느 부분에 집중할 것인가에 대해 학습하는 것이며, Attention을 사용하면 '일반화'가 가능하다. 즉, 새로운 데이터가 입력되어도 충분히 좋은 결과를 나타낼 수 있도록 도와준다.

 

 

 

 

Decoder

Tacotron Decoder

 

Decoder의 아래에 입력 데이터인 <GO> frame은 Decoder, 즉 시계열 데이터의 시작을 알리는 데이터로 큰 의미는 없다. (하지만 반드시 필요) 우리는 이 <GO> frame의 데이터와 Encoder에서 학습된, 문장의 특징을 잘 갖고 있는 단어 임베딩들을 (Encoder CBHG의 맨위쪽, 초록색 Embeddings) Attention 계층에서 학습시키고 (특징을 또한번 잡아내고) 일반 RNN을 사용하여 n개의 스펙토그램으로 출력한다. 이 Spectrogram은 음성 신호로 변환되기 직전의 숫자 데이터로, 발음, 음성에 대한 정보를 담고 있다. 즉, 결론적으로 Encoder에 들어온 단어 데이터들을 Decoder의 Attention과 RNN을 통해 음성 신호로 변환될 수 있는 숫자 데이터로 바꿔준다고 이해하면 되겠다. 이에 대한 자세한 설명은 PPT p.103부터 참고하길 바란다.

 

이렇게 스펙트로그램 데이터를 만들면 CBHG를 통해 또한번 특징을 잡은 후 하나의 시계열 데이터로 출력한다. 이 데이터를 스펙트로그램을 음성 데이터로 변환해주는 Griffin-Lim을 통해 음성 데이터로 출력한다.

 

 

 

 

 

 

 

위의 구조가 Tacotron의 구조이다. 정말... 정말 복잡하다... 사실 이해하고 보면 그렇게 어렵지는 않은데 다양한 개념들이 섞여서 헷갈린다. 하지만 그냥 엄청엄청 쉽게 이해를 하자면 악착같이 시계열 데이터들에 대해 특징을 잡아내고 일반화를 하기 위해 노력하는 짓을 n번 반복하여 결과물을 만들어내는 악착같은 모델이라고 이해하면 되겠다.

 

 

 

 


 

 

 

 

Multi Spekaer Tacotron - Speaker Embedding

여기서 끝이 아니다. 우리는 Multi Speaker Tacotron을 사용하기 때문에 Multi Speaker에 대해서도 이해해야한다. 사실 이 부분에 대해서는 완벽하게 이해를 아직 하지 못했기 때문에 대략적으로 설명하고 넘어가도록 하겠다. (큐ㅠ)

 

Multi Speaker Tacotron은 Baidu에서 발표한 Deep Voice2에 기재된 내용으로, 쉽게 말하자면 여러명의 발화자에 대해 적은 메모리 사용량으로도 효과적으로 학습할 수 있다는 내용이다. 이에 대한 자세한 설명은 PPT의 p.159부터 참고하길 바란다.

 

간략하게 설명하자면 N명의 발화자(Speaker) 정보를 가진 Speaker Embedding을 만들어 Encoder CBHG의 CNN부분(정확히는 residual connection)과 RNN부분에 삽입한다. 그리고 Decoder Pre-net과 RNN에 삽입하여 적은 메모리 사용량으로 효과적으로 여러명의 음성 특징을 학습할 수 있게 한다.

 

Multi Speaker Tacotron을 사용하면 결론적으로 잘 학습된 Attention이 잘 학습되지 않은 Attention의 학습에 도움을 주어 적은 양의 데이터로도 충분히 좋은 효과를 볼 수 있다. 필자가 이해하기로는 전이학습과는 다르지만, 결론적으로 학습이 잘된 Attention이 학습이 안된 Attention의 학습에 도움을 준다는 것이 전이학습과 비슷한 '결'이지 않을까 싶다. 이 부분에 대해서는 아직 정확하게 알지 못하기 때문에 추가적으로 기재하도록 하겠다.

 

아무튼 Speaker Embedding을 사용하여 여러 화자에 대한 Attention을 학습하면 내가 원하는 특징(예를 들자면 발화 속도, 억양과 같은)만을 추출하여 다른 화자에게 대입할 수 있다. 이 부분에 대해서도 PPT p.185부터 참고하길 바란다.

 

 

 

 

 


 

 

 

 

설명이 부족하거나 이해가 가지 않는 부분에 대해서는 우리가 참고한 github의 주인인 carpedm20님의 PPT동영상을 참고하길 바란다. (이미 너무 남발하긴 했지만ㅋㅋㅋㅋ) 큰 틀에서 이해하기엔 동영상이 최고다... 흑흑 이제 드디어 끝났다.. 타코트론아 많은 깨달음을 줘서 고맙지만,,, 참,, 힘들었다,,,,★

 

 

 

 

 

 

내가 딥러닝을 제대로 이해하기 시작한게 사실상 올해부터였다. 인공지능을 공부했던건 작년부터였지만 그때는 머신러닝을 이해하는 것도 벅찼고 CNN은 더 벅찼으면 RNN은 사실상 포기였다. 하지만 취업이 바로 안되고(ㅠㅠ) 할 것도 없기에 애매하게 아는 것보단 완벽하게 이해하는게 낫겠다 싶어서 국비 지원으로 인공지능을 다시 배웠다. 6개월 과정에서 나는 SQL, LINUX, HADOOP, R 등 엄청 다양한걸 많이 배웠는데 다 이게 피가되고 살이 되지 않겠나 싶다.

 

암튼 이렇게 구구절절하게 글을 쓰는 이유는 최종 팀프로젝트가 RNN 기반이기 때문이다. 이번에는 책까지 구매해가며 먼저 책을 읽고 수업을 듣고 스터디까지 해서 CNN은 잘 이해했는데 RNN은 그래도 너무 어려운기라! 근데 2번이나 각잡고 배웠는데ㅠㅠ; 이걸 또 포기하기엔 내 자존심이 용납이 안되서 그냥 팀원들한테 욕심으로 RNN과 관련된 프로젝트를 하자고 했고, 다들 OK 해준 덕분에 이 프로젝트를 진행할 수 있었다.

 

나는 일단 일을 벌려야 한다. 욕심이 있으니까 벌려놓으면 그걸 잘하려고 열심히 하기 때문이다. 결과적으로 RNN과 관련된 프로젝트로 일을 벌린건 잘한 일이었다. 사실 지금도 정확히 RNN을 이해했다고 볼 수는 없겠지만 이 프로젝트를 하겠다고 RNN을 다시 공부하고 또 블로그에 글을 정리해가고 팀원들에게 설명을 해주면서 대충 그 흐름은 파악한 것 같다. 그리고 무엇보다 팀프로젝트 결과가 좋다. 넘 행복하다!!!!

 

 

 

 


 

 

 

 

사실 아이디어의 시작은 아주 간단했었다. 거창한 이유로 TTS를 하고 싶었던건 아니고, 매일 9시부터 6시까지 학원에 나가 공부를 했었는데 코로나가 심각해지면서 비대면 수업으로 전환되면서 ZOOM으로 수업을 하게 됬는데 선생님 목소리 데이터가 너무 깨끗한거다! 정말 음질이 너무너무 깨끗했다. 그리고 개인적으로 선생님 목소리도 좋으셔서 음~ 이거 뭔가 데이터가 쓸만할 것 같은걸...? 이라는 생각이 들었었다.

 

그러다 팀 아이디어 회의에서 RNN과 관련된 프로젝트를 하고 싶다는 내 말에 다들 하나 둘씩 아이디어를 냈는데, 선생님의 목소리로 TTS를 만들어보자는 의견이 나왔다. 처음엔 다들 간단하다고 생각했지만 이걸 구현할 수 있는가는 다른 얘기인건 수많은 공대생들은 다 뼈저린 경험으로 알고 있을 것이다. 나는 그 공대생 중에 하나였고, 이걸 과연 우리 수준에서 구현할 수 있는지에 대해 찾아보기 시작했다.

 

그러다 이 동영상을 보게 되었다.

딥러닝을 이용한 아이유 음성 TTS PoC

 

그리고 더보기에 올라온 블로그를 참고하기 시작했다. 이 분은 심지어 라디오 데이터를 사용했는데도 이렇게 잘 나왔는데, 나라고 안될건 없었다. 심지어 데이터 양도 그렇게 많지 않았음에도 충분히 좋은 결과가 나왔었다.

이건.. 이건 할만하다...!!!

 

그렇게 이 프로젝트에서 가장 소중하고 감사한 carpedm20님깃허브를 참고할 수 있게 되었다. 사실 나는 그 전까지만 해도 깃허브를 알기만 했지 도대체 어떻게 쓸 수 있는지를 이해하지 못했는데 이 프로젝트 덕에 깃허브까지 이해를 했다. ㅠㅠ 정말 소중한 프로젝트인걸...?

 

그래서 열심히 전처리하고 데이터 수집하고,,, 했다. 데이터는 준비 됐다. 양질의 4+시간의 데이터를 수집했고 그 과정에서 아주 간단한 파이썬 코드도 구현했다. 엄청 간단하지만 나름 코드 짠 내가 자랑스러웠다ㅋㅋㅋㅋㅋㅋㅋ 그래서 이제 깃허브를 참고해서 학습하기만 하면 됐다! 그랬다!!!!!! 근데 이게 진~짜 오류가 엄청 났다... 엄청난 양의... 모듈들을 다운 받아야했지만... 그게 왜이렇게 오류들이 나는지.. 솔직히 나는 그 빨간 글자들을 보면서 하기 싫었는데 다행히 팀원분 중에 한 분이 엄청엄청 열심히 오류 수정하면서 환경 구성을 해주셔서 아주 잘~! GPU 환경에서 잘 돌아갈 수 있게 되었다.

 

우리가 사용한 CUDA version은 8.0이고 cudnn은 6.0을 사용하였다.

 

암튼 이 주저리 Preview 글에서는 내가 활용했던.. 너무 간단해서 창피하기까지한 파이썬 코드를 같이 첨부하도록 하겠다.

 

전처리과정.ipynb
0.01MB

 

이 코드는 정말 간단하게 총 데이터양이 몇시간인지를 판단해주는 함수 하나랑 csv 파일을 json으로 바꿔주기 위한 전처리 코드들이랑 무음 기준으로 알아서 효과적으로 긴 시간의 음성 데이터를 라벨링하기 쉽게 짤라주는 코드 하나가 있다.

 

손석희 데이터처럼 구글 API를 사용하고 싶었는데, 선생님은 대본 없이 그냥 말하시다보니 구글 API의 불안정함을 잡아줄 수 있는 부분이 없어서 이건 안타깝게도 그냥 다 사람이 했다... 원래 사람이 최고다... 사람은... 갈린만큼 좋은 결과물을 내놓지...

 

그리고 프로젝트 이름이 DJ You인 이유는, 음성 합성에 사용했던 선생님의 성이 유씨인것도 있지만 사람의 음성만 있으면 그 사람의 특징을 살려내면서 음성합성이 가능한 모델이기 때문에 선생님(Yu)은 물론, 당신(You)도 DJ가 될 수 있다는 의미에서 DJ You로 만들었다.

 

암튼! 그렇다는 이야기다. 지금까지의 얘기가 이 프로젝트를 하게 된 이유, 전처리에 대한 주저리 정도라면 앞으로는 실제 사용한 모델인 Multi Speaker Tacotron에 대해 설명하도록 하겠다.

 

 

 

 

참고한 케글 데이터 (2020/07/05까지의 데이터로 프로젝트 구현함)

 

Novel Corona Virus 2019 Dataset

Day level information on covid-19 affected cases

www.kaggle.com

 

 

 

코로나 확진자 시각화

더보기

필요한 라이브러리 우선 설치

1
2
3
4
5
6
7
8
9
10
11
12
13
# install.packages('ggplot2')
# install.packages('maps')
# install.packages('dplyr')
# install.packages('rjson')
# install.packages('plotly')
# install.packages('data.table')
 
library(ggplot2)
library(maps)
library(dplyr)
library(rjson)
library(plotly)
library(data.table)
cs

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
corona <- read.csv("c:/data/covid/covid_19_data.csv")
corona2 <- read.csv("c:/data/covid/time_series_covid_19_confirmed.csv")
 
# 나라별 코드 갖고오기
df <- read.csv("https://raw.githubusercontent.com/plotly/datasets/master/2014_world_gdp_with_codes.csv")
 
# 코로나 데이터에 코드 join 하기
<- left_join(corona2,df,by=c("Country.Region"="COUNTRY"))
x[x$Country.Region=="US",]$CODE <- "USA"
 
# 나라, 코드, (현재까지의) 확진자 컬럼만 있는 새로운 테이블 생성
real <- data.table('country'=x$Country.Region,'code'=x$CODE,'confirmed'=x$X7.5.20)
 
# CODE 결측치 확인
# real[is.na(real$code)==TRUE,]
 
# 직접 CODE 넣어주기 위한 작업
# library(doBy)
# orderBy(~COUNTRY,df)
# real[is.na(real$code)==TRUE,]
 
# Congo = COG
real[real$country=='Congo (Brazzaville)',]$code <- 'COG'
real[real$country=='Congo (Kinshasa)',]$code <- 'COD'
 
# Diamond Princess : 크루즈
# Czech = CZE
real[real$country=='Czechia',]$code <- 'CZE'
 
# Gambia = GMB
real[real$country=='Gambia',]$code <- 'GMB'
 
# Holy See = 바티칸시티
# Macedonia = MKD
real[real$country=='North Macedonia',]$code <- 'MKD'
 
# Taiwan* = TWN
real[real$country=='Taiwan*',]$code <- 'TWN'
 
# West Bank and Gaza은 팔레스타인이지만 지도 위치상 이스라엘로 취급 = ISR
real[real$country=='West Bank and Gaza',]$code <- 'ISR'
 
# Eswatini는 나라이지만 위치상 남아공으로 취급 South Africa = ZAF
real[real$country=='Eswatini',]$code <- 'ZAF'
 
# code 별로 확진자 그룹짓기
<- aggregate(real$confirmed,by=list(real$code),FUN=sum)
names(x) <- c("code","confirmed")
 
# 고른 색깔 분포를 원했는데 미국, 인도, 러시아가 너무 확진자가 많아서 이상치가 되어버려서 log함수를 새로 만듦
x$log_confirmed <- log(x$confirmed)
x$country <- left_join(x,df,by=c('code'='CODE'))$COUNTRY
 
x$hover <- with(x,paste(country,':',confirmed))
 
<- list(
  showframe = FALSE,
  showcoastlines = FALSE,
  projection = list(type = 'Mercator')
)
fig <- plot_geo(x)
fig <- fig %>% add_trace(
  z = ~log_confirmed, color = ~log_confirmed, colors = 'Reds',
  text = ~hover, locations = ~code
)
fig <- fig %>% colorbar(title = 'corona confirmed')
fig <- fig %>% layout(
  title = '코로나 확진자',
  geo = g
)
 
fig
cs

 

확진자 시각화

 

 

 

코로나 완치자 시각화

더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
corona <- read.csv("c:/data/covid/time_series_covid_19_recovered.csv")
corona2 <- read.csv("c:/data/covid/time_series_covid_19_confirmed.csv")
 
# 나라별 코드 갖고오기
df <- read.csv("https://raw.githubusercontent.com/plotly/datasets/master/2014_world_gdp_with_codes.csv")
 
# 코로나 데이터에 코드 join 하기
<- left_join(corona,df,by=c("Country.Region"="COUNTRY"))
x[x$Country.Region=="US",]$CODE <- "USA"
 
# 나라, 코드, (현재까지의) 확진자 컬럼만 있는 새로운 테이블 생성
real <- data.table('country'=x$Country.Region,'code'=x$CODE,'recovered'=x$X7.5.20)
 
# CODE 결측치 확인
# real[is.na(real$code)==TRUE,]
 
# 직접 CODE 넣어주기 위한 작업
# library(doBy)
# orderBy(~COUNTRY,df)
# real[is.na(real$code)==TRUE,]
 
# Congo = COG
real[real$country=='Congo (Brazzaville)',]$code <- 'COG'
real[real$country=='Congo (Kinshasa)',]$code <- 'COD'
 
# Diamond Princess : 크루즈
# Czech = CZE
real[real$country=='Czechia',]$code <- 'CZE'
 
# Gambia = GMB
real[real$country=='Gambia',]$code <- 'GMB'
 
# Holy See = 바티칸시티
# Macedonia = MKD
real[real$country=='North Macedonia',]$code <- 'MKD'
 
# Taiwan* = TWN
real[real$country=='Taiwan*',]$code <- 'TWN'
 
# West Bank and Gaza은 팔레스타인이지만 지도 위치상 이스라엘로 취급 = ISR
real[real$country=='West Bank and Gaza',]$code <- 'ISR'
 
# Eswatini는 나라이지만 위치상 남아공으로 취급 South Africa = ZAF
real[real$country=='Eswatini',]$code <- 'ZAF'
 
# code 별로 확진자 그룹짓기
<- aggregate(real$recovered,by=list(real$code),FUN=sum)
names(x) <- c("code","recovered")
 
# 고른 색깔 분포를 원했는데 특정 국가가 완치자 수가 많아서 log함수를 새로 만듦
x$log_recovered <- ifelse(x$recovered==0,0,log(x$recovered))
x$country <- left_join(x,df,by=c('code'='CODE'))$COUNTRY
 
x$hover <- with(x,paste(country,':',recovered))
 
<- list(
  showframe = FALSE,
  showcoastlines = FALSE,
  projection = list(type = 'Mercator')
)
fig <- plot_geo(x)
fig <- fig %>% add_trace(
  z = ~log_recovered, color = ~log_recovered, colors = 'Blues',
  text = ~hover, locations = ~code
)
fig <- fig %>% colorbar(title = 'corona confirmed')
fig <- fig %>% layout(
  title = '코로나 완치자',
  geo = g
)
 
fig
cs

 

완치자 시각화

 

 

단순히 수치적으로는 당연하게도 인구수가 많은 미국, 브라질, 중국, 러시아 등이 진한 색으로 나타난다.

완치자와 확진자의 비율에 대한 코드를 구현하여 어떤 나라가 코로나에 대응을 잘 했는지에 대해 알아보자.

 

 

완치자/확진자 비율 시각화

더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# 나라별 코드 갖고오기
df <- read.csv("https://raw.githubusercontent.com/plotly/datasets/master/2014_world_gdp_with_codes.csv")
 
# 코로나 데이터에 코드 join 하기
<- left_join(corona,df,by=c("Country.Region"="COUNTRY"))
<- left_join(x,corona2,by=c("Country.Region" = "Country.Region"))
x[x$Country.Region=="US",]$CODE <- "USA"
 
# 나라, 코드, (현재까지의) 확진자 컬럼만 있는 새로운 테이블 생성
real <- data.table('country'=x$Country.Region,'code'=x$CODE,'recovered'=x$X7.5.20.x,'confimred'=x$X7.5.20.y)
 
# CODE 결측치 확인
# real[is.na(real$code)==TRUE,]
 
# 직접 CODE 넣어주기 위한 작업
# library(doBy)
# orderBy(~COUNTRY,df)
# real[is.na(real$code)==TRUE,]
 
# Congo = COG
real[real$country=='Congo (Brazzaville)',]$code <- 'COG'
real[real$country=='Congo (Kinshasa)',]$code <- 'COD'
 
# Diamond Princess : 크루즈
# Czech = CZE
real[real$country=='Czechia',]$code <- 'CZE'
 
# Gambia = GMB
real[real$country=='Gambia',]$code <- 'GMB'
 
# Holy See = 바티칸시티
# Macedonia = MKD
real[real$country=='North Macedonia',]$code <- 'MKD'
 
# Taiwan* = TWN
real[real$country=='Taiwan*',]$code <- 'TWN'
 
# West Bank and Gaza은 팔레스타인이지만 지도 위치상 이스라엘로 취급 = ISR
real[real$country=='West Bank and Gaza',]$code <- 'ISR'
 
# Eswatini는 나라이지만 위치상 남아공으로 취급 South Africa = ZAF
real[real$country=='Eswatini',]$code <- 'ZAF'
 
# 컬럼생성
<- aggregate(real$confimred,by=list(real$code),FUN=sum)
<- aggregate(real$recovered,by=list(real$code),FUN=sum)
<- data.frame("code"=a$Group.1,"confirmed"=a$x,"recovered"=b$x)
 
# 캐나다가 이상치이므로 제대로된 값을 넣어줌
x[x$code =="CAN",]$confirmed <- 107590
x[x$code =="CAN",]$recovered <- 8783
x['vs'<- x$recovered/x$confirmed
 
x$country <- left_join(x,df,by=c('code'='CODE'))$COUNTRY
 
x$hover <- with(x,paste(country,':',recovered))
 
<- list(
  showframe = FALSE,
  showcoastlines = FALSE,
  projection = list(type = 'Mercator')
)
fig <- plot_geo(x)
fig <- fig %>% add_trace(
  z = ~vs, color = ~vs, colors = 'Greens',
  text = ~hover, locations = ~code
)
fig <- fig %>% colorbar(title = 'corona confirmed')
fig <- fig %>% layout(
  title = '코로나 완치자/확진자',
  geo = g
)
 
fig
cs

 

완치자/확진자 비율 시각화

 

 

 

대체로 초창기에 난리가 났던 아시아 국가들이 확진자에 비한 완치자 비율이 높았다.

우리는 코로나 확산을 막기 위해 가장 좋은 방법이 '마스크'라는 것을 안다.

따라서 나는 이를 잘 지킨 우리나라와 세계 각국들의 마스크 사용량을 비교하여 실질적으로 얼마나 마스크가 코로나 확산 방지에 도움이 되는지에 대한 데이터를 분석하려 했다.

 

마스크를 실질적으로 잘 착용하는지 아닌지에 대해서는 한국 이외의 다른 나라에 대해서는 정확히 알 수가 없었다.

따라서 나는 일차적으로 우리나라 마스크 5부제에 착안하여 구글 트렌드를 활용하여 마스크 검색량이 높은 날 +7일 부터 마스크 착용의 효과가 나타난다는 가설로 마스크와 코로나 확산 방지의 관계성을 파악하고자 했다.

 

 

 

 

 

 


 

 

 

 

 

 

대한민국 국민들의 마스크 검색량과 확진자 추이

더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
mask_fact <- function(name,num){
    covid <- read.csv("c:/data/covid/covid_19_data.csv")
    data <- covid[covid$Country.Region==name,]
    data_ <- aggregate(data$Confirmed,by=list(data$ObservationDate),FUN=sum)
    names(data_) <- c("date","confirmed")
 
    fname <- file.choose()
    mask_data <- read.csv(fname)
    mask_data$date2 <- 1:nrow(mask_data)
 
    data_$date2 <- as.Date(data_$date,format='%m/%d/%Y')
 
    data <- data.table('date'=data_$date,'confirmed'=data_$confirmed)
 
    mask_data2 <- mask_data[c(1:nrow(data)),]
    mask_data2$confirmed <- data_$confirmed
 
    # 일일확진자 컬럼 생성
    mask_data2$day_confirmed <- mask_data2$confirmed - lag(mask_data2$confirmed)
    mask_data2$day_confirmed[1<- 1
    mask_data2$mask_fact <- shift(mask_data2$mask,7)
    mask_data2
 
    fig <- plot_ly(mask_data2, x = ~date, y = ~day_confirmed, name = 'confirmed', type = 'scatter', mode = 'lines'
    fig <- fig %>% add_trace(y = ~mask*num, name = 'mask', mode = 'lines')
    fig <- fig %>% add_trace(y = ~mask_fact*num, name = 'mask_fact', mode = 'lines')
    fig <- fig %>% layout(title = paste(name,"국민들의 마스크 검색량과 확진자 추이"))
    fig
}
 
#sort(unique(corona$Country.Region)) # 나라 찾기
# 그래프의 경향성을 보기위해 최대값이 100인 마스크 검색량과 확진자를 맞추기 위해
# 임의의 숫자를 mask 검색량에 곱하여 그래프를 그림
mask_fact("South Korea",7)
cs

우리나라는 마스크 효과가 착실하게 잘 나타난다.

 

 

우리나라 데이터를 통해서 구글 트렌드의 '마스크 검색량'이 어느정도 관계성을 보여준다고 생각하여, 다른 나라에 대해서도 같은 작업을 반복했다.

 

 

미국

 

미국의 코로나 확진자 추이와 마스크 검색량에 대해서는 상관성이 없다는 결론이 나왔다.

하지만 의료관련 종사자들은 하나같이 '마스크'의 중요성에 대해 언급하고 있기 때문에 나는 미국인들의 마스크 검색량이 한국과 같이 마스크 착용으로 이루어지지 않았을 것이라는 추측을 하였다. 이를 증명하기 위해서는 다른 나라들에 대한 마스크 검색량과 그에 따른 코로나 확산 추이를 봐야했다.

 

 

 

싱가포르

 

독일

 

 

싱가포르와 독일에 대해서 구글 트렌드와 코로나 확진자 추이를 보았으나, 오히려 미국보다 더 상관성이 없다는 것을 파악할 수 있었다. 구글 트렌드에서의 '마스크 검색량'이 실제 마스크 착용으로 이루어지는 것은 오직 우리나라 뿐이었다. 따라서 나는 다른 데이터를 구해야만 했다.

 

내가 찾은 데이터는 YouGov의 Wearing a face mask when in public places 부분이었다. 이에 대한 데이터를 csv 파일로 다운 받아, 마스크를 쓴다고 응답한 사람들의 퍼센트와 실질적인 확진자 감소 추이에 대해 분석하고자 했다.

 

 

 

 

 


 

 

 

 

 

마스크 착용과 코로나 확산 감소의 관계성 파악

더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
survey_mask <- function(name,num){
    covid <- read.csv("c:/data/covid/covid_19_data.csv")
    data <- covid[covid$Country.Region==name,]
    data_ <- aggregate(data$Confirmed,by=list(data$ObservationDate),FUN=sum)
    names(data_) <- c("date","confirmed")
    data_$date2 <- as.Date(data_$date,format='%m/%d/%Y')
 
    # 일일확진자 컬럼 생성
    data_['day_confirmed'<- data_$confirmed - lag(data_$confirmed)
    data_$day_confirmed[1<- 1
 
    # 설문조사 그래프
    survey <- read.csv("c:/data/covid/yougov-chart.csv")
    survey['date'<- substr(survey$DateTime,1,10)
    survey['date2'<- as.Date(survey$date,format='%Y-%m-%d')
 
    new <- left_join(survey,data_,by=c("date2"="date2"))
 
    new$confirmed[is.na(new$day_confirmed)] <- 0
    new['country'<- new[name]
 
    fig <- plot_ly(new, x = ~date2, y = ~country*num, name = name, type = 'scatter',mode = 'lines+markers',connectgaps = TRUE,text = ~country)
    fig <- fig %>% add_trace(y = ~day_confirmed, name = 'day_confirmed', mode = 'lines+markers',connectgaps = TRUE)
    fig <- fig %>% layout(title = paste(name,"국민들의 마스크 착용률과 확진자 감소 추이"))
    fig
}
 
survey_mask('Germany',100)
cs

 

베트남에 대해서는 코드가 약간 다르다.

 

독일, 베트남, 이탈리아 등 YouGov에서 받은 csv 파일에 비교적 최근까지의 응답이 있던 나라들에 대해서 마스크 착용과 코로나 확산 감소에 대한 그래프를 그렸더니 마스크 착용 응답 적었을 때보다 높아졌을 때 코로나 확진자가 감소한 것을 볼 수 있었다. 실질적으로 마스크가 코로나 확산 방지에 도움이 된다는 것을 데이터로 파악할 수 있었다.

 

 

미국에 대해서도 약간 코드가 다르다. 알아서.. 하시길...

 

위의 나라들과 달리 미국은 응답이 높아지면서 확진자가 감소하다가 갑작스럽게 확진자가 많아졌다.

이에 대해서는 2가지 가설을 언급할 수 있겠는데,

첫번째로는 YouGov에 응답한 미국인이 너무 적어 표본이 되지 못했다는 것과 두번째로는 허위 응답을 했다는 것이다.

 

하지만 위의 데이터에서 응답이 높아질수록 실제 확진자 수가 감소한 경향을 보이고, 다른 나라들이 위의 데이터에 어느정도 신빙성을 보이고 있기 때문에 나는 미국인들이 허위 응답을 했다는 결론을 내렸다. 다들 마스크를 잘 쓰고 다녔으면 좋겠다...

 

 

 

 

 


 

 

 

 

 

실제로 이 기사 내용에 따르면, 마스크 착용 이후 호흡기감염병들이 많이 줄어듦을 알 수 있다.

또한 개인 위생에 대한 중요성이 대두되면서 눈 질환에 대해서도 환자가 적어진 것으로 나타났다.

 

 

출처 : https://news.v.daum.net/v/20200508050119955

 

 

결론은 더워도 마스크 잘 쓰고 다니자는 이야기입니다.

 

 

 

+ Recent posts