Top-k 샘플링
가장 확률이 높은 k개 토큰으로 선택지를 제한하고 출력 다양성에 미치는 영향을 살펴봅니다.
Top-k 샘플링은(는) CoddyKit의 무료 AI Prompt Engineering 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 AI Prompt Engineering 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. AI Prompt Engineering 강의에는 총 4개의 강의가 포함되어 있습니다.
상위 k 샘플링이란?
상위 k 샘플링은 각 단계에서 확률이 가장 높은 k개의 토큰만 샘플링하도록 모델을 제한합니다. 상위 k에 포함되지 않는 모든 토큰에는 확률 0이 할당되므로 선택할 수 없습니다.
k=1은 탐욕적 디코딩입니다(확률이 가장 높은 토큰 하나만 사용). k=50은 일반적인 창작 범위입니다. k가 어휘 크기와 같으면 제한 없는 샘플링과 같습니다.
상위 k 알고리즘
알고리즘은 상위 p보다 간단합니다:
- 전체 어휘에 대해 softmax 확률을 계산합니다
- 확률에 따라 토큰을 내림차순으로 정렬합니다
- 확률이 가장 높은 k개의 토큰만 남기고 나머지는 모두 0으로 설정합니다
- 상위 k개 토큰의 확률을 다시 정규화하여 합이 1이 되게 합니다
- 다시 정규화된 분포에서 샘플링합니다
import numpy as np
def softmax(logits, temperature=1.0):
scaled = logits / temperature
e = np.exp(scaled - np.max(scaled))
return e / e.sum()
def top_k_sample(logits, k=50, temperature=1.0):
probs = softmax(logits, temperature)
# Find top-k indices
top_k_indices = np.argsort(probs)[::-1][:k]
top_k_probs = probs[top_k_indices]
# Renormalize
top_k_probs = top_k_probs / top_k_probs.sum()
# Sample
chosen = np.random.choice(top_k_indices, p=top_k_probs)
return chosen
# With a 10-token vocabulary:
logits = np.random.randn(10)
print('Chosen token:', top_k_sample(logits, k=3))k=1: 탐욕적 디코딩
k=1이면 확률이 가장 높은 토큰 하나만 후보 집합에 포함됩니다. 크기가 1인 집합에서 샘플링하면 결정론적으로 이루어지므로 모델은 항상 해당 토큰을 선택합니다. 이는 탐욕적 디코딩(온도=0)과 동일합니다.
logits = np.array([3.0, 2.0, 1.0, 0.5, -1.0])
# k=1: greedy
top_1 = top_k_sample(logits, k=1)
print(f'k=1 always picks: {np.argmax(logits)}') # index 0, the highest logit
print(f'top_k_sample result: {top_1}') # always 0
# Multiple runs
for _ in range(5):
print(top_k_sample(logits, k=1), end=' ')
# Output: 0 0 0 0 0 — perfectly deterministic일반적인 창작 범위: k=50
k=50은 창작 텍스트 생성에서 일반적으로 사용되는 기본값입니다. 각 단계에서 50개의 토큰을 탐색할 수 있게 하면서 모델이 확신이 매우 낮은 토큰을 선택하지 못하게 합니다.
어휘가 50,000개의 토큰으로 구성되어 있다면 k=50은 각 단계에서 모델이 토큰의 상위 0.1%만 고려한다는 뜻입니다. 이는 상당한 제한으로, 어휘의 대부분이 제외됩니다.
import openai
client = openai.OpenAI(api_key='sk-...')
# Note: OpenAI API does not expose top_k directly in chat completions.
# Top-k is primarily a parameter in Hugging Face Transformers and Anthropic's API.
# Hugging Face example:
from transformers import pipeline
generator = pipeline('text-generation', model='gpt2')
output = generator(
'Once upon a time',
max_new_tokens=100,
do_sample=True,
top_k=50,
temperature=1.0
)
print(output[0]['generated_text'])Anthropic의 Claude API에서 상위 k
Anthropic의 Claude API는 top_k를 직접 매개변수로 제공합니다. 이를 통해 고정된 어휘 잘라내기가 Claude의 출력에 미치는 영향을 쉽게 실험할 수 있습니다.
import anthropic
claude = anthropic.Anthropic(api_key='sk-ant-...')
# top_k limits the number of tokens considered
message = claude.messages.create(
model='claude-opus-4-5',
max_tokens=256,
temperature=1.0,
top_k=50, # sample from top 50 most probable tokens
messages=[{
'role': 'user',
'content': 'Write a short poem about debugging code.'
}]
)
print(message.content[0].text)고정 k 문제
상위 k의 근본적인 한계는 해당 단계에서 모델의 확신 정도와 관계없이 k가 고정된다는 점입니다.
모델이 매우 확신하는 경우(한 토큰의 확률이 95%인 경우)에도 k=50이면 관련성이 거의 없는 토큰 49개가 포함됩니다. 모델이 매우 불확실한 경우(토큰 50개의 확률이 각각 약 2%인 경우)에는 k=50이 실제로 적절할 수 있습니다.
문제는 문맥에 따라 k=50이 지나치게 제한적일 수도 있고 지나치게 허용적일 수도 있다는 점입니다. 상위 p는 동적인 핵 크기를 사용하여 이 문제를 해결합니다.
# Illustrating the fixed-k problem
logits_confident = np.array([5.0] + [0.1] * 9) # model is very sure
logits_uncertain = np.array([1.0] * 10) # model has no idea
probs_conf = softmax(logits_confident)
probs_unc = softmax(logits_uncertain)
print('Confident — top 3 tokens cover:', np.sort(probs_conf)[::-1][:3].sum().round(3))
# ~0.998 — k=50 is extremely wasteful, includes near-zero probability tokens
print('Uncertain — top 3 tokens cover:', np.sort(probs_unc)[::-1][:3].sum().round(3))
# ~0.30 — k=50 may actually be needed to cover a reasonable nucleus분포 꼬리에서의 상위 k
상위 k와 상위 p의 차이는 분포의 꼬리에서 가장 크게 나타납니다:
- 상위 k=50에서는 50번째 토큰의 확률이 0.001%일 수도 있습니다(가능성이 극히 낮지만 여전히 후보 집합에 포함됨)
- 상위 p=0.9에서는 90% 핵의 범위를 벗어나는 모든 토큰이 제외됩니다 — 상위 k에 포함될 토큰도 마찬가지입니다
상위 p는 순위에서의 위치가 아니라 확률을 기준으로 가능성이 낮은 토큰을 제외하므로 꼬리의 동작을 더 원칙적으로 처리합니다.
# Tail behavior comparison
import numpy as np
# Highly skewed distribution (one dominant token)
skewed_logits = np.array([4.0, 2.0, 1.5, 1.0, 0.5,
0.1, 0.0, -0.1, -0.5, -1.0])
probs = softmax(skewed_logits)
print('Probability of tokens 6-9 (tail):')
for i in range(6, 10):
print(f' Token {i}: {probs[i]:.4%}')
# These tokens are very unlikely but are included in top-k=10
# Top-p=0.9 would exclude them entirely상위 k와 상위 p 결합
일부 구현에서는 상위 k와 상위 p를 모두 적용합니다. 먼저 상위 k로 잘라 낸 다음, 해당 집합 안에서 상위 p 핵 샘플링을 적용합니다. 이렇게 하면 어휘 크기에 상한을 설정하는 동시에(상위 k) 확률 기반 필터링도 적용할 수 있습니다(상위 p).
def top_k_top_p_sample(logits, k=50, p=0.9, temperature=1.0):
probs = softmax(logits, temperature)
# First apply top-k
top_k_indices = np.argsort(probs)[::-1][:k]
top_k_probs = probs[top_k_indices]
# Then apply top-p within top-k
sorted_k = np.sort(top_k_probs)[::-1]
cumulative = np.cumsum(sorted_k)
nucleus_size = np.searchsorted(cumulative, p) + 1
final_indices = top_k_indices[:nucleus_size]
final_probs = top_k_probs[:nucleus_size]
final_probs = final_probs / final_probs.sum()
return np.random.choice(final_indices, p=final_probs)상위 k가 상위 p보다 선호되는 경우
상위 p가 이론적으로 더 뛰어나지만, 일부 상황에서는 상위 k가 선호됩니다:
- 제한된 어휘 과제: 모델이 고정된 집합에서만 출력해야 할 때(예: 선다형 A/B/C/D) 작은 상위 k(4)를 사용하면 이를 직접 강제할 수 있습니다
- 재현성: 상위 k의 동작은 ‘항상 정확히 50개의 토큰을 고려한다’고 설명하기 쉬워 추론하기가 더 쉽습니다
- 하드웨어 최적화 구현: 일부 추론 엔진은 상위 p보다 상위 k를 더 효율적으로 구현합니다
# Constrained output with top-k=4
# For a multiple choice task (A, B, C, D)
# If A/B/C/D tokens have indices 32, 33, 34, 35
# top-k=4 with those as the top-4 logits forces selection from those 4 only
multiple_choice_prompt = (
'Answer with only A, B, C, or D.\n'
'What is the capital of France?\n'
'A) Berlin\n'
'B) Paris\n'
'C) Rome\n'
'D) Madrid\n'
'Answer:'
)
# With temperature=0, top_k=1: always picks the highest logit token실용적인 상위 k 지침
상위 k를 사용할 경우와 선택할 값:
- k=1: 탐욕적 방식 / 사실 기반 과제
- k=5–20: 집중형 창작 과제, 최소한의 변동성
- k=40–100: 대부분의 언어 모델에서 일반적인 창작 범위
- k=500 이상: 매우 개방적인 탐색(거의 필요하지 않으며 대신 상위 p를 사용하십시오)
대부분의 최신 LLM API에서는 상위 p가 선호되는 매개변수입니다. 어휘에 엄격한 상한이 필요하거나 API가 상위 p는 제공하지 않고 상위 k만 제공할 때 상위 k를 사용하십시오.
TOP_K_GUIDELINES = {
'factual_qa': 1, # greedy
'code_generation': 10, # near-greedy, correct syntax
'summarization': 20, # slightly varied but focused
'chat': 50, # natural variation
'creative_writing': 100, # wider vocabulary exploration
'poetry': 200, # unusual word choices encouraged
}
def call_with_top_k(task, prompt, model='claude-opus-4-5'):
k = TOP_K_GUIDELINES.get(task, 50)
claude = anthropic.Anthropic(api_key='sk-ant-...')
return claude.messages.create(
model=model,
max_tokens=512,
top_k=k,
messages=[{'role': 'user', 'content': prompt}]
)상위 k와 온도를 함께 사용하기
상위 k와 온도는 순차적으로 적용됩니다. 먼저 온도가 로짓 분포의 형태를 다시 조정하고, 그다음 상위 k가 이를 확률이 가장 높은 k개의 토큰으로 잘라 냅니다. 두 가지를 함께 사용하는 방식은 허깅 페이스 트랜스포머 파이프라인에서 일반적입니다.
일반적인 조합은 온도=0.9(중간 정도의 다양성) + 상위 k=50(어휘를 엄격하게 제한)입니다. 이렇게 하면 높은 온도만 사용할 때의 평탄함과 꼬리 샘플링 문제를 모두 피할 수 있습니다.
from transformers import pipeline
generator = pipeline('text-generation', model='gpt2')
# Combined top-k + temperature
output = generator(
'The future of AI is',
max_new_tokens=80,
do_sample=True,
top_k=50,
temperature=0.9
)
print(output[0]['generated_text'])
# Compare: top-k=1 (greedy)
greedy_output = generator(
'The future of AI is',
max_new_tokens=80,
do_sample=False # greedy, equivalent to top_k=1
)
print(greedy_output[0]['generated_text'])이해도 확인
상위 k 샘플링에서 k=1로 설정하면 모델은 어떤 동작을 보입니까?
복습: 상위 k 샘플링
상위 k 샘플링은 샘플링하기 전에 어휘를 확률이 가장 높은 k개의 토큰으로 잘라 냅니다:
- k=1: 탐욕적 디코딩 — 결정적이며 항상 최상위 토큰을 선택합니다
- k=50: 일반적인 창작 범위 — 다양성과 일관성의 균형
- 핵심 한계: 모델의 확신도와 관계없이 k가 고정됩니다 — 너무 많이 허용하거나 너무 엄격하게 제한할 수 있습니다
- 상위 p와 비교: 상위 p의 동적 누클리어스는 확신도에 맞춰 조정되지만 상위 k는 그렇지 않습니다
어휘를 엄격하게 제한해야 할 때 상위 k를 사용하십시오. 대부분의 실서비스 애플리케이션에서는 상위 p를 우선하십시오. 다음 수업에서는 특정 사용 사례에 맞는 매개변수 선택을 다룹니다.
자주 묻는 질문
“Top-k 샘플링” 강의는 무료인가요?
네 — “Top-k 샘플링” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 AI Prompt Engineering 강의 전체를 잠금 해제할 수 있습니다. AI Prompt Engineering 강의에는 총 4개의 강의가 포함되어 있습니다.
“Top-k 샘플링”에서 뭘 배우나요?
가장 확률이 높은 k개 토큰으로 선택지를 제한하고 출력 다양성에 미치는 영향을 살펴봅니다. 브라우저에서 직접 실행하는 실습 코드로 AI Prompt Engineering을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
AI Prompt Engineering을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 AI Prompt Engineering은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.
“Top-k 샘플링” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 AI Prompt Engineering 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 AI Prompt Engineering 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.