이 문서는 다음 전제를 두고 설명한다.
- 컴퓨터는 글자, 이미지, 소리 자체를 바로 이해하지 못한다.
- 모든 입력은 결국 숫자 배열로 바뀐다.
- 모델은 숫자 배열을 여러 번 변환해서 결과를 만든다.
- 학습은 결과가 틀렸을 때, 틀린 정도를 줄이도록 내부 숫자를 조금씩 고치는 과정이다.
- LLM은 “사람처럼 이해하는 프로그램”이라기보다, 구현 관점에서는 “지금까지의 토큰을 보고 다음 토큰을 예측하는 거대한 신경망”이다.
핵심 한 문장:
신경망은 숫자 상태를 여러 층에서 바꾸는 구조이고, LLM은 텍스트를 숫자 상태로 바꾼 뒤 다음 토큰을 예측하도록 학습한 신경망이다.
텐서(tensor) 는 신경망 안에서 흐르는 숫자 배열이다.
- 숫자 하나는 스칼라(scalar)
- 숫자 한 줄은 벡터(vector)
- 숫자 표는 행렬(matrix)
- 벡터와 행렬을 더 일반화한 숫자 배열이 텐서다
구현 관점에서는 이렇게 보면 된다.
텐서 = 현재 정보 상태
예를 들어 이미지라면 픽셀 숫자들이 텐서가 된다. 텍스트라면 토큰을 숫자로 바꾼 뒤 만든 벡터들이 텐서가 된다.
주의할 점:
텐서의 곱이 항상 “새로운 상태를 추가한다”는 뜻은 아니다.
더 정확히는 다음처럼 외우는 게 좋다.
- 행렬곱(matrix multiplication)은 현재 상태를 다른 관점으로 변환한다.
- 내적(dot product)은 두 벡터가 얼마나 비슷한 방향인지 비교한다.
- 가중합(weighted sum)은 여러 정보를 중요도에 따라 섞는다.
- 잔차 연결(residual connection)은 이전 상태에 새로 계산한 변화를 더한다.
따라서 안전한 표현은 이렇다.
텐서 연산은 현재 상태를 변환하거나 섞는 과정이다. 그중 잔차 연결은 이전 상태에 새 정보를 더하는 구조로 볼 수 있다.
퍼셉트론(perceptron) 은 여러 입력을 받아 하나의 출력을 만드는 가장 단순한 신경망 구조다.
퍼셉트론은 다음처럼 동작한다.
입력
→ 각 입력의 중요도 조절
→ 기준값 조정
→ 출력
여기서 중요한 용어가 두 개 있다.
가중치(weight) 는 각 입력을 얼마나 중요하게 볼지 정하는 숫자다.
예를 들어 “시험 점수로 합격 여부를 판단한다”고 하면, 수학 점수를 더 중요하게 볼지, 영어 점수를 더 중요하게 볼지를 정하는 숫자가 가중치다.
편향(bias) 은 결과가 얼마나 쉽게 활성화될지 조정하는 숫자다.
예를 들어 같은 점수라도 합격 기준이 낮으면 쉽게 합격하고, 기준이 높으면 쉽게 탈락한다. 이 기준을 밀어주는 역할이 편향이다.
외울 문장:
가중치는 입력의 중요도이고, 편향은 판단 기준의 위치다.
뉴런(neuron) 또는 노드(node) 는 입력을 받아 계산한 뒤 출력을 내보내는 작은 계산 단위다.
신경망은 뉴런을 여러 개 연결해서 만든다.
층(layer) 은 뉴런들이 모여 있는 한 단계다.
보통 신경망은 다음 세 부분으로 나뉜다.
입력층 → 은닉층 → 출력층
입력층(input layer) 은 데이터를 처음 받는 층이다. 은닉층(hidden layer) 은 중간 계산을 수행하는 층이다. 출력층(output layer) 은 최종 결과를 내는 층이다.
은닉층이라고 부르는 이유는 사용자가 직접 정답처럼 관찰하는 값이 아니라, 모델 내부에서 만들어지는 중간 상태이기 때문이다.
외울 문장:
입력층은 데이터를 받고, 은닉층은 중간 표현을 만들고, 출력층은 최종 판단을 만든다.
단순한 퍼셉트론 하나는 복잡한 문제를 잘 표현하지 못한다.
예를 들어 단순한 직선 하나로 나눌 수 있는 문제는 처리할 수 있지만, 여러 조건이 섞인 문제는 어렵다.
그래서 다층 퍼셉트론(MLP, Multi-Layer Perceptron) 처럼 층을 여러 개 쌓는다.
층을 쌓는다는 것은 다음 의미다.
원본 입력
→ 1차 해석
→ 2차 해석
→ 더 추상적인 해석
→ 최종 판단
예를 들어 이미지 인식이라면 다음처럼 볼 수 있다.
픽셀
→ 선/모서리
→ 눈/코/입 같은 부분
→ 얼굴
→ 사람
LLM도 비슷하다.
토큰
→ 단어 수준 의미
→ 문장 안 문맥
→ 문단 흐름
→ 다음 토큰 예측
외울 문장:
층을 쌓는다는 것은 한 번에 답을 내는 것이 아니라, 중간 표현을 계속 만들어가며 답에 가까워지는 것이다.
활성화 함수(activation function) 는 뉴런이 계산한 값을 다음 층으로 넘기기 전에 한 번 꺾거나 제한하는 함수다.
대표적인 활성화 함수는 다음과 같다.
- 시그모이드(sigmoid): 값을 0과 1 사이로 부드럽게 압축한다.
- ReLU(Rectified Linear Unit): 음수는 0으로 만들고, 양수는 그대로 통과시킨다.
- GELU(Gaussian Error Linear Unit): ReLU와 비슷하지만 더 부드럽게 동작한다.
왜 필요할까?
활성화 함수 없이 층을 여러 개 쌓으면, 결국 큰 선형 변환 하나와 비슷해진다. 그러면 층을 깊게 만든 의미가 줄어든다.
선형(linear) 은 직선적인 변환이다. 비선형(nonlinear) 은 직선 하나로 표현하기 어려운 변환이다.
현실 데이터는 대부분 비선형이다. 문장 의미, 이미지 형태, 사람의 선택 같은 것들은 단순한 직선 관계로 설명하기 어렵다.
외울 문장:
가중치 층은 정보를 섞고, 활성화 함수는 그 섞임을 비선형으로 꺾어서 복잡한 패턴을 표현하게 한다.
순전파(forward propagation) 는 입력이 모델을 통과해서 출력이 나오는 과정이다.
흐름은 다음과 같다.
입력 텐서
→ 가중치와 곱함
→ 편향을 더함
→ 활성화 함수를 통과함
→ 다음 층으로 전달
→ 최종 출력
예를 들어 손글씨 숫자 인식 모델이라면, 입력은 손글씨 이미지이고 출력은 “0일 가능성, 1일 가능성, 2일 가능성...” 같은 점수다.
외울 문장:
순전파는 현재 가중치로 일단 예측해보는 과정이다.
손실 함수(loss function) 는 모델의 예측이 정답과 얼마나 다른지 숫자로 표현하는 함수다.
예를 들어 정답이 “3”인데 모델이 “8”이라고 강하게 예측했다면 손실이 크다. 정답이 “3”이고 모델도 “3”에 높은 점수를 줬다면 손실이 작다.
신경망은 정확도를 직접 고치는 것이 아니다. 손실을 줄이도록 내부 가중치를 고친다.
외울 문장:
손실은 모델이 얼마나 틀렸는지를 나타내는 벌점이다.
역전파(backpropagation) 는 손실을 기준으로, 각 가중치가 결과 오류에 얼마나 영향을 줬는지 거꾸로 계산하는 과정이다.
순전파가 예측값과 손실을 계산하는 과정이라면, 역전파는 각 가중치의 책임과 수정 방향을 계산하는 과정이다.
순전파:
입력 → 출력 → 손실 계산
역전파:
손실의 기울기 → 출력층 → 은닉층 → 입력 쪽 가중치
여기서 중요한 점은, 손실함수 자체가 뒤로 전달되는 것이 아니다.
뒤로 전달되는 것은 손실함수를 미분한 값, 즉 기울기(gradient) 이다.
기울기는 다음을 알려준다.
이 가중치를 늘리면 손실이 커지는가?
이 가중치를 줄이면 손실이 작아지는가?
얼마나 수정해야 하는가?
역전파의 결과로 각 가중치에 대한 기울기가 계산된다.
역전파의 결과:
각 가중치의 gradient
그리고 이 gradient를 이용해서 실제 가중치를 바꾸는 것은 옵티마이저이다.
역전파:
수정 방향 계산
옵티마이저:
가중치 실제 수정
외울 문장:
역전파는 틀린 결과를 보고, 각 가중치가 손실에 얼마나 영향을 줬는지와 어느 방향으로 고쳐야 하는지를 계산하는 과정이다.
더 짧게 외우면:
역전파는 가중치별 책임과 수정 방향을 계산한다.
옵티마이저(optimizer) 는 역전파로 구한 기울기를 사용해서 가중치를 실제로 갱신하는 알고리즘이다.
역전파는 방향을 알려준다. 옵티마이저는 그 방향으로 실제 이동을 수행한다.
예를 들어 “이쪽으로 가면 산 아래로 내려간다”를 알려주는 것이 기울기라면, “얼마나 빠르게, 어떤 방식으로 걸어갈지”를 정하는 것이 옵티마이저다.
대표적인 옵티마이저는 다음과 같다.
SGD(Stochastic Gradient Descent) 는 가장 기본적인 방식이다. 현재 미니배치에서 구한 기울기의 반대 방향으로 조금 이동한다.
Momentum 은 이전 이동 방향을 어느 정도 기억해서, 지그재그 움직임을 줄인다.
AdaGrad 는 자주 많이 움직인 가중치는 작게 움직이고, 덜 움직인 가중치는 크게 움직이도록 조정한다.
Adam(Adaptive Moment Estimation) 은 Momentum과 AdaGrad 계열의 장점을 합친 방식으로 많이 사용된다.
외울 문장:
역전파는 수정 방향을 계산하고, 옵티마이저는 그 방향으로 가중치를 갱신한다.
학습률(learning rate) 은 한 번에 가중치를 얼마나 크게 수정할지 정하는 값이다.
학습률이 너무 크면 손실이 줄어드는 지점을 지나쳐서 학습이 불안정해진다. 학습률이 너무 작으면 학습이 너무 느리다.
배치(batch) 는 한 번에 묶어서 처리하는 데이터 묶음이다.
미니배치(mini-batch) 는 전체 데이터 중 일부만 뽑아 만든 작은 배치다. 실제 학습에서는 전체 데이터를 한 번에 쓰기보다 미니배치를 반복해서 쓰는 경우가 많다.
에폭(epoch) 은 전체 훈련 데이터를 한 바퀴 다 사용한 횟수다.
예를 들어 훈련 데이터가 10,000개이고, 미니배치 크기가 100이면 미니배치 100번을 처리해야 전체 데이터를 한 번 본 것이다. 이게 1에폭이다.
외울 문장:
학습률은 보폭, 미니배치는 한 번에 보는 문제 묶음, 에폭은 전체 문제집을 몇 번 풀었는지다.
신경망 학습은 다음 순서로 반복된다.
1. 미니배치를 뽑는다.
2. 순전파로 예측한다.
3. 손실 함수로 틀린 정도를 계산한다.
4. 역전파로 기울기를 계산한다.
5. 옵티마이저가 가중치를 갱신한다.
6. 이 과정을 여러 번 반복한다.
이 과정을 반복하면 가중치가 데이터에 맞게 조정된다.
외울 문장:
학습은 예측, 채점, 책임 계산, 수정의 반복이다.
모델은 내부에 W와 b를 가지고 있다.
W: 가중치 → 입력값을 얼마나 중요하게 볼지 정하는 값
b: 편향 → 결과를 보정해주는 값
학습의 목표는 W와 b를 좋은 값으로 바꾸는 것이다.
학습 전체
└── 여러 번 반복
└── 한 번의 학습 step
├── 1. 순전파
│ └── 현재 W, b로 예측값을 만든다.
│
├── 2. 손실 계산
│ └── 예측값과 정답의 차이를 계산한다.
│
├── 3. 역전파
│ └── W와 b를 어떻게 바꿔야 할지 계산한다.
│ 이때 gradient가 저장된다.
│
└── 4. 옵티마이저
└── 저장된 gradient를 보고 W와 b를 실제로 수정한다.
과적합(overfitting) 은 모델이 훈련 데이터만 너무 외워서 새로운 데이터에는 약해지는 현상이다.
예를 들어 시험 문제집의 답 순서만 외우면 같은 문제집은 잘 풀지만, 새 문제가 나오면 못 푼다. 이것이 과적합이다.
일반화(generalization) 는 처음 보는 데이터에도 잘 작동하는 능력이다.
과적합을 줄이는 방법에는 다음이 있다.
- 데이터를 더 많이 사용한다.
- 모델을 너무 크게 만들지 않는다.
- 드롭아웃을 사용한다.
- 가중치 감소를 사용한다.
- 검증 데이터로 성능을 확인한다.
드롭아웃(dropout) 은 학습 중 일부 뉴런을 임시로 꺼서 특정 경로에만 의존하지 않게 만드는 방법이다.
가중치 감소(weight decay) 는 가중치가 너무 커지지 않도록 벌점을 주는 방법이다.
검증 데이터(validation data) 는 학습에는 직접 쓰지 않고, 모델이 잘 일반화되는지 확인하는 데이터다.
외울 문장:
학습 데이터만 잘 맞히는 것은 부족하고, 처음 보는 데이터에도 맞아야 한다.
LLM은 텍스트를 그대로 처리하지 못한다.
텍스트는 다음 과정을 거쳐 숫자 텐서가 된다.
문장
→ 토큰
→ 토큰 ID
→ 토큰 임베딩
→ 위치 임베딩 추가
→ 트랜스포머 입력
토큰(token) 은 텍스트를 쪼갠 조각이다. 단어일 수도 있고, 단어 일부일 수도 있고, 문장부호일 수도 있다.
토큰화(tokenization) 는 문장을 토큰으로 쪼개는 과정이다.
예를 들어 “나는 학교에 간다.”는 다음처럼 쪼개질 수 있다.
나 / 는 / 학교 / 에 / 간 / 다 / .
실제 LLM에서는 단어 단위보다 더 세밀한 단어 조각 단위를 많이 쓴다.
어휘집(vocabulary) 은 모델이 아는 토큰 목록이다.
토큰 ID(token ID) 는 각 토큰에 붙인 숫자 번호다.
예를 들어 다음처럼 볼 수 있다.
"학교" → 1532
"간" → 482
"." → 13
외울 문장:
LLM은 문장을 토큰으로 쪼개고, 토큰을 번호로 바꾼 뒤, 그 번호를 벡터로 바꿔 처리한다.
임베딩(embedding) 은 토큰 ID를 의미를 담은 벡터로 바꾸는 과정이다.
토큰 ID 자체는 단순 번호다. 번호 1532가 482보다 크다고 해서 더 중요한 단어라는 뜻은 아니다. 그래서 번호를 그대로 쓰지 않고, 학습 가능한 벡터로 바꾼다.
임베딩 벡터(embedding vector) 는 토큰의 의미를 담는 숫자 묶음이다.
처음에는 임베딩 값이 무작위에 가깝다. 학습을 반복하면서 비슷한 문맥에 등장하는 토큰들은 비슷한 방향의 벡터가 되도록 조정된다.
예를 들어 “왕”, “여왕”, “남자”, “여자” 같은 단어들은 학습 후 의미상 관계가 벡터 공간 안에 어느 정도 반영될 수 있다.
외울 문장:
토큰 ID는 단순 번호이고, 임베딩은 그 번호를 의미 있는 벡터로 바꾼 것이다.
어텐션은 기본적으로 토큰들의 순서를 저절로 알지 못한다.
“개가 사람을 물었다”와 “사람이 개를 물었다”는 같은 단어를 쓰지만 순서가 다르기 때문에 의미가 다르다.
그래서 위치 임베딩(positional embedding) 을 더한다.
위치 임베딩은 “이 토큰이 몇 번째 위치에 있는가”를 알려주는 벡터다.
토큰 임베딩 + 위치 임베딩 = LLM의 실제 입력 벡터
외울 문장:
토큰 임베딩은 “무슨 토큰인가”를 담고, 위치 임베딩은 “몇 번째 토큰인가”를 담는다.
트랜스포머(transformer) 는 LLM의 핵심 구조다.
GPT 계열 모델은 보통 디코더 전용 트랜스포머(decoder-only transformer)를 사용한다.
트랜스포머 블록은 크게 두 부분이 반복된다.
셀프 어텐션
→ MLP
조금 더 구체적으로 보면 다음과 같다.
입력 벡터
→ 셀프 어텐션
→ 잔차 연결
→ 정규화
→ MLP
→ 잔차 연결
→ 정규화
→ 다음 블록
정규화(normalization) 는 값의 크기나 분포가 너무 흔들리지 않도록 안정화하는 처리다.
레이어 정규화(layer normalization) 는 트랜스포머에서 자주 쓰이는 정규화 방식이다.
외울 문장:
트랜스포머 블록은 토큰끼리 정보를 주고받는 어텐션과, 각 토큰을 따로 가공하는 MLP로 이루어진다.
어텐션(attention) 은 현재 토큰을 이해하기 위해 어떤 다른 토큰을 참고할지 정하는 구조다.
예를 들어 “그 동물은 작지만 빠르다. 그것은 토끼였다.”라는 문장에서 “그것”이 무엇인지 알려면 앞 문장의 “동물” 정보를 참고해야 한다.
어텐션은 다음 일을 한다.
현재 토큰이 무엇을 찾는지 만든다.
다른 토큰들이 어떤 정보를 갖고 있는지 만든다.
현재 토큰과 다른 토큰들의 관련도를 계산한다.
관련도가 큰 토큰의 정보를 더 많이 가져온다.
외울 문장:
어텐션은 현재 토큰이 참고해야 할 토큰을 찾고, 그 정보들을 비율대로 섞어 가져오는 구조다.
어텐션은 보통 세 가지 벡터를 사용한다.
쿼리(query) 는 현재 토큰이 찾고 싶은 정보다. 키(key) 는 각 토큰이 가진 검색용 특징이다. 값(value) 은 실제로 가져올 내용이다.
검색 엔진에 비유하면 쉽다.
Query = 검색어
Key = 문서의 검색용 색인
Value = 실제 문서 내용
어텐션의 흐름은 다음과 같다.
Query와 Key를 비교한다.
→ 관련도 점수를 만든다.
→ 점수를 비율로 바꾼다.
→ 그 비율만큼 Value를 섞는다.
→ 현재 토큰의 새 문맥 정보가 된다.
외울 문장:
Query는 찾는 것, Key는 비교 대상, Value는 실제 가져올 정보다.
대명사 예시보다 Query, Key, Value를 이해하기 쉬운 예시는 형용사가 명사를 꾸미는 경우다.
예를 들어 다음 문장을 보자.
A fluffy blue creature roamed the verdant forest.
여기서 creature는 그냥 “생물”이 아니라, 앞의 fluffy와 blue 정보를 받아서 “복슬복슬하고 파란 생물”이라는 문맥 벡터로 바뀌어야 한다.
이때 creature 위치의 Query는 다음과 같은 역할을 한다고 볼 수 있다.
Query(creature)
≈ “나를 설명하는 형용사가 앞에 있는가?”
각 토큰의 Key는 “내가 어떤 Query에 잘 걸리는가”를 나타낸다.
Key(fluffy)
≈ “나는 뒤의 명사를 설명하는 형용사다”
Key(blue)
≈ “나는 뒤의 명사를 설명하는 형용사다”
Key(roamed)
≈ “나는 동작을 나타내는 동사다”
Key(verdant)
≈ “나는 뒤의 forest를 설명하는 형용사다”
그러면 creature의 Query와 각 Key를 비교했을 때 다음처럼 되는 것이 이상적이다.
Query(creature) · Key(fluffy) → 큼
Query(creature) · Key(blue) → 큼
Query(creature) · Key(roamed) → 작음
Query(creature) · Key(forest) → 작음
중요한 점은 Key(fluffy)가 선택되었다고 해서 Key 자체를 가져오는 것이 아니라는 점이다.
실제로 가져오는 것은 같은 토큰에서 만들어진 Value(fluffy)다.
Value(fluffy)
≈ “상대 토큰의 벡터에 fluffy 의미를 추가하는 정보”
Value(blue)
≈ “상대 토큰의 벡터에 blue 의미를 추가하는 정보”
그래서 creature의 새 문맥 정보는 다음처럼 만들어진다.
새로 가져온 문맥 정보
=
0.45 × Value(fluffy)
+ 0.45 × Value(blue)
+ 0.02 × Value(roamed)
+ ...
이 정보가 기존 creature 벡터에 더해지면, creature는 문맥상 “복슬복슬하고 파란 생물”에 가까운 벡터가 된다.
외울 문장:
Query와 Key는 무엇을 참고할지 정하고, Value는 참고한 뒤 실제로 가져오는 정보다.
더 짧게 외우면:
Q와 K로 가중치를 만들고, 그 가중치로 V를 섞는다.
같은 토큰 벡터 x에서 Query, Key, Value가 모두 만들어진다.
하지만 서로 다른 학습 파라미터를 사용한다.
Q = xW_Q
K = xW_K
V = xW_V
W_Q, W_K, W_V가 다르기 때문에 같은 토큰에서 나온 Q, K, V도 보통 서로 다른 벡터다.
역할도 다르다.
Query = 내가 찾는 조건
Key = 내가 그 조건에 걸릴 수 있는 검색용 특징
Value = 선택되었을 때 실제로 전달할 정보
비유하면 다음과 같다.
Query = 검색어
Key = 검색 색인
Value = 검색 결과로 열어볼 실제 내용
따라서 Key와 Value는 같은 토큰에 대응되지만, 동일한 것이 아니다.
외울 문장:
Key는 찾기 위한 벡터이고, Value는 찾은 뒤 가져올 벡터다.
Q/K/V를 설명할 때는 벡터 크기와 파라미터 크기를 구분해야 한다.
멀티헤드 어텐션에서는 전체 임베딩 차원 d_model을 여러 head가 나눠서 본다.
예를 들어:
d_model = 768
head 수 = 12
d_head = 64
이면 각 head에서 한 토큰의 Q, K, V 벡터는 보통 64차원이다.
입력 토큰 벡터: 768차원
한 head의 Query: 64차원
한 head의 Key: 64차원
한 head의 Value: 64차원
이 의미에서는 Q/K/V 벡터가 원래 토큰 임베딩보다 작은 편이라고 볼 수 있다.
하지만 Q/K/V를 만드는 전체 파라미터까지 작다고 말하면 부정확하다.
구현에서는 보통 모든 head의 Q, K, V를 한 번에 만들기 때문이다.
W_Q: d_model × d_model
W_K: d_model × d_model
W_V: d_model × d_model
또는 한 행렬로 합쳐서 다음처럼 계산하기도 한다.
W_QKV: d_model × 3d_model
따라서 head 하나의 Q/K/V 벡터는 작지만, 모든 head를 합친 Q/K/V projection 파라미터는 꽤 크다.
기본 트랜스포머 블록에서 대략적인 파라미터 규모는 다음처럼 볼 수 있다.
멀티헤드 어텐션 projection:
W_Q + W_K + W_V + W_O
≈ 4 × d_model²
MLP/FFN:
보통 d_model → 4d_model → d_model 구조
≈ 8 × d_model²
즉 일반적인 구조에서는 MLP/FFN 쪽 파라미터가 어텐션 projection보다 더 많은 경우가 많다.
정리하면 다음과 같다.
head 하나의 Q/K/V 벡터:
작은 편이다.
모든 head를 합친 Q/K/V 파라미터:
무시할 만큼 작지 않다.
트랜스포머 블록 전체에서:
보통 MLP/FFN 파라미터가 attention projection보다 더 크다.
외울 문장:
Q/K/V 벡터는 head 단위로 작지만, Q/K/V를 만드는 전체 행렬은 모델의 중요한 파라미터 덩어리다.
어텐션 점수(attention score) 는 Query와 Key가 얼마나 잘 맞는지를 나타내는 값이다.
보통 Query와 Key의 내적을 사용한다. 내적은 두 벡터가 비슷한 방향이면 커지고, 관련이 적으면 작아진다고 볼 수 있다.
그런데 어텐션 점수는 음수일 수도 있고, 합이 1도 아니다. 그래서 이 점수를 비율처럼 바꿔야 한다.
소프트맥스(softmax) 는 여러 점수를 모두 양수로 만들고, 전체 합이 1이 되게 바꾸는 함수다.
소프트맥스를 통과한 결과가 어텐션 가중치(attention weight) 다.
어텐션 가중치는 “각 토큰을 얼마나 참고할 것인가”를 나타낸다.
외울 문장:
어텐션 점수는 관련도 원점수이고, 어텐션 가중치는 참고 비율이다.
셀프 어텐션(self-attention) 은 같은 입력 안의 토큰들이 서로를 참고하는 어텐션이다.
입력 문장 자체가 Query도 되고, Key도 되고, Value도 된다.
예를 들어 “인도 음식점”의 “인도”와 “인도 주행 금지”의 “인도”는 글자는 같지만 의미가 다르다.
처음 임베딩 단계에서는 같은 토큰이므로 비슷한 벡터일 수 있다. 하지만 셀프 어텐션을 지나면 주변 단어를 참고해서 서로 다른 문맥 벡터가 된다.
인도 + 음식점 문맥 → India 의미 쪽
인도 + 주행 금지 문맥 → sidewalk 의미 쪽
외울 문장:
셀프 어텐션은 같은 문장 안의 토큰들이 서로를 참고해 문맥이 반영된 벡터로 바뀌게 한다.
GPT식 LLM은 다음 토큰을 예측한다.
예를 들어 입력이 다음과 같다고 하자.
나는 오늘 학교에
모델은 다음 토큰으로 “갔다” 같은 단어를 예측해야 한다.
학습 중에는 전체 문장을 알고 있다.
나는 오늘 학교에 갔다
그런데 “학교에” 위치에서 “갔다”를 예측해야 하는데, 모델이 뒤쪽의 “갔다”를 미리 볼 수 있으면 답을 훔쳐보는 것이 된다.
그래서 마스킹(masking) 을 사용한다.
마스킹은 현재 위치보다 뒤에 있는 토큰을 보지 못하게 막는 처리다.
외울 문장:
마스킹은 다음 토큰 예측에서 미래 정답을 훔쳐보지 못하게 하는 가림막이다.
멀티헤드 어텐션(multi-head attention) 은 여러 개의 어텐션을 병렬로 실행하는 구조다.
하나의 어텐션 헤드는 한 가지 관점으로 문맥을 볼 수 있다.
예를 들어 어떤 헤드는 주어와 동사의 관계를 볼 수 있고, 어떤 헤드는 대명사가 무엇을 가리키는지 볼 수 있고, 어떤 헤드는 형용사가 어떤 명사를 꾸미는지 볼 수 있다.
어텐션 헤드(attention head) 는 어텐션을 수행하는 하나의 독립적인 관점이다.
외울 문장:
멀티헤드 어텐션은 같은 문장을 여러 관점으로 동시에 읽게 하는 구조다.
트랜스포머에는 어텐션만 있는 것이 아니다.
어텐션 다음에는 MLP(Multi-Layer Perceptron) 또는 FFN(Feed-Forward Network) 이 들어간다.
어텐션은 토큰끼리 정보를 주고받게 한다. MLP는 각 토큰 벡터를 따로 처리한다.
즉, 어텐션에서는 “토큰들이 서로 대화”한다. MLP에서는 “각 토큰이 자기 내부 정보를 다시 가공”한다.
MLP는 보통 다음처럼 동작한다고 볼 수 있다.
벡터를 더 큰 공간으로 펼친다.
→ 활성화 함수로 필요한 특징만 남긴다.
→ 다시 원래 크기의 벡터로 줄인다.
→ 기존 벡터에 더한다.
외울 문장:
어텐션은 문맥을 섞고, MLP는 각 토큰 벡터 안의 특징을 가공한다.
잔차 연결(residual connection) 은 어떤 블록의 출력만 쓰는 것이 아니라, 블록에 들어가기 전 입력을 다시 더하는 구조다.
예를 들어 다음처럼 볼 수 있다.
새 상태 = 이전 상태 + 새로 계산한 변화
이 구조가 중요한 이유는 이전 정보를 완전히 버리지 않고, 필요한 변화만 추가할 수 있기 때문이다.
LLM의 벡터는 여러 블록을 지나면서 계속 바뀐다. 이때 잔차 연결이 있으면 기존 의미를 보존하면서 문맥 정보를 조금씩 누적할 수 있다.
외울 문장:
잔차 연결은 이전 상태를 버리지 않고 새 변화만 덧붙이는 구조다.
사전학습(pretraining) 은 거대한 텍스트 데이터로 모델을 먼저 학습시키는 단계다.
GPT식 모델의 사전학습 목표는 다음 토큰 예측이다.
입력: 나는 오늘 학교에
정답: 갔다
이 방식은 사람이 따로 정답 라벨을 붙이지 않아도 된다. 텍스트 자체에서 다음 토큰이 정답이 되기 때문이다.
이를 자기지도학습(self-supervised learning) 이라고 볼 수 있다.
외울 문장:
LLM 사전학습은 텍스트 자체를 문제와 정답으로 만들어 다음 토큰을 맞히는 과정이다.
파인튜닝(fine-tuning) 은 이미 사전학습된 모델을 특정 목적에 맞게 추가 학습시키는 과정이다.
사전학습 모델은 기본적으로 문장을 이어 쓰는 능력을 가진다. 하지만 챗봇처럼 지시를 따르게 하려면 질문과 답변 형태의 데이터로 추가 학습을 시킨다.
예를 들어 다음과 같은 데이터가 사용될 수 있다.
질문: 이 문장을 영어로 번역해줘.
답변: ...
지시 튜닝(instruction fine-tuning) 은 사용자의 지시와 그에 맞는 응답을 학습시키는 방식이다.
외울 문장:
사전학습은 언어의 기본 패턴을 배우는 단계이고, 파인튜닝은 원하는 행동 방식을 맞추는 단계다.
LLM은 한 번에 전체 답변을 만드는 것이 아니다.
보통 다음 토큰을 하나 예측하고, 그 토큰을 입력 뒤에 붙이고, 다시 다음 토큰을 예측한다.
이런 방식을 자기회귀(autoregressive) 생성이라고 한다.
흐름은 다음과 같다.
프롬프트 입력
→ 다음 토큰 확률 계산
→ 토큰 하나 선택
→ 입력 뒤에 붙임
→ 다시 다음 토큰 확률 계산
→ 반복
로짓(logits) 은 소프트맥스 전에 나오는 원점수다. 샘플링(sampling) 은 확률 분포에서 실제 다음 토큰을 고르는 과정이다. 온도(temperature) 는 샘플링을 더 보수적으로 할지, 더 다양하게 할지 조절하는 값이다.
온도가 낮으면 가장 그럴듯한 토큰을 더 자주 고른다. 온도가 높으면 덜 뻔한 토큰도 고를 가능성이 커진다.
외울 문장:
LLM 생성은 다음 토큰 예측, 선택, 이어붙이기의 반복이다.
컨텍스트 길이(context length) 는 모델이 한 번에 볼 수 있는 최대 토큰 수다.
LLM은 무한히 긴 대화를 전부 기억하는 것이 아니다. 정해진 컨텍스트 길이 안에 들어온 토큰만 직접 참고할 수 있다.
대화가 너무 길어지면 앞부분 정보가 잘리거나 약해질 수 있다.
외울 문장:
컨텍스트 길이는 모델이 한 번에 펼쳐놓고 읽을 수 있는 작업 공간의 크기다.
신경망 일반 학습 흐름:
데이터 준비
→ 텐서로 변환
→ 순전파
→ 손실 계산
→ 역전파
→ 옵티마이저로 가중치 갱신
→ 반복
LLM 학습 흐름:
텍스트 준비
→ 토큰화
→ 토큰 ID 변환
→ 임베딩
→ 위치 정보 추가
→ 트랜스포머 블록 통과
→ 다음 토큰 예측
→ 손실 계산
→ 역전파
→ 옵티마이저로 가중치 갱신
→ 반복
LLM 생성 흐름:
프롬프트 입력
→ 토큰화
→ 임베딩
→ 트랜스포머 통과
→ 다음 토큰 확률 계산
→ 토큰 선택
→ 뒤에 붙임
→ 반복
- 텐서(tensor) 는 신경망 안에서 흐르는 현재 정보 상태다.
- 가중치(weight) 는 입력의 중요도를 정하는 학습 가능한 숫자다.
- 편향(bias) 은 뉴런이 얼마나 쉽게 반응할지 정하는 기준 조정값이다.
- 층(layer) 은 텐서를 한 단계 변환하는 계산 묶음이다.
- 활성화 함수(activation function) 는 신경망이 비선형 패턴을 표현하게 만든다.
- 순전파(forward propagation) 는 현재 가중치로 예측하는 과정이다.
- 손실 함수(loss function) 는 예측이 얼마나 틀렸는지 점수화한다.
- 역전파(backpropagation) 는 각 가중치의 책임과 수정 방향을 계산한다.
- 옵티마이저(optimizer) 는 기울기를 사용해 가중치를 실제로 갱신한다.
- 토큰(token) 은 LLM이 읽는 텍스트 조각이다.
- 임베딩(embedding) 은 토큰을 의미 벡터로 바꾸는 과정이다.
- 위치 임베딩(positional embedding) 은 토큰의 순서를 알려준다.
- 어텐션(attention) 은 관련 있는 토큰의 정보를 가져오는 구조다.
- Query, Key, Value 는 각각 찾는 조건, 검색용 특징, 실제 가져올 정보다.
- 셀프 어텐션(self-attention) 은 같은 문장 안의 토큰들이 서로를 참고하는 구조다.
- 마스킹(masking) 은 미래 토큰을 못 보게 막는다.
- MLP(Multi-Layer Perceptron) 는 각 토큰 벡터를 따로 가공한다.
- 잔차 연결(residual connection) 은 이전 상태에 새 변화를 더한다.
- 사전학습(pretraining) 은 대량 텍스트로 다음 토큰 예측을 배우는 단계다.
- 파인튜닝(fine-tuning) 은 특정 행동을 하도록 추가 학습시키는 단계다.
- 자기회귀(autoregressive) 생성은 다음 토큰을 하나씩 붙여 문장을 만드는 방식이다.
데이터는 텐서다. 신경망은 텐서를 변환하는 층들의 묶음이다. 가중치는 학습되는 규칙이다. 활성화 함수는 복잡한 표현을 가능하게 한다. 순전파는 예측이다. 손실은 틀린 정도다. 역전파는 책임 계산이다. 옵티마이저는 가중치 수정이다. LLM은 텍스트를 토큰 벡터로 바꾼다. 위치 임베딩은 순서를 넣는다. 어텐션은 필요한 문맥을 가져온다. Query는 찾는 조건, Key는 검색용 특징, Value는 실제 가져올 정보다. Q와 K로 가중치를 만들고, 그 가중치로 V를 섞는다. 마스킹은 미래 정답을 가린다. GPT는 다음 토큰 예측을 반복해 문장을 만든다.