카톡 대화 데이터를 BERT로 잘 학습시킬 수 있을까? - Dialog-BERT 만들기 3편

How can we train BERT on dialogue data?

백영민 | 2019년 08월 07일

지난 1편, 2편에서는 Dialog-BERT를 학습하기 위해 데이터를 준비하는 과정(한국어 데이터 전처리 및 tokenize)에 대해 소개했었습니다. 이번에는 본격적인 BERT 학습 과정에 대해 이야기 해보려고 합니다. 대화 데이터를 학습하기 위한 다양한 전략들을 살펴보고, 어떤 방법이 가장 효과가 좋았는지 실험을 통해 알아보겠습니다.

Contents

  1. 들어가며
    1. BERT란 무엇일까요?
    2. 왜 BERT를 선정했나요?
  2. 실험 준비 과정
    1. 실험 파이프라인의 구성
    2. 평가 방법
  3. 대화체의 학습이 가능할까?
    1. 문어체로 pre-training
    2. 대화체로 pre-training
  4. 세션 데이터를 학습시키기 위한 pre-training 방법
    1. Next Session Prediction
    2. Turn Separation Token & Turn ids
    3. 세션의 구성 방식
  5. 최종 모델 학습
  6. 이 글을 마치며

들어가며

BERT란 무엇일까요?

2018년 10월 하나의 모델이 GLUE(General Language Understanding Evaluation), SQuAD(Stanford Question Answering Dataset) 등 다양한 벤치 마크에서 이전 모델들의 성능을 큰 격차로 능가하는 사건이 발생했습니다! 바로 BERT, Bidirectional Encoder Representation from Transformer(Devlin et al., 2018)라는 모델의 등장인데요, 2019년 7월 기준 다음과 같이 여러 리더보드에서 BERT 기반 모델들이 여전히 상위권을 차지하고 있는 것을 볼 수 있습니다.

GLUE 벤치 마크 리더 보드
SQaUD 벤치 마크 리더 보드

BERT는 많은 양의 unlabeled corpus를 이용하여 Transformer(Vaswani et al., 2017) encoder를 학습하고, 이를 통해 얻어진 모델을 downstream task에서 fine-tuning 하는 모델로 다양한 NLP task에서 state-of-the-art 성능을 기록하였습니다. 이어질 내용에서 BERT를 왜 선정했고 한국어 대화에서 어떻게 학습시켰는지 살펴보려고 합니다. 아래의 문서를 참조하시면 앞으로의 내용을 더 잘 이해하실 수 있습니다.

왜 BERT를 선정했나요?

“Dialog-BERT 만들기 1편”에서 설명했듯이 대화 데이터는 각 유저 별로 발화의 형태가 다양하고 잦은 변형이 일어납니다. 또한 시간에 따라 신조어나 줄임말 등이 새로 등장하기도 하고, ㅇㅇ, ㅋㅋ과 같이 짧은 발화부터 편지 형식의 장문까지 등장합니다. 그래서 대화 자체의 흐름을 깊게 이해할 필요가 있습니다. 다음과 같은 부분들을 고려하여 BERT라는 모델을 학습하기로 결정하였습니다.

Contextual Representation

많은 NLP task들에서 Word2Vec(Mikolov et al., 2013), GloVe(Pennington et al., 2014), FastText(Bojanowski el al., 2017) 등의 토큰 단위의 representation을 Word Embedding의 초기값으로 이용합니다. 이 방법은 큰 성능 향상을 가져왔지만 여전히 다음과 같은 문제점을 가지고 있습니다.

이러한 문제를 해결하고자 ELMO(Peters et al., 2018)와 같은 Contextual Embedding을 이용하는 방법(Feature-based approach)과 ULMFit(Howard and Ruder, 2018), BERT(Devlin et al., 2018), XLNet(Yang et al., 2019) 등의 language model(LM)로 pre-training을 진행하여 언어 자체에 대해 학습하고, 특정 task에 대해 transfer learning 하는 방법(Fine-tuning approach) 등이 활발히 연구되고 있습니다.

