LLM·트랜스포머

LLM / 24번째 글

샘플링 전략: Temperature, Top-k, Top-p와 그 대안

모델이 내놓은 확률 분포를 어떻게 데우고 어디서 자르는지를 한 편에 정리한다. Temperature·Top-k·Top-p의 원리와 한계, 그리고 min-p·Typical Sampling·Contrastive Search가 그 한계를 어디서 메우는지를 숫자로 따라간다.

PALDYN Team33 MIN READ

지난 글에서 LLM이 한 번에 붙들 수 있는 정보의 양, 곧 컨텍스트 윈도우의 구조와 한계를 봤다. 컨텍스트가 「무엇을 읽는가」였다면 이 글은 「읽고 나서 무엇을 내놓는가」다. 모델이 다음 토큰 하나를 고르는 그 자리에서 우리가 실제로 손댈 수 있는 값들, Temperature와 Top-k와 Top-p, 그리고 그 셋으로 안 되는 자리를 메우는 대안들을 한자리에 모은다.

이 값들을 이해하면 「왜 같은 프롬프트에 다른 답이 나오는가」를 정확히 설명할 수 있다. 더 쓸모 있는 것은 그 반대 방향이다 — 답이 매번 달라져서 곤란할 때, 반대로 답이 늘 똑같아서 곤란할 때 어느 손잡이를 어느 쪽으로 돌려야 하는지가 정해진다. 손잡이는 크게 두 종류다. 분포의 모양을 바꾸는 것과 분포의 일부를 아예 잘라 버리는 것이고, 실무에서 쓰는 설정은 대부분 이 둘의 조합이다. 뒤로 갈수록 나오는 대안들은 셋째 종류다 — 확률이 아닌 다른 잣대를 하나 더 들여온다.

한 스텝의 확률 분포

로짓과 소프트맥스

LLM의 텍스트 생성은 자동회귀(autoregressive) 과정이다. 지금까지의 토큰을 전부 컨텍스트로 받아 다음 토큰 하나를 정하고, 그 토큰을 컨텍스트 끝에 붙여 같은 일을 되풀이한다. 그러니 이 글이 다루는 모든 결정은 「토큰 하나를 고르는 한 번의 선택」이고, 문장 하나를 만드는 동안 그 선택이 수십에서 수백 번 일어난다.

한 번의 선택에서 모델이 내놓는 것은 어휘(vocabulary) 전체에 대한 로짓(logit) 벡터다. 로짓은 아직 확률이 아니라 크기 제한이 없는 점수이고, 어휘가 5만 개면 5만 차원짜리 실수 벡터다. 이것을 확률로 바꾸는 것이 소프트맥스(softmax)다.

P(토큰i)=ezi∑jezjP(\text{토큰}_i) = \frac{e^{z_i}}{\sum_{j} e^{z_j}}

지수를 씌워 전부 양수로 만들고 총합으로 나눠 합이 1이 되게 한다. 여기서 놓치기 쉬운 사실이 하나 있다. 모델이 하는 일은 여기서 끝난다. 모델은 분포를 내놓을 뿐 토큰을 고르지 않는다. 고르는 일은 모델 밖의 몇십 줄짜리 코드가 하고, 이 글에 나오는 파라미터는 전부 그 코드 안에 있다. 가중치를 한 개도 건드리지 않고 출력의 성격을 크게 바꿀 수 있는 이유가 이것이다.

다양성과 일관성

한 스텝의 선택이 다음 스텝의 입력이 되므로 선택의 효과는 누적된다. 그래서 여기서 근본적인 긴장이 생긴다. 다양성이 너무 낮으면 텍스트가 단조롭고 반복적이 되고, 너무 높으면 문맥과 상관없는 단어가 튀어나와 문장이 무너진다. 아래에 나오는 모든 전략은 이 하나의 트레이드오프를 서로 다른 방식으로 다룬다.

샘플링 전략 비교

표를 먼저 보면 지형이 잡힌다. 다양성과 일관성 두 축에서 양쪽 모두 최고인 칸이 없다. Greedy는 일관성이 매우 높은 대신 다양성이 없고, Random Sampling은 정반대다. 가운데의 Top-p·Typical·Contrastive는 어느 쪽도 극단으로 가지 않으면서 균형점을 조금씩 다른 자리에 놓는다. 고르는 문제가 아니라 태스크가 어느 쪽 실패를 더 못 견디는지를 정하는 문제다.

Greedy와 Random Sampling

Greedy Decoding은 매 스텝 확률이 가장 높은 토큰을 그냥 고른다. 구현이 가장 단순하고, 같은 입력에서 언제나 같은 출력이 나오는 결정적(deterministic) 특성을 가진다. 이 예측 가능성이 장점이다. 고객 지원 챗봇이나 사실 조회 시스템처럼 응답이 일관돼야 하는 곳에서는 매번 다른 답보다 늘 같은 답이 더 믿을 만하고, 테스트를 재현할 수 있다는 것도 실무에서는 큰 값이다.

단점은 반복 루프다. 더 나은 선택이 없는 자리에 들어서면 모델이 같은 구절을 계속 만들어 낸다. 「오늘 날씨가 맑다」로 시작해 「맑다 맑다 맑다」로 이어지는 현상이 전형적이다. 그리고 매 스텝의 최선만 고르므로 지역 최적해(local optimum), 곧 지금 자리에서는 좋아 보이지만 문장 전체로는 나쁜 경로에 갇힐 수 있다.

반대쪽 끝이 Random Sampling이다. 모델이 낸 확률 분포 그대로 뽑는다. 0.001% 확률의 토큰도 0.001%의 빈도로 선택된다. 이론상 가장 다양하지만 실제로는 문장이 무의미해지는데, 그 이유는 꼬리의 크기를 계산해 보면 분명하다. 어휘 5만 개 중 4만 개가 각각 0.001%씩만 갖고 있어도 그 합은 40%다. 한 스텝에서 열에 넷은 꼬리에서 뽑는다는 뜻이고, 백 토큰짜리 문단이라면 꼬리에 빠지지 않고 끝날 확률은 사실상 0이다. 그래서 순수한 Random Sampling은 실무에서 쓰지 않는다. Temperature를 낮춰 부드럽게 만들거나, 아래에서 볼 필터로 꼬리를 잘라 낸 뒤에 쓴다.

Temperature

로짓 나눗셈

Temperature(TT)는 소프트맥스에 넣기 전에 로짓을 TT 로 나눈다. 식에서 달라지는 것은 그 나눗셈 하나뿐이다.

PT(토큰i)=ezi/T∑jezj/TP_T(\text{토큰}_i) = \frac{e^{z_i / T}}{\sum_{j} e^{z_j / T}}

이름이 온도인 것은 비유가 아니라 유래다. 통계물리의 볼츠만 분포가 정확히 이 꼴이고 거기서 TT 자리에 실제 온도가 들어간다. 온도가 높으면 입자가 여러 상태에 흩어지고 낮으면 바닥 상태에 몰리는데, 확률 분포에서 벌어지는 일도 같다. 그래서 「분포를 데운다」는 표현이 그대로 통한다.

확률의 비

무엇이 정확히 달라지는지는 두 토큰의 확률 비를 보면 한 줄로 나온다. 분모의 총합이 약분되어 사라지기 때문이다.

PT(i)PT(j)=(P1(i)P1(j))1/T\frac{P_T(i)}{P_T(j)} = \left( \frac{P_1(i)}{P_1(j)} \right)^{1/T}

원래 비에 1/T1/T 제곱이 걸린 것이 전부다. 확률이 각각 60%와 20%인 두 토큰의 비는 3이다. T=2T = 2 로 올리면 이 비가 30.5≈1.733^{0.5} \approx 1.73 으로 줄고, T=0.5T = 0.5 로 내리면 32=93^{2} = 9 로 벌어진다. 두 토큰이 뽑힐 가능성의 격차가 줄거나 커질 뿐, 어느 쪽이 앞인지는 절대 뒤집히지 않는다. 온도로는 2등을 1등으로 만들 수 없고, 다만 2등이 실제로 뽑히는 빈도를 크게 올릴 수는 있다.

양 끝도 이 식에서 읽힌다. TT 가 0으로 가면 지수 1/T1/T 가 무한대로 가서 1등과 나머지의 비가 무한대가 되고, 결국 Greedy와 같아진다. 실제로는 0으로 나눌 수 없으므로 구현들은 T=0T = 0 을 나눗셈이 아니라 「Greedy로 처리하라」는 표시로 특수 취급한다. 반대로 TT 가 무한대로 가면 모든 비가 1이 되어 어휘 전체가 균등 분포, 곧 완전 무작위가 된다.

온도별 분포 모양

Temperature 효과: 확률 분포 변화

같은 로짓에 세 온도를 걸었을 때의 차이다. T=0.3T = 0.3 에서는 A가 78%를 차지하고 B·C·D가 15%·5%·2%로 밀린다. T=1.0T = 1.0 은 모델이 학습한 원본 분포 그대로이고 52%·28%·13%·7%다. T=2.0T = 2.0 에서는 A가 38%까지 내려오고 B가 30%로 따라붙어, 네 토큰 중 무엇이 나와도 이상하지 않은 상태가 된다.

직관적으로 온도는 모델의 「자신감」을 조절하는 슬라이더다. 낮은 온도는 확실한 것만 말하는 태도이고, 높은 온도는 조금 더 과감하게 말하는 태도다. 다만 슬라이더가 모든 토큰에 똑같이 작용하지는 않는다. 위 숫자에서 A는 78%에서 38%로 절반쯤 줄었는데 D는 2%에서 12%로 여섯 배가 됐다. 낮은 확률 쪽이 온도에 훨씬 민감하다. 앞의 비 공식에서 지수가 걸리는 것이 격차이고, 격차가 큰 쌍일수록 그 지수의 효과를 크게 받기 때문이다. 온도를 0.2만 올렸는데 출력의 성격이 확 달라졌다면 대개 꼬리 쪽에서 일어난 일이다.

온도의 한계

여기서 Temperature의 구조적 한계가 나온다. 온도는 꼬리를 자르지 않는다. TT 를 아무리 올려도 확률이 0이 되는 토큰은 하나도 없고, 오히려 올릴수록 꼬리가 살찐다. 앞에서 계산한 「꼬리 4만 개의 합 40%」가 T=1.5T = 1.5 에서는 더 커진다는 뜻이다.

창의적인 글을 원해 온도를 1.3까지 올렸더니 문장이 갑자기 무너지는 자리가 정확히 이것이다. 원한 것은 2등과 3등이 더 자주 나오는 것이었는데, 실제로 얻은 것은 5,000등도 가끔 나오는 상태다. 필요한 것은 다른 종류의 손잡이다 — 분포의 모양을 바꾸는 것이 아니라 후보의 명단 자체를 줄이는 것.

꼬리 자르기

Top-k

Top-k 샘플링은 확률 상위 kk 개만 남기고 나머지 토큰의 로짓을 −∞-\infty 로 만든다. 그 상태로 소프트맥스를 다시 통과시키면 잘린 토큰의 확률이 정확히 0이 되고, 남은 kk 개끼리 합이 1이 되도록 저절로 재정규화된다. k=50k = 50 이면 5만 개 어휘 중 50개만 후보이고, 나머지 49,950개는 아무리 운이 나빠도 뽑히지 않는다.

한계는 kk 가 고정이라는 데서 온다. 분포의 모양이 어떻든 후보 수가 늘 같다. 다음 토큰이 거의 확정적인 자리, 예컨대 상위 3개가 99%를 차지하는 자리에서도 50개를 유지하므로 나머지 47개가 남은 1%를 나눠 갖는데, 그 1%가 통째로 문맥에 안 맞는 토큰일 수 있다. 반대로 분포가 극도로 평평해서 상위 200개가 고만고만한 자리에서는 그중 50개만 남긴다. 확률이 사실상 같은 50번째와 51번째가 하나는 살고 하나는 잘리는 것이고, 아무 근거 없는 경계다.

Top-k vs Top-p 비교

그림의 예를 놓고 보자. 다음 토큰 후보가 the 40%, a 28%, an 18%, one 8%, this 4%, my 2%로 늘어서 있다. k=3k = 3 이면 the·a·an 셋만 남고 나머지 셋은 확률이 0이 된다.

Top-p

Holtzman 등(2019)이 제안한 Top-p 샘플링(nucleus sampling)은 이 경직성을 없앤다. 확률이 높은 순서대로 더해 나가다가 누적합이 pp 를 넘는 순간까지의 토큰 집합, 곧 「핵(nucleus)」에서만 뽑는다.

같은 분포에 p=0.85p = 0.85 를 걸어 보자. the까지 40%, a까지 68%, an까지 86%다. 세 번째에서 0.85를 넘었으므로 후보는 the·a·an 셋이다. 여기까지는 k=3k = 3 과 결과가 같지만, 분포가 달라지는 순간 갈린다. the가 90%로 치솟는 자리라면 Top-p는 첫 토큰에서 이미 기준을 넘으므로 후보를 하나로 줄이는데, Top-k는 그때도 셋을 남긴다. 반대로 상위 열 개가 8%씩 고르게 나뉜 자리라면 Top-p는 열한 번째까지 열어 주고 Top-k는 여전히 셋에서 자른다.

분포 형태에 적응한다는 것이 Top-p의 전부이고, 이 하나 때문에 주요 생성 API가 거의 다 이 손잡이를 열어 두게 됐다. 값의 의미도 읽기 쉽다. p=0.9p = 0.9 는 「모델이 확신하는 90%만큼만 쓰고 나머지 10%는 버린다」는 뜻이다.

min-p

2024년에 나온 min-p 샘플링은 기준을 또 한 번 바꾼다. 누적합이 아니라 최고 확률 대비 비율로 자른다. min_p = 0.05라면 1등 확률의 5%가 문턱이 되고, 그보다 낮은 토큰을 전부 버린다.

위의 여섯 토큰에 적용해 보자. 1등이 40%이므로 문턱은 2%이고, 꼴찌인 my까지 여섯 개가 모두 살아남는다. 모델이 확신하지 못하는 자리라 후보를 넓게 연 것이다. 반대로 1등이 90%인 자리라면 문턱이 4.5%로 올라가 4%짜리와 2%짜리가 잘려 나간다. Top-p가 「합이 얼마나 모였나」를 보는 반면 min-p는 「1등이 얼마나 확신하나」를 본다. 적응한다는 점은 같은데 무엇에 적응하는지가 다르다.

구현도 더 가볍다. 정렬해서 누적합을 따라갈 필요 없이 곱셈 한 번과 비교 한 번이면 끝난다. 오픈소스 추론 엔진들이 비교적 빨리 이 옵션을 받아들인 이유다.

필터의 적용 순서

실제 코드에서는 이 값들이 순서대로 적용된다.

import torch
import torch.nn.functional as F

def sample(logits, temperature=1.0, top_k=0, top_p=1.0):
    logits = logits / temperature                      # 1) 분포의 모양

    if top_k > 0:                                      # 2) 후보 수의 상한
        kth = torch.topk(logits, top_k).values[-1]
        logits[logits < kth] = float('-inf')

    if top_p < 1.0:                                    # 3) 누적 확률의 상한
        probs = F.softmax(logits, dim=-1)
        sorted_probs, idx = torch.sort(probs, descending=True)
        cumsum = torch.cumsum(sorted_probs, dim=-1)
        remove = cumsum - sorted_probs > top_p         # 넘기 직전까지는 남긴다
        logits[idx[remove]] = float('-inf')

    return torch.multinomial(F.softmax(logits, dim=-1), 1).item()

순서가 결과를 바꾼다. Temperature로 분포를 먼저 데운 뒤에 잘라야 「데운 상태의 누적 90%」가 되는데, 순서를 뒤집어 자르고 나서 데우면 경계가 온도와 무관하게 정해진다. 온도를 올릴수록 후보가 넓어지기를 기대했는데 후보 수가 꿈쩍도 하지 않는 상황이 그래서 생긴다. 대부분의 라이브러리가 위 순서로 고정해 두었으니 직접 구현할 때만 신경 쓰면 된다.

둘 이상을 함께 걸면 모든 조건을 통과한 토큰만 남는다. top_k=50과 top_p=0.9를 같이 주면 상위 50개로 한 번 자르고 그 안에서 누적 90%로 한 번 더 자르므로, 매 스텝 둘 중 더 엄격한 쪽이 실질적인 경계가 된다. 셋을 함께 쓰는 설정이 흔한 것은 각각의 극단적 동작을 서로가 막아 주기 때문이다.

확률 밖의 기준

지금까지 나온 방법은 모두 확률 순위 하나로 후보를 정했다. 다음 셋은 잣대를 하나 더 들여온다.

Typical Sampling

Meister 등(2023)이 제안한 Typical Sampling은 확률이 높은 토큰이 아니라 전형적인 토큰을 남긴다. 기준이 되는 것은 엔트로피(entropy)로, 분포가 얼마나 퍼져 있는지를 재는 값이자 「이 자리에서 모델이 평균적으로 얼마나 놀랄 것인가」에 해당한다. Typical Sampling은 각 토큰이 주는 놀라움이 그 평균에 가까운 것들만 후보로 남긴다.

직관은 사람의 말버릇에서 온다. 우리는 늘 가장 예측 가능한 단어를 고르지 않는다. 「오늘 날씨가 좋아서 ___」라는 자리에서 「산책을 했다」는 예측 가능하고 자연스럽지만, 「철학적 사색에 빠졌다」는 덜 예측적이면서도 여전히 말이 된다. 사람의 문장은 놀라움이 0인 단어와 지나치게 큰 단어 사이 어딘가에서 오간다.

그래서 Top-p와 결정적으로 다른 자리가 생긴다. 모델이 지나치게 확신하는 토큰, 즉 놀라움이 평균보다 훨씬 낮은 토큰도 후보에서 빠질 수 있다. 확률 순으로만 자르는 방법에서는 1등이 잘리는 일이 절대 일어나지 않는다. 전체 성능은 Top-p와 비슷한 수준이지만 자연스러운 일상 대화체를 만들 때 더 나은 경향이 있다고 보고되는 이유가 이 차이에 있다.

Su 등(2022)이 제안한 Contrastive Search는 기존 방법들의 가장 큰 약점인 퇴화(degeneration, 같은 구절이 계속 되풀이되는 현상)를 정면으로 겨냥한다. 토큰을 고를 때 모델의 확률과 이미 생성한 텍스트와의 유사도를 함께 본다.

score(v)=(1−α)⋅Pmodel(v∣context)−α⋅max⁡u∈Vpastsim(hv,hu)\text{score}(v) = (1 - \alpha) \cdot P_\text{model}(v \mid \text{context}) - \alpha \cdot \max_{u \in V_\text{past}} \text{sim}(h_v, h_u)

α\alpha 는 다양성 페널티의 강도(0~1)이고, sim은 은닉 상태(hidden state, 모델이 각 토큰 자리에서 들고 있는 내부 벡터) 사이의 코사인 유사도다. 이미 나온 토큰들과 표현 공간에서 가까운 후보일수록 감점을 받아 뽑히기 어려워진다.

앞의 방법들과 다른 점은 과거를 본다는 것이다. Temperature도 Top-k도 Top-p도 현재 스텝의 분포만 보므로, 같은 문맥이 다시 오면 같은 분포를 내고 같은 토큰을 다시 뽑는다. Greedy의 반복 루프가 구조적으로 생기는 이유가 이것이고, Contrastive Search는 그 고리를 점수 계산 안에서 끊는다.

Contrastive Search 개념도

그림처럼 한 스텝이 세 걸음으로 나뉜다. Top-k로 후보를 좁히고, 후보마다 은닉 상태를 이미 나온 토큰들과 견주고, 확률에서 그 유사도를 깎은 점수로 하나를 고른다. 첫 걸음이 Top-k인 것은 선택이 아니라 필수다 — 어휘 5만 개 전부에 대해 은닉 상태 유사도를 계산할 수는 없다. 곧 Contrastive Search는 Top-k 위에 얹히는 방법이고, 실무에서 자주 쓰는 값이 α=0.6\alpha = 0.6, k=4k = 4 인 것도 그래서다. 여기의 kk 는 앞에서 본 Top-k의 그 kk 와 같은 값이다. 대신 후보마다 은닉 상태를 꺼내 비교해야 하므로 한 스텝이 더 비싸다. 긴 텍스트에서 반복이 실제로 문제일 때 그 값을 치를 만하다.

Repetition Penalty

같은 목적을 훨씬 싸게 노리는 손잡이가 Repetition Penalty다. 이미 생성된 토큰의 로짓을 그만큼 깎아 다시 뽑힐 확률을 낮춘다. 1.0이면 적용하지 않는 것이고, 1.2~1.5 사이에서 억제가 적당히 강해진다. 긴 글을 뽑을 때 같은 문장이 되풀이되는 현상을 막는 가장 손쉬운 방법이다.

