어텐션과 트랜스포머

Sirius·2023년 3월 12일

1. RNN기반 Seq2Seq

문서의 번역은 매우 어려운 작업이다.
문서의 분류는 하나의 결론만 생성하면 되지만 번역은 단어들을 순차적으로 생성해야 하기 때문이다. 심지어 단어들의 길이는 가변적이다.

seq2seq=Words>Model>Wordsseq2seq = Words -->Model--> Words

"hello world"를 "bonjour le monde"로 번역


위 그림은 은닉층에 들어가는 입력인 hello, world 등은 임베딩한 벡터로 변환하는 과정이 생략됐음. 즉 들어가는 입력은 각각의 단어가 임베딩 변환된 벡터값

1 인코더

인코더는 영어문장을 이해하는 역할을 함
은닉층을 통해 앞 단어로부터 순차적으로 정보가 축적되고 마지막 end입력을 받은 은닉층의 노드는 영어문장 전체의 문맥 정보를 내포하는 역할을 한다.

2 디코더

디코더는 이 문맥정보로부터 프랑스어 문장을 생성하는 역할을 한다.
start는 문장의 시작 혹은 번역의 시작을 알리는 벡터이다.
이 시작 신호와 그 전까지의 축적된 문맥정보로 첫단어 bonjour를 예측한다.
그리고 이 bonjour는 다음 입력값으로 사용된다.

2. 어텐션

seq2seq의 문제점은 문맥정보가 인코더의 마지막 벡터 하나에 집중되는 현상이다.

만약 문장의 길이가 백 단위로 이루어진 문장이라면 하나의 마지막 벡터에 너무 많은 정보가 축적된다.

"With great power comes great responsibility."를 "큰 힘에는 큰 책임이 따른다."로 번역함에 있어서 '책임'을 예측할때, 이 단어에 가장 많은 영향을 미치는 원문의 단어는 'responsibility'이다.
어텐션 메커니즘은 딥러닝의 특성을 살려서 'responsibillity'가 '책임'의 예측에 직접 관여하게 하는 것이다.

context vector에는 첫 단어의 예측에 가장 많은 영향을 미치는 단어에 대한 정보가 담긴다.
우선 단어들마다 계산된 어텐션 스코어에 소프트맥스를 적용하여 각각의 단어에 가중치를 생성한다. 또한 이 값들을 단어들의 임베딩 벡터에 대해 가중치를 반영해 가중합계를 구하면 컨텍스트 벡터가 된다.

컨텍스트벡터=Σ각단어의임베딩벡터(그단어의가중치)컨텍스트 벡터 = \Sigma 각단어의 임베딩 벡터 * (그 단어의 가중치)

그림에서 현재의 값 중 bonjour에는 hello가 가장 큰 영향을 준다.(0.7)
이 컨텍스트 벡터는 (인코더의 마지막 벡터 + 디코더의 입력값)과 합쳐져서 첫 단어를 생성한다.

컨텍스트 벡터는 당연히 예측할 단어의 순서에 따라 계속 바뀐다.

3. 셀프 어텐션(Self-Attention)과 트랜스포머

3.1 셀프어텐션

셀프어텐션의 목적은 문장내에서 단어 간 영향을 표현하는 것이다.

다시 말해서 셀프 어텐션에서는 각 단어들이 어떤 단어에 미치는 정보를 선별해 자신에게(어떤 단어) 축적한다.

각 단어는 자신에게 오는 어텐션 정보를 가지고 있다. 따라서 seq2seq 모형과는 다르게, 한 벡터가 전체 문맥에 대한 정보를 축적하고 있지 않다.

1) 인코딩 과정에서 문맥에 대한 정보는 각 단어에 골고루 분포함
2) 디코딩 과정에서 입력 문장의 모든 단어의 임베딩 벡터를 어텐션 형태로 활용함

3.2 트랜스포머

1) 인코더 부분은 문장을 입력받아 문맥정보(셀프 어텐션 정보)를 추출한다.

2) 디코더 부분은 인코더로부터 각 단어의 임베딩 벡터(셀프어텐션정보를 가짐)를 이용해 단어를 하나씩 예측한다.

이때 인코더로 부터 오는 어텐션 정보 + 자신의 셀프 어텐션 정보를 함께 사용한다.

3) 또한 Nx층이라는 것은 "저렇게 생긴 층이 N개 겹쳐 있다는 것이다.", 하나의 층은 '멀티헤드셀프어텐션'과 '피드포워드 층'으로 구성돼 있다.

3.3 트랜스포머의 인코더

인코더를 보면 층을 거치더라도 단어들이 합쳐져서 하나의 벡터가 되지는 않는다.

1) 셀프 어텐션 층은 어떤 단어(Thinking)에 대해 영향을 미치는 다른 모든 단어들의 정보를 결합한다.
즉 self-attention의 출력은 Thinking에 영향을 미치는 단어들의 결합된 정보이다.

2) 피드포워드층은 단어별로 분리돼 있다. 따라서 단어들 간의 정보가 결합되지 않는다.

3.3.1 인코더의 셀프 어텐션

셀프어텐션은 query, key, value 세개의 벡터를 이용해서 계산된다.

  • Q: 이 3개의 벡터들은 어떻게 생성되는가?
    A: 입력 단어의 임베딩 벡터로부터 각각의 가중치 행렬 W(Q), W(K), W(V)을 뽑는다. -> <이것이 3개의 벡터의 초기값임>