기존 핑퐁의 모든 모델들은 FastText 기반의 word representation을 이용하고 있었기 때문에 위의 문제점들을 그대로 갖고 있었습니다. 그래서 ELMO를 시도했으나 짧은 발화의 비중이 높고, 주제 도메인이 넓은 일상 대화의 특성상 일반적인 language modeling 방식(한 방향의 context만 이용하는 방식)으로는 perplexity가 일정 수준 이하로 떨어지지 않았고 학습이 어려웠습니다. BERT는 양방향 context를 이용할 수 있을 뿐만 아니라 sentence 단위의 task들(Natural Language Inference, Text Similarity, Paraphrase 등)과 단어(토큰) 단위의 task들(SQuAD, NER 등)에서 그 가능성을 증명했습니다. 특히 Natural Language Inference 나 Text Similarity는 저희가 풀고자 하는 문제와 유사하기 때문에 BERT의 Contextual Representation으로 위 문제들을 개선하고자 했습니다.

Architecture

핑퐁 팀이 만들었던 모델들은 대부분 pre-trained word embedding과 Dual-LSTM 구조(Lowe et al., 2015)에 기반한 sentence representation을 이용했습니다. 다른 모듈들(CNN, attention)을 추가하거나 RNN layer을 더 쌓는 등의 모델 구조에 따른 실험을 진행했으나 눈에 띄는 성능 향상이 없었습니다. 또한 이 구조로는 발화 쌍(싱글 턴)의 관계만 모델링 할 수 있었기 때문에 여러 발화(멀티 턴)를 고려할 수 있으면서도, 특히 일상대화라는 언어에 대한 깊은 이해가 필요한 도메인을 다루고 있기 때문에 언어를 깊이 이해할 수 있는 모델 구조와 학습 방법을 필요했습니다.

Transformer 모델이 소개된 이후로 Transformer 기반 모델들(BERT, GPT, XLNET 등)에 대한 연구가 활발히 이어져 왔습니다. 이들은 다음과 같은 장점들로 다양한 task에서 기존의 RNN, CNN, Attention 등의 조합으로 만들어진 모델들을 능가하는 결과를 보여 주었습니다.

저희는 기존의 구조(Dual-LSTM)에 비해 조금 더 깊은 이해를 할 수 있는 구조, 더 나아가 여러 발화들(멀티 턴)을 고려할 수 있는 구조를 찾고 있었고, Transformer로 이를 해결하고자 했습니다.

Pre-training

저희가 기존에 사용했던 방법은 pre-training된 word representation을 이용하여 바로 특정 task를 학습했습니다. (<문장1>, <문장2>)의 쌍이 주어졌을 때, <문장1> 다음에 <문장2>가 오는 것이 적절한가를 예측하는 문제를 푸는 모델(1편의 기준 모델의 구성과 훈련 부분 참조)을 학습 했을 때 다음과 같은 문제가 발생했습니다.

BERT의 학습 과정은 크게 Pre-training 단계와 Fine-tuning 단계로 구분됩니다. Pre-training 단계에서는 언어 자체에 대한 이해도를 높이고, Fine-tuning에서는 이를 이용하여 특정 task를 풀게 됩니다. Pre-training에서 많은 대화 데이터들을 봄으로써, 언어 및 대화에 대한 이해도를 높이고 위와 같은 문제를 완화하고자 했습니다.

실험 준비 과정

저희의 목적은 “일상 대화 데이터”를 BERT를 이용하여 잘 학습하는 것입니다. “문어체”와 “대화체”는 여러 차이점을 가지고 있습니다. 문어체는 일상생활에서 사용하지 않고 문서 한정으로 사용하는, 즉 글을 쓰기 위해 사용하는 문체입니다. 대화체는 일상적인 대화에서 주로 사용하는 문체입니다. 저희가 갖고 있는 데이터는 주로 대화체의 형태를 띠고 있습니다. 이 챕터는 저희가 진행했던 실험들을 시간 순서로 진행해 보겠습니다.

KorQUaAD 벤치 마크 리더 보드

BERT는 KorQuAD와 같은 한국어 문어체 데이터에 대해서 좋은 성능을 보인다는 것을 증명했습니다. 하지만 대화체 특히 “채팅”에 대해서 BERT를 성공적으로 학습한 사례는 찾을 수 없습니다. 저희 핑퐁팀은 “BERT를 대화체에 성공적으로 적용 해보기”라는 목표를 가지고 여러 실험들을 진행했습니다.

