페이지

2021년 12월 31일 금요일

딥러닝을 통한 한글 문장의 질의응답 예측은 어떻게 할까? – 2편

1편에서 한글 질의응답 시스템, 질의응답 처리절차, 데이터세트, 성능평가까지 살펴보았다. 이제 이어서 훈련, KoertTokenizer 환경 준비부터 파인튜닝 그리고 평가까지의 절차를 살펴보도록 하자.

시작하기 전에, 1편에서 한글 질의응답 성능에서 HanBERT 가 가장 성능이 좋다고 하였는데, Huggingface Transformers 2020KoELECTRA 를 보니, small model base-model에서 인간의 성능(EM 80.17, F1 91.2)을 모두 능가하는 성능을 달성하였다. Small Base의 차이, ELECTRA 등에 대한 자세한 내용은 여기를 참고하기 바란다. 

<그림 1. Huggingface 한글질의 응답 성능 비교>

 

BERT 언어모델 훈련

 아래 그림 2 와 같이 Bert에 입력되는 두개의 문장은 Token, Segment, Position이라는 임베딩이 단어 임베딩 단위로 이루어져 Bert 에 입력된다. 이때 최종 입력되는 형태인 그림 최상단의 input 을 보면 ①과 같이 문장 처음에 [CLS]가 삽입되고 ②와 같이 문장 일부를 가려(MASK)버리고,  ③과 같이 문장과 다음 문장을 구별하는 [SEP] 구별자가 들어가고 ④와 같이 단어 임베딩으로 WordPiece tokenizer 를 사용하는데playing play ##ing 로 어절이 분리된다. 구글은 BERT WordPiece 를 사용했지만 구현체를 공개하지 않아 대부분의 한국어 NLP 개발자들은 SentencePiece 를 사용한다. SentencePiece 는 단어 분리 알고리즘을 사용하기위해 사전 토큰화 작업없이 전처리를 하지않은 raw 데이터에 바로 단어 토크나이저를 사용할 수 있다는 이점을 제공한다. Tokenizer 에 대해서는 이전 뉴스레터 16 를 참고.


<그림 2. BERT 에 입력되는 토큰의 임베딩>

 

monologg/KoBERT 모델의 훈련

1편에서 git clone 을 통해 설치된 monologg/KoBERT 코드의 home 디렉토리 밑에 run_squad.py 그리고 data models 폴더를 확인하면서 아래와 같은 명령어를 수행함으로써 모델 훈련이 시작된다. ①번과 같이 model_name monologg/kobert 가 입력되어야 한다. ②번에 output_dir models 로 해주어야 models 밑에 훈련 output checkpoint 파일들이 저장된다. ③에 저장 step 4000회 마다 저장된다.  까지 저장된 것을 확인하면 훈련이 끝난 것이다.

<그림 3. Monologg/kobert 훈련 명령어>

 

훈련된 모델의 성능은 KorQuAD_v1.0_dev.json 파일을 대상으로 아래와 같은 파이선 명령어를 통해 평가할 수 있다.  evaluate_v1_0.py 파일은 KorQuAD에서 제공하는 evaluation script 로 평가한 결과는 EM 51.09, F1 78.36으로 huggingface official monologg/KoBert 성능(EM: 52.81, F1: 80.27)에 근접한 것을 확인할 수 있다.

KoBertTokenizer 환경 준비

본 시스템은 huggingface transformers monologg/kobert 모델을 사용하고 있지만, huggingface transformers v2.9.0 부터 tokenization 관련 API 가 일부 변경되었다. 이에 맞춰 기존의 tokenization_kobert.py를 상위 버전에 맞게 수정한 버전은 여기를   참조.  따라서 transformers 버전은 반드시 3.0 이상을 설치할 것을 권고한다.

우선 한글 tokenizer 를 사용하려면 KoBertTokenizer 를 아래와 같이 import 해야 한다.  BERT 언어모델, KoBERT, SentencePiece 등은 이전 뉴스레터 16, KoBERT 의 한글 tokenizer 에 대해 보다 자세한 사항은 뉴스레터  17 를 참고바란다.


