참조 사이트
- SKALA 4기 - LLM과 Transformer 아키텍처 (SK AX SKALA)
- The Curious Case of Neural Text Degeneration (Holtzman et al., 2019)
- Hugging Face - How to generate text: using different decoding strategies
개요

지난 [LLM Pipeline 5]에서는 어텐션을 거친 텐서들이 깊은 신경망 레이어를 지나며 안정적으로 순전파되도록 지탱해 주는 잔차 연결(Residual Connection)과 정규화(RMSNorm), 그리고 비선형 사실적 지식을 저장하고 변환하는 SwiGLU FFN 기반의 트랜스포머 블록 연산을 살펴보았다.
트랜스포머 블록의 최종 레이어를 거쳐 출력된 결과물은 각 토큰의 고차원 맥락 정보가 최종 반영된 [Batch, Time, Dimension] (이하 [B, T, D]) 형태의 3차원 은닉 상태(Hidden State) 텐서이다. 하지만 이 은닉 상태는 모델 내부에서만 인지되는 추상적인 실수 공간의 연속적인 밀집 좌표일 뿐이며, 사람이 읽을 수 있는 문자가 아니다.
이번 글에서는 트랜스포머 파이프라인의 최종 완결 단계로서, 이 고차원 은닉 상태를 모델의 어휘 사전 크기만큼의 점수로 확장하는 언어 모델 헤드(LM Head)와 로짓(Logits)의 생성 메커니즘, 이를 수학적 확률 분포로 치환하는 Softmax 연산, 그리고 최종 다음 토큰의 무작위성과 창의성을 미세하게 제어하는 4대 디코딩 및 샘플링 전략(Greedy, Temperature, Top-k, Top-p)을 정리한다.
💡 용어 사전: 언어 모델 헤드(LM Head / Language Model Head)
트랜스포머의 최종 블록을 빠져나온 최종 은닉 상태(Hidden State)의 각 토큰 벡터(D차원)를 모델이 인지하는 전체 어휘 사전 크기(V차원)의 로짓 벡터로 투영하는 최상단 출력 선형 레이어(Linear Projection Layer)이다.
1. 언어 모델 헤드(LM Head)와 로짓(Logits)의 본질