실험 파이프라인의 구성

실험 파이프라인

Google이 제공하는 공식 BERT 코드는 미리 입력 코퍼스의 전처리를 진행하고, TF record로 변환하는 과정을 거칩니다. 이 단계에서 각 example의 최대 길이, masking 확률, 짧은 문장이 들어갈 확률 등을 미리 정해야 합니다. 그 후에 만들어진 TF record를 이용하여 Pre-training과 Fine-tuning을 진행합니다. 데이터 처리, 모델, 학습에 사용된 하이퍼 파라메터는 다음과 같습니다.

Hyperparameter & Training environment

평가 방법

BERT가 잘 학습되었는지 판단하기 위해서는 Pre-training의 성능 뿐만 아니라 fine-tuning, 즉 downstream task에서의 성능도 확인해야 합니다. Text Similarity, Reply Matching, Intent Classification, Multi-turn Reaction 총 4개의 downstream task를 계획했습니다. 최종 학습 이전에 빠른 실험 iteration을 위해서 두 발화사이의 관계를 예측하는 문제일 뿐만 아니라 비교적 빠르게 결과를 확인할 수 있는 text similarity task로 성능을 측정하였습니다..

Pre-training
Fine-tuning

대화체의 학습이 가능할까?

처음에 대화체에 BERT를 적용할 수 있을지에 대한 PoC(Proof of Concept)를 진행했습니다. 대화는 다양한 길이와 주제를 가진 문장들로 구성되어 있고, 말투, 자주 사용하는 단어, 표현과 같이 사람들 별로 조금씩 다른 특징들을 가지고 있습니다. 그래서 pre-training의 두 가지 objective(Masked-LM, Next Sentence Prediction)을 어떻게 적용할 수 있을지 여러 실험을 통해 결정했습니다.

데이터 셋의 구성

문어체 데이터(위키 + 나무위키)

대표적인 문어체 데이터로 위키와 나무 위키를 꼽을 수 있습니다. 손쉽게 dump 파일을 구할 수 있고, parser 또한 공개된 코드들이 많아서 처리하기에 용이합니다. 또한 논문에서 사용한 데이터셋인 만큼 BERT 학습 전략을 바로 적용해도 비교적 좋은 결과를 기대할 수 있습니다.

대화체 데이터

대화체 데이터로는 사내에 보유하고 있는 100억 건의 카카오톡 대화 데이터를 이용했습니다. 이중 일부를 통해서 가공한 single-turn 형태의 비교적 작은 데이터셋인 일명 8000만 pair 데이터를 통해서 실험을 진행하였습니다.

8000만 pair 데이터(약 2.1GB): 대화 데이터에서 추출한 (Utterance 1, Utterance 2)의 pair로 구성(Multi-turn은 고려할 수 없음) 된 데이터입니다. 새로운 데이터 정제 루틴이 확정되기 전에 만들어진 dataset으로 주로 단일 발화 혹은 발화 pair의 관계를 파악하는 문제들을 풀고 전처리가 완료되기 전 대화체 데이터에 대한 적용 가능성을 확인하기 위해 이용했습니다.

  <발화 A>                   <발화 B>
  안녕? 내이름은 핑퐁이야        안녕 만나서 반가워
  어제 뭐했어? ㅋㅋㅋㅋ         나 어제 영화봤어!
  점심 때 맛있는거 먹었어?       응 햄버거 먹었어 ㅎㅎ

문어체로 pre-training

먼저, 문어체 데이터로 학습(pre-training)한 모델이 대화체에서 좋은 성능(fine-tuning)을 보여줄 수 있을지에 대한 실험을 진행했습니다. 위키피디아와 나무 위키를 이용하여 pre-training, text similarity task로 fine-tuning을 진행했고 기존에 핑퐁 팀이 사용하고 있던 모델을 baseline으로 두고 비교했습니다.

Result
wiki + namu wiki result
Discussion