그리고 아래와 같은 명령을 통해 tokenizer 를 사용할 수 있게 된다. models 디렉토리에는 훈련된 checkpoint 파일들이 있어야 한다


Tokenizer.tokenize 를 통해 토큰화된 결과를 확인해보자. Encode 는 인코딩된 숫자로 나타나고 나중에 decode 하면 원문으로 복원된다. 와 같이 sentencepiece 방식의 토크나이저 가 확인되고 encode 결과에 [CLS] 에 해당하는 ‘2’ 와 마지막에 [SEP] 에 해당하는 ‘3’ 으로 나타남을 확인할 수 있다.


질의응답 문제 해결을 위해 BERT 모델 활용 변경

 BERT 는 위 그림 2 와 같이 이어지는 두개의 문장을 mask 모델과 다음 문장 예측과 같은 방법으로 학습하는 자기지도(self-supervised) 방식이다. 반면 질의응답은 아래 그림 4와 같이, [SEP]로 분리된 문장을 질문과 원문으로 다르게 활용한다.

 

<그림 4. 질의응답의 BERT 학습 방식>

 

파인 튜닝

  사전훈련 모델이란 BERT 같은 대용량 데이터세트의 자연어 언어 모델 작업을 사전에 훈련시켜 놓은 모델을 뜻한다. 이미 검증된 성능으로 훈련시킨 언어모델의 가중치를 사용함으로써 한글 질의응답이 담긴 소규모 train dev 데이터세트로도 좋은 성능을 낼 수 있다. 파인 튜닝(fine tuning)이란 BERT 와 같은 사전 학습 모델의 가중치를 그대로 사용하여 BERT 사전 학습된 가중치의 이점으로 한글 질의응답데이터세트를 질문과 원문의 입력으로 변형하여 훈련시키는 것을 말한다. 아래 그림 5 는 사전 학습된 모델을 로드 할 때 training=False로 하여  BERT 모델에서 마지막 트랜스포머 계층 까지만 모델이 로드되게 하는 개념을 설명하기위한 하나의 예이다. 전이학습절차, 모델 파인튜닝에 대한 자세한 내용은 이전 뉴스레터 15를 참고 바란다.


<그림 5. 사전 학습 모델 로드>

 

아래 그림 6는 파인 튜닝의 이해를 돕기 위해  Keras 로 구현된 fine tuning 모델 모듈 예시다. 위의 그림 5와 같이 BERT 로 로드 된 모델에 그림 6과 같이 My_layer_Start My_layer_End 의 완전연결층을 추가하여 파인 튜닝 모델을 완성한다.

   에서 Bert 모델에서 출력된 질문과 원문의 두 입력 값이 파인 튜닝 모델의 입력으로 입력된다. ②는 NonMasking 함수를 지정해서, Bert 모형의 자체 Masking 된 텐서들을 풀어줘야 한다. ③에서 MyLayer_Start는 정답의 첫 번째 단어를 예측하는 것을 담당하고, MyLaer_End는 정답의 마지막 단어를 예측하는 것을 담당한다. , BERT 의 마지막 입력을 받아서, 2개의 텐서에 출력을 내보내는 두 layer 의 역할은 동일하다. 여기서 SEQ_LEN 즉 최대 입력되는 토큰 수는 BERT 에서 512 까지를 최대값으로 설정되어 있다.


<그림 6. 모델 파인 튜닝 예>

 

평가

 파인튜닝 모델을 위에서 설명한 monologg/KoBert 모델에 완전연결층을 추가하여 구현 할 수 있으나 HuggingfaceBERT – transformers 4.12.5 document BertForQuesionAnswering 에 나와있는 예제 를 참조하여 평가 모듈을 구현할 수 있다. 이때 transformers 버전은 4.0 이상의 환경일 경우에만 정상 작동한다. 따라서, 파인튜닝 학습은 transformers 3.3.1 을 준수하고 평가 모듈 작성시에는 4.0 이상을 고려해야 한다.

  아래 그림 7 은 수행관 결과이다. ①은 질문, ②는 원문, ③은 KorQuAD_v1.0_train 데이터세트에 있는 정답 컬럼에서 가져온 값, ④는 본 질의응답 시스템에서 예측한 답이다.

