Field Log · Entry

신경망 학습 입문: Logit·Softmax·Loss·Gradient 한 번에 연결하기 (4/10)

입력에서 logit과 확률, loss, gradient를 거쳐 가중치를 갱신하는 신경망 학습 루프

오늘의 결론

  • neural network의 학습은 예측하고, 오차를 재고, 각 parameter의 책임을 계산해 조금 수정하는 반복입니다.
  • logit은 정규화 전 점수이고 softmax는 이를 확률 분포로 바꿉니다.
  • cross entropy는 정답 token에 낮은 확률을 줄수록 큰 손실을 부과합니다.
  • inference에서는 보통 parameter를 바꾸지 않습니다. prompt나 RAG context를 넣는 것은 학습과 다릅니다.

LLM 설명에서 “모델이 다음 token을 학습한다”는 말을 자주 듣습니다. 하지만 그 사이에는 logit, probability, loss, gradient, optimizer라는 단계가 있습니다. 이 연결을 모르면 temperature와 softmax를 혼동하거나, RAG를 모델 재학습으로 오해하기 쉽습니다.

신경망의 forward와 backward 학습 루프

그림 1. forward pass가 예측과 loss를 만들고, backward pass가 각 parameter의 gradient를 계산한 뒤 optimizer가 값을 갱신한다.


Parameter와 activation부터 구분하기

모델 안의 숫자를 모두 “가중치”라고 부르면 헷갈립니다.

이름의미요청 사이에 유지되는가
parameter학습으로 바뀌는 weight와 bias모델 checkpoint에 저장됨
activation입력이 layer를 통과하며 만들어진 중간값해당 forward pass 동안 생성됨
hyperparameterlearning rate, batch size 같은 학습 설정사람이 정하거나 탐색
gradientloss가 parameter 변화에 얼마나 민감한지backward pass에서 계산

LLM의 “7B”는 보통 학습 가능한 parameter가 약 70억 개라는 뜻입니다. context token 수나 KV cache 크기를 뜻하지 않습니다.

Forward pass: 입력에서 점수까지

아주 단순한 다음-token 문제를 생각해 봅시다.

입력: "서울은 대한민국의"
후보 vocabulary: [수도, 도시, 강]
정답: 수도

모델이 여러 layer를 통과한 뒤 후보마다 다음과 같은 score를 냈다고 합시다.

logits = [2.0, 1.0, 0.1]
           수도  도시   강

이 숫자가 logit입니다. 확률이 아니므로 합이 1일 필요도 없고 음수도 가능합니다. logit은 후보 간 상대 선호를 표현하는 정규화 전 점수입니다.

Softmax: logit을 확률로

softmax는 각 logit에 지수 함수를 적용하고 전체 합으로 나눕니다.

softmax(z_i) = exp(z_i) / Σ_j exp(z_j)

위 logit을 계산하면 대략 다음과 같습니다.

exp(2.0) = 7.39
exp(1.0) = 2.72
exp(0.1) = 1.11
합       = 11.22

P(수도) ≈ 7.39 / 11.22 = 0.659
P(도시) ≈ 2.72 / 11.22 = 0.242
P(강)   ≈ 1.11 / 11.22 = 0.099

모든 확률은 0과 1 사이이고 합이 1입니다. 가장 큰 logit의 순위는 softmax 후에도 유지됩니다.

수치 안정성을 위해 실제 구현은 가장 큰 logit을 먼저 빼고 계산합니다. 모든 logit에 같은 상수를 빼도 softmax 결과는 변하지 않습니다.

Cross entropy: 정답에 준 확률을 채점하기

정답이 “수도”라면 one-hot target은 [1, 0, 0]입니다. 단일 정답 분류의 cross entropy는 사실상 정답에 준 확률의 음의 로그입니다.

loss = -log P(정답)
     = -log(0.659)
     ≈ 0.417

정답 확률이 0.9라면 loss는 약 0.105로 작고, 0.01이라면 약 4.605로 큽니다. 모델이 정답에 자신이 없을수록 더 큰 벌점을 받습니다.

PyTorch의 CrossEntropyLoss는 보통 raw logits를 직접 받습니다. 내부에서 log-softmax와 negative log likelihood를 결합하므로, 모델 출력에 softmax를 먼저 적용해 다시 넣으면 의도와 달라질 수 있습니다.

Backpropagation: 누구를 얼마나 고칠지 계산하기

loss가 0.417이라는 사실만으로는 수십억 parameter 중 무엇을 바꿔야 할지 모릅니다. backpropagation은 chain rule을 이용해 각 parameter에 대한 미분값을 효율적으로 계산합니다.

∂loss / ∂weight

이 값이 gradient입니다.

  • gradient가 양수: weight를 조금 줄이면 loss가 내려가는 방향일 수 있음
  • gradient가 음수: weight를 조금 늘리면 loss가 내려가는 방향일 수 있음
  • 절댓값이 큼: 현재 loss가 그 parameter 변화에 민감함

“gradient가 parameter의 중요도”라고 단순화하면 안 됩니다. 특정 batch와 현재 parameter 상태에서 loss가 어떻게 변하는지를 나타내는 국소적인 기울기입니다.

Optimizer: gradient를 사용해 parameter 갱신하기

가장 단순한 gradient descent 갱신은 다음과 같습니다.

weight_new = weight_old - learning_rate × gradient

learning rate가 너무 크면 최솟값을 지나치며 발산할 수 있고, 너무 작으면 학습이 매우 느립니다. 실제 LLM 학습은 Adam 계열 optimizer, learning-rate schedule, gradient clipping, mixed precision 등 많은 장치를 사용하지만 기본 루프는 같습니다.