pre-training 단계에서는 loss가 잘 떨어졌고(수렴이 잘 되었고) accuracy도 좋은 결과를 얻을 수 있었습니다. 하지만 downstream task(fine-tuning 단계)에서는 기존의 모듈보다 낮은 성능을 보여 주었습니다. 저희는 pre-training(문어체)과 fine-tuning(대화체)에 이용되는 데이터의 “분포 차이” 때문에 이런 현상이 발생한다는 결론을 내렸습니다.

대화체로 pre-training

앞선 실험에서 문어체로 pre-training 한 모델은 대화체 fine-tuning task에서 좋지 못한 결과를 보여 주었습니다. 그래서 pre-training 단계에서 대화체를 이용한 실험을 진행했습니다. 먼저 8000만 pair 데이터로 pre-training을 진행하기 위해서 Next Sentence Prediction 문제를 새로 정의해야 했습니다.

실제 데이터에 존재하는 utterance pair는 positive sample 이고 Utterance B를 랜덤으로 sampling하여 negative sample 을 만들었습니다.

Utterance A: 안녕? 내 이름은 핑퐁이야! Utterance B: 안녕 만나서 반가워! - Positive sample
Utterance A: 안녕? 내 이름은 핑퐁이야! Utterance B: 어제 그 영화 너무 재밌었는데.. - Negative sample

다음으로, 다양한 길이의 문장들이 있지만 특히 짧은 문장 및 ㅇㅇ, ㅋㅋ와 같은 표현이 자주 등장하는 데이터에서 Masked-LM을 성공적으로 학습할 수 있을지에 대한 의문이 있었습니다. 그래서 다음과 같이 세 가지 실험을 진행했습니다.

Result
dialogue pre-training result
Discussion

대화체 pre-training 결과는 세 가지 실험 모두 비슷한 결과를 보여 주었습니다. Masked-LM은 약 30% 초반, NUP는 약 82% 후반을 기록했는데, 문어체 결과에 비해 다소 떨어지는 결과입니다. 하지만 대화체의 경우 문어체에 비해 [MASK] 토큰 자리에 다양한 토큰이 올 수 있고, NUP 또한 Utterance A에 대해 다양한 Utterance B가 올 수 있기 때문에 얻어진 결과라고 생각합니다. 처음의 걱정과 달리 Masked-LM의 수렴이 잘 이루어졌고, 무엇보다도 모든 모델이 downstream task에서 기존 baseline 대비 약 5%의 성능 향상을 보였습니다.

문어체 모델을 대화체로 추가 학습한 경우, 문어체에 대한 pre-training 성능이 크게 떨어졌고, 다른 방법들에 비해 성능 향상을 보여 주지 못했습니다. 또한 Masking 확률을 줄인 모델도 기존 확률의 모델에 비해 Masked-LM 정확도에서 비슷한 성능을 보였습니다. 대화체의 pre-training과 기존 설정만으로 충분히 좋은 representation을 얻을 수 있고, 이를 이용하면 다른 downstream task에서 좋은 결과를 기대할 수 있다는 결론을 내릴 수 있었습니다.

세션 데이터를 학습시키기 위한 pre-training 방법

앞의 실험들에서 대화체의 pre-training 만으로도 좋은 representation을 만들 수 있었습니다. 따라서 이번 챕터 부터는 대화 데이터를 조금 더 잘 이용할 수 있는 학습 전략에 대해 소개드리고자 합니다. 지난 1편에서 다뤘던 세션 단위 전처리를 통해 약 2억 5천만 세션의 데이터를 얻을 수 있었습니다. 이번에는 세션 단위의 데이터를 기존의 BERT에 어떻게 적용했는지 알아보겠습니다. (이 챕터부터 진행되는 실험은 모두 세션 데이터를 이용하였습니다.)

데이터 셋의 구성

2.5억 세션 데이터(약 107GB, 메타 정보 포함): 1편에서 소개 드린 방법으로, Multi-turn을 고려할 수 있는 모델을 만들기 위해 세션 단위의 데이터를 구성했습니다. 세션은 “공통의 주제로 진행되는 연속된 대화의 단위”이고 각 세션은 2개 이상의 발화들로 구성됩니다. 최종 모델 학습 이전까지는 전체 데이터의 약 1/10 (2500만 세션 데이터)를 이용하였습니다.

  <세션 A>
  A: 안녕? 내 이름은 핑퐁이야!
  B: 안녕! 만나서 반가워
  A: 응 ㅎㅎ 너는 몇살이야?

  <세션 B>
  A: <NAME> 아 혹시 지금 전화할 수 있어~~?
  B: 응응 지금 할 수 있어!
  A: 알겠어! 지금 걸게! ㅎㅎ