1) query: 어텐션을 받는 단어가 어텐션과 관련해 다른 단어들에게 던지는 질문이다.
ex> "나한테 영향주는 넘들 손들어봐"

2) key: query에 대한 대답이다
ex> "내가 당신에게 큰 영향을 주고 있어요"

3.3.2 인코더의 셀프 어텐션 계산

1)
"나는 고양이를 좋아한다"라는 문장을 임베딩하여 각 단어에 대한 벡터를 얻는다.

임베딩의 차원수(d)는 4로 가정

X=[[1,0,1,0],
[0,3,0,3],
[1,1,1,1]]

추가로 아래와 같은 Query, Key, Value의 가중치 행렬을 가정한다.

W_Q = 
[[1, 0, 1],
 [1, 0, 0],
 [0, 0, 1]
 [0, 1, 1]]

W_K = 
[[0, 0, 1],
 [1, 1, 0],
 [0, 1, 0],
 [1, 1, 1]]

W_V = 
[[0, 2, 0],
 [0, 3, 0],
 [1, 0, 3],
 [1, 1, 0]

2) 셀프 어텐션을 수행하기 위해서는 각각임베딩값의 Query, Key, Value 행렬이 필요하다.(행렬의 곱 연산)

"나는"의 Q = X x W_Q = [1, 0, 2]
"나는"의 K = X x W_K = [0, 1, 1]
"나는"의 V = X x W_V = [1, 2, 3]

"고양이를"의 Q = X x W_Q = [3, 3, 3]
"고양이를"의 K = X x W_K = [6, 6, 3]
"고양이를"의 V = X x W_V = [3, 12, 0]

"좋아한다"의 Q = X x W_Q = [2, 1, 3]
"좋아한다"의 K = X x W_K = [2, 3, 2]
"좋아한다"의 V = X x W_V = [2, 6, 3]


Q = 
[[1, 0, 2]
 [3, 3, 3]
 [2, 1, 3]]

K =
[[0, 1, 1]
 [6, 6, 3]
 [2, 3, 2]]
 
V = 
[[1, 2, 3]
 [3, 12, 0]
 [2, 6, 3]]

"나는"이 "고양이를"에 영향을 받는 정도를 계산하기 위해서는 "나는"의 Q벡터(query)와 모든 K(key)벡터를 내적한다.

이 내적값이 바로 attention score이다.

또한 두벡터 a . b = a^T x b 로도 표현할 수 있다.

Q x K^T
[[1, 0, 2]	[[0, 6, 2]
 		  x [1, 6, 3] 
            [1, 3, 2]]
 = [2, 12, 6]

score = [2, 12, 6]

첫번째 2는 첫번째 쿼리벡터랑 첫번째 키 벡터사이의 문맥관계,
두번째 12는 첫번째 쿼리벡터랑 두번째 키 벡터사이의 문맥관계,
두번째 6은 첫번째 쿼리벡터랑 세번째 키 벡터사이의 문맥관계

3) 그렇게 해서 나온 score를 키벡터 차원의 제곱근으로 나눈다.(dk = 3)
score=[23,123,63]score = [{2\over\sqrt{3}}, {12\over\sqrt{3}}, {6\over\sqrt{3}}]

반올림
score = [1.15, 7, 3.5] 

4) 소프트 맥스 계산

softmax([1.15, 7, 3.5]) = [0.0028, 0.968, 0.0292]

5) 소프트맥스에서 출력된 벡터 x Value 벡터 = Sum

V = [[1, 2, 3]
    [3, 12, 0]
   [2, 6, 3]]

self_attention = [0.0028, 0.968, 0.0292] x V = 

[2.9652, 11.7968, 0.096]

트랜스포머에서는 위의 인코더 층을 병렬로 연결한 멀티헤드 어텐션을 사용한다. (CNN에서 채널을 통해 다양한 관점으로 이미지를 해석하고 이를 다시 결합하는 것을 떠올리면 됨)
ex> 의견이 서로 다른 여러 사람이 각자의 관점으로 문장 해석 후 그 의견들을 다시 취합

트랜스포머를 발표한 구글의 논문에서는 각 6개의 인코더층과 6개의 디코더 층을 사용함, 층이 쌓일수록 깊게 어텐션을 학습할 수 있다. 그러나 많은 시간과 자원이 소모된다.

3.4 트랜스포머의 디코더

  • 인코더 vs 디코더
    1) 디코더에는 인코더에서 디코더로 향하는 멀티헤드 어텐션 층이 하나 더 있음

만약 영어에서 한국어로 번역을 한다고 한다면, 디코더에서 생성한 한글단어가 query를 던진다.
그리고 key와 value는 인코더에 있는 영어단어로부터 온다.

한국어 단어에 영향을 미치는 영어 단어들의 영향력을 표현하는 것이 인코더-디코더 파트이다. 따라서 생성되고 있는 한국어 단어에 대한 어텐션 정보는 인코더에 있는 영어 단어로부터 와야함

2) 디코더 셀프 어텐션 층은 인코더와 다르게 Masked가 추가돼 있다.
Masked는 디코더의 특성상 셀프 어텐션이 뒤에서 앞으로 갈 수 없어서 만들어진 방법이다.

디코더는 하나의 단어를 반복해 생성한다.

처음 디코더가 실행되면 번역의 첫 단어를 생성한다. 다음 턴에는 처음 생성한 단어 정보를 이용해 둘째 단어를 생성한다.

즉 Masked는 디코더에서 순방향으로만 어텐션이 향하는 것을 구현한 메커니즘이다.

0개의 댓글