Transformer Block의 최종 출력은 각 위치의 문맥 정보를 담은 D차원 은닉상태다. 하지만 언어 모델의 최종 목적은 이 은닉상태 자체를 출력하는 것이 아니라, 어휘 사전 V개의 토큰 중 다음에 올 토큰을 예측하는 것이다. 따라서 마지막 은닉상태를 어휘 크기V에 대응하는 점수 벡터로 변환하는 별도의 선형층이 필요하며, 이를 LM Head라고 한다.
① 은닉 상태에서 어휘 확률 공간으로의 투영
최종 레이어를 거친 문맥 은닉 텐서 h_T ∈ ℝ^(B × T × D)는 디코딩 첫 단계로 언어 모델 헤드를 통과한다. LM Head는 최종 은닉 상태의 각 토큰 표현을 Vocabulary 전체에 대한 로짓 벡터로 투영한다.
- 입력: D차원의 은닉 벡터 (LLaMA-3 기준 D = 4,096)
- 출력 가중치 행렬 (W_LM): D차원을 V차원으로 변환하는 행렬 W_LM ∈ ℝ^(D × V) (LLaMA-3-8B 기준 V = 128,256)
- 결과물 (z): 어휘 사전에 있는 V개의 단어 각각에 할당되는 정규화되지 않은 점수표 z ∈ ℝ^(B × T × V)
💡 용어 사전: 로짓(Logits, z)
신경망 최상단의 선형 레이어가 활성화 함수(Softmax)를 거치기 직전 출력하는 정규화되지 않은 원시 실수 점수 벡터이다. 음의 무한대(-∞)부터 양의 무한대(+∞)까지의 범위를 갖는다.
② 가중치 공유(Weight Tying) 기법
입력 토큰 ID를 D차원 벡터로 투영하는 첫 번째 임베딩 행렬 W_E ∈ ℝ^(V × D)와 최종 출력을 담당하는 LM Head 행렬 W_LM ∈ ℝ^(D × V)는 서로 전치(Transpose) 관계에 가깝다. 이 점에 착안해 두 행렬의 가중치를 하나로 공유하는 방식을 가중치 공유(Weight Tying, W_LM = W_Eᵀ)라고 한다.
가중치를 공유하면 학습할 파라미터 수를 대폭 줄이고 입력 임베딩과 출력 표현 사이의 일관성을 유도할 수 있다. 다만 모델 아키텍처의 설계 목적에 따라 가중치를 별도로 학습하기도 한다.
- 가중치 공유 적용 모델: GPT-2, Gemma 등 (파라미터 절약 및 경량화 이점)
- 가중치 미공유 모델: LLaMA-3 8B 등 (W_LM ≠ W_Eᵀ, 독자적인 파라미터 학습을 통한 어휘 표현력 확보)
③ 왜 [B, T, V] 중에서 마지막 위치 [B, 1, V]만 생성 시 사용하는가?
트랜스포머의 최종 블록 연산을 마치면 시퀀스 내의 모든 단어 개수(T)만큼 생성된 은닉 상태 벡터가 나오고, LM Head를 통과하면 [B, T, V] 크기의 로짓 텐서가 생성된다.
하지만 새로운 단어를 하나씩 예측해서 붙여 나가는 추론(Inference) 단계에서 필요한 것은 오직 '가장 마지막(맨 오른쪽에 추가된) 토큰'이 예측한 다음 단어의 로짓뿐이다. 따라서 실제 생성 과정에서는 logits[:, -1, :] 과 같이 마지막 시점 인덱스만 슬라이싱하여 [B, 1, V] 차원으로 줄인 뒤 디코딩 연산을 진행한다.
이처럼 매 생성 단계마다 이전 토큰들의 Key와 Value를 다시 계산하는 비용을 줄이기 위해, 이미 계산된 K/V를 저장하고 다음 단계에서 재사용하는 KV Cache가 널리 사용된다.
2. Softmax: 원시 점수에서 확률 분포로의 수학적 변환

LM Head가 연산해 낸 로짓 z는 각 토큰 후보의 상대적인 선호도를 나타내는 실수 점수다. 하지만 로짓은 확률이 아니므로 그대로는 확률적 샘플링에 사용할 수 없다. Softmax는 이 로짓을 각 토큰의 확률로 변환하고, 모든 토큰 후보의 확률 합이 정확히 1.0(100%)이 되도록 정규화한다.
- Softmax 수식:
- Softmax(z_i) = e^(z_i) / ( Σ e^(z_j) ) (j = 1 부터 V까지)
- 자연상수 지수 변환 (e^(z_i)): 모든 원시 로짓 값에 자연상수 거듭제곱을 취함으로써 음수 영역의 수치들을 모두 0보다 큰 양수로 치환한다. 동시에 지수함수의 특성 덕분에 원본 점수의 작은 차이가 명확한 확률 격차로 증폭된다.
- 분모 정규화 (Σ e^(z_j)): 사전 내 V개의 모든 토큰 후보가 가진 지수값들의 총합으로 각 토큰 지수값을 나누어, 모든 확률의 합산이 정확히 1.0이 되도록 맞춘다.
이 Softmax 처리를 마친 뒤, 모델은 비로소 "다음 자리에 오기 가장 적합한 단어 후보들"의 명확한 확률 지도를 얻게 된다.
3. 디코딩 전략 1: 탐욕 탐색(Greedy Search)과 문맥 퇴행 한계