Next Session Prediction

세션 단위의 데이터를 이용하면 Masked-LM은 동일하게 적용 가능하지만 Next Sentence Prediction 문제는 어떻게 적용해야 할까요? 세션 단위의 데이터를 pre-training에서 이용하기 위해 Next Session Prediction 문제를 정의합니다.

Next Session Prediction은 두 대화들(세션의 일부)을 주고 해당 세션들이 같은 세션 인지 예측하는 Binary Classification 문제입니다. 각 대화들은 한 개 이상의 발화로 구성됩니다. 기존에는 Next Sentence Prediction 문제를 풀기 위해 [SEP] 토큰과 Segment id(Embedding)을 이용하여 두 Segment를 분리했습니다. 이와 비슷하게 Next Session Prediction 문제를 풀기 위해 [SEP] 토큰과 Session id를 이용하여 두 세션을 분리합니다. 결과적으로 데이터의 형식은 [CLS] 세션 A [SEP] 세션 B [SEP]가 됩니다. 위의 세션 데이터를 이용하여 Positive, Negative sample을 만들면 다음과 같습니다.

[CLS] 안녕? 내 이름은 핑퐁이야! 안녕! 만나서 반가워 [SEP] 응 ㅎㅎ 너는 몇살이야? [SEP] - Positive Sample
[CLS] 안녕? 내 이름은 핑퐁이야! 안녕! 만나서 반가워 [SEP] 응응 지금 할 수 있어! [SEP] - Negative Sample

Turn Separation Token & Turn ids

위의 방법으로 데이터가 구성되면, [SEP] 토큰과 Session id로 을 기준으로 두 개의 세션을 구분할 수 있습니다. 각 세션은 특정 유저들 사이의 대화로 구성되어 여러 발화가 존재할 수 있습니다. 대화에서는 각 발화가 어떤 화자로부터 왔는지에 대한 정보가 매우 중요합니다. 하지만 위의 예시처럼 구성된다면 "안녕? 내 이름은 핑퐁이야!""안녕! 만나서 반가워"가 다른 화자로부터 왔다는 것을 구분할 수 없습니다. 이를 구분하기 위해 Turn Separation Token([SEPT])과 Turn Id 을 추가했습니다.

위의 예시에 Turn Separation Token 및 Turn id를 추가하면 다음과 같습니다.

[CLS] 안녕? 내 이름은 핑퐁이야! [SEPT] 안녕! 만나서 반가워 [SEPT] [SEP] 응 ㅎㅎ 너는 몇살이야? [SEPT][SEP] - Positive Sample
[CLS] 안녕? 내 이름은 핑퐁이야! [SEPT] 안녕! 만나서 반가워 [SEPT] [SEP] 응응 지금 할 수 있어! [SEPT][SEP] - Negative Sample
Turn separation token & Turn ids

세션 데이터를 이용하여 학습했을 때, Turn Separation Token 및 Turn id의 효과가 있는지 확인하기 위해 4가지 실험을 진행했습니다.

Result
Turn separation token & Turn ids result
Discussion

먼저 Masked-LM을 분석해보면, 대부분 비슷한 결과를 얻을 수 있었지만, 화자에 대한 근거를 주지 않은 #1이 가장 낮은 결과를 보였습니다. Turn Separation token을 추가한 #2#4는 Turn id만 추가한 #3에 비해 낮은 결과를 보여 주었는데, 제한된 길이에서 [SEPT] 토큰을 추가하게 되면 해당 토큰 수만큼 길이에서 손해를 보게 되기 때문이라고 생각할 수 있습니다.

이전 실험들에 비해 Masked-LM 정확도의 절대적 수치가 크게 상승한 이유는 Tokenizer를 교체했기 때문입니다. “나는 밥 먹었어”라는 문장을 SentencePiece를 이용하면 “나는”과 같이 자주 등장하는 명사+조사 조합이 하나의 토큰으로 tokenize 되지만 Mecab에서는 “나” + “는”으로 tokenize 됩니다. “나는”이 [Mask] 토큰으로 치환되는 것에 비해 “나” 또는 “는”이 [Mask] 토큰으로 치환되는 것이 조금 더 쉽다고 볼 수 있습니다. 결과적으로 Mecab tokenizer를 이용했을 때, 정확도의 절대적 수치가 향상됩니다.

