LLM 엔지니어링3장 · Attention 과 Transformer, GPT 직접 구현6 / 23← 이전목차다음 →MetaContents

3장. Attention 과 Transformer, GPT 직접 구현

Attention 의 원리

도서관에서 자료를 찾는 모습을 떠올려 보세요. 손에는 "배송 지연에 관한 자료"라는 질문 쪽지가 있습니다. 서가의 책마다 제목표가 붙어 있고, 질문과 잘 맞는 제목표의 책일수록 더 자세히 읽어 내용을 모읍니다. Attention 이 하는 일이 이것입니다.

질문 Q 와 제목표 K 를 견주고, 점수를 비율로 바꿔, 그 비율만큼 내용 V 를 섞는 Attention 흐름도

1번 질문(Q)은 지금 글자가 찾고 싶은 것, 2번은 다른 글자들의 제목표(K)와 얼마나 맞는지 점수를 내는 단계입니다. 3번에서 점수를 합이 1 인 비율로 바꾸고, 4번에서 그 비율만큼 각 글자의 내용(V)을 섞습니다. 여기서 질문 쪽지가 쿼리, 제목표가 키, 책의 내용이 밸류입니다.

Q, K, V 는 어디서 오나

글자마다 임베딩 벡터가 있습니다. 이 벡터에 서로 다른 가중치를 곱해 Q, K, V 세 벡터를 만듭니다. 세 가중치는 2장의 nn.Linear 와 같은 층이고, 학습으로 정해집니다.

벡터만드는 법도서관으로 치면
Q(쿼리)임베딩 × Wq내가 들고 있는 질문 쪽지
K(키)임베딩 × Wk책마다 붙은 제목표
V(밸류)임베딩 × Wv책의 실제 내용

점수를 비율로: softmax

견주기 점수는 아무 크기나 될 수 있습니다. softmax 는 이것을 "몇 퍼센트씩 참고할지"로 바꿉니다.

Python
import torch

scores = torch.tensor([2.0, 1.0, 0.1])        # 세 글자와 견준 점수
weights = torch.softmax(scores, dim=0)        # 0~1 사이, 합이 1 인 비율로
print(weights.round(decimals=3))
print(weights.sum())

점수 2.0, 1.0, 0.1 이 비율 0.659, 0.242, 0.099 로 바뀌고, 합은 1 입니다. 점수가 높은 글자를 더 많이, 그러나 다른 글자도 조금씩 참고합니다.

코드에 나오는 함수

코드쉬운 뜻
torch.softmax(scores, dim=0)점수를 0과 1 사이의 비율로 바꾸고, 그 합이 1이 되게 한다. 점수가 클수록 비율도 크다
dim=0어느 축을 따라 합을 1로 맞출지 정한다. 여기서는 숫자가 한 줄뿐이라 0번 축 전체가 대상이다
.round(decimals=3)소수 셋째 자리까지 반올림해 보기 좋게 한다. 값을 출력할 때만 쓴다
weights.sum()모든 값을 더한다. softmax 의 결과라 1이 나온다

softmax 는 점수의 차이를 키우는 성질이 있습니다. 2.0 과 1.0 은 두 배 차이지만, 비율은 0.659 와 0.242 로 두 배보다 크게 벌어집니다.

이 코드가 뜻하는 것

도서관 비유로 읽으면, 질문 쪽지와 세 책의 제목표를 견준 점수가 2.0, 1.0, 0.1 입니다. softmax 를 지나면 "첫째 책에서 65.9%, 둘째 책에서 24.2%, 셋째 책에서 9.9% 를 가져와 섞는다"는 비율표가 됩니다. 점수가 가장 높은 책만 읽는 것이 아니라, 덜 맞는 책도 조금씩 참고한다는 점이 중요합니다. 이 비율표가 위 흐름도의 3번이고, 4번에서 이 비율대로 내용(V)을 섞습니다.

줄하는 일도서관으로 치면
scores = torch.tensor([2.0, 1.0, 0.1])견주기 점수 셋을 텐서로 만든다세 책의 제목표가 질문과 맞는 정도
torch.softmax(scores, dim=0)점수를 합이 1 인 비율로 바꾼다책마다 얼마나 읽을지 나눈 비율표
weights.sum()비율을 모두 더해 1 인지 확인한다나눈 몫을 모으면 전부(100%)가 된다

softmax 는 어떻게 계산하나

softmax 의 계산은 세 걸음입니다. 점수마다 2장 "활성화 함수" 절에서 본 exp(e 를 그 점수만큼 곱한 값)를 구하고, 모두 더한 뒤, 각자를 그 합으로 나눕니다.

점수 2.0, 1.0, 0.1 이 exp 를 지나 7.389, 2.718, 1.105 가 되고 합 11.213 으로 나눠 0.659, 0.242, 0.099 가 되는 흐름도

그림은 왼쪽에서 오른쪽으로 읽습니다. 1번의 점수가 2번에서 exp 를 지나 모두 양수가 되고, 3번에서 셋의 합 11.213 으로 나눠 비율이 됩니다. 나눈 몫을 모두 더하면 꼭 1 이 됩니다.

Python
import torch

scores = torch.tensor([2.0, 1.0, 0.1])
e = torch.exp(scores)                  # 1) 점수마다 exp: 모두 양수가 된다
total = e.sum()                        # 2) 모두 더한다
manual = e / total                     # 3) 각자를 합으로 나눈다
print(e.round(decimals=3), total.round(decimals=3))
print(manual.round(decimals=3))
print(torch.softmax(scores, dim=0).round(decimals=3))   # 함수의 결과와 같다