Softmax를 거치면 각 토큰에 대한 확률 분포가 만들어진다. 하지만 확률 분포를 얻었다고 해서 다음 토큰이 자동으로 결정되는 것은 아니다. 예를 들어 가장 높은 확률의 토큰을 항상 선택할 수도 있고, 일정 범위의 후보 중에서 확률적으로 선택할 수도 있다. 따라서 확률 분포에서 실제로 다음 토큰을 선택하는 방법을 결정하는 과정이 필요하며, 이를 디코딩(Decoding)이라고 한다.
Greedy Search, Temperature Sampling, Top-k Sampling, Top-p Sampling 등은 모두 이 단계에서 사용되는 전략이다.
가장 직관적인 단어 선택법은 매 추론 시점마다 확률 분포 내 가장 높은 확률(1위)을 기록한 단어 하나만을 확정적으로 고르는 탐욕 탐색(Greedy Search)이다.
- 동작 원리: next_token = argmax( Softmax(z) )
- 이점: 알고리즘 계산량이 낮고, 고정된 입력 텍스트에 대해 항상 동일한 출력 결과가 보장되는 결정론적(Deterministic) 작동 방식을 가진다. 정밀한 수치 연산, 정형화된 코드 생성, 고정된 정답이 정해진 태스크에 적합하다.
- 한계: 매 단계에서 국소적으로 가장 확률이 높은 단어만 이어 붙이게 되면 전체적인 문맥 흐름이 극도로 단순해진다. 최악의 경우 동일 단어나 문장이 반복되는 무한 루프(Repetition Loop)와 문맥 퇴행(Text Degeneration) 현상이 발생한다.
따라서 일정한 무작위성과 어휘 다양성을 확보하여 자연스러운 문장을 출력하기 위해 확률 가중 기반의 확률적 샘플링(Stochastic Sampling) 기법들이 사용된다.
4. 디코딩 전략 2: 템퍼러처(Temperature) 조절

템퍼러처(Temperature, T)는 로짓 z를 Softmax 연산에 대입하기 직전 임의의 스케일링 상수 T로 나누어 주어, 확률 분포의 첨도(Peakiness)와 다양성을 동적으로 미세 조절하는 온도계 역할을 한다.
- Temperature 적용 수식:
- Probability_i = e^(z_i / T) / ( Σ e^(z_j / T) )
① T = 1.0 (기본값)
- 모델이 학습 시 저장해 둔 고유한 로짓 값 크기 비율 그대로 Softmax 확률을 매핑한다.
② T < 1.0 (낮은 온도, Cold)
- 로짓 스케일을 1.0 미만의 양수 상수로 나누면 원래 가지고 있던 로짓들 간의 격차가 기하급수적으로 증폭된다.
- 확률 분포가 가장 우세한 상위 소수 단어로 극단적으로 쏠리며 뾰족해진다(Sharpening).
- 효과: 모델의 오답 가능성이나 엉뚱한 어휘 선정을 줄여 확률이 높은 후보에 선택이 집중되므로 보다 보수적이고 일관된 출력을 유도한다.. (논리적 분석, 사실 기반 질의응답)
③ T > 1.0 (높은 온도, Hot)
- 모든 점수의 편차를 줄여 평탄하게 다듬어 준다.
- 어휘 간의 상대적인 격차가 좁아지며 확률 분포가 평평해지므로(Flattening), 일반적인 상황에서 순위가 낮았던 어휘 후보들이 선택받을 수 있는 다양성을 확보하게 된다.
- 효과: 창의적인 작문이나 아이디어 도출에 유리하지만, 온도가 과도하게 높을 경우 비논리적인 단어들이 샘플링되어 문맥이 깨지는 현상이 발생한다.
5. 디코딩 전략 3: Top-k 샘플링 (고정 개수 순위 필터링)