Next Session Prediction는 각 방법에 따라 큰 차이가 나는 결과를 얻을 수 있었습니다. #1의 경우 세션에서 각 화자를 구분할 수 있는 방법이 없으므로 예상과 동일하게 가장 낮은 정확도를 보였습니다. #2(Turn Separation Token 추가)#3(Turn id 추가)에서는 각각 화자를 구분할 수 있는 다른 방법을 이용했는데, #1에 비해 월등히 높은 결과를 보였습니다. 또한 Turn id로 Embedding에 직접 더해주는 방법이 Turn Separation Token을 이용하는 방법보다 효과적이라는 것을 알 수 있었습니다. 마지막으로 #4에서는 두 가지 방법을 모두 이용하면 각각을 이용하는 것보다 좋은 결과를 얻을 수 있었습니다.

최종적으로 이후 단계부터는 화자를 구분하기 위한 두 가지 방법을 모두 이용하는 #4의 방법을 채택했습니다.

세션의 구성 방식

위의 실험들에서 만들었던 데이터의 형식은 [CLS] 세션 A [SEP] 세션 B [SEP] 이고, 각 세션은 한 문장 이상으로 구성되는 것 이외에 별도의 조건이 없었습니다. 세션의 구성에 대해 추가적인 조건들을 적용하여 실험을 진행하고 가장 효과적인 방식을 채택했습니다.

Result
Masked-LM result
Next Session Prediction result
Discussion

위 3가지 조건으로 train/test dataset을 구성하여 모델을 학습하고, 3개의 test셋에 대해 각각의 결과 및 평균을 확인했습니다. #0은 이전 실험에서 Seperation Token, Seperation id를 모두 사용한 #4 모델의 결과입니다.

Masked-LM부터 살펴보면, #1을 제외한 나머지 방법들은 비슷한 결과를 보였습니다. #1은 pair로 구성된 data로 학습을 진행하여 여러 발화로 구성된 session을 보지 못했기 때문에 #2#3 test에서 낮은 정확도를 보였습니다.

NSP에서는 다양한 양상이 등장했는데, 하나하나 살펴보겠습니다.

  1. 당연히 모든 경우에서 training set과 분포가 같은 test set을 이용한 경우 가장 높은 정확도를 보였습니다.
  2. #1의 경우 pair 데이터에 대해서만 학습했음에도 불구하고 #1의 test뿐만 아니라 #2의 test 에서도 비교적 높은 결과를 보여 주었습니다. 이는 #1#2 모두 비슷한 길이의 문장이 [SEP] 토큰을 기준으로 앞뒤로 들어가 비슷한 패턴을 가지기 때문으로 추측할 수 있습니다. Text Similarity(fine-tuning task)에서도 pair 단위의 문제이다 보니 좋은 결과를 기록했습니다.
  3. #2의 경우 특히 training set과 분포가 같은 #2 test에서 높은 정확도를 기록했습니다. 처음에 생각했던 것처럼 문제가 가장 쉬워서 이러한 결과가 나타났다고 해석할 수 있습니다. 하지만 다른 두 test(#1, #2)에 대해서는 매우 낮은 정확도를 기록했는데, 키워드 단위로 구분할 수 있는 쉬운 문제로 학습되어 대략적인 느낌으로 판단하게 되고, 비교적 복잡한 문제들은 잘 풀지 못한다고 해석할 수 있습니다.
  4. #3의 경우 평균적으로 모든 test뿐만 아니라 Text Similarity(fine-tuning task)에서 pair 단위의 문제임에도 불구하고 가장 높은 정확도를 보였습니다. 이는 세 가지 방법 중 가장 어려운 문제를 학습하여 다른 방법들에 비해 키워드나 어투 등의 단순한 특징 이외에 문맥 등의 깊은 이해가 가능했기 때문이라고 생각합니다. #2 test의 정확도가 낮은 이유는 세션 B에 여러 발화가 들어가는 경우가 학습에 등장하지 않는 패턴이기 때문에 발생하는 현상으로 볼 수 있습니다.