싼 이유는 보는 것이 다르기 때문이다. Contrastive Search가 표현 공간의 거리를 재는 반면 이쪽은 토큰 id가 같은지만 확인하므로 계산이 사실상 공짜다. 대신 무딘 도구다. 문자열이 같으면 무조건 깎으므로 반복하는 것이 맞는 토큰까지 함께 깎인다. 코드의 변수명, 인물의 이름, 한국어의 조사와 어미가 전부 여기에 걸린다. 값을 1.5까지 올려 놓고 코드를 생성시키면 같은 변수를 두 번째로 쓰지 못해 엉뚱한 이름이 튀어나오는 식이다. 코드나 표처럼 반복이 정상인 출력에서는 벌점 없음인 1.0에 가깝게 두는 편이 안전하고, 반복이 정말 문제라면 값을 올리기보다 Contrastive Search 쪽을 먼저 본다.

태스크별 설정

권장 조합

파라미터 선택은 결국 태스크의 성격이 정한다. 출발점으로 삼을 만한 조합은 이렇다.

태스크 Temperature Top-k Top-p 설명
코드 생성 0.1~0.3 10~20 0.9 정확성 최우선
사실 답변 0.1~0.5 - 0.9 환각 최소화
대화 응답 0.7~0.9 - 0.9~0.95 자연스러움
창의적 글쓰기 0.9~1.2 - 0.95 다양성 최대화
시 / 소설 1.0~1.5 - 0.95~1.0 독창성 허용
요약 0.3~0.5 - 0.9 일관성 유지

표를 관통하는 규칙은 하나다. 정답이 하나뿐인 태스크는 온도를 내리고, 정답이 여럿인 태스크는 온도를 올린다. 코드와 사실 답변은 틀린 답이 명확히 존재하므로 아래쪽이고, 시와 소설은 「다른 답」이 곧 값이므로 위쪽이다. 요약이 가운데인 것도 같은 이유다 — 표현은 여러 가지가 가능하지만 내용은 원문에 묶여 있다.

Top-p가 거의 모든 줄에서 0.9~0.95에 머무는 것도 눈여겨볼 만하다. 주 손잡이는 Temperature이고 Top-p는 안전망으로 두는 구성이다. 꼬리에서 사고가 나지 않게 막아 두고 다양성은 온도로 조절한다. 코드 생성에만 Top-k가 함께 적혀 있는 이유도 같은 맥락이다. 코드는 한 토큰만 틀려도 실행이 안 되므로 안전망을 이중으로 건다.

transformers 인자

Hugging Face transformers에서는 위 조합이 인자 이름 그대로 들어간다.

from transformers import pipeline

gen = pipeline("text-generation", model="gpt2")

# 사실 질문 — Greedy
gen("The capital of France is", do_sample=False, max_new_tokens=20)

# 창의적 글쓰기 — Temperature + Top-p
gen("Once upon a time", do_sample=True, temperature=0.9, top_p=0.95,
    max_new_tokens=100)

# 긴 글에서 반복 억제 — Contrastive Search
gen("The story begins", penalty_alpha=0.6, top_k=4, max_new_tokens=200)

do_sample=False가 Greedy이고, do_sample=True와 함께 temperature·top_k·top_p를 주면 그 조합이 적용된다. 앞에서 본 나머지 방법들도 min_p·typical_p·repetition_penalty처럼 각자의 이름으로 자리가 있다. Contrastive Search만 사정이 다르다 — penalty_alpha와 top_k로 켜는 것은 그대로지만, 최근 transformers는 이 인자를 deprecated로 표시하고 Hub에 올리는 커스텀 생성 방법 쪽으로 옮기는 중이다. 쓰기 전에 지금 버전의 문서를 확인한다.

가장 자주 밟는 함정은 첫 줄에 있다. do_sample=False인 채로 temperature를 넘기면 그 값은 쓰이지 않는다. 샘플링을 안 하는데 분포를 데워 봐야 argmax는 그대로이기 때문이다. transformers가 「이 플래그는 샘플링 기반 생성에서만 쓰인다」는 경고를 한 줄 찍어 주기는 하지만 다른 로그에 묻히기 쉽다. 온도를 바꿔 가며 실험하는데 출력이 한 글자도 안 변한다면 파라미터 값보다 이 스위치를 먼저 확인한다.