Temperature를 높여 다양한 어휘 선택을 허용했을 때 발생하는 문제는, 어휘 사전 극하단 꼬리 부분(Long Tail)에 분포된 지극히 낮은 확률의 부적절한 단어 후보가 우연히 샘플링되어 문맥이 끊기는 오류이다. 이를 방지하기 위해 후보군을 사전에 거르는 Top-k 샘플링을 적용한다.
- 동작 원리: 확률 값이 가장 높은 상위 k개의 토큰 후보군만을 순위 기준으로 선별하고, 나머지 k+1위 이하의 하위 단어들의 로짓은 -∞ 처리하여 후보에서 완전히 차단한다.
- 한계 (고정 k의 경직성):
- 확신도가 매우 높은 상황: "대한민국의 수도는 [서울(99%), 부산(0.5%), 대전(0.1%)...]"처럼 특정 단어의 확신이 지배적인 상황에서도 고정된 k = 50을 적용하면, 하위 49개의 무의미한 단어들까지 억지로 후보군에 남아 오작동을 유발할 수 있다.
- 확신도가 넓게 분산된 상황: "오늘 저녁 메뉴는 [피자(5%), 파스타(4%), 일식(3%)...]"처럼 선택지가 수십 가지 이상으로 고르게 분산된 상황에서도 고정된 k = 50을 적용하면, 그 뒤에 오는 의미 있는 후보 단어들이 순위 기준에 의해 잘려 나간다.
6. 디코딩 전략 4: Top-p (Nucleus) 샘플링 (누적 확률 동적 필터링)
고정된 개수 k를 취하던 한계를 극복하기 위해, Holtzman et al. (2019)은 확률의 누적 합산값(p)을 기준으로 후보군의 범위를 동적으로 결정하는 Top-p(Nucleus) 샘플링을 제안했다.
- 동작 원리: 확률을 내림차순으로 정렬하여 p_1 ≥ p_2 ≥ ... ≥ p_V 인 상태에서, 누적 확률의 합이 지정값 p 이상이 되는 최소한의 후보 집합만을 가변적으로 선택한다.
- 수식:
- k_effective = min { k' : Σ p_i ≥ p } (i = 1 부터 k'까지)
이렇게 선별된 최소 집합에 포함되는 단어들만 남기고, 나머지 토큰은 로짓 값을 -∞로 가려 소프트맥스 가중치 계산에서 제외한다.
💡 용어 사전: Top-p (Nucleus) 샘플링
사전에 고정된 개수를 자르는 대신, 확률이 높은 순서대로 단어를 누적해 그 합이 p(예: 0.9)에 도달할 때까지만 후보군으로 포함하는 동적 필터링 기법이다. 문맥의 확신도에 따라 후보군 크기가 자동으로 늘어나거나 줄어든다.
💡 Top-p의 동적 필터링 작동 방식
- 분포가 뾰족하고 확신이 뚜렷할 때: 1위 단어 단독으로 93%의 확률을 확보했다면, p = 0.9 기준선은 1위 단어 하나만으로 즉시 만족되므로 샘플링 후보가 단 1개로 자동 축소되어 오답을 차단한다.
- 분포가 완만하고 선택지가 고를 때: 여러 단어가 고르게 확률을 나누어 가졌다면, 누적 합 90%를 채울 때까지 후보군 리스트가 자동으로 수십 개로 유연하게 확장되어 풍부한 표현력을 보장한다.
따라서 대부분의 언어 모델 생성 환경에서는 Temperature와 Top-p 두 변수를 결합하여 모델의 텍스트 톤앤매너를 제어한다.
💡 [심화 분석] 반복 억제와 최신 샘플링 기법
- 반복 억제기법(Repetition Penalty / Frequency Penalty): 이미 생성된 토큰들의 로짓 값을 의도적으로 감산하여 동일한 문구가 무한 반복 생성되는 현상을 억제한다.
- Min-p 샘플링: 가장 높은 확률을 기록한 1위 토큰의 확률에 고정 비율(예: 0.05)을 곱한 값을 기준으로, 이 기준보다 작은 확률 후보를 필터링하는 최신 기법이다. Top-p보다 문맥의 확신도에 따라 후보 영역을 직관적으로 제어하여 최신 오픈소스 환경에서 활발히 채택되고 있다.
7. 4가지 디코딩 및 샘플링 제어 방법 핵심 비교