실행하면 exp 의 결과는 7.389, 2.718, 1.105 이고 합은 11.213 입니다. 세 걸음을 직접 적어 계산한 값(manual)과 torch.softmax 의 값이 모두 0.659, 0.242, 0.099 로 같습니다.

이 코드는 torch.softmax 한 줄 안에서 일어나는 계산을 우리가 한 줄씩 직접 적어 보고, 그 값이 함수의 결과와 같은지 견주는 코드입니다. 변수 이름 manual 은 영어로 "손으로 하는"이라는 뜻으로, 종이에 연필로 계산했다는 말이 아니라 "함수에 맡기지 않고 단계를 직접 적어 구했다"는 뜻입니다.

줄하는 일값
scores = torch.tensor([2.0, 1.0, 0.1])세 책과 견준 점수를 텐서로 만든다2.0, 1.0, 0.1
e = torch.exp(scores)1걸음. 점수마다 e(약 2.718)를 그 점수만큼 곱한 값을 구한다. 결과는 언제나 양수다7.389, 2.718, 1.105
total = e.sum()2걸음. 세 값을 모두 더한다11.213
manual = e / total3걸음. 칸마다 합으로 나눈다. 텐서를 숫자 하나로 나누면 모든 칸이 같은 수로 나뉜다0.659, 0.242, 0.099
.round(decimals=3)찍을 때 소수 셋째 자리까지 반올림해 보기 좋게 한다. 계산한 값 자체는 바뀌지 않는다
torch.softmax(scores, dim=0)같은 계산을 함수 한 줄로 한다0.659, 0.242, 0.099

3걸음을 숫자로 풀면 7.389 ÷ 11.213 = 0.659, 2.718 ÷ 11.213 = 0.242, 1.105 ÷ 11.213 = 0.099 입니다. 셋을 더하면 1 이 되어, 전체를 100% 로 보고 몫을 나눈 것이 됩니다. 함수와 직접 계산한 값이 똑같으므로, 앞으로 torch.softmax 를 보면 "exp 로 키우기, 모두 더하기, 합으로 나누기"의 세 걸음을 떠올리면 됩니다.

왜 exp 를 쓰나

까닭설명
음수도 비율로 만들 수 있다exp 는 언제나 양수를 내므로, 점수가 -1, -2 처럼 음수여도 비율이 된다. 점수를 그대로 합으로 나누면 음수 비율이 생긴다
큰 점수를 더 크게 키운다점수 차이가 1 이면 exp 의 차이는 약 2.7배가 된다. 그래서 2.0 과 1.0 은 두 배 차이인데 비율은 0.659 와 0.242 로 2.7배 벌어진다
미분하기 좋다부드러운 곡선이라 기울기를 구하기 쉽다. 역전파로 학습해야 하는 신경망에 맞다

이름의 뜻: 부드러운 최댓값

가장 큰 점수 하나만 고르고 나머지는 버리는 것을 영어로 max(또는 argmax)라고 합니다. 점수 2.0, 1.0, 0.1 에 이것을 쓰면 비율은 1, 0, 0 이 됩니다. softmax 는 이것을 부드럽게(soft) 만든 것이라, 가장 큰 점수에 가장 많이 주되 다른 점수에도 조금씩 나눠 줍니다. 그래서 이름이 soft + max 입니다.

방법점수 2.0, 1.0, 0.1 의 결과읽는 법
가장 큰 것만(argmax)1, 0, 0첫째 책만 읽는다
softmax0.659, 0.242, 0.099첫째 책을 주로, 나머지도 조금 읽는다
점수에 3 을 곱한 뒤 softmax0.950, 0.047, 0.003점수 차이를 키우면 argmax 쪽으로 다가간다

마지막 줄처럼 점수를 키우면 softmax 가 한쪽으로 쏠리고, 줄이면 고르게 퍼집니다. 이 성질을 글쓰기에 쓰는 것이 뒤의 "다음 글자 고르기: 생성과 온도" 절의 온도입니다.

알아 두면 좋은 성질

  • 모든 점수에 같은 수를 더해도 결과가 같습니다. 2.0, 1.0, 0.1 에 10 을 더한 12.0, 11.0, 10.1 도, 음수인 -1.0, -2.0, -2.9 도 비율은 똑같이 0.659, 0.242, 0.099 입니다. 점수의 크기 자체가 아니라 점수끼리의 차이만 보기 때문입니다.
  • 2차원 표에 쓸 때는 dim 이 중요합니다. 다음 절 "셀프 어텐션 계산"에서는 글자마다 한 줄씩 점수가 있는 표에 dim=-1(마지막 축, 곧 줄마다)을 줘서, 줄마다 합이 1 이 되게 합니다.

주의할 점

  • 비유에서는 사람이 질문을 정하지만, Attention 에서는 Q, K, V 를 만드는 가중치를 학습이 정합니다. 무엇을 질문할지도 모델이 배웁니다.
  • Attention 의 결과는 "가장 맞는 글자 하나"가 아니라 여러 글자의 내용을 비율대로 섞은 벡터입니다.
← 이전 절3장 · 순서를 읽는 모델과 한계다음 절 →3장 · 셀프 어텐션 계산