NLP 5. 문장 임베딩 만들기
1. 문장 임베딩 만들기
자연어 처리를 위한 모델 구조
문장임베딩
단어 수준의 임베딩 기법은 자연어의 특성인
모호성 (동음이의어)를 구분하기 어렵다는 한계가 있었다
2017년 이후에는 ELMO나 Transformer와 같은 언어모델에서
문장 수준의 언어 모델링을 고려해서 한계점을 돌파
언어 모델
자연어 문장 혹은 단어에 확률을 할당하여 컴퓨터가 처리할 수 있도록 하는 모델
주어진 입력에 대해 가장 자연스로운 단어 시퀀스를 찾을 수 있음
언어 모델링
주어진 단어들로부터 아직 모르는 단어들을 예측하는 작업을 말함
총 n개의 단어로 구성된 문장에서, (n-1)개의 단어가 주어졌을 때,
n번째 위치에서 출현할 단어의 예측을 확률적으로 표현하면 다음과 같음
$P(w_n | w_1, w_2, w_3, \dots , w_{n-1})$
문장은 어순을 고려하여 여러 단어로 이루어진 단어 시퀀스라고도 부르며,
n개의 단어로 구성된 단어 시퀀스($W$)를 확률적으로 표현하면 다음과 같음
$\begin{aligned} P(W) &= P(w_1, w_2, w_3, \dots, w_n) \newline &= P(w_1) \times P(w_2|w_1) \times P(w_3|w_1, w_2) \times \dots \times P(w_n|w_1, w_2, \dots , w_{n-1})\end{aligned}$
특정 문장을 확률로 표현할 수 있다는 특징 $\Rightarrow$ 대부분의 자연어 처리 작업들에 활용 가능
ex. 기계번역, 챗봇 …
단어 시퀀스에 확률을 할당하는 주요 방법은
- 문장 내 masking된 단어를 예측하거나
(Masked Language Modeling) - 이전 단어들이 주어졌을 때, 다음 단어를 예측하도록 하는 것
(Next Token Prediction)
Seq2Seq
등장 배경
DNN이 음성 인식, 사물 인식에서 꾸준한 성과
but 모델의 입/출력의 크기가 고정된다는 한계점이 존재
자연어처리는 가변적인 입/출력을 가지기 때문에 어려웠음
RNN은 시퀀스 단위의 처리를 가질 수 있었지만,
반복되는 셀의 개수만큼 처리해야해서 입출력이 달라지면 사용 불가
Seq2Seq
LSTM 또는 GRU 기반의 구조를 가지고 고정된 길이의 단어 시퀀스를 입력으로 받아, 입력 시퀀스에 알맞은 길이의 시퀀스를 출력해주는 언어모델
모델 구조
sequence to sequence는 한 문장을 다른 문장으로 변환하는 모델이란 의미
Seq2Seq는 가변 길이의 입/출력을 처리하기 위해서 Encoder/Decoder 구조를 채택
인코더가 input을 context vector로 만들고 (인코딩)
인코더가 인코딩한 context vector를 입력으로 받는 디코더가 출력 문장을 생성(디코딩)
이런 방식으로 서로 다른 입출력 시퀀스에 대응가능
LSTM이나 GRU를 사용하는 이유는, RNN의 문제인 Long-term dependency를 해결하는 모델이기 때문
Seq2Seq 모델을 학습할 때에는 Teacher forcing이라는 기법을 사용한다.
Teacher forcing : 이전 셀에서 예측한 단어를 다음 셀의 입력으로 하지 않고
실제 정답 단어를 다음 셀의 입력으로 넣음
한계점
- 고정된 크기의 벡터에 모든 정보를 압축하다 보니 정보 손실 발생
- RNN 구조의 고질적인 문제인 Vanishing Gradient Problem
Attention Mechanism
seq2seq 모델은 입력 문장이 길면 번역 품질이 떨어진다.
정확도가 떨어지는 것을 보정해주기 위한 기법
아이디어
decoder에서 출력 단어를 예측하는 매 시점(time step)마다, 인코더에서의 전체 입력 문장을 다시 한번 참고한다.
단 전체 입력 문장을 동일한 비율로 참고하는 것이 아니라, 예측해야할 단어와 연관이 있는 입력 단어 부분을 더 집중(attention)해서 보게 된다.
$Attention(Q,K,V) = (Attention Value)$ 으로 표현한다.
유사도를 계산해서 각각의 값에 반영해서, 그 값을 다 더해서 반환
Q = Query : t 시점에서 디코더 셀에서의 hidden state K = Keys : 모든 시점의 인코더 셀 각각에 대한 hidden state들 V = Values : 모든 시점의 인코더 셀 각각에 대한 hidden state들
어텐션의 종류
- dot
- scaled dot
- general
- concat
- location - base
ELMo
기존 워드 임베딩의 한계
같은 표제어에 따라서 의미가 아예 달라지는 경우를 서로 다르게 임베딩을 할 수 없었음
하지만 ELMo에서는 가능
ELMo
Embeddings from Language Model
특징
- 사전 학습된 단어 표현을 사용함
대량의 자연어 코퍼스를 미리 학습해서 일반화된 언어 특성을 모델의 파라미터에 함축하는 방법 - bi-directional LSTM으로 부터 얻은 벡터를 사용한다.
biLM
bi-directional language model
기존 seq2seq 모델은 한 방향으로만 진행된다.
biLM은 입력 문장을 양 방향의 언어 모델링을 통해 문맥적인 표현을 반영해서 입력 문장의 확률을 예측
ELMo는 이 layer에서 나온 벡터 표현을 선형 결합으로 단어를 표현
목적함수
$\displaystyle \sum^N_{k=1} (log p(t_k|t_1, \dots, t_{k=1} ; \Theta_x, \overset{\rightarrow}{\Theta}{LSTM}, \Theta_s) + log p(t_k|t{k+1}, \dots, t_N; \Theta_x, \overset{\leftarrow}{\Theta}_{LSTM}, \Theta_s)$
forward, backward LSTM이 서로 같은 단어 임베딩 $\theta_x$와 softmax layer인 $\theta_s$를 공유해서, log-likelihood 수식으로 표현 가능
학습방법
사전학습된 biLM이 있다면, 지도학습 형태의 다운스트림 작업을 수행하기 위한 언어 모델을 이용한다.
학습 데이터 셋 내 문장들을 통과시켜서 문장을 구성하는 각각의 단어 토큰 k에 대한 layer representation을 계산한다.
biLM에서는 총 L개의 layer에 대해 2L+1개의 layer representation을 얻을 수 있어서 모두 계산하면 파라미터 모두 freeze
이후, ELMo를 추가한 지도학습 다운스트림 작업을 수행하는 모델을 학습하여 task specific한 softmax 가중치를 얻을 수 있다.
이후 ELMo를 통합하는 방법은 단어 임베딩에 ELMo 모델에서 학습한 $ELMo^{task}_K$를 concatenate하는 것
요약
- ELMo는 기존의 단어 임베딩 구조가 문맥의 정보를 충분히 반영하지 못한다는 한계를 지적
- 양방향 학습이 가능한 biLM으로부터 문맥 내 정보를 충분히 반영하는 문장 벡터 표현을 학습한다.
- 넓은 범위의 NLP 문제들에서 ELMo를 적용했을 때 많은 성능 향상을 가져오는 것을 보임
- 정성 평가 결과를 통해 ELMo 벡터 표현이 문맥 내 단어 의미를 잘 반영하고 있음
Transformer
트랜스포머란?
2017년 구글이 발표한 모델
seq2seq 구조인 인코더-디코더를 따르지만, Attention만으로 구현된 모델
RNN을 사용하지 않는다.
기존 RNN 구조의 고질적인 문제인 Vanishing Gradient Problem
고정된 크기의 벡터에 모든 정보를 압축해서 정보 손실 발생
입력을 순차적으로 처리하기 때문에 병렬화가 불가능함
트랜스포머 모델은 입/출력에 대한 병렬화를 가능하게 하며 실제로 효율적으로 높은 성능에 도달 가능
attention
input 혹은 output 데이터에서 sequence distance에 무관하게 서로간의 dependencies를 모델링할 수 있음
모델 구조
인코더에서 입력 시퀀스를 입력받고, 디코더에서 출력 시퀀스를 출력하는 인코더-디코더 구조
seq2seq 구조에서는 인코더-디코더 각각이 하나의 RNN 모델처럼 작동했다면
트랜스포머에서는 인코더와 디코더라는 단위가 N개로 확장되는 구조
인코더로부터 정보를 전달받아 디코더가 출력 결과를 만들어닌다.
시작 토큰으로 <sos>을 입력으로 받고, <eos>가 나올 때 까지 문장을 출력함.
포지셔널 인코딩
RNN에서는 순차적으로 처리하기 때문에 위치 정보가 자연스럽게 반영되었다.
하지만 병렬적으로 처리하는 transformer에서는 위치 정보가 없다.
이를 해결하기 위해 단어의 위치 정보를 얻기 위해 각 단어의 임베딩 벡터에 위치 정보들을 더해서 모델의 입력으로 사용
$\rightarrow$ 포지셔널 인코딩
포지셔널 인코딩이 포함된 트랜스포머 구조
인코딩 값이 더해지는 과정을 시각화하면 위와 같다.
포지셔널 인코딩의 값은 아래의 두 개 함수를 사용한다.
$PE_{(pos, 2i)} = sin(pos/10000^{2i/d_{model}})$
$PE_{(pos, 2i+1)} = cos(pos/10000^{2i/d_{model}})$
$pos$, $i$, $d_{model}$과 같은 추가적인 변수는
포지셔널 임베딩이 임베딩 벡터와의 덧셈에 사용되는 목적을 알아야한다.
임베딩 벡터가 모인 행렬과 포지셔널 인코딩 값을 더해서 값을 내기 때문에, 포지셔널 인코딩도 행렬 형태이다.
$pos$
입력 문장에서의 임베딩 벡터의 위치
$i$
임베딩 벡터 내의 차원의 인덱스를 의미
임베딩 벡터 내 위치가 (pos, 2i)일 때는 $sin$, (pos, 2i+1)일 때는 $cos$
$d_{model}$
트랜스포머의 모델 구조에서 각각의 layer의 출력 차원을 의미하는 트랜스포머의 하이퍼파라미터
layer의 입/출력 크기를 맞춰줘야 하기 때문에 대부분의 수식들에 포함되어있음
트랜스포머의 어텐션 구조
- 인코더에서 사용되는 어텐션
- 디코더에서 사용되는 어텐션
- 디코더에서 사용되는 어텐션
트랜스포머의 셀프 어텐션
하나의 문장 내에서 단어 간의 관계를 파악하기 위해서 사용하는 어텐션 메커니즘
본질적으로 Query, Key, Value가 동일
동작 원리
- Q, K, V 벡터 얻기
각 단어 벡터들로부터 Q, K, V 추상화하는 작업을 진행 - Scaled dot-product Attention
Q, K, V 벡터로 기존의 어텐션 메커니즘과 동일하다. - 행렬 연산으로 일괄 처리하기
Q 행렬을 K행렬을 전치한 행렬과 곱하면 각각의 단어의 Q벡터와 K벡터의 내적이 각 행렬의 원소가 되는 행렬이 출력
위 행렬을 각각 $\sqrt{d_k}$로 나눠주면, 각 행과 열이 두 단어 간 어텐션 스코어 값을 가지는 행렬
트랜스포머의 멀티헤드 어텐션
$d_{model}$의 차원을 가진 단어 벡터를 $num_heads$로 나눈 차원으로 어텐션을 수행
$d_{model}$ / $num_head$의 차원을 가지는 Q, K, V에 대해서 어텐션을 $num_head$번 수행가능하다.
이 어텐션 메커니즘이 병렬적으로 이뤄지고, 이때 각각의 어텐션 값 행렬은 어텐션 헤드이다.
트랜스포머의 인코더
num_layers 만큼 인코더 층을 쌓는다.
각각 2개의 sublayer로 나뉘어진다.
- multi-head Self-Attention layer
- Position-wise FFNN(Feed Forward Neural Network)
Position-wise FFNN
일반적인 DNN의 feedforward 신경망
잔차연결
residual connection
sublayer의 출력에 입력 값을 더해주는 기법
레이어 정규화
layer normalization
잔차연결의 입력을 x, 잔차연결과 레이어 정규화를 모두 수행한 후의 결과 행렬을 LN이라고 하면, 수식은 아래와 같다.
$LN=LayerNorm(x+sublayer(x))$
트랜스포머의 디코더
num_layers 만큼 연산을 하는데 이때마다 인코더에 보낸 출력을 디코더 layer에서 모두 사용
Teacher Forcing 기법을 사용해서 훈련해서 정답 문장에 해당되는 문장 행렬을 한번에 입력
그러나 트랜스포머는 문장을 통째로 넣기 때문에 정답 단어까지 참조되게된다.
look-ahead mask
디코더의 첫번째 sublayer인 멀티 헤드 셀프 어텐션에서 어텐션 스코어 행렬에서 마스킹 적용
인코더-디코더 어텐션
입력 문장과 출력 문장 간의 관계도 학습에 사용하겠다는 말
요약
트랜스포머는 NLP가 아닌 분야에서까지 SOTA 모델로 자리잡고, 사용성과 성능을 동시에 잡았다.
모델 구조가 커져도 모델 내부 파라미터를 효과적으로 사용할 수 있어서 scaling-law에 대한 연구에서도 효과를 발휘
참조 : 트랜스포머
GPT
모델 요약
2018년 6월에 OpenAI에서 제안한 모델
unsupervised pre-training과 supervised fine-tuning의 조합을 사용해서 접근
특정 작업을 학습하기 위한 데이터 셋이 부족하기 때문에 비정형 텍스트를 사용
unsupervised pre-training이기 때문에 input text가 존재하지 않아 transformer decoder로만 구성
모델 학습
- unsupervised pre-training
대규모 코퍼스에서 언어모델을 학습 - supervised fine-tuning
특정 작업에 대한 데이터로 모델을 fine-tuning
unsupervised pre-training
목적함수는 likelihood를 최대화하도록 사용
$L_1(U) = \displaystyle \sum_i log P(u_i | u_{i-k},\dots,u_{i-1};\Theta)$
입력 문맥 token에 multi-headed self-attention을 적용하고, 목표 token에 대한 출력 분포를 얻기 위해 position-wise feedforward layer 적용
transformer 디코더로 계속 next token prediction 학습
supervised fine-tuning
GPT-1의 output을 downstream task에 적절하도록 선형변환해서 softmax에 넣음
$P(y|x^1, \dots, x^m) = softmax(h^m_l W_y)$
task에 맞는 $L_2$ loss를 설계한다.
$L_2(C) = \displaystyle \sum_{(x,y)} log P(y|x^1,\dots,x^m)$
그리고 사전 학습 때의 목적함수를 보조 함수로 사용한다.
$\because$ 일반화와 수렴 속도를 가속화하기 위함
Task Specific Input Transformation
사전학습이 next token prediction이라는 모델링으로 진행되서 downstream task와 다를수밖에 없다.
따라서 input을 변형해야한다.
의의
- 모델 구조의 변형이 거의 없음
이전 사전 학습 모델들은 finetune 시 모델 구조를 변형해야했지만, GPT-1은 변형하지 않음 - 추가되는 파라미터의 수가 매우 적음
구조 변경 없이 linear layer를 마지막에 추가하는 간단한 추가 작업만 수행함
BERT
개요
- feature based approach
ELMo : pre-trained representations을 하나의 추가적인 feature로 활용 - fine-tuning approach
task-specific parameter 수는 최소화, 모든 사전 학습 파라미터를 바꿔 학습
구조
multi-layer bidirectinal transformer encoder
양방향 transformer encoder를 여러 층 쌓은 것
입력에서 3가지의 embedding vector를 합침
모든 input 시퀀스의 첫번째 토큰은 [CLS] 토큰.
대응되는 최종 hidden state는 분류문제를 해결하기 위해 sequence representation들을 함축
사전학습
- MLM : 마스킹해서 모델링
- NSP : next sentence prediction, 다음 문장을 예측하는 모델링
fine-tuning
- QA task
- Paraphrasing task