| 디코딩 방식 | 핵심 메커니즘 | 주요 파라미터 | 주요 특징 및 장점 | 추천 활용 분야 |
| Greedy Search | 최고 확률 토큰 1개 선택 | 없음 (T = 0 대응) | 결정론적이며 항상 동일한 출력 보장 | 코드 생성, 정밀 계산, 사실 기반 질의응답 |
| Temperature | 로짓 스케일링을 통한 분포 평탄도 조절 | T | 생성 다양성과 보수성 전반을 제어 | 챗봇 대화, 일반 자연어 작문 |
| Top-k Sampling | 상위 k개 후보만 유지하는 고정 필터 | k (보통 40 ~ 50) | 낮은 확률의 하위 노이즈 어휘 진입 차단 | 문맥 안정성이 요구되는 범용 생성 |
| Top-p (Nucleus) | 누적 확률 합 p 기준 동적 가변 필터 | p (보통 0.9 ~ 0.95) | 문맥 확신도에 따라 후보군 크기 자율 조절 | 자연스러운 문장 생성 및 창의적 텍스트 |
8. PyTorch로 구현하는 종합 디코딩 파이프라인
앞서 설명한 템퍼러처(Temperature), Top-k 필터링, Top-p (Nucleus) 필터링이 결합되어 최종 [Batch, 1]의 다음 토큰 인덱스를 추출하는 파이토치 함수는 다음과 같다.
import torch
import torch.nn.functional as F
def sample_next_token(logits, temperature=1.0, top_k=0, top_p=0.0):
"""
Args:
logits (torch.Tensor): LM Head를 거쳐 출력된 [B, V] 차원의 원시 로짓 점수 텐서
temperature (float): 확률 분포를 스케일링하는 온도 변수 (0.0 이면 Greedy)
top_k (int): 상위 k개의 후보 토큰 고정 필터링 크기 (0 이면 비활성화)
top_p (float): 누적 확률 p 기준 가변 필터링 임계치 (0.0 이면 비활성화)
"""
if temperature < 0.0:
raise ValueError("Temperature must be non-negative.")
if temperature == 0.0:
# 1. 탐욕 탐색 (Greedy Search): 가장 점수가 높은 토큰 인덱스 직접 반환
return torch.argmax(logits, dim=-1, keepdim=True)
# Temperature 스케일링 적용
logits = logits / temperature
vocab_size = logits.size(-1)
if top_k > vocab_size:
top_k = vocab_size
next_tokens = []
# 각 배치 데이터별 독립 필터링 루프
for i in range(logits.size(0)):
each_logits = logits[i].clone() # [V]
# 2. Top-k 필터링 적용
if top_k > 0:
top_val, _ = torch.topk(each_logits, top_k)
# k번째 경계값보다 점수가 낮은 하위 토큰들은 -inf 처리
indices_to_remove = each_logits < top_val[-1]
each_logits[indices_to_remove] = -float('Inf')
# 3. Top-p (Nucleus) 필터링 적용
if top_p > 0.0 and top_p < 1.0:
sorted_logits, sorted_indices = torch.sort(each_logits, descending=True)
sorted_probs = F.softmax(sorted_logits, dim=-1)
cumulative_probs = torch.cumsum(sorted_probs, dim=-1)
# 누적 확률 임계값을 초과하는 인덱스 마스킹
sorted_indices_to_remove = cumulative_probs > top_p
# 1위 토큰은 마스킹 대상에서 제외
sorted_indices_to_remove[..., 1:] = sorted_indices_to_remove[..., :-1].clone()
sorted_indices_to_remove[..., 0] = False
indices_to_remove = sorted_indices[sorted_indices_to_remove]
each_logits[indices_to_remove] = -float('Inf')
# 4. 필터링된 확률 재구성 및 다항 분포 샘플링
probs = F.softmax(each_logits, dim=-1)
next_token = torch.multinomial(probs, num_samples=1)
next_tokens.append(next_token)
return torch.stack(next_tokens).view(-1, 1)
# 실행 및 검증
if __name__ == "__main__":
torch.manual_seed(42)
B, V = 2, 10
dummy_logits = torch.randn(B, V) * 5.0
print("입력 로짓 텐서 [B, V]:\n", dummy_logits)
print()
# 1. Greedy Search
greedy_out = sample_next_token(dummy_logits, temperature=0.0)
print("1. Greedy Search 결과:\n", greedy_out)
# 2. Temperature 0.7
temp_out = sample_next_token(dummy_logits, temperature=0.7)
print("2. Temperature (0.7) 결과:\n", temp_out)
# 3. Top-k(5) + Top-p(0.9) 복합 샘플링
topk_topp_out = sample_next_token(dummy_logits, temperature=0.8, top_k=5, top_p=0.9)
print("3. Top-k(5) + Top-p(0.9) 결과:\n", topk_topp_out)
9. 데이터 파이프라인 텐서 차원(Tensor Shape) 변화 최종 요약