<그림 7. 질의응답 수행 결과>

 

또한, Huggingface monologg/KoElectra small v3 모델을 Nvidia A100 GPU 2 대로 훈련하여 파인튜닝 한 결과, 아래 그림과 같이 EM: 82.59, F1:91.49 를 기록하여 인간의 성능인 EM: 80.17, F1: 91.2 를 능가함을 확인하였고 질의응답에서도 더 나은 성능을 보였다.


결언

지금까지 1편에서 딥러닝을 이용한 한글 질의응답 처리절차, 데이터세트, 성능평가 그리고 이번 2편에서 훈련, KoertTokenizer 환경 준비, 파인튜닝 그리고 평가까지의 절차를 살펴보았다. Huggingface transformers 기반 BERT 모델 중에 monologg/KoBert 를 중심으로 살펴보았다. 이외에도 104개 국어를 지원하는 Bert-mutilingual 도 별도의 한글 토큰화 없이도 자체 모델만으로도 F1 score 90.25% 로 높은 점수를 내고 있고, 그 이후에 선보인 KoELECTRA 모델은 앞에 살펴본 바와 같이 사람의 성능을 뛰어넘는 결과를 보여준다.

다만 KorQuAD 1.0 대상의 질의응답은 입력 시퀀스가 몇 가지 단락의 한글 문장만이 대상이어서, KorQuAD 2.0 과 같이, 한글 위키백과 전체에서 답을 찾고, 표와 리스트도 포함된 다양한 형태와 길이로 사람의 성능을 뛰어넘는 딥러닝 기반 질의응답 시스템이 발전하고 있어서 향후 많은 발전이 기대되는 부분이라고 할 수 있겠다.

딥러닝을 통한 한글 문장의 질의응답 예측은 어떻게 할까? – 1편

 질의응답(question&answer)

질의응답이란 자연어처리 기술을 활용하여 주어진 문장에 대하여 질문을 던졌을 때 이에 대한 답을 예측하는 인공지능의 분야를 뜻한다. 한국어 Machine Reading Comprehension 분야에서 발전해 왔다. 아래 그림 1과 같이 60,407 행의 index, 질문, 원문, , 정답이 원문에서 시작하는 위치 등의 컬럼이 있는 데이터세트를 가지고 질의응답 예측을 살펴본다. 원문과 질문 그리고 정답에서도 알 수 있듯이, AI에 이러한 데이터세트를 훈련시키면, 새로운 질문에 대하여 AI는 원문으로부터 정답이 시작되고 끝나는 위치를 반환한다.


   <그림 1. Korean Question Answering Dataset >

 

한국어 질의응답 과제를 위한 데이터세트

 위의 그림 1 에 데이터세트는 LGCNS 가 미국 스탠포드대학의 기계 독해 기반의 표준데이터세트인 SQuAD v1.0 이라는 데이터 생성방식을 벤치마크하여 표준성을 확보하여 KorQuAD v1.1 이라는 이름으로 생성한 데이터세트다. 이 의미는 SQuAD에서 train dev .json 파일을 로드하는 방식을 KorQuAD에서 똑같이 사용할 수 있다는 뜻이다.  여기 에서 다운로드 받을 수 있으며 KorQuAD_v1.0_train.json KorQuAD_v1.0_dev.json 파일을 받을 수 있다. 훈련용은 60,407 행의 데이터, 테스트용 dev 5,774 행의 데이터이다. 이 외에도, 우리가 이후에 살펴볼 Huggingface Transformers 라이브러리에 등재된 monologg/kobert 모델을 사용할 때 git clone 으로 data 디렉토리 밑에 이들 데이터세트들도 포함되어 있으니 미리 다운로드 받지 않아도 된다. 평가할 수 있는 스크립트도 함께 다운로드 되는데 TEST 데이터에서 EM 80.17% / F1 91.20% SQuAD v1.1 에 대한 인간의 성능이라고 한다. 아래 그림 2 KorQUAD v1.0 의 테스트 세트로 평가한 Exact Match(EM) F1 스코어가 있다.

<그림 2. KorQuAD 1.0 리더보드>

 

리더보드를 보면 추출형 질의응답에서 이미 EM F1 점수에서 인간의 성능을 훨씬 넘어선 것을 알 수 있다. Exact Match(EM)는 정답과 예측 값이 얼마나 정확히 예측하는지에 대한 비율을 나타내고, F1 은 음절 기준으로 얼마나 중복되는지를 고려한 점수이다. KorQuAD 2.0 KorQuAD 1.0 과 는 다르게 1~2 문단이 아닌 위키피디아 문서 전체에서 답을 찾는 것과 같이 매우 긴 문서와 함께 표와 리스트도 포함된 데이터로 보다 실제 업무현장 환경과 같은 질의응답이 가능해진다. KorQuAD 2.0에서 인간 성능은 EM 68.82/F1 83.86 에 비해 리더보드의 1위는 EM 77.86/F1 89.82 로 이 역시 인간 성능을 앞선다.

 

질의응답 처리 절차

딥러닝을 통한 대략적인 질의응답 처리 절차는 아래 그림 3과 같다. Huggingface Transformers 라이브러리를 이용하여 구현하였으며 monologg/KoBERT-Transformers repo 를 사용하였다. README 파일을 보면 transformers 는 반드시 3.0 이상을 설치할 것을 권고하고 있다. 그리고 tokenizer 는 설치된 kobert_transformers /tokenization_kobert.py 를 사용해야 한다. Tokenizer를 사용하려면, kobert_transformers/tokenization_kobert.py 파일을 복사한 후, KoBertTokenizer 를 임포트하면 된다. Monologg/koBERT 모델을 훈련하는데 NVIDIA A100-PCIE-40GB GPU 1 개를 사용하였다. NVIDIA 벤치마크에서 V100 32GB 대비 약 4배의 처리성능을 보이는 것으로 되어있다. Torch 1.10.0, Python 3.8, Cuda 11.3 의 환경에서 훈련하였다.

1.    repo 에 있는 github 주소로부터 repository 를 복사하여 git clone 한다.

2.    Transformers3.0 이상으로 하여 torch 등의 관련 라이브러리들을 설치한다. 저자는 초기 훈련은 README 권고 환경으로 하고 나중에 파인튜닝 이후에 transformers 4.1.0 환경을 사용하였다. Transformers 4.0 까지는 이슈가 없는 걸로 나와있다.

3.    python3 run_squad.py 를 통하여 README 에 명기된 데로 훈련을 시행한다. 참고로 disk 용량은 10GB에서 용량부족을 만났으므로 여유 있게 30GB 정도로 잡아주는 것이 좋다. 이때 data 폴더 밑에는 한글 KorQuAD 데이터세트인 KorQuAD_v1.0_train.json KorQuAD_v1.0_dev.json 이 있어야 한다. Repo 에 담겨있지만, 혹시 없으면 KorQuAD github repo 에서 다운로드 받아야 한다.


<그림 3. 질의응답 처리 절차>

 

훈련이 진행되면 models 폴더 밑에 checkpoint-xxxx 같은 체크포인트 파일들이 생 긴다. models 폴더의 weight 값들을 가지고 나중에 전이학습을 통해 KoBERT 모델이 한글 질의응답을 진행하게 되므로 checkpoint-24000 까지 완성이 되었는지 확인이 필요하다.

1.    위에 모델이 생성된 이후에 KorQuAD 데이터세트에서 함께 다운로드 받은 evaluate_v1.0.py (repo clone 시 이미 파일에 담겨있음)로 성능을 평가한다.

2.    위의 사전 훈련된 모델을 사용하여 한글 tokenizer 기반의 질문과 원문이 입력이 되어 정답의 시작 포인트와 끝 포인트를 출력하는 모듈을 사용하여 질의응답 모듈을 작성

 

한글 질의응답 시스템

  자연어처리 분야 중에서 질의응답 혹은 기계독해(Machine Reading Comprehension)는 주어진 본문과 질문을 컴퓨터가 이해하고 스스로 해답을 제시하는 인공지능 태스크로 질의응답, 챗봇, 계약서 및 약관리스크 분석, 그리고 금융권의 컴플라이언스 등 다양한 분야에서 응용될 수 있다.

RNN 기반의 언어모델을 보완한 트랜스포머 언어모델인 BERT의 등장은 자연어처리 기술에 획기적인 발전을 가져왔다. 아래 그림 3과 같이 트랜스포머 기반 모델의 사전학습과 전이학습은 기계번역, 문장 분류, 기계 독해, 개체명 인식 등의 다양한 자연어 처리 분야에서 SOTA(State-Of-The-Arts)를 달성하는 업적을 이루었다. 특히, 기계 독해의 객관적인 지표로 활용되는 SQuAD 데이터셋의 리더 보드에서는 BERT 기반의 사전학습 모델이 대부분을 차지하고 있을 정도로 BERT의 대외적인 성능 과 활용도는 실질적으로 입증되고 있다. 2018 10월 구글에서 기존 SQuAD 1.1 task에서 human performance를 넘어서는 BERT 모델에 대한 논문을 발표했다. BERT 모델에 대해서는 이전 뉴스레터 16를 참고하기 바란다.

  본 과제에서의 한글 질의응답시스템은 기계 독해의 객관적인 지표로 활용되고 있는 KorQuAD 1.0 을 대상으로 최대 512 바이트 길이의 한글 본문과 질문을 입력하면 질의응답시스템이 본문중에서 질문에 해당하는 정답의 단어 나 문장의 처음 위치와 마지막 위치를 리턴하는 시스템을 구현하는 것이다.

 


<그림 3. BERT 사전학습을 통한 downstream 태스크 예>

 

Huggingface KoBert Transformers 라이브러리

  HuggingfaceTransormers 기반의 BERT, BART, ELECTRA 등등의 최신 자연어처리 알고리즘들을 Tensorflow, Torch로 구현한 transformers repository 를 제공할 뿐 아니라, 한글 토크나이저를 지원하는 우리가 사용하는 molonogg/KoBERT-Transformers 같은 개인이 만든 모델을 transformers를 통해 직접 업로드/다운로드하여 사용할 수 있게 되었다.

Tokenizer를 사용하려면 `tokenization_kobert.py`에서 `KoBertTokenizer`를 임포트해야 하며 아래와 같이 사용한다. BertModel KoBertTokenizer 를 임포트 한 후에 각각을 .from_pretrained(‘monologg/kobert’) 로 사전학습모델을 불러 사용한다.

 

KorQuAD 1.0 데이터세트

KorQuAD(The Korean Question Answering Dataset, 한국어 질의응답 데이터셋)는 한국어 기계독해(MRC)를 위해 LGCNS에서 구축한 대규모 질의응답데이터셋으로 한국어MRC 모델을 학습하고 그 성능을 평가하는 일에 사용되고 있다. 아래 그림 4 와 같이 버전 1.0 2.0 은 차이가 있고 본 시스템에서는 1.0 데이터세트를 사용한다.

<그림 4. KorQuAD 1.0 2,0 비교>

 

한글 질의응답 성능평가

Huggingface KoBERT 사전학습 모델을 이용한 한글 질의응답 성능 결과는 아래 그림 5 와 같다. 사람 성능 이 EM 80.17, F1 91.2 인 것을 감안하면 성능이 아직 못 미침을 알 수 있다

<그림 5. Huggingface BERT 모델 별 한글 질의응답 성능>

Huggingface 의 한글 질의응답의 다른 모델로 HanBERT EM 78.74, F1 92.02, 그리고 문장의 mask 훈련을 generator discriminator 로 가장 그럴듯한 문장을 맞추는 형태로 학습하는 KoELECTRA-base 의 경우는 EM 61.10, F1 89.59 를 나타내어 현재는 HanBERT 가 가장 사람의 능력에 근접한 것으로 보인다.

  지금까지 한글 질의응답 시스템, 질의응답 처리절차, 데이터세트, 성능평가까지 살펴보았다. 2편에서 KorQuAD 데이터를 통한 훈련, 파인튜닝, 및 평가까지 살펴보겠다.


