AI Engineering/이론

Attention 레이어 해부하기 (QK회로, OV회로)

마늘냄새폴폴 2026. 9. 24. 18:47

안녕하세요! 오랜만에 여유가 생겨서 포스팅을 쓸 시간이 생겼네요. 이번 포스팅에서는 그동안 미뤘던 수학 얘기를 좀 할까합니다. 저는 포스팅을 최대한 쉽게 쓰려고하는 편인데 그래도 앞으로 AI 이론 포스팅을 수월하게 작성하기 위해서는 반드시 한번 짚고 넘어가야한다고 생각해서 아쉽지만 이번 포스팅에는 수식이 잔뜩 나올 예정입니다...

 

이번 포스팅은 이렇게 이루어져있습니다. 

 

1) Attention 수식의 전체적인 모습

2) 행렬의 계산방법

3) QK회로와 K의 전치 이유

4) 루트 dk로 나누는 이유

5) Softmax의 존재의의와 필요성

6) OV회로와 잔차 연결

 

자 이제 본격적으로 시작하도록 하겠습니다!

 

Attention 수식의 전체적인 모습

우선 Attention 수식의 전체적인 모습에 대해서 짚고 넘어가겠습니다. 

 

GPT씨가 써준 Attention 수식입니다. 

 

딱 보면 이게 뭐야싶어서 이렇게 나눠서 볼겁니다

이제 각각이 무엇인지는 천천히짚고 넘어가도록하고...

 

Attentino 수식에서 궁극적으로 하고싶은 말은 다음과 같습니다. 

 

"다음 토큰에 필요한 맥락을 가져와서 가장 확률 높은 다음 토큰을 뱉는 과정"

 

자, 이제 어떤 기작으로 다음 토큰을 뱉는지 확인해보죠

 

행렬의 계산방법

수학 얘기는 아주 잠깐, 빠르게 짚고 넘어가겠습니다. 

 

행렬은 행과 열로 이루어져있고 각각의 행렬을 벡터로 표시할 수 있습니다. 우리가 고등학생때 배우는 2차원의 벡터, 3차원의 벡터 뿐만 아니라 수십, 수백차원의 벡터로 표현할 수 있다는 장점이 있습니다. 

 

그리고 행렬을 어떻게 쌓느냐에 따라서 우리는 행벡터, 열벡터로 나누곤합니다. 이게 무슨 소리냐하면 "나는 각 행에 대한 데이터에 의미를 부여할거야"라면 이건 그냥 행벡터로 부르는거고 각 열에 대한 데이터에 의미를 부여하면 열벡터가 된다는 뜻입니다. 

 

네, 그냥 이 수식을 적은 사람의 마음입니다. 

 

그리고 행렬의 계산은 이렇게 이루어집니다. 

이런 행렬이 있다고 한다면 

 

1행 : (1, 2)

2행 : (3, 4)

1열 : (1, 3)

2열 : (2, 4)

 

여기까진 쉽죠

 

자 이제 행렬 두개를 곱해보겠습니다. 

 

 

이거 계산을 어떻게 해야하냐면 위의 행렬 곱을 편의상 1번행렬, 2번행렬이라고 하겠습니다. 

 

  1. 1번 행렬의 1번행과 2번 행렬의 1번열을 곱해줍니다. 
  2. 1번 행렬의 1번행과 2번 행렬의 2번열을 곱해줍니다. 
  3. 2번 행렬의 2번행과 2번 행렬의 1번열을 곱해줍니다.
  4. 2번 행렬의 2번행과 2번 행렬의 2번열을 곱해줍니다. 

즉, 수식으로 쓰면

17은 1x5 + 2x6의 결과이구요

23은 1x7 + 2x8의 결과입니다. 

39는 3x5 + 4x6의 결과

53은 3x7 + 4x8의 결과입니다. 

 

여기서 찾을 수 있는 행렬곱의 규칙은 1번행렬은 행만, 2번행렬은 열만 가지고 곱한다는 말입니다. 

 

 

QK회로와 K의 전치 이유

 

다시 Attention을 가져왔습니다. 여기서 QK는 Q행렬과 K행렬을 곱했다는 뜻입니다. 그럼 위에 T는 무엇이냐 바로 "전치" 행렬의 순서를 바꾼겁니다. 

 

이렇게 두개를 놓고 비교하면 좀 더 편하게 이해할듯싶네요. 

 

2번행렬의 원래 행이 열로 바뀐겁니다. 

 

그럼 Attention에서는 K를 왜 전치할까요? 

 

그건 왜냐하면 기본적으로 Q, K가 모두 행벡터이기 때문입니다. 머신러닝에서는 보통 행벡터로 표현하는 것이 일반적이었고 Q, K도 그 관습대로 행벡터로 쌓았습니다. 

 

각 행이 토큰(단어)이고 이렇게 행으로 쌓는게 일반적이었거든요. 

 

근데 앞서도 설명했듯이 행렬의 곱은 뭐다? 1번행렬의 행과 2번행렬의 열을 곱하는겁니다. 지금 전치를 안하고 QK를 해버리면 K에 있는건 행별로 토큰이 있는건데 K의 열은 아무 의미가 없는 그냥 숫자나열입니다. 

 

그래서 이걸 뒤집어서 K의 각토큰을 행벡터로 표현하는게 아니고 열벡터로 표현하겠다는겁니다. 

 

 

이렇게요. 

 

그럼 Q행렬에 전치된 K행렬을 곱하면 그 의미는 "Q행렬에 있는 토큰과 K행렬에 있는 토큰끼리의 유사도를 확인하겠다." 이렇게 해석할 수 있는겁니다. 

 

