Deeper Learning

GPT 본문

AI/Deep Learning

GPT

Dlaiml 2021. 2. 22. 23:28

Self-Supervised Pre-Training Models

문서 분류, 감성 분석, 질의응답, 문장 유사성 파악, 원문함의 등 과제는 각각 주어진 과제에 알맞은 처리가 완료된 데이터가 필요하다.

미분류 corpus의 경우 매우 많으나 특정 목적을 위해 Labeling, 전처리가 완료된 데이터는 현저히 부족하다.

미분류 corpus를 사용하여 언어 모델을 학습시키고 특정 목적에 맞게 fine-tuning 하는 것으로 이를 어느 정도 해결할 수 있다.

비지도 학습인 미분류 corpus로 학습한 언어모델과 이를 supervised fine-tuning 하는 Self-supervised pre-training을 통해 언어이해(NLU)를 달성하는 것이 GPT의 목적이다.

 

GPT-1

GPT-1은 OpenAI에서 발표한 모델로 Transformer의 Decoder를 사용하는 모델이다.

GPT-1은 먼저 label이 되어있지 않은 corpus를 사용하여 비지도학습을 통해 언어 모델을 학습한다.

LM loglikelihood

Special Token을 제안하여 효과적으로 학습이 이루어진다.

<S>: Start

<E>: Extract

$: Delimeter

 

GPT-1 Architecture

다음 token의 예측을 통한 Language Modeling 학습을 마친 후 여러가지 목적에 따라 다음과 같이 input의 형태를 Special token을 사용하여 조정함으로써 목적에 맞는 과제를 수행할 수 있다.

 

분류의 경우 Start token과 Extract Token을 Text의 앞뒤에 추가하고 이를 GPT-1을 통과시켜 Extract token의 결괏값을 Dense Layer를 통해 원하는 차원으로 선형 이동시켜 그 값을 label과 비교하여 Loss를 산출할 수 있게 된다.

 

Fine-Tuning 과정에서 기존 Base-Model인 GPT-1의 Learning rate는 마지막에 새로 추가된 Layer의 LR보다 작게 설정되어 기존에 매우 거대한 Corpus로 학습되어 언어의 특성을 추출하는 Weight의 변화를 줄인다.

 

GPT-1 

총 12개의 Transformer의 Decoder를 쌓아올려 만들어진 모델로 768차원, 12개의 head를 사용한 Multi-Head Self-Attention이 내부에서 이루어진다.

 

Activation 함수로는 GELU가 사용되었는데 이는 다음과 같이 근사가 가능하다.

 

GELU 근사

 

Experiment Result

 

위와 같이 여러 과제에 대해 모두 기존의 모델보다 좋은 성능을 보였다.

 

GPT-2

GPT-2는 GPT-1보다 더 좋은 품질의 40GB의 Text를 통해 학습된 언어모델이다.

데이터는 많은 추천을 받은 reddit의 link와 Wikipedia 등을 포함하여 구성되었다.

 

GPT-2 LM Generation

위는 GPT-2에 사람이 쓴 문장을 주고 뒤의 문장을 생성해가며 작성하도록 한 결과다. 

주어진 문장에서 Scientist, Unicorn과 같은 단어뿐만 아니라 전체적인 문맥을 파악하여 매끄럽게 문장을 이어나가는 결과를 보인다.

 

Byte pair encoding(BPE)를 사용하여 글자 단위에서 빈도에 따라 글자가 합성되고 의미를 나타내는 가장 작은 단위의 sub-word를 bottom up 방식으로 지정하고 이를 사용하여 vocab이 생성된다.

 

[low, lower, newest, widest]에 BPE를 적용시키자.

