C.W.K.
Stream
Lesson 03 of 05 · published

곱 규칙: 곱셈이 덧셈이 되다

~10 min · product-rule, log-likelihood, underflow

Level 0수학 초심자
0 XP0/59 lessons0/13 achievements
0/100 XP to next level100 XP to go0% complete

AI 를 자기 자신에게서 구한 주문

AI 에 가장 중요한 로그 항등식:

다시 읽기. 왼쪽은 곱셈, 오른쪽은 덧셈. 로그가 어려운 연산 (작은 float 많이 곱하기) 을 쉬운 거 (그 로그 합) 로 trade. 이건 표기 편의가 아니야 — 엔지니어링 기적.

수치 underflow: 이 항등식이 푸는 버그

Float32 가 약 까지 표현. 0.001 짜리 100 확률 곱:

결과는 수학적으로 작지만 0 아님. Float32 가 어쨌든 0 으로 round. 이제 손실 = , 학습 crash.

로그 먼저: . 완벽 정상 float. 확률 곱하기 대신 로그-확률 합. 끝.

Log-Likelihood 가 곳곳에

이래서 거의 모든 확률 ML 손실에 로그:

  • Cross-entropy 손실: — 참 클래스 로그-확률 합.
  • 최대 likelihood 추정: X, maximize.
  • 언어 모델 학습: 다음 토큰의 negative log-likelihood 최소화, 수백만 토큰 합.
확률 많이 곱해야 하면 로그 먼저 합쳐. 수학 동일; 수치 훨씬 나음.

Code

왜 로그가 옵션 아닌가·python
import numpy as np

probs = np.array([0.001] * 100)

# Naive 방식 — underflow
direct = np.prod(probs)
print(direct)            # 0.0  — float32/64 가 포기

# Log-likelihood 방식 — 완벽 작동
log_total = np.sum(np.log(probs))
print(log_total)         # -690.776...
print(np.exp(log_total)) # 1e-300 — 로그로만 계산 가능
PyTorch 가 logits 사랑하는 이유·python
import torch

# PyTorch cross-entropy 가 이미 로그 공간에 살아
logits = torch.tensor([[2.0, 1.0, 0.5]])    # raw 모델 출력
target = torch.tensor([0])                   # 정답 클래스 인덱스

loss = torch.nn.functional.cross_entropy(logits, target)
# 내부적으로: log_softmax (logits) → target 인덱스 픽 → 음수
print(loss.item())                           # ~0.42

External links

Exercise

0.5 를 1000 번 자기 곱 (np.prod 0.5 배열). NumPy 가 뭘 줘? 이번엔 1000 * np.log(0.5). 그러고 결과를 np.exp. 왜 두 번째 경로만 살아남?
Hint
0.5^1000 ≈ 9.3e-302 — float64 한계. 로그 경로 = -693.15 계산, exp 하면 작은 수 복원. Product 경로는 NumPy 버전마다 달라 unreliable.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 2

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.
  1. Elechemist
    Elechemist

    import numpy as np

    방법 1

    x = np.prod(np.full(1000, 0.5)) print(x)

    방법 2

    y = np.exp(1000 * np.log(0.5)) print(y)

    비교

    print(x == y)

    첫번째 방법에서는 확률을 계속 곱하기 때문에 언더플로우가 나버려서 0이되어버림

    1. 피파
      피파· warmElechemistElechemist

      맞아요, Elechemist님. 이 lesson의 핵심을 거의 정확히 잡으셨어요.

      다만 한 가지 nuance만 붙이면, 0.5 ** 1000은 float64에서는 아직 아주 작은 양수로 남을 수 있어요. 그래도 구조적으로는 말씀하신 방향이 맞아요. 확률을 계속 곱하는 방식은 금방 수치 바닥에 가까워지고, 더 긴 sequence나 더 작은 확률에서는 언더플로우로 0이 되어 버리거든요.

      그래서 log space로 바꾸면 “곱하기”가 “더하기”가 되고, 모델이 아주 작은 확률도 훨씬 안정적으로 다룰 수 있어요. 지금 실험이 바로 그 감각을 잡는 좋은 예예요.