누적된 날씨 관련 시계열(timeseries) 데이터로부터 미래 온도는 어떻게 예측할까?

 시계열(timeseries)

이번 호에서는 시계열(timeseries) 데이터로부터 24시간 이후의 온도를 예측하는 문제를 다뤄보고자 한다. 이러한 미래 온도를 예측하는 문제에서 사용하는 시계열이란 데이터는 지금까지 다루어 왔던 데이터 형식과 다른 형태로, 주가의 일일 변동, 매장의 일주일간의 매출액, 환자의 몸에 부착된 장치에서 측정되는 파형과 같이 일정한 간격으로 측정되어 확보된 데이터세트를 뜻한다. 따라서 시계열데이터는 반복 주기, 안정 상태와 갑작스러운 돌출파형 등의 시간의 흐름에 따른 경과 등의 시스템의 역학관계를 이해하는 것이 중요하다. 주로 이러한 시계열 관련되어 머신러닝 작업에서 가장 많이 수행하는 작업이 예측이다. 반복되는 계열로부터 이후의 계열에서 어떤 일이 발생할지를 예측하는 것이다.

딥러닝을 이용하여 이러한 문제를 해결하기위해 우선 순환신경망(Recurrent Neural Network)을 사용하고, 독일의 Jena에 위치한 막스플랑크 생물지구화학 연구소의 기상 관측소에 2009년부터 2016년 사이에 매 10분 간격으로 저장된 온도, 압력, 습도 등등의 14가지 측정값 들이 저장된 시계열 데이터를 사용한다. 문제의 정의는 이러한 누적된 날씨관련 데이터로부터 다음 날 온도를 예측하는 것이다. 순환신경망(RNN)의 동작원리에 대해 좀 더 알고 싶을 경우에는 지난 뉴스레터9를 참고.

온도 예측 문제

우선 사용할 jena 기상관측소의 데이터를 아래와 같이 다운로드 받는다.



<그림 1. 시계열 데이터 다운로드>

 

그 다음 아래 그림 2와 같이 csv 파일을 열어, 파일을 살펴보자. 전체 420,451 행의 데이터가 각각 datetime 시간 기록, 압력, 온도 등의 14개 일기관련 값과 헤더를 가지고 있다. lines 에는 header 가 분리된 내용만 담김을 알 수 있다.


<그림 2. Jena 기후 데이터의 탐색>

데이터의 첫번째 행을 보면 아래와 같이 14개의 컬럼에 대응하는 값들이 ‘,’ 에 의해 구별되어 부동소숫점(float) 형식으로 저장되어 있다.


데이터들 로부터 타겟과 데이터를 분리한다. 섭씨 온도를 담는 temperature 와 모든 데이터를 담은 raw_data 의 두 개의 Numpy array 를 생성. ①번에서 첫번째 컬럼인 datatime 이 배제되었고 ②에서 데이터의 온도에 해당하는 내용이 temperature 에 담기고 ③에서 모든 데이터(온도 포함)가 raw_data에 담긴다.


<그림3. 타겟과 데이터의 분리>

 

 아래 그림 4와 같이 matplot 을 사용해 2009년부터 2016년까지의 8년간 420,451 레코드의 온도를 표시해본다. 8번 매년 반복되는 패턴이 선명하게 나타난다. 데이터는 매 10분 간격으로 측정되어 하루는 24 * 6 = 144 , 1년은 52,560, 8년은 420,480 이다.


<그림 4. 8년간의 온도(섭씨) 변화>

 

주어진 지난 시계열 데이터로 미래의 예측을 하려면 validation이나 test 데이터가 training 데이터보다 최신의 것이어야 한다. 왜냐하면 과거를 기반으로 미래를 예측하는 것이기때문에 훈련데이터 할당이 validation 이나 test 보다 우선시되어야 한다. 시간 순서로 처음의 50%train에 그 다음 25%validation 그리고 마지막 최신의 25%test 로 할당한다. 아래 그림과 같이 train 210225 샘플을 보유한다.


