참고 : Do it! BERT와 GPT로 배우는 자연어처리

3. 숫자 세계로 떠난 자연어

Language Model ( 언어 모델 )

  • 단어 시퀀스에 “확률을 부여”하는 모델
  • ex) $n$ 개의 단어로 구성 시 : $P(w_1,w_2,…,w_n)$
    • 조건부 확률로 분해해서 쓰면 :
      • $P(w_1,w_2,…,w_n) = \prod_{i=1}^{n} P(w_i \mid w_1,…,w_{i-1})$.
  • 넓은 의미의 언어 모델 : $P(w \mid \text{context})$


[1] 순방향 언어모델 (Forward LM)

  • “이전 단어들”(=컨텍스트)이 주어졌을 때, “다음 단어 맞히기”
  • ex) GPT, ELMo


[2] 역방향 언어모델 (Backward LM)

  • ex) ELMo

    ( ELMo = Forward LM + Backward LM )


[3] 마스크 언어모델 (Masked LM)

  • 빈칸 뚫고 맞추기
  • 순방향/역방향 모델과는 달리, “문장 전체의 맥락” 파악 가능
  • ex) BERT


[4] 스킵그램 모델 (Skip-gram Model)

  • 특정 단어 “앞/뒤의 특정 범위” 내를 참고
  • ex) word2vec (2013)


트랜스포머

  • seq2seq 기반의 모델
    • 소스&타겟의 길이 달라도 OK
  • teacher forcing
    • 학습 중의 decoder 입력 : “실제 정답”
    • 추론 중의 decoder 입력 : “이전의 예측값”


트랜스포머 블록

  • 구성요소
    • 1) Multi-head Attention
    • 2) Feed Forward NN ( FFNN )
    • 3) Residual Connection
    • 4) Layer Normalization
  • 인코더 & 디코더의 블록은 본질적으로 크게 다르지 X
    • 인코더 : 마스크 X
    • 디코더 : 마스크 O & 인코더/디코더 멀티헤드어텐션


트랜스포머의 output

  • “정답에 해당하는 단어의 확률값”
  • target 언어의 “어휘 수” 만큼의 차원을 가진다


어텐션 vs 셀프 어텐션

  • 차이점 1
    • 어텐션 : source 시퀀스 전체 & target 단어 1개
    • 셀프 어텐션 : 입력 sequence 전체 끼리
  • 차이점 2
    • 어텐션 : RNN 구조 상
    • 셀프 어텐션 : RNN 구조 X
  • 차이점 3
    • 어텐션 : target 단어 1개 생성할때, 어텐션 1회 수행
    • 셀프 어텐션 : 인코더 & 디코더 블록 개수만큼 수행


셀프 어텐션

  • 각 단어는 Q,K,V로 변환됨
  • ex) 6개의 단어(토큰)로 구성된 문장
    • 6개의 Q 벡터
    • 6개의 K 벡터
    • 6개의 V 벡터
  • 셀프 어텐션을 “블록(레이어) 수”만큼 반복한다


Notation

  • 단어 임베딩 차원 : $d$

  • 단어 개수 : $n$

  • 입력 시퀀스 : $\mathbf{X}$ …..$(n, d)$ 차원

  • Q,K,V를 만들어주는 weight 행렬
    • $\mathbf{W}_Q$ …..$(d, d_Q=d_K)$ 차원
    • $\mathbf{W}_K $…..$(d, d_Q=d_K)$ 차원
    • $\mathbf{W}_V$ …..$(d, d_v)$ 차원
  • 어텐션 : $\text{Attention}(\mathbf{Q},\mathbf{K},\mathbf{V})= \text{softmax}(\frac{\mathbf{Q}\mathbf{K}^T}{\sqrt{d_k}}) \mathbf{V}$


