Temperature와 Top-P로 LLM의 창의성 조절하기

AI가 다음 단어를 선택하는 확률 분포와 Temperature, Top-P(핵 샘플링) 파라미터로 환각을 줄이고 창의성을 조절하는 방법을 다룹니다.

무료 공개 · 최근 수정

온도를 0으로 설정하면 왜 항상 똑같은 대답이 나올까?

로컬 개발 환경에서는 백 번을 테스트해도 완벽하게 통과하던 결제 승인 데이터 파싱 코드가, 프로덕션 서버에 배포하자마자 간헐적으로 JSONDecodeError를 뿜으며 장애를 일으키는 경우가 있습니다. 원인을 추적해 보면 LLM API 호출 함수에 아무 생각 없이 방치해 둔 기본값 temperature: 1.0 때문인 경우가 대부분입니다. 99번은 깔끔한 JSON을 내놓다가도 딱 한 번 엉뚱한 마크다운 백틱이나 사족을 덧붙여 백엔드 파서를 깨뜨린 것입니다.

동일한 질문을 여러 번 입력했을 때 매번 토씨 하나 틀리지 않고 똑같은 답변을 얻으려면 생성 파라미터인 온도를 0으로 설정하면 됩니다. 반대로 온도를 1.2나 1.5처럼 높게 설정하면 기상천외하고 독창적인 비유를 쏟아내거나 때로는 전혀 맥락에 맞지 않는 횡설수설을 시작합니다. 개발자가 흔히 '창의성 조절기'라고 부르는 이 수치들은 사실 지능의 깊이를 조절하는 것이 아니라, 다음 등장할 후보 단어들을 주사위 던지듯 뽑아내는 확률 통계적 추첨 규칙을 조절하는 매개변수입니다.

대규모 언어 모델은 질문에 대한 '정답 사실'을 검색하여 출력하는 백과사전이 아닙니다. 지금까지 주어졌거나 직전까지 생성된 모든 텍스트 문맥을 기반으로, 그 뒤에 올 가장 그럴듯한 다음 단어의 조건부 확률 분포(Conditional Probability Distribution)를 예측하는 거대한 확률 계산 엔진입니다. 모델이 계산해 낸 수만 개의 후보 단어 확률 중에서 최종 단어 하나를 확정 짓는 과정을 샘플링(Sampling)이라고 하며, 이 샘플링의 성격을 결정짓는 두 축이 바로 Temperature와 Top-P입니다.

로짓과 소프트맥스, 그리고 Temperature의 수학적 원리

신경망 모델의 마지막 선형 변환 계층을 통과하면 전체 어휘 사전에 등록된 모든 단어 토큰에 대해 정규화되지 않은 실수 점수인 로짓(Logit, z)이 부여됩니다. 예를 들어 "대한민국의 수도는"이라는 문장 뒤에 올 후보로 '서울'에는 14.2, '세종'에는 9.8, '부산'에는 8.1, '사과'에는 -3.5 같은 점수가 매겨지는 식입니다. 이 로짓 점수들을 모두 더해 1이 되는 확률 값으로 변환하기 위해 소프트맥스(Softmax) 함수를 적용하며, 이때 로짓 점수를 나누어 주는 분모 상수가 온도(Temperature, T)입니다.

P(x_i) = exp(z_i / T) / ∑ exp(z_j / T)