최종 모델 학습

여기까지 최종 모델 학습을 위한 모든 실험을 진행했습니다! 위의 실험들에서 검증한 내용을 바탕으로 모든 데이터를 이용한 최종 모델 학습을 진행했습니다. 최종 모델에 이용한 조건들을 정리하면 다음과 같습니다.

  1. 데이터: 2억 5천만 세션 → TF record로 변환 시 약 10억 examples
  2. 모델: BERT-base
  3. 목표 epoch: 20 (10,000,000 step)
  4. Fine-tuning task: Text Similarity, Reply Matching, Intent Classification
  5. Turn Separation Token & Turn ids: 사용
  6. 세션 구성: [CLS] (여러 발화) [SEP] (하나의 발화) [SEP]

빠르게 확인이 가능한 fine-tuning task와 pre-training task는 약 10만 step단위로 성능을 확인했습니다. 10,000,000 step을 완료 하기까지 TPU v3-8을 이용하였을 때, 약 29일정도 소요되었습니다.

학습 결과 (pre-training)

Masked-LM result(좌), NSP result(우)

모든 학습이 끝났을 때, Masked-LM에서는 약 56%, Next Session Prediction에서는 약 90%의 정확도를 기록했습니다. 모든 데이터를 사용하고 더 많은 step을 학습하여, 위 실험들의 성능을 훨씬 뛰어넘는 결과를 얻을 수 있었습니다.

학습 결과 (fine-tuning)

Fine-tuning result

Text Similarity

두 발화가 주어졌을 때, 해당 발화들이 같은 의미인지 구분하는 binary classification 문제입니다. 같은 의미이면 1, 다른 의미이면 0으로 labeling 되어있습니다. 모델은 두 발화의 유사도를 수치화합니다.

수고 많았네 얼른 씻고 쉬어     고생 많았어요 이제 씻고 얼른 쉬어 - Positive sample
넹 씻고 연락할게용           들어가서 씻고 카톡해줘용 - Negative sample

Reply Matching

두 발화가 주어졌을 때, 해당 발화들이 자연스럽게 이어지는지 구분하는 binary classification 문제입니다. 모델은 앞 발화와 뒤 발화의 이어짐도(자연스러움)을 수치화합니다.

오늘 택배 온대         헉 말만 들어도 설렌다 ㅠㅠ - Positive Sample
지금 시간 돼?          항상 응원 할게! - Negative Sample

Intent Classification

발화의 의도를 예측하는 Multi-class classification 문제입니다. 의도는 45개로 사전에 정의되어 있습니다.

런던 놀러가자 - 장소 예약
강남가는 버스가 있어? - 장소 교통수단 물음

이 글을 마치며

작년 10월부터 시작해서 NLP에서 가장 핫이슈였던 BERT를 대화 데이터를 이용하여 학습해 보았습니다. 한국어 대화체를 BERT에 적용한 성공적인 사례가 없었기에 많은 시행착오가 있었지만 초기 목표를 달성하는데 성공했습니다. 여러 실험 iteration을 돌며 약 3달간 진행하였고, 최종적으로 기존 모델의 성능을 모두 뛰어넘는 만족할 만한 결과를 얻었습니다. pre-training 단계에서 1000만 step이 끝나기 직전까지도 조금씩이지만 각 pre-training task의 성능이 향상되는 모습을 볼 수 있었습니다. 최근 RoBERTa(Liu et al., 2019) 와 같은 많은 연구들에서 BERT는 아직 underfit 되어 있고, 많은 데이터와 큰 베치 사이즈, 많은 학습을 통해 더 좋은 성능을 이끌어 낼 수 있다는 결과를 보여주었습니다. 저희 핑퐁팀도 앞으로 다양한 실험들을 통해 더 좋은 성능을 이끌어 내고자 합니다. Dialog-BERT 학습하기 마지막 시리즈 4편 에서는 3편에서 만들어진 BERT를 이용하여 “Multi-turn을 고려하는 문제”를 해결하는 과정을 다루도록 하겠습니다.

Reference