멀티 헤드 어텐션

  • 셀프 어텐션을 “동시에” 여러버 수행
  • 각 헤드의 출력값 : $\mathbf{Z}_0,…\mathbf{Z}_H$
    • $\mathbf{Z}_i$ 의 차원 : $(n, d_v)$
    • $[\mathbf{Z}_0,\mathbf{Z}_1,…,\mathbf{Z}_H]$ 의 차원 : $(n, d_vH)$
  • $\mathbf{W}_O$ 의 차원 : $(d_vH, \text{dim})$
    • $\text{dim}$ : 목표 차원 수


Encoder의 어텐션

  • source 언어들 끼리의 self-attention
  • ex) 한글-영어 번역 => 한글 & 한글의 self-attention


Decoder의 어텐션

  • 2개의 어텐션
    • 1) 마스크 멀티헤드 self-attention
    • 2) Encoder-Decoder 멀티헤드 attention
  • 1) 마스크 멀티헤드 어텐션
    • 영어 & 영어의 self-attention
    • 치팅 방지를 위해, 뒷 부분 “마스킹”
  • 2) Encoder-Decoder 멀티헤드 어텐션
    • 한글 & 영어의 attention


Layer Normalization ( 레이어 정규화 )

  • 데이터 “별”로 정규화
  • ex) data17의 feature 1=1,feature2=2, feature3=3
    • 평균 : (1+2+3) / 3 = 2
    • 표준편차 : 0.8164
import torch
x = torch.tensor([[1.0, 2.0, 3.0],
                 [1.0, 1.0, 1.0]])

LN = torch.nn.LayerNorm(x.shape[-1]) # 차원 수 =3

output = LN(x)

print(LN.weight)
print(LN.bias)


Drop out ( 드롭 아웃 )

import torch
DO = torch.nn.Dropout(p = 0.2)

x = torch.randn(1, 10)

output = DO(x)
  • 20% 확률로 죽은 애들 : 0
  • 80% 확률로 살아남은 애들 : 1/(1-0.2) 배


옵티마이저

from torch.optim import Adam
opt = Adam(model.parameters(), lr = model.learning_rate)


BERT vs GPT

  • GPT : LM / 순차적 / 문장 생성에 탁월 / Transformer의 DECODER 만 사용
  • BERT : MLM / 양방향 / 문장 의미 추출에 탁월 / Transformer의 ENCODER 만 사용


단어 / 문장의 벡터화

  • pre-train 완료 이후, “단어/문장” 수준의 임베딩 추출하기
  • 활용도 :
    • 문장 벡터 : Document Classification (문서 분류)
    • 단어 벡터 : Named Entity Recognition (개체명 인식)


코드

from transformers import BertTokenizer, BertConfig, BertModel
BERT_dir = 'beomi/kcbert-base'

# (1) config
config = BertConfig.from_pretrained(BERT_dir)

# (2) model
model = BertModel.from_pretrained(BERT_dir,
                                 config = config)
# (3) tokenizer
tokenizer = BertTokenizer.from_pretrained(BERT_dir,
                                          do_lower_case = False)

# (4) Input 생성
sentences = ["xxxx", "yyyy"]

inputs_dict = tokenizer(
    sentences,
    max_length = 10,
    padding = "max_length",
    truncation = True
)

inputs_tensor = {k : torch.tensor(v) for k,v in inputs_dict.items()}
# (5) output
outputs = model(**inputs_tensor)
# (6) "단어 수준 벡터" 
outputs.last_hidden_state # (2,10,768)

# (7) "문장 수준 벡터"
outputs.pooler_output # (2,768)
  • outputs.last_hidden_state 의 차원 : (2,10,768)

    • 2 : 문장 개수
    • 10 : 최대 길이 10
    • 768 : 각 토큰의 임베딩 차원
  • outputs.pooler_output의 차원 : (2,768)

    • [CLS] 토큰이 FFNN 한번 걸쳐 나옴
    • 2 : 문장 개수
    • 768 : 문장의 임베딩 차원

Tags:

Categories:

Updated: