0Pricing
AI Prompt Engineering · 강의

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보다 간단합니다:

  1. 전체 어휘에 대해 softmax 확률을 계산합니다
  2. 확률에 따라 토큰을 내림차순으로 정렬합니다
  3. 확률이 가장 높은 k개의 토큰만 남기고 나머지는 모두 0으로 설정합니다
  4. 상위 k개 토큰의 확률을 다시 정규화하여 합이 1이 되게 합니다
  5. 다시 정규화된 분포에서 샘플링합니다
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 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. LLM에서 Temperature란 무엇인가요?
  2. Top-p 핵 샘플링
  3. Top-k 샘플링
  4. 사용 사례에 맞는 매개변수 선택
← AI Prompt Engineering(으)로 돌아가기