<그림 5. 분할 된 데이터의 샘플 수 산출>

 

데이터 정규화

데이터들이 모두 숫자로 되어있어서 신경망이 소화할 수 있는 벡터화는 필요 없지만, 14개 항목의 값들의 범위는 제 각각이다. 할당된 210,225 개의 훈련데이터에 대해 평균과 표준편차를 계산하여 정규화를 시킨다.

 

<그림 6. 훈련데이터 정규화>

 

아래 그림 7keras 의 내장된 데이터셋 유틸리티인 timeseries_dataset_from_array 예를 보자. ①을 통해 0부터 9까지의 정수 배열을 생성한다. dummy_dataset을 생성하는 인자로 ②는 우리가 생성할 시퀀스는 처음부터 끝에서 세번째까지 샘플링 할 것임을 설정 즉 [0 1 2 3 4 5 6], ③은 시퀀스가 만약 데이터의 N번째에서 시작이라면 타겟은 데이터의 N+3 이 된다는 설정. 아래 출력과 같이 [0, 1, 2]에서 타겟은 3 이 된다. ④ 시퀀스 길이는 3


 <그림 7. Kerastimeseries_dataset_from_array 사용 예>

 

 데이터세트 구성

 위에서 살펴본 keras timeseries_dataset_from_array 를 활용하여 아래 그림 8과 같이 설정한다. ①샘플 비율은 기록이 10분마다 이루어지므로 한 시간에 6개 데이터 샘플링. ②시퀀스 길이는 5일 동안 즉 120 시간. ③의 delay는 결국 5일 동안의 시퀀스 길이에 더한 24시간 후의 샘플링 숫자를 가리키는 10분마다의 총 샘플링 숫자. ④는 위의 그림 7의 ②와 같이 우리가 생성할 시퀀스를 설정하는 것. ⑤는 위의 그림 7의 ③과 같이 타겟 설정. ⑥은 앞의 그림 5num_train_samples 을 가리킨다.

<그림 8. train 데이터세트 설정>

train 데이터세트는 (samples, targets)의 튜플 형태로 만들어진다. 여기서 sample batch 256개의 샘플을, 각 샘플은 계속되는 120시간의 입력 데이터로 보유된다. target은 해당하는 256 개의 온도 array 형태 데이터이다. 샘플은 임의로 섞이기 때문에(shuffle=True), sample[0] sample[1] 과 같이 batch에서 연속된 두 시퀀스가 반드시 유사하다고 볼 수 없다.

val_dataset 은 그림 8train 데이터세트 설정과 모두 내용이 같다 다만 이전 그림 5. 에서 설명한 바와 같이, 훈련 데이터세트 이후에 validation set 를 할당하므로,  start_index=num_train_samples, end_index=num_train_samples+num_val_sample로 바뀐다.

test_dataset 은 마찬가지로 모든 설정이 같고 다만, start_index = num_train_samples +num_val_sample이고 end_index 는 결국 마지막까지 에 해당하므로 별도 표시하지 않는다.

 

순환신경망 동작 개요

 단순한 순환신경망(RNN) 구조를 통해 작동 원리를 살펴보자. 아래 그림 9를 보면, input, output, state 라고 하는 값들이 우측으로 진행됨에 따라 t-1, t, t+1 이라는 timestep을 가지고 움직이는 것을 볼 수 있다. 아주 단순하게 RNN을 다른 신경망과 구별 지어 설명한다면, 이전 loop의 반복 동안에 연산 된 값을 재사용하는 for  loop으로 설명할 수 있다. ③번의 output_t 를 보면, input_t weight Wo vector dot product 수행한 ①과, 이전 상태의 output state_t weight Uo vector dot product 가 된 ②와 bias bo 를 합산하여 activation 함수를 거쳐서 산출됨을 알 수 있다. 여기서는 t timestep 을 의미하는데 아래 그림은 결국 이러한 ③번의 output 연산이 timestep t 를 따라 반복되는 것임을 나타낸다.