이 수식에서 분모에 들어가는 T 값이 0에 가까워질수록 원래 점수가 가장 높았던 1등 토큰과 2등 이하 토큰들 사이의 격차가 기하급수적으로 벌어집니다. 반대로 T 값이 1보다 커질수록 지수 함수의 밑이 평탄화되면서 점수 간의 격차가 급격히 줄어듭니다.

  • T = 0 (또는 극단적 수렴): 가장 높은 로짓을 기록한 단 하나의 토큰에 100%의 확률이 쏠립니다. 이를 수학적으로 탐욕적 탐색(Greedy Search, Argmax)이라 부르며, 확률적 무작위성이 0이 되어 대부분 단일한 결정론적 출력이 보장됩니다. 다만 GPU 병렬 연산의 미세한 부동소수점 오차로 드물게 다른 토큰이 선택될 수 있으므로, 엄격한 재현성이 필요할 때는 API의 seed 파라미터를 함께 고정합니다.
  • T = 0.7 (기본 권장 영역): 1등 단어가 여전히 매우 높은 선택 확률을 가지지만, 문맥상 어울리는 23등의 자연스러운 동의어들에게도 1020% 수준의 선별 기회가 분배되어 문장이 한결 부드러워집니다.
  • T >= 1.5 (고온도 과열 영역): 모든 단어의 확률이 거의 균등해집니다. 어휘 사전 구석에 있는 희귀 단어나 부적절한 단어까지 높은 확률로 추첨 바구니에 들어가므로 문법이 붕괴하고 심각한 환각(Hallucination)이 유발됩니다.

신경망 로짓이 온도 조정을 거쳐 핵 샘플링으로 필터링되어 최종 토큰을 도출하는 3단계 흐름

그림: 로짓 출력에서 온도 스케일링과 Top-P 컷오프로 이어지는 샘플링 흐름

위 그림은 원본 로짓 벡터가 온도에 의해 스케일링된 후, 소프트맥스를 거쳐 누적 확률 컷오프로 정제되는 전체 파이프라인을 보여 줍니다.

꼬리 확률을 안전하게 잘라내는 Top-P 핵 샘플링

온도만 올려서 문장의 다양성을 확보하려 들면 말도 안 되는 오답 토큰이 당첨될 위험이 상존하므로, 후보군의 누적 확률을 기준으로 유효 범위를 제한하는 핵 샘플링(Nucleus Sampling; Top-P)을 함께 사용합니다. 2020년 아리 홀츠먼(Ari Holtzman) 등이 제안한 Top-P는 확률이 높은 순서대로 후보 단어들을 정렬한 뒤, 그 확률의 누적합이 지정한 임계값 P(예: 0.9 또는 90%)에 도달할 때까지만 후보군에 포함하고 나머지 긴 꼬리(Long Tail)의 희박한 단어들을 완전히 버리는 기법입니다.

예를 들어 "오늘 날씨가 정말"이라는 문장 뒤에 '좋다(50%)', '맑다(30%)', '덥다(12%)', '춥다(6%)', '컴퓨터(0.1%)' 순으로 확률이 산출되었다고 가정해 봅니다.

  1. P = 0.8로 설정한 경우: '좋다'(0.5) + '맑다'(0.3) = 0.8이므로 오직 이 두 단어 중에서만 다음 단어를 추첨합니다. 12%의 '덥다'조차 후보에서 제외됩니다.
  2. P = 0.95로 설정한 경우: '좋다'(0.5) + '맑다'(0.3) + '덥다'(0.12) = 0.92이며 '춥다'(0.06)를 더해 0.98이 되므로 상위 4개 단어가 모두 후보군에 포함됩니다. 하지만 0.1% 미만의 무관한 단어 '컴퓨터'는 차단됩니다.

Top-P의 가장 큰 장점은 후보군의 개수가 고정되지 않고 문맥에 따라 동적으로 변한다는 점입니다. 다음 단어가 명백한 상황("대한민국의 수도는 [서울]")에서는 1등 단어 하나만으로도 확률 90%를 넘겨 후보군이 1개로 축소되지만, 다음 단어의 갈래가 무궁무진한 창작 상황에서는 후보군이 수십 개로 유연하게 늘어납니다.

[참고] Top-K와 Top-P의 차이점