이게 바로 "QK회로"라고 부르는 것이고 Attention레이어에서 어떤 맥락을 가져올 것이냐를 담당하고 있습니다. 

 

루트 dk로 나누는 이유

Q행렬과 K행렬을 서로 내적하면서 더하다보면 이런 값이 나옵니다. 

 

그러니까 dk는 Q와 K행렬(벡터)에 있는 숫자의 개수이고 이것이 곧 차원이됩니다. 

 

차원이 커질수록 더 많은 값을 더하게 되니까 내적값(스칼라)의 크기도 커집니다. 예를 들어서 내적이 너무 커지면 나중에 softmax 함수를 씌울때 확률이 너무 극단적으로 변해버립니다. 

 

이 softmax는 바로 뒤에서 이야기해보겠습니다. 

 

확률이 극단적으로 변해버리면 모델이 사실상 한 토큰만 바라보게되고, 그럼 학습할 때도 문제가 생기기 때문에 확률을 안정적으로 바꾸려고 dk로 나누는겁니다. 

 

그럼 그냥 dk가 아니고 왜 루트를 씌우냐? 

 

서로 독립적인 값을 여러개 더할 때 합의 분산은 dk배, 표준편차는 루트dk배 커지기 때문이고 그래서 이 때문에 루트dk로 나누는거죠. 

 

Softmax의 존재의의와 필요성 

왜 갑자기 softmax라는게 나오냐하면 이렇게 QK 행렬곱과 루트dk로 나눴을 때의 문제 때문입니다. 

 

이 계산 결과의 값은 음수가 될 수도 있고, 합이 1도 아니라서 확률을 나타내지도 않고, 몇 퍼센트를 차지하고있는지 보이지도 않습니다. softmax는 자연상수 e를 이용해서 모든 값을 양수이면서 합이 1인 가중치로 바꿔버립니다. 

 

예를 들어서 

 

이렇게 나오는거고 그럼 "첫번째 K의 위치를 66.5%, 두번째는 24.5%, 세번째는 9%로 바라보겠다" 라는 의미로 확산됩니다. 

 

OV회로와 잔차 연결

V도 결국 행벡터인데 이 모든 QK회로에서의 결과물을 V와 곱하면 어떻게 되냐.

 

QK회로에서의 결과물은 스칼라(값)입니다. 그래서 이 상태에서 행렬(벡터)에 곱해주면 각 토큰에 가중치가 붙어서 나옵니다. 

 

 

예를 들어서 이런 V벡터가 있었다고 가정해보겠습니다. 

 

그 상태에서 각 토큰의 확률을 곱해주면?

 

이렇게 됩니다. 

 

여기까지가 일반적인 Attention 연산의 끝입니다. 

 

어..? 근데 토큰이 아직 안뱉어졌는데요..

 

그렇습니다. 아직까지는 V벡터에 있는 토큰이 얼마나 높은 확률로 선택될 것인가만 나와있지 실제 토큰의 출력으로 이어지진 않았습니다. Attention 수식에서도 V까지만 있으니 다음 토큰은 어디로 갔냐하면

 

Attention을 Head의 출력까지 포함된 수식으로 바꾸면 다음과 같습니다. 

 

 

저기 뒤에 이상한놈이 붙었습니다. Wo는 뭐죠? 

 

Wo는 Output 즉, 출력에 대한 가중치입니다. 

 

그러니까 V벡터와 QK회로의 값을 곱해서 V벡터 안의 어떤 토큰이 높은 확률을 가진다고 판단한 뒤 Wo 가중치를 통과해서 실제로 어떤 토큰을 뱉을지가 결정되는겁니다. 

 

물론.. 이 단계에서 토큰을 진짜 뱉는건 아닙니다. Wo를 쉽게 설명하기위해서 토큰을 뱉는다고 표현했지만 사실은 잔차스트림에 잔차연결을 통해 의미를 델타(차이)만큼 더하는 과정입니다. 

 

그래서 실제로는 토큰이 뱉어지는건 수십겹의 Attention레이어와 MLP레이어를 통과하고 맨 뒤에있는 출력층에서 결정되는 것이고 지금 우리가 알아본 과정은 레이어 하나, 그리고 그 중에서도 Attention레이어, 그 중에서도 수많은 헤드의 집합중에 딱 하나의 과정을 본 것입니다. 

 

LLM 내부 Transformer 과정에서는 이런 연산이 수십개 이루어져 하나의 Attention 레이어를 이루고 이런 연산이 다시 수십번 이루어져 출력층에 도달하는 것이니 토큰을 하나 뱉기 위해서는 최소 수백번에서 많게는 수천번까지의 계산이 이루어지고 토큰이 뱉어진다는 의미입니다. 

 

마치며

사실 이론 공부를 처음 시작하게 된 올해 1월에 비하면 많은 부분을 놓치고 포스팅을 했습니다. 이번에 시간이 많이 남을때 모든 내용을 정리하고 하나의 흐름으로 정리하고자합니다. 

 

일단 시작은 Attention의 가장 기본적인 연산으로 시작해봤습니다. 다음 포스팅은 이런 Attention 연산이 모여 하나의 Attention 레이어가 되는데 이 과정에서 여러 Q, K, V의 집합이 서로 힘을 합치는데 이 과정에서 생기는 다양한 문제들, 그리고 그 문제를 어떻게 해결했는지 연구자들의 눈물겨운 온몸비틀기를 포스팅할 예정입니다. 

 

그래서 다음 포스팅은 MHA, MQA, GQA에 대한 내용으로 찾아뵙도록 하겠습니다. 

 

긴 글, 심지어 수식까지 있는 글을 끝까지 읽어주셔서 감사합니다. 오늘도 화이팅입니다!