1. 들어가며
- 2018년 10월 SQuAD(Stanford Question Answering Dataset) 리더보드에 Human performance를 능가하는 점수로 1위 자리를 갱신한 모델이 나타나서 엄청난 주목을 끌었다.
- 이른바, 사람보다 퀴즈를 잘 푸는 인공지능이 나타났다는 소식은 딥러닝 자연어처리 분야에 충격적인 뉴스가 아닐 수 없었다.
- 구글에서 발표한 논문에 소개된 이 모델의 이름은 BERT(Bidirectional Encoder Representations from Transformers)였다.
- 이 모델은 340MB나 되는 엄청난 사이즈의 파라미터를 가진 모델을 수십 GB나 되는 코퍼스를 학습 시켜 만든 pretrained model이다.
- 이 모델은 SQuAD뿐 아니라 당시 거의 모든 자연어처리 태스크의 SOTA(State-of-the-art)를 갱신하는 기염을 토했다.
- 단순히 성능이 개선되어사만이 아니라, BERT는 엄청난 규모의 언어 모델(Language Model)을 pretrain하고 이를 어떤 태스크에든 약간의 fine-tuning만을 통해 손쉽게 적용하여 해결하는 제너럴한 방식이 가능함을 입증하여, 자연어처리 패러다임의 근본적인 변화를 불러왔다.
- 이후 수많은 후속 모델들이 BERT의 아이디어를 더욱 발전, 확장시켜 나가면서, 이전에는 기대할 수 없었던 자연어처리 기술 발달을 가속화해 가고 있다.
- 오늘은 이 BERT 모델 구조를 살펴보고, Pretrained Model을 활용하여 한국형 SQuAD인 KorQuAD 태스크를 수행하는 모델을 학습해본다.
- 이 과정을 통해 Contextual Word Embedding의 개념과 자연어처리 분야의 최근 트렌드인 전이학습(Transfer Learning) 활용 방법까지 함께 숙지하도록 한다.
2. KorQuAD Task
- KorQuAD 소개
1) 오늘은 KorQuAD(The Korean Question Answering Dataset, 한국어 질의응답 데이터셋)을 통해 자연어처리 분야의 기계독해(Machine Reading Comprehension, MRC) 태스크를 다룰 예정이다.
2) 이 데이터셋은 미국 스탠퍼드 대학에서 구축한 대용량 데이터셋인 SQuAD를 벤치마킹한 것이다.
3) 자연어 처리에 입문하게 되면 흔히 감성분석 등의 Text Classification, 또는 Encoder-Decoder 구조의 모델을 통한 변역 태스크를 많이 다루게 될 것이다.
4) 그러나 자연어처리 분야에서 기계독해 태스크는 머신이 자연어의 의미를 정확하게 이해하고 사람의 질문에 정확하게 답변할 수 있는지를 측정하는 아주 중요한 분야이다.
5) 그래서 SQuAD 데이터셋은 언어 모델의 성능을 측정하는 가장 표준적인 벤치마크로 인정받고 있다.
- SQuAD와 KorQuAD 모두 현재는 2.0 버전까지 올라갔다.
- KorQuAD는 딥러닝 기반 QA(질의응답), 한국어 독해 능력을 측정하는 가장 중요한 태스크로 손꼽히고 있다.
- 오늘은 KorQuAD 1.0 데이터를 가지고 실습했다. 그외 실험해서 활용할 model, vocab, text corpus 데이터 등을 미리 다운로드 받았다.
- 그리고 코드로 패키지를 로딩하고, 데이터를 불러보고, 전처리(띄어쓰기 단위 정보관리, Tokenize by Vocab, Improve Span, 데이터셋 분리, 데이터 분석(Question, Context, Answer, Word Cloud), 데이터 로드) 및 시각화 등을 수행했다.
3. LSTM을 이용한 도전
- 우선 KorQuAD 태스크를 LSTM 모델을 활용하여 학습해 본다.
- 코드가 다소 복잡해 보이지만 Input 2개, Output이 2개인 모델이라는 점에 주목하자.
1) 2개의 Input은 이전 스텝에서 보았던 train_inputs[0], train_inputs[1]이 들어간다. 이들은 각각 Question + Context의 데이터와 Segment이다.
2) 그리고 Output은 Answer의 시작점과 끝점의 위치이다.
- 코드를 수행한 다음 20epochs만 훈련을 진행했다. 1epochs 당 5분가량 걸렸다. 또한 5epoch 이상 val_start_accuracy가 좋아지지 않으면 훈련을 종료하게 했다.
- 훈련이 마무리된 뒤 시각화도 해봤다.
- LSTM을 통해 진행했던 결과가 val_loss가 낮아지지 않고, val_accuracy들도 크게 좋아지지 않았다.
- KorQuAD 태스크는 데이터셋만 가지고 사전 준비 없이 학습했을 때 일정 이상 좋아지지 않는다는 것을 알 수 있었다. 이는 모델을 다양하게 바꿔봐도 결과가 비슷할 것이라고 한다.
4. BERT의 모델 구조
- 여기서는 우리들이 Transformer 모델 구조에 대해 어느 정도 선수지식을 가지고 있다는 가정하에 설명을 했다.
- Transformer 모델은 Self-Attention으로 이루어진 Encoder-Decoder 구조를 가지고 있어서 변역기 모델 형태를 구현하는데 적당했다.
- BERT는 여기서 Transformer Encoder 구조만을 활용한다. Layer 개수는 12개 이상으로 늘리고, 전체적으로 파라미터 크기가 훨씬 커지긴 했지만 기본적인 구조는 동일하다.
- 그런데 Decoder가 없다면 모델은 어떻게 학습을 시킬까?
- 위 그림의 왼쪽을 보면 BERT의 입력을 Transformer Encoder에 넣었을 때, 출력 모델이 Mask LM, NSP 라는 2가지 문제를 해결하도록 되어있다.
- 이들은 각각 다음과 같은 내용이다.
1) Mask LM
(1) 입력 데이터가 "나는 <mask> 먹었다" 일 때 BERT 모델이 <mask>가 "밥을" 임을 맞출 수 있도록 하는 언어 모델이다.
(2) 이전의 Next Token Prediction Language Model과 대비 시켜 이른바 "다음 빈칸에 알맞은 말은" 문제를 엄청나게 풀어보는 언어 모델을 구현한 것이다.
2) Next Sentence Prediction
(1) 이 경우는 입력데이터가 "나는 밥을 먹었다. <SEP> 그래서 지금 배가 부르다"가 주어졌을 때 <SEP>를 경계로 좌우 두 문장이 순서대로 이어지는 문장이 맞는지를 맞추는 문제이다.
(2) BERT 모델은 이 두 문장을 입력으로 받았을 때 첫 번째 바이트에 NSP 결과값을 리턴하게 된다.
- 여기서 주목할 것은 바로 위 그림에 나타나는 BERT 모델의 입력 부분이다.
- 텍스트 입력이 주어졌을 때, 실제로 모델에 입력되는 것은 Token, Segment, Position Embedding의 3가지가 더해진 형태이다.
- 실제로 그 이후 layer normalization과 dropout이 추가로 적용된다. 각각의 역할은 아래와 같다.
1) Token Embedding
(1) BERT는 텍스트의 tokenizer로 Word Piece model이라는 subword tokenizer를 사용한다.
(2) 문자(char) 단위로 임베딩하는 것이 기본이지만, 자주 등장하는 긴 길이의 subword도 하나의 단위로 만들어 준다.
(3) 자주 등장하지 않는 단어는 다시 subword 단위로 쪼개진다.
(4) 이것은 자주 등장하지 않는 단어가 OOV(Out-of-vocabulary) 처리되는 것을 방지해 주는 장점도 있다.
(5) 그래서 최종적으로 Word Piece 모델의 각 임베딩이 입력된다.
2) Segment Embedding
(1) 기존 Transformer에 없던 독특한 임베딩이다.
(2) 이것은 각 단어가 어느 문장에 포함되는지 그 역할을 규정하는 것이다.
(3) 이전 스텝에서 KorQuAD 데이터셋을 분석하면서 살펴봤지만, 특히 QA 문제처럼 이 단어가 Question 문장에 속하는지, Context 문장에 속하는지 구분이 필요한 경우에 이 임베딩은 유용하게 사용된다.
3) Position Embedding
(1) 이 임베딩은 기존의 Transformer에서 사용되던 position embedding과 동일하다.
- 그리고 코드를 통해 BERT 모델 구성을 더욱 디테일하게 살펴봤다.
5. BERT 모델을 이용한 도전
- 이제 BERT 모델을 활용하여, LSTM으로 풀어봤던 KorQuAD 태스크를 다시 학습해 봤다.
- 아마도 데이터셋 구성은 동일하기 때문에 별도의 추가조치가 필요하지 않을 것이다.
- 모델의 차이만 비교해 보기 위해 일부러 두 모델이 사용하는 Tokenizer를 동일하게 구성했다.
- 코드를 통해 BERT 레이어에 Fully Connected를 붙어 KorQuAD용으로 finetune하기 위한 모델 클래스를 만들었다.
- 그리고 메모리 한계때문에 배치사이즈는 32로 뒀다.
- 다음으로 학습을 본격적으로 진행했다.
1) BERT는 사실 pretrained 모델을 활용하는데 의의가 있다.
2) 하지만 우리가 실습을 위해 pretraining을 수행하기에는 도저히 시간상 한계가 있다.
3) 워크스테이션급 하드웨어를 동원해서 1달 가까이 학습을 시켜야 성능이 나오는 거대한 모델이기 때문이다.
4) 이번에는 BERT 모델만 구성한 후 전혀 pretraining 없이 학습을 진행해 봤다. (pretrained model을 활용하는 것은 프로젝트에서 할 예정이다.)
- 이번 학습도 20epochs만 했다. 1epochs당 5분 가량 소요된다. 그리고 Early stopping을 적용했다.
- 결과는 크게 차이가 나지 않았다.
- 우리 모델에는 수많은 코퍼스를 통해 정교하게 얻어진 Word Embedding이 반영되지 않았기 때문이다.
- 그럼 pretrained model을 활용하여 finetuning하면 어떻게 될까?
6. 프로젝트 : Pretrained model의 활용
- 이제 본격적으로 pretrained model을 활용해 본다.
- 사용해야 할 모델 구조나 데이터셋 구조, 배치 구조는 이전과 동일하다.
- 노드의 안내를 따라 이미 다운로드한 pretrained model을 활용하는 학습을 다시 진행했다.
- STEP 1. pretrained model 로딩하기
1) pretrained model을 로드하여 model을 생성하는 코드를 작성했다. model 구조는 이전과 동일하다.
- STEP 2. pretrained model finetune 하기
1) 학습을 진행하는 코드도 이전과 동일하다. 단지 학습해야 할 모델이 랜덤 초기화된 것이 아니라 pretrained model을 로드한 것일 뿐이다.
- STEP 3. Inference 수행하기
1) finetune 학습이 완료된 model을 활용하여 실제 퀴즈 풀이 결과를 확인해봤다.
- STEP 4. 학습 경과 시각화 비교분석
1) pretrained model 사용 여부에 따라 학습 수행 경과가 어떻게 달라지는지를 시각화를 포함하여 비교분석을 진행했다.
'공부 > AIFFEL' 카테고리의 다른 글
FUNDAMENTAL 33. Regularization (0) | 2021.03.22 |
---|---|
FUNDAMENTAL 32. Likelihood(MLE와 MAP) (0) | 2021.03.19 |
FUNDAMENTAL 31. Ainize, 나의 원클릭 포트폴리오 만들기 (0) | 2021.03.17 |
Exploration 18 : 문자를 읽을 수 있는 딥러닝 (1) | 2021.03.16 |
FUNDAMENTAL 30. 딥네트워크, 서로 뭐가 다른 거죠? (0) | 2021.03.15 |