초기에 쓰이던 Top-K 샘플링은 확률의 높고 낮음에 상관없이 무조건 상위 K개(예: 40개) 단어만 남기는 고정 개수 방식이었습니다. 하지만 후보 단어 간의 격차가 극심할 때도 억지로 K개를 채우느라 엉뚱한 단어가 후보군에 끼어들거나, 반대로 후보군이 넓어야 할 때 선택의 폭을 강제로 좁히는 단점이 있었습니다. Top-P는 확률 누적합을 기준으로 삼아 이러한 고정 개수의 맹점을 해결했습니다.

작업 목적별 권장 파라미터 조합

실제 프로덕션 시스템에서 API를 호출할 때는 수행하려는 태스크의 성격에 맞춰 파라미터를 명확히 분리해야 합니다.

적용 분야권장 Temperature권장 Top-P주된 이유
JSON 파싱, SQL 작성, 코드 생성0.0 ~ 0.21.0문법적 규격 준수와 재현성이 최우선
고객 지원 FAQ, 문서 요약0.3 ~ 0.50.8 ~ 0.9사실 왜곡을 방지하면서 자연스러운 문장 유지
대화형 일반 챗봇0.70.9반복적인 느낌을 피하고 적절한 유연성 부여
브레인스토밍, 마케팅 문구 기획0.9 ~ 1.10.95다채로운 어휘 조합과 독창적 발상 유도

OpenAI와 Anthropic의 공식 엔지니어링 가이드에서는 "Temperature와 Top-P 두 파라미터를 동시에 조절하지 말고, 둘 중 하나만 변경하고 다른 하나는 기본값(1.0)으로 유지하라"고 권고합니다. 두 변수가 모두 확률 분포의 형태와 후보군 크기에 복합적으로 간섭하기 때문에, 둘을 함께 움직이면 원하는 결과 품질의 원인을 역추적하기 어려워지기 때문입니다.

파이썬 코드로 확인하는 온도별 확률 분포 변화

다음 예제는 가상의 로짓 점수 배열에 대해 서로 다른 온도(T = 0.2, 1.0, 2.0)를 적용했을 때 소프트맥스 확률이 어떻게 극적으로 재편되는지 보여 줍니다.

import math
 
  # 모델이 출력한 가상의 4개 토큰 로짓 점수 (예: ['사과', '바나나', '포도', '비행기'])
logits = [6.0, 4.0, 3.0, 0.5]
tokens = ["사과", "바나나", "포도", "비행기"]
temperatures = [0.2, 1.0, 2.0]
 
def softmax_with_temp(z_list, temp):
    scaled = [z / temp for z in z_list]
    # 지수 연산 오버플로 방지를 위한 최댓값 차감
    max_val = max(scaled)
    exp_vals = [math.exp(s - max_val) for s in scaled]
    sum_exp = sum(exp_vals)
    return [round(e / sum_exp, 4) for e in exp_vals]
 
for t in temperatures:
    probs = softmax_with_temp(logits, t)
    print(f"--- Temperature: {t} ---")
    for tok, p in zip(tokens, probs):
        print(f"  {tok}: {p * 100:.2f}%")

실행 결과는 다음과 같습니다.

--- Temperature: 0.2 ---
  사과: 100.00%
  바나나: 0.00%
  포도: 0.00%
  비행기: 0.00%
--- Temperature: 1.0 ---
  사과: 84.09%
  바나나: 11.38%
  포도: 4.19%
  비행기: 0.34%
--- Temperature: 2.0 ---
  사과: 60.43%
  바나나: 22.23%
  포도: 13.48%
  비행기: 3.86%

실행 출력에서 볼 수 있듯이 온도가 0.2일 때는 1등 토큰 '사과'가 100.00%에 수렴하여 사실상 완벽한 결정론에 도달합니다. 반면 온도를 2.0으로 올리면 전혀 엉뚱한 단어인 '비행기'의 당첨 확률이 0.34%에서 3.86%로 11배 이상 치솟습니다. 이 확률 역학을 숙지하면 파이프라인의 환각을 체계적으로 억제할 수 있습니다.

참고 문서

설명이 어렵거나 잘못된 부분을 발견하셨나요?

문서 수정 의견 보내기