<그림 9. RNN 개념도>

 

 아래 그림 10은 아주 간단한 RNN 실행을 보여준다. 위의 그림9와 함께 보면 좀 더 이해하는데 도움이 될 것 같다. ①번에 RNN(timesteps, input_features)의 형태로 2D tensor 가 입력 값으로 들어갈 수 있게 설정한다. ②에서 우선 초기 상태 state_t 를 모두 0인 벡터로 초기화 한다. ③④의 U, W, b weight 매트릭스다. 임의의 초기값으로 생성한다. ⑤번에서 input_t (input_features) 형태의 벡터이다. ⑥번은 위의 그림 9의 가운데 박스에서 일어나는 연산이다. 결국 ⑤번부터 ⑧번까지의 사이클은, timestep 만큼 loop 를 수행하는데, 이전 반복 연산의 결과 state_t와 현재시점t시간에서의 입력(input_t)으로 (input_features)형태의 값을 받아, 이 둘 즉 state_t input_t 를 합쳐서 output t를 만들어내는 것이다. ⑦번에서 이 output successive_outputs 라는 리스트에 timestep 에 따라 계속 추가해 넣는다. ⑧에서 output_t state_t 로 지정해주어 다음 timestep 에서 이 output_t 가 다시 입력으로 들어갈 수 있도록 해준다. 그리하여 for loop 이 끝나면, ⑨와 같이 output_t timestep 만큼 쌓인 final_output_sequence 2D tensor (timesteps, output_features) 형태로 만들어진다.


<그림 10. Numpy 로 작성된 단순한 RNN>

 

LSTM 층을 사용한 24시간 후 온도 예측

자 이제 실제 LSTM 층을 통해서 온도예측을 수행해보자. 아래 그림 11과 같이 keras 를 통하여 ①과 같이 input 을 정의하고, 32unit 을 가진 LSTM 층을 설정하는데, dropout 없이 실행하면 바로 과적합이 일어난다. ③번의 Dense 층에도 일반화를 위해 Dropout 층을 추가한다. 여기서 한가지, ⑥번에 시간을 측정했는데 이유는 ②번의 unroll=True 를 설명하기 위해서이다.


 <그림 11. LSTM 층을 사용한 훈련 및 평가>

 

Keras LSTM 이나 GRU GPU 상에서 수행할 때, 복잡한 RNN 이 아닌, 디폴트 인자로 수행할 경우, cuDNN 커널을 사용하게 되는데, 과적합을 방지하기위해 ②번의 recurrent dropout 과 같은 인자를 사용하면 cuDNN 커널의 도움을 받을 수 없어 2~5배 정도의 GPU 속도 저하를 경험한다. ⑦번에 WARNING 메시지가 그것이다. cuDNN을 사용하지 않을 때 속도를 올리기 위해 unrolling=True 로 설정하는 것이 좋다. 설정하지 않았을 때 Nvidia RTX 2080Ti 1 GPU에서 50 epoch 를 훈련하는데 276분이 소요되던 것이 설정하고는 101분으로 줄었다. ⑤번에서 평가는 mean absolute error 로 측정하였다. , 예측한 24시간 이후의 정답 온도의 평균 몇 도(섭씨)의 차이를 보이는 가를 측정한다는 뜻이다

 

결언

 지금까지 기상관련 8년간 10분 간격으로 측정된 시계열 데이터세트를 이용하여 순환신경망으로 24시간 후의 온도를 예측하는 것을 살펴보았다. 위의 그림 11의 훈련을 50 epoch 수행하고 난 결과는 아래와 같다. Validated Mean Absolute Error 값은 2.3176 을 얻었다. MAE 예측 값과 실제 값의 차이에 대한 절대값에 대해 평균을 낸 값으로, 간단한 RNN 층을 이용하여 24시간 이후 온도 예측에서 실제 값과 약 2.32도 차이를 보이는 결과를 얻었다.