파라미터 과적합

마지막은 실무에서 가장 흔한 실수다. 눈앞의 프롬프트 하나에 맞춰 값을 과도하게 다듬으면 다른 프롬프트에서 오히려 나빠진다. 좋은 접근은 태스크 유형별 기본값을 먼저 정해 두고(코드는 0.2, 대화는 0.8 같은 식) 사용자 피드백에 따라 소폭만 조정하는 것이다. 규모가 되면 A/B 테스트로 실제 선호도를 재는 편이 감보다 낫다.

한 가지 더 보태자면, 값을 만지기 전에 프롬프트를 의심하는 편이 대개 이득이다. Temperature를 0.7에서 0.65로 내려서 얻는 것보다 지시문 한 줄을 명확히 해서 얻는 것이 크다. 그리고 비교할 때는 같은 설정으로 여러 번 뽑아 봐야 한다. 샘플링은 확률적이므로 한 번씩만 뽑아 비교하면 파라미터의 효과와 그날의 운을 구별할 수 없다.

한 스텝 결정의 한계

지역 최적해

여기까지 나온 모든 방법에는 공통점이 있다. 한 스텝 안에서 결정이 끝난다. 현재 분포를 데우거나 자르거나 다른 잣대로 다시 매긴 뒤 토큰 하나를 뽑고, 다음 스텝으로 넘어간다. 한 번 뽑은 토큰을 되돌리는 장치는 어디에도 없다.

그런데 지금 확률이 가장 높은 토큰이 문장 전체로 보면 나쁜 선택일 수 있다. 첫 자리에서 0.4짜리를 골랐더니 뒤가 전부 0.3대로 이어지는데, 0.35짜리를 골랐으면 뒤가 0.8씩 이어졌을 수도 있다. Greedy의 지역 최적해가 바로 이 상황이고, 온도를 올려 다른 토큰이 나올 여지를 만드는 것은 그 함정을 우연에 맡기는 해법이다. Contrastive Search는 과거를 보는 만큼 한 발 더 나갔지만, 그 역시 미래는 보지 않는다.

지역 최적해

탐색으로의 전환

그렇다면 후보 문장을 여러 개 동시에 들고 끝까지 가 본 뒤 고르면 어떨까. 그 순간 문제의 성격이 바뀐다. 「분포를 어떻게 자를까」가 아니라 「가능한 문장들의 공간을 어떻게 뒤질까」가 되고, 후보를 몇 개나 들고 갈지, 언제 가망 없는 가지를 버릴지, 길이가 다른 후보를 어떻게 공평하게 비교할지 같은 새 질문이 따라온다.

다음 글에서는 그 탐색 쪽 방법들을 다룬다. 매 스텝 여러 후보를 나란히 이어 가며 문장 전체의 점수로 최종 선택을 하는 방식이고, 이 글에서 본 필터들은 거기서도 후보를 좁히는 부품으로 그대로 다시 나온다. 무엇을 뽑을지 정하는 일과 어디를 뒤질지 정하는 일은 서로 다른 문제이고, 실제 시스템은 둘을 겹쳐 쓴다.


읽어주셔서 감사합니다. 😊

LATEST

LLM·트랜스포머의 최신 글

LLM·트랜스포머2026.08.14

작은 모델을 우리 일에 맞추는 법

파인튜닝이 실제로 고치는 것은 지식이 아니라 행동입니다. 데이터 몇 건이 필요한지, LoRA가 무엇을 바꾸는지, 학습 전에 무엇을 먼저 만들어야 하는지를 정리합니다.

15 MIN
LLM·트랜스포머2026.08.13

작은 모델로 내려도 되는지 판단하는 법

비용·지연·품질은 같은 방향으로 움직이지 않습니다. 폴백을 붙였을 때의 손익분기, 격차가 벌어지는 작업 유형, 그리고 내리기 전에 통과해야 할 네 관문을 정리합니다.

10 MIN
LLM·트랜스포머2026.08.13

작은 모델이 다시 쓸 만해진 이유

10억에서 100억 파라미터 사이의 모델이 다시 실무에 들어오고 있습니다. 무엇이 달라졌는지, 메모리는 어떻게 계산하는지, 무엇을 잘하고 무엇을 못하는지 정리합니다.

10 MIN