optimizer.zero_grad()  # 이전 step의 누적 gradient 초기화
logits = model(input_ids)
loss = criterion(logits, target_ids)
loss.backward()        # gradient 계산
optimizer.step()       # parameter 갱신

PyTorch에서는 gradient가 기본적으로 누적되므로 매 step마다 초기화하는 이유도 여기서 나옵니다.

Batch, step, epoch

학습 로그를 읽을 때 자주 섞이는 단어입니다.

용어
sample학습 예시 하나
batch한 번의 forward/backward에 함께 처리하는 sample 묶음
step보통 optimizer가 한 번 parameter를 갱신한 시점
epoch전체 학습 데이터를 한 바퀴 사용한 것

LLM pretraining은 데이터가 매우 커서 “몇 epoch”보다 token 수와 training step으로 규모를 표현하는 경우가 많습니다. gradient accumulation은 작은 micro-batch 여러 개의 gradient를 모아 큰 effective batch처럼 갱신하는 기법입니다.

LLM의 정답은 한 칸 옆 token이다

causal language model은 한 sequence에서 여러 next-token 문제를 동시에 만듭니다.

입력: [나는] [RAG를] [만든다] [EOS]
정답: [RAG를] [만든다] [EOS] [다음 없음]

각 위치는 왼쪽 context를 보고 바로 다음 token을 맞힙니다. sequence가 길이 4라면 여러 위치의 cross-entropy를 평균하거나 합산해 loss를 만듭니다. 이 구조 덕분에 label을 사람이 일일이 붙이지 않아도 원문 text 자체에서 대규모 학습 예시를 만들 수 있습니다.

Pretraining, fine-tuning, inference

단계parameter 변경입력목적
pretraining대규모 text일반적인 언어 패턴과 지식 학습
supervised fine-tuninginstruction-response 예시지시 수행 방식 학습
preference/alignment 학습선호·보상 신호응답 행동 조정
inference아니오prompt와 context현재 parameter로 출력 생성
RAG보통 아니오prompt + 검색 문서외부 근거를 요청 시점에 제공

RAG가 “모델에게 새 지식을 학습시킨다”는 표현은 기술적으로 부정확합니다. 일반적인 RAG는 parameter를 갱신하지 않고, inference 입력에 필요한 지식을 붙입니다. 세션이 끝나면 모델이 그 문서를 영구적으로 기억하는 것도 아닙니다.

Embedding 모델은 어떻게 학습하는가

앞 글의 semantic embedding도 학습 결과입니다. 단순화하면 관련 query-document 쌍은 가까워지고, 무관한 쌍은 멀어지도록 contrastive loss를 사용할 수 있습니다.

positive: ("E17 원인은?", "E17은 냉각수 유량 저하 알람이다")
negative: ("E17 원인은?", "사과 보관 온도는 1~4도다")

학습 batch 안의 다른 문서를 negative로 쓰거나, 검색하기 어려운 hard negative를 별도로 고릅니다. 어떤 negative를 보여 주느냐가 검색 모델의 경계를 만듭니다. 그래서 범용 embedding이 내 도메인의 비슷한 장비 코드들을 잘 구분하지 못할 수 있습니다.

Inference에서 temperature는 학습률이 아니다

둘 다 숫자라 자주 혼동하지만 완전히 다릅니다.

  • learning rate: 학습 중 gradient로 parameter를 얼마나 바꿀지
  • temperature: inference 중 logit 분포를 얼마나 평평하거나 뾰족하게 만들지

temperature를 바꿔도 모델 parameter는 변하지 않습니다. 다음 글들에서 generation sampling을 별도로 계산합니다.

10분 실습: 세 logit의 loss 비교하기

import torch
from torch.nn.functional import cross_entropy

target = torch.tensor([0])  # 정답 index: 수도

good = torch.tensor([[2.0, 1.0, 0.1]])
bad = torch.tensor([[0.1, 2.0, 1.0]])

print(torch.softmax(good, dim=-1))
print("good loss:", cross_entropy(good, target).item())
print("bad loss :", cross_entropy(bad, target).item())

정답 index의 logit을 하나씩 올리거나 내리면서 probability와 loss가 어떻게 변하는지 보세요. 코드보다 “정답 확률이 낮으면 음의 로그가 커진다”는 관계를 이해하는 것이 목표입니다.

자주 하는 오해

“softmax 출력이 모델의 객관적 신뢰도다.”

softmax는 주어진 후보 vocabulary 안의 상대 분포입니다. 모델이 calibration되어 있다는 보장은 없고, 사실성 확률도 아닙니다.

“loss가 낮으면 제품 답변이 무조건 좋다.”

training loss는 학습 목표에 대한 평균입니다. retrieval 정확성, instruction following, factuality 같은 제품 지표와 별도 평가가 필요합니다.

“prompt를 바꾸는 것도 모델 학습이다.”

prompt engineering은 입력을 바꾸는 것이고 parameter update가 없습니다. in-context learning이라는 이름에도 일반적으로 gradient 학습은 일어나지 않습니다.

스스로 확인하기

  1. logit과 probability의 차이는 무엇인가?
  2. 정답 token 확률이 낮아질수록 cross-entropy loss는 왜 커지는가?
  3. backpropagation과 optimizer가 각각 하는 일은 무엇인가?
  4. RAG 문서를 prompt에 넣는 것과 fine-tuning의 차이는 무엇인가?

다음 글에서는 이 학습 목표가 만드는 핵심 모델인 다음-token 언어모델을 살펴봅니다.

참고자료