단어 단위로 count: [l o w : 5, l o w e r : 2, n e w e s t : 6, w i d e s t : 3

먼저 글자 단위로 분리하면 초기 vocab은 [l, o, w, e, r, n, w, s, t, i, d]이 된다.

 

지정된 iteration 횟수만큼 가장 빈도가 높은 유니 그램의 쌍이 새롭게 vocab에 추가된다.따라서 es(9 = 6 + 3)이 새롭게 vocab에 추가된다.

 

vocab: [l, o, w, e, r, n, w, s, t, i, d, es]

 

dictionary도 다음과 같이 update 된다.dict: [l o w : 5, l o w e r : 2, n e w e s t : 6, w i d e s t : 3] -> [l o w : 5, l o w e r : 2, n e w (es) t : 6, w i d (es) t : 3]

 

이 과정을 반복한다. 다음으로 est (9 = 6 + 3)이 새롭게 vocab에 추가되며 dictionary도 업데이트된다.

 

총 10회 반복하였을 때 dictionary, vocab은 다음과 같다.

 

dict: [low : 5, low e r : 2, newest : 6, widest : 3]vocab: [l, o, w, e, r, n, w, s, t, i, d, es, est, lo, low, ne, new, newest, wi, wid, widest]

 

이를 구현한 파이썬 코드는 다음과 같다.

from typing import List, Dict, Set
from itertools import chain
import re
from collections import defaultdict, Counter


def build_bpe(
        corpus: List[str],
        max_vocab_size: int
) -> List[int]:
    """ BPE Vocabulary Builder
    Implement vocabulary builder for byte pair encoding.
 

    Arguments:
    corpus -- List of words to build vocab
    max_vocab_size -- The maximum size of vocab

    Return:
    idx2word -- Subword list
    """
    # Special tokens
    PAD = BytePairEncoding.PAD_token  # Index of <PAD> must be 0
    UNK = BytePairEncoding.UNK_token  # Index of <UNK> must be 1
    CLS = BytePairEncoding.CLS_token  # Index of <CLS> must be 2
    SEP = BytePairEncoding.SEP_token  # Index of <SEP> must be 3
    MSK = BytePairEncoding.MSK_token  # Index of <MSK> must be 4
    SPECIAL = [PAD, UNK, CLS, SEP, MSK]

    WORD_END = BytePairEncoding.WORD_END  # Use this token as the end of a word
    # YOUR CODE HERE
    vocab = {' '.join(k)+' '+WORD_END:v for k, v in dict(Counter(corpus)).items()}
    def get_stats(vocab):
      pairs = defaultdict(int)
      for word, freq in vocab.items():
        symbols = word.split()
        for i in range(len(symbols)-1):
          pairs[symbols[i],symbols[i+1]] += freq
      return pairs

    def merge_vocab(pair, v_in):
      v_out = {}
      bigram = re.escape(' '.join(pair))
      p = re.compile(r'(?<!\S)' + bigram + r'(?!\S)')
      for word in v_in:
        w_out = p.sub(''.join(pair), word)
        v_out[w_out] = v_in[word]
      return v_out
      
    idx2word = list(set([i for k in vocab.keys() for i in k.split() if not i == WORD_END ]))
    num_merges = max_vocab_size - len(idx2word) - 6
    for i in range(num_merges):
        pairs = get_stats(vocab)
        try:
            best = max(pairs, key=pairs.get)
        except:
            break
        idx2word.append(''.join(best))
        vocab = merge_vocab(best, vocab)
    idx2word = SPECIAL+sorted(list(set(idx2word)),key=len, reverse=True)+[WORD_END]

    
    
    return idx2word

 

Transformer Decoder에서 추가적인 구조적 차이는 Layer Normalization의 위치를 조정하였으며, n번째 residual layer의 weight의 초기화 과정에서 1/root(n)을 곱하였고, 마지막 self-attention block 다음에 layer normalization이 추가로 적용되었다.

 

 

GPT-3

175 billion parameters로 구성된 모델로, few-shot, zero-shot learning에서 기존의 모델보다 좋은 성능을 보였다.3.2M batch size, 96 Attention layers로 구성되어 있다.

 

N-shot learning

 

Zero-shot learning의 경우 Text인 task description 만을 보고 어떤 과제를 수행하여야 하는지 모델이 판단하고 prompt에 알맞은 답을 낸다.N-shot learning의 경우 N개의 예시를 보고 예측을 한다.

 

N-shot learning performance

N-shot learning의 성능은 언어 모델의 parameters 개수가 많아질수록 좋아지며 few-shot learning이 가장 빠른 성능 향상을 보인다.

 

GPT-3는 여러 task에서 놀라운 performance를 보였으며, 데이터의 양과 모델의 크기의 증가로 훨씬 좋은 성능을 기록할 수 있음을 증명하였다.

 

Reference

[1] Alec Radford et. al. Improving Language Understanding by Generative Pre-Training. url

[2] Naver Connect Boostcamp AI Tech - Self-supervised pre-trained model (주재걸 교수님)

[3] 딥러닝을 이용한 자연어 처리 입문 - BPE

 

 

 

'AI > Deep Learning' 카테고리의 다른 글

Knowledge Distillation  (0) 2021.03.11
Graph Neural Network (GNN)  (0) 2021.02.26
Adam Optimizer  (0) 2021.02.14
Autoencoder  (0) 2021.02.11
Gradient Descent  (0) 2021.02.10
Comments