텍스트 원본에서 시작하여 모델 내부 연산을 거쳐 최종 단어를 추출하기까지, 6대 파이프라인에 따른 데이터 텐서 차원의 전체 흐름은 다음과 같다.
- [B, T]: 1편 토크나이저를 통해 텍스트가 정수 토큰 시퀀스로 변환된다.
- [B, T]: 2편 데이터로더에서 슬라이딩 윈도우와 스트라이드를 거쳐 학습용 미니배치로 분절된다.
- [B, T, D]: 3편 토큰 임베딩과 위치 인코딩(RoPE)을 거쳐 고차원 의미 좌표와 어순 정보가 결합된 3차원 실수 밀집 텐서로 확장된다.
- [B, T, D]: 4편 셀프 어텐션과 멀티헤드 어텐션을 통과하며 토큰 간의 상호 문맥 정보가 동적으로 결합된다.
- [B, T, D]: 5편 잔차 연결, RMSNorm 정규화, SwiGLU FFN을 거치며 사실적 지식이 비선형으로 가공되고 심층 레이어를 안정적으로 순전파한다.
- [B, T, V]: 6편 LM Head 선형 투영을 통해 전체 어휘 사전 크기만큼의 로짓 점수로 팽창한다.
- [B, 1, V]: 마지막 시점
[:, -1, :]을 슬라이싱한 뒤 Softmax 및 Temperature, Top-k, Top-p 필터링을 거쳐 다음 단어의 확률 분포를 확정한다. - [B, 1]: 확률적 샘플링을 통해 최종 1개의 다음 토큰 ID를 결정하고, 디토크나이저(Detokenizer)를 통해 다시 사람이 읽을 수 있는 텍스트로 환원된다.
요약 및 [LLM Pipeline 시리즈] 완결
- 어휘 공간 투영: 트랜스포머 레이어가 완성한 은닉 벡터
[B, T, D]는 LM Head의 선형 투영을 거쳐 전체 어휘 사전 크기의 점수인[B, T, V]로짓으로 확장된다. - 디코딩 제어: 단조로운 반복과 문맥 퇴행을 방지하기 위해 Temperature(분포 첨도 제어), Top-k(하위 노이즈 차단), Top-p(누적합 동적 가변 필터)를 결합하여 최적의 다음 단어
[B, 1]을 선별한다. - End-to-End 파이프라인 완결: 생성된 단어 ID는 다시 입력 시퀀스 끝에 추가되어 다음 단어를 예측하는 자기회귀(Auto-regressive) 루프를 반복하며 최종 문장을 완성한다.
이로써 [0편: 전체 아키텍처 조감도]부터 출발하여 [1편: 토크나이저와 BPE], [2편: 데이터로더], [3편: 토큰 임베딩과 RoPE], [4편: 셀프 어텐션], [5편: 트랜스포머 블록], 그리고 마지막 [6편: LM Head와 디코딩 전략]까지 이어지는 LLM의 End-to-End 데이터 파이프라인 전체 과정이 완결되었다.
학습한 내용을 바탕으로 LLM 기반으로 글을 작성했기에, 군데군데 설명이 빈약하거나, 흐름상 빠진 부분도 있다.
계속 공부하면서 내용을 보충해 나갈 예정이다.
틀린 부분이 있거나 인용한 부분에 대해 문제가 있을 시
댓글로 알려주시면 감사하겠습니다.