cross-entropy 손실함수 완전 정복 — 심화 학습서

02. 분류 손실로서의 cross-entropy — softmax · sigmoid · BCE · $p_t$ 통합

Contents

01장은 cross-entropy를 정의할 때 qq가 이미 확률분포라고 가정했다. 그런데 실제 모델은 확률이 아니라 raw 점수(로짓 zz)를 낸다. 이 장은 그 빠진 고리, 곧 로짓에서 확률을 거쳐 cross-entropy 숫자까지 가는 계산 파이프라인을 끝까지 판다.

분류 한 번의 흐름은 항상 같은 4단계다.

softmax (multi-class)
or sigmoid (binary)

input x

neural net (backbone + head)

logits z
(raw scores, any real number)

probabilities q
(0..1, sum=1 for softmax)

cross-entropy
L = -log(prob of true class)

true label y

loss (a number)

입력에서 손실까지, 로짓과 확률을 거치는 분류 한 번의 흐름.

핵심 용어를 정해 두자(00장 §0.6 기호표의 호명).

  • 로짓(logit) zz: 네트워크의 마지막 선형층 출력이다. softmax/sigmoid를 통과하기 전의 raw 점수다. 부호 제한도 합 제한도 없어 어떤 실수든 가능하다. "로짓"은 어원상 로지스틱의 역함수 logit(p)=logp1p\text{logit}(p)=\log\frac{p}{1-p}를 뜻한다. 딥러닝에서는 "확률화 직전의 raw 점수"라는 넓은 뜻으로 쓴다.
  • 확률 qq (이진에서는 p^\hat p): 로짓을 softmax/sigmoid로 0~1 범위로 짠 값이다.
  • 라벨 yy: 정답이다. 다중 클래스는 정수 인덱스나 one-hot 벡터, 이진은 0/1이다.
  • 손실 LL: 그 샘플에 대한 cross-entropy 한 숫자다.

이제 "로짓 → 확률" 변환기 두 개를 차례로 본다.


2.1 모델 출력을 확률로 — softmax와 sigmoid

softmax — 여러 로짓을 상호배타 확률분포로

KK개 클래스의 로짓 벡터 z=(z1,,zK)z=(z_1,\dots,z_K)에 대해

  softmax(z)i=ezij=1Kezj  \boxed{\;\text{softmax}(z)_i = \frac{e^{z_i}}{\displaystyle\sum_{j=1}^{K} e^{z_j}}\;}

이 출력 벡터 q=softmax(z)q=\text{softmax}(z)는 확률분포의 두 조건을 항상 만족한다. 하나씩 풀어쓰자.

성질 1 — 모두 양수. 분자 ezi>0e^{z_i}>0이고 분모도 양수들의 합이다. 따라서 어떤 qiq_i든 0보다 크다. 로짓이 음수여도 e()e^{(\cdot)}가 양수로 보내준다.

성질 2 — 합이 1. 분모가 모든 분자의 합이므로

i=1Kqi=i=1Kezijezj=iezijezj=1.\sum_{i=1}^{K} q_i = \sum_{i=1}^{K}\frac{e^{z_i}}{\sum_j e^{z_j}} = \frac{\sum_i e^{z_i}}{\sum_j e^{z_j}} = 1.

성질 1과 2를 합치면 qq는 진짜 확률분포다. 01장의 cross-entropy에 그대로 넣을 수 있다.

성질 3 — 순서 보존(단조). za>zb    eza>ezb    qa>qbz_a > z_b \iff e^{z_a} > e^{z_b} \iff q_a > q_b. 로짓이 큰 클래스가 확률도 크다. 가장 큰 로짓이 가장 확률 높은 예측이다(argmax 일치).

성질 4 — 평행이동 불변(translation invariance). 모든 로짓에 같은 상수 cc를 더해도 출력이 안 바뀐다.

softmax(z+c)i=ezi+cjezj+c=eceziecjezj=ezijezj=softmax(z)i.\text{softmax}(z+c)_i = \frac{e^{z_i+c}}{\sum_j e^{z_j+c}} = \frac{e^{c}e^{z_i}}{e^{c}\sum_j e^{z_j}} = \frac{e^{z_i}}{\sum_j e^{z_j}} = \text{softmax}(z)_i.

ece^c가 분자와 분모에서 약분된다. 실제 구현은 이 성질을 활용한다. c=maxizic=-\max_i z_i를 빼서 softmax(zmaxz)\text{softmax}(z-\max z)를 계산하면 큰 eze^z의 overflow를 막는다(safe softmax). 값은 같고 수치만 안전하다. 수치안정 상세는 04장 §4.1에서 다룬다.

⚠️ 불변은 평행이동에만. 모든 로짓에 같은 수를 곱하면(scaling) 결과가 바뀐다. 이게 다음 온도 이야기다.

성질 5 — 온도(temperature) τ\tau. softmax(z/τ)\text{softmax}(z/\tau)로 쓰면 τ\tau가 작을수록 가장 큰 로짓에 확률이 쏠린다(sharp, 저엔트로피). τ\tau가 클수록 고르게 퍼진다(uniform, 고엔트로피). τ=1\tau=1이 표준 softmax다. 온도는 distillation·calibration에서 중요하지만 깊은 다룸은 이 책 범위 밖이다.

왜 하필 지수 eze^z인가. 두 가지를 동시에 해결한다.

  1. 양수화. 로짓은 음수일 수 있지만 확률은 음수면 안 된다. e()e^{(\cdot)}는 어떤 실수든 양수로 보낸다(단조 증가).
  2. 상대 강조(부드러운 max). 지수는 큰 값을 불균형하게 키워 1등 로짓에 확률을 더 몰아준다. 그래서 "soft한 argmax", 곧 soft-max다. 그냥 zi/zjz_i/\sum z_j로 정규화하면 음수·0합 문제가 생기고 강조 효과도 없다.

더 깊은 이유 하나는 03장에서 드러난다. softmax와 CE를 합치면 로그가 지수를 상쇄해 gradient가 깔끔한 qyq-y가 된다. Goodfellow et al.은 "음의 로그우도의 log가 softmax의 exp를 되돌린다(undoes)"고 표현한다.

sigmoid — 단일 로짓을 양성 확률로

이진 분류는 클래스가 둘(양성=1, 음성=0)뿐이다. 그래서 로짓 하나 zz만 내고 양성일 확률 p^\hat p를 sigmoid(로지스틱 함수)로 짠다.

  σ(z)=11+ez  ,p^=σ(z),1p^=ez1+ez=σ(z).\boxed{\;\sigma(z) = \frac{1}{1+e^{-z}}\;},\qquad \hat p=\sigma(z),\quad 1-\hat p = \frac{e^{-z}}{1+e^{-z}} = \sigma(-z).

여기서 p^=σ(z)\hat p=\sigma(z)는 00장 §0.6에서 정한 예측 양성확률이다. 01장의 진짜 분포 pp와는 다른 양이다(예측 측 대 정답 측). 이 장부터 이진의 예측 확률은 일관되게 p^\hat p로 쓴다.

  • z+z\to+\inftyp^1\hat p\to 1(양성 확신), zz\to-\inftyp^0\hat p\to 0(음성 확신), z=0z=0이면 p^=0.5\hat p=0.5(반반)다.
  • σ(z)=1σ(z)\sigma(-z)=1-\sigma(z)라는 대칭이 곧 "음성 확률"을 준다.

sigmoid = 2-클래스 softmax (특수화 증명)

sigmoid는 새 함수가 아니라 softmax의 K=2K=2 특수경우다. 클래스 0의 로짓을 z0z_0, 클래스 1을 z1z_1이라 하면 클래스 1의 softmax 확률은

softmax([z0,z1])1=ez1ez0+ez1.\text{softmax}([z_0,z_1])_1 = \frac{e^{z_1}}{e^{z_0}+e^{z_1}}.

분자·분모를 ez1e^{z_1}로 나눈다. 평행이동 불변으로 z00z_0\to0을 잡아도 같다(즉 z:=z1z0z:=z_1-z_0).

=1ez0z1+1=11+e(z1z0)=σ(z1z0)=σ(z).= \frac{1}{e^{z_0-z_1}+1} = \frac{1}{1+e^{-(z_1-z_0)}} = \sigma(z_1-z_0) = \sigma(z).

두 로짓의 차 z=z1z0z=z_1-z_0 하나면 충분하다. 그게 sigmoid의 입력이다. 그래서 이진 분류는 로짓을 1개만 둔다(2개가 아니다).

K = 2,
z := z1 - z0

is the special case of

softmax (K classes)

sigmoid sigma(z) = 1/(1+e^-z)

sigmoid는 클래스가 둘일 때의 softmax로 환원된다.

수치 확인: σ(2.197)=0.89998\sigma(2.197)=0.89998softmax([2.197,0])1=0.89998\text{softmax}([2.197,0])_1=0.89998이 정확히 일치한다.


Advertisements

2.2 categorical cross-entropy — 다중 클래스, 단일 정답

one-hot 라벨과 정의

클래스가 KK개이고 정답이 정확히 하나(클래스 cc)인 상황이다. 라벨을 one-hot 벡터 yy로 쓴다(§0.4). 정답 자리만 1, 나머지는 0이다.

y=(y1,,yK),yk={1k=c0kc.y = (y_1,\dots,y_K),\quad y_k = \begin{cases}1 & k=c\\ 0 & k\neq c.\end{cases}

예측은 q=softmax(z)q=\text{softmax}(z)다. categorical cross-entropy는

  CE=k=1Kyklogqk  .\boxed{\;\text{CE} = -\sum_{k=1}^{K} y_k \log q_k\;}.

one-hot에서 한 항으로 환원

yy가 one-hot이라 yc=1y_c=1이고 나머지 yk=0y_k=0이다. 그래서 합에서 정답 항만 살아남는다.

CE=kyklogqk=yc=1logqckcyk=0logqk=logqc.\text{CE} = -\sum_{k} y_k\log q_k = -\underbrace{y_c}_{=1}\log q_c - \sum_{k\neq c}\underbrace{y_k}_{=0}\log q_k = \boxed{-\log q_c}.

01장과의 한 줄 연결. 일반 cross-entropy는 H(p,q)=kpklogqkH(p,q)=-\sum_k p_k\log q_k였다(01장 §1.4). 라벨 분포 pp가 one-hot이면(정답에 전 확률 몰빵) H(p,q)=logqcH(p,q)=-\log q_c로 정확히 위 식이 된다. 즉 "분류 CE = 정답 분포가 one-hot인 cross-entropy"다. 01장의 그 특수화가 여기서 softmax 출력 qq로 구체화됐다.

그래서 실전 categorical CE는 "정답 클래스에 모델이 준 확률의 음로그" 한 줄로 끝난다. softmax를 직접 끼워 넣으면

CE=logqc=logezcjezj=zc+logjezj.\text{CE} = -\log q_c = -\log\frac{e^{z_c}}{\sum_j e^{z_j}} = -z_c + \log\sum_{j} e^{z_j}.

오른쪽 형태는 정답 로짓을 빼고 log-sum-exp를 더한 꼴이다. 바로 PyTorch가 내부에서 계산하는 모양이다(§2.5). 둘째 항 logjezj\log\sum_j e^{z_j}가 그 악명 높은 log-sum-exp다. 수치안정 처리는 04장 §4.1에서 본다.

logits z (K-dim)

softmax

q (prob dist)

one-hot y (true = c)

pick q_c

CE = -log q_c

softmax로 확률을 만든 뒤 정답 자리 qcq_c만 골라 음로그를 취한다.

수치예제 — 3클래스 로짓 z=(2.0,1.0,0.1)z=(2.0,\,1.0,\,0.1)

이 예제는 이 책의 주 예제(running example)다. 03장 gradient와 05장 walkthrough가 같은 숫자를 이어받는다.

1단계: softmax. overflow 방지로 maxz=2.0\max z=2.0을 빼고 지수를 취한다(성질 4).

kk zkz_k ezk2.0e^{z_k-2.0} qk=ezk2.0q_k=\dfrac{e^{z_k-2.0}}{\sum}
0 2.0 1.0000001.000000 0.659001
1 1.0 0.3678790.367879 0.242433
2 0.1 0.1495690.149569 0.098566
1.5174481.517448 1.0000001.000000

2단계: 정답에 따른 CE. CE=logqc\text{CE}=-\log q_c.

정답 클래스 cc qcq_c CE=logqc\text{CE}=-\log q_c 해석
0 (로짓 최대) 0.659001 0.417030 잘 맞힘 → 작은 손실 (easy)
1 (중간) 0.242433 1.417030 애매 → 중간 손실
2 (로짓 최소) 0.098566 2.317030 거의 못 맞힘 → 큰 손실 (hard)

읽는 법은 이렇다. 정답이 모델이 자신 없어 한 클래스(2번)일수록 CE가 크다. 같은 로짓, 같은 예측이라도 정답이 무엇이냐에 따라 손실이 다르다. CE는 "정답에 준 확률"만 보기 때문이다.

🔎 우아한 패턴. 세 CE 값 0.417, 1.417, 2.317의 차이가 정확히 로짓 차이(2.0−1.0=1.0, 1.0−0.1=0.9)와 같다. 왜일까. CE=zc+logjezj\text{CE}=-z_c+\log\sum_j e^{z_j}에서 둘째 항은 정답과 무관한 상수다(logjezj=2.417030\log\sum_j e^{z_j}=2.417030). 정답을 바꾸면 CE는 딱 zc-z_c만큼만 평행이동한다.


Advertisements

2.3 binary cross-entropy (BCE)와 베르누이 우도

BCE 정의

이진 분류에서 라벨은 y{0,1}y\in\{0,1\}, 모델의 양성 확률은 p^=σ(z)\hat p=\sigma(z)다. binary cross-entropy는

  BCE=[ylogp^+(1y)log(1p^)]  .\boxed{\;\text{BCE} = -\big[\,y\log \hat p + (1-y)\log(1-\hat p)\,\big]\;}.

이건 사실 K=2K=2 one-hot CE를 푼 것과 같다. one-hot이 (1y,y)(1-y,\,y), 확률이 (1p^,p^)(1-\hat p,\,\hat p)이므로 kyklogqk=[(1y)log(1p^)+ylogp^]-\sum_k y_k\log q_k = -[(1-y)\log(1-\hat p)+y\log \hat p]가 되어 위 식 그대로다.

유도 — 베르누이 우도의 음로그

BCE는 그냥 던져진 식이 아니다. 최대우도추정(MLE)에서 자연히 떨어진다(01장 §1.6의 이진 버전). 양성 확률 p^\hat p인 베르누이 분포에서 라벨 yy를 관측할 확률(우도)은

P(yp^)=p^y(1p^)1y(  y=1p^,    y=01p^  ).P(y\mid \hat p) = \hat p^{\,y}\,(1-\hat p)^{1-y} \quad\Big(\;y=1\Rightarrow \hat p,\;\; y=0\Rightarrow 1-\hat p\;\Big).

지수 yy1y1-y가 스위치 역할을 해 한 식으로 두 경우를 표현한다. 음의 로그우도를 취하면

logP(yp^)=[ylogp^+(1y)log(1p^)]=BCE.-\log P(y\mid \hat p) = -\big[\,y\log \hat p + (1-y)\log(1-\hat p)\,\big] = \text{BCE}.

즉 BCE를 최소화하는 일이 베르누이 우도를 최대화하는 일이다.

ptp_t로 통합 — 두 경우를 한 줄로

라벨에 따라 항이 갈리는 게 거추장스럽다. 정답 클래스에 모델이 준 확률 ptp_t를 정의한다(00장 §0.5의 그 ptp_t).

  pt={p^y=1  (양성이 정답)1p^y=0  (음성이 정답)  \boxed{\;p_t = \begin{cases} \hat p & y=1 \;(\text{양성이 정답})\\ 1-\hat p & y=0 \;(\text{음성이 정답})\end{cases}\;}

그러면 y=1y=1일 때 둘째 항이 0이라 logp^=logpt-\log \hat p=-\log p_t다. y=0y=0일 때 첫째 항이 0이라 log(1p^)=logpt-\log(1-\hat p)=-\log p_t다. 두 경우 모두

  BCE=logpt  .\boxed{\;\text{BCE} = -\log p_t\;}.

categorical의 logqc-\log q_c와 같은 골격이다(qcq_cptp_t 둘 다 "정답에 준 확률"). 다중클래스든 이진이든 cross-entropy는 결국 "정답에 준 확률의 음로그"다.

easy/hard 직관과 logpt-\log p_t 곡선

BCE=logpt\text{BCE}=-\log p_tptp_t의 함수로 보자.

p_t -> 1
(confident in true class)

-log p_t -> 0
EASY (small loss)

p_t -> 0
(doubts true class)

-log p_t -> +inf
HARD (large loss)

정답에 확신할수록 손실이 0으로, 정답을 의심할수록 손실이 무한대로 간다.

  • pt=1p_t=1이면 손실 0이다. 완벽히 맞힌 것이다.
  • pt=0.5p_t=0.5log0.5=0.693-\log 0.5 = 0.693이다. 반반(찍기)이다.
  • pt0p_t\to 0이면 손실이 ++\infty로 간다. 정답을 강하게 부정하니 가장 큰 벌점이다.

ptp_t가 클수록 easy, 작을수록 hard다. 단, easy 샘플(pt=0.95p_t=0.95)도 손실이 정확히 0은 아니다(log0.950.0513-\log 0.95\approx0.0513).

Focal Loss로 가는 다리. 위에서 본 "0이 아닌 잔여 손실"이 easy 샘플 수천 개에 쌓이면 학습을 지배할 수 있다. 이를 고치려고 CE에 변조항 (1pt)γ(1-p_t)^\gamma를 곱한 것이 Focal Loss (1pt)γlogpt-(1-p_t)^\gamma\log p_t다. 잘 맞히는 쉬운 샘플의 손실을 깎고 어려운 샘플에 집중하는 CE의 확장이다. 이 책은 이 다리만 놓는다(04장 §4.3에서 한 번 더). 깊은 유도는 별도 주제로 안내한다.

수치예제 — BCE 표

BCE=[ylogp^+(1y)log(1p^)]=logpt\text{BCE}=-[y\log \hat p+(1-y)\log(1-\hat p)] = -\log p_t. 두 식이 모든 행에서 일치한다.

yy p^=σ(z)\hat p=\sigma(z) ptp_t BCE=logpt\text{BCE}=-\log p_t 해석
1 0.90 0.90 0.105361 양성을 양성으로 확신 → easy
1 0.50 0.50 0.693147 반반 → 찍기 수준
1 0.30 0.30 1.203973 양성인데 음성 쪽으로 기움 → hard
1 0.10 0.10 2.302585 양성을 강하게 부정 → 매우 hard
0 0.10 0.90 0.105361 음성을 음성으로 확신 → easy
0 0.20 0.80 0.223144 음성에 약간 confidence ↓
0 0.80 0.20 1.609438 음성인데 양성으로 오판 → hard

대칭에 주목하자. (y=1,p^=0.9)(y{=}1,\hat p{=}0.9)(y=0,p^=0.1)(y{=}0,\hat p{=}0.1)은 둘 다 pt=0.9p_t=0.9라 같은 손실 0.105다. CE는 "정답에 준 확률"만 보므로 라벨이 뭐든 ptp_t가 같으면 손실이 같다.


2.4 multi-class vs multi-label — softmax-CE냐 sigmoid-BCE냐

두 문제 유형

구분 multi-class (단일 라벨) multi-label (다중 라벨)
질문 "이 중 하나는 무엇?" "각 속성이 있나/없나?"
라벨 정확히 한 클래스가 정답 (상호배타) 여러 클래스가 동시에 참 가능 (독립)
개 vs 고양이 vs 새 (사진 1장에 1동물) 사진 속성: {야외?, 사람있나?, 밤인가?} 동시 가능
출력층 로짓 KK개 → softmax (합=1) 로짓 KK개 → 클래스마다 독립 sigmoid
손실 categorical CE =logqc=-\log q_c 클래스마다 BCE 합/평균 klogpt,k\sum_k -\log p_{t,k}
확률 제약 kqk=1\sum_k q_k = 1 (한 클래스↑면 다른 건↓) p^k\hat p_k 독립, 합 제약 없음

핵심 차이는 상호배타성이다. softmax는 분모를 공유해 클래스끼리 확률을 경쟁시킨다(하나 오르면 다른 게 내림). 정답이 하나일 때 옳다. sigmoid-per-class는 각 채널이 독립이다. 그래서 "야외이면서 동시에 밤"처럼 여러 라벨이 같이 참일 수 있다.

yes (single-label)

no (labels independent,
several can be true)

exactly one correct?
(classes mutually exclusive?)

softmax over K logits
-> categorical CE = -log q_c

sigmoid per class
-> BCE per class, then sum/mean

정답이 하나뿐인지가 softmax-CE와 sigmoid-BCE를 가르는 갈림길이다.

규칙은 한 줄이다. 정답이 정확히 하나면 softmax-CE, 여러 라벨이 동시에 가능하면 클래스별 sigmoid-BCE다.

실전 한 줄. 멀티태스크 모델(예: 운전자 모니터링)은 태스크마다 출력 형태가 다르다. 졸음 3단계(정상/경미/심각)처럼 상호배타 분류는 softmax+CE를 쓴다. "안경 착용? 마스크 착용? 흡연 중?"처럼 동시에 참일 수 있는 다중 속성은 클래스별 sigmoid+BCE를 쓴다. 한 모델이 두 손실을 태스크별로 섞어 쓰는 게 정상이다.

multi-label 수치예제

3개 독립 속성, 로짓 z=(2.197,1.386,0.847)z=(2.197,\,-1.386,\,0.847), 라벨 y=(1,0,1)y=(1,0,1)이다. 각 채널을 sigmoid에 통과시킨 뒤 BCE를 구한다.

채널 zkz_k p^k=σ(zk)\hat p_k=\sigma(z_k) yky_k pt,kp_{t,k} BCEk=logpt,k\text{BCE}_k=-\log p_{t,k}
0 2.197 0.9000 1 0.9000 0.105383
1 −1.386 0.2000 0 0.8000 0.223202
2 0.847 0.6999 1 0.6999 0.356764
평균 0.228450

multi-class와 달리 로짓 사이에 분모 공유가 없다. 채널 0의 큰 로짓이 채널 1·2 확률에 전혀 영향을 주지 않는다(독립). 그래서 "둘 다 참"을 표현할 수 있다.


2.5 프레임워크 관례 — PyTorch가 실제로 하는 일

이론을 코드로 옮길 때 가장 많이 깨지는 지점이다. 그래서 왜 프레임워크가 로짓을 직접 받는지 짚고 간다. 한 줄 직관은 이렇다. 확률을 거치지 않고 로짓에서 바로 손실을 계산하면 수치적으로 안전하다(04장 §4.1).

CrossEntropyLoss: 로짓 + 정수라벨 → 내부 log-softmax + NLL

PyTorch nn.CrossEntropyLoss는 softmax를 적용하지 않은 raw 로짓과 정수 클래스 인덱스(one-hot 아님)를 받는다. 공식 문서는 "The input is expected to contain the unnormalized logits for each class (which do not need to be positive or sum to 1, in general)." 그리고 "this case is equivalent to applying LogSoftmax on an input, followed by NLLLoss."

CrossEntropyLoss = LogSoftmax + NLLLoss를 한 클래스로 합친 것이다. 정수 라벨 yny_n일 때 한 샘플 손실은

n=logexp(xn,yn)c=1Cexp(xn,c)=logqyn.\ell_n = -\log\frac{\exp(x_{n,y_n})}{\sum_{c=1}^{C}\exp(x_{n,c})} = -\log q_{y_n}.

§2.2의 logqc-\log q_c와 같다. PyTorch는 클래스-확률 타깃(soft label)도 지원한다(n=cyn,clogqn,c\ell_n=-\sum_c y_{n,c}\log q_{n,c}). label smoothing·distillation에서 쓴다(04장).

logits z

LogSoftmax
(log q = z - logsumexp z)

NLLLoss
(pick -log q at target idx)

target = int class index

loss

CrossEntropyLoss는 안에서 LogSoftmax와 NLLLoss를 차례로 돌린다.

수치 확인: F.cross_entropy([[2.0,1.0,0.1]], target=0) = 0.417030. §2.2 손계산과 정확히 일치한다.

BCEWithLogitsLoss: 로짓 → 내부 sigmoid + BCE

nn.BCEWithLogitsLoss는 로짓(sigmoid 전)을 받는다. 공식 문서는 "This loss combines a Sigmoid layer and the BCELoss in one single class. ... we take advantage of the log-sum-exp trick for numerical stability."

별도 nn.BCELoss는 확률 p^\hat p를 받는다. 하지만 로짓을 직접 받는 BCEWithLogitsLoss가 수치적으로 안전하다(sigmoid를 따로 하면 log(0)\log(0) 위험). 클래스 불균형용 pos_weight(양성 가중)로 재현율과 정밀도를 trade-off할 수 있다. weighted loss 상세는 04장 §4.3에서 본다.

라벨 표현 정리

표현 형태 쓰는 곳
정수 인덱스 y=2y=2 (스칼라) PyTorch CrossEntropyLoss 기본 (메모리·속도 유리)
one-hot 벡터 y=(0,0,1,)y=(0,0,1,\dots) 손계산·정보이론 식·soft label
multi-hot 벡터 y=(1,0,1,)y=(1,0,1,\dots) multi-label (BCEWithLogitsLoss)

정수 인덱스에서 one-hot으로 가는 건 동치다(logqc-\log q_c가 정수 cc 자리 하나만 보므로). PyTorch가 정수를 받는 건 같은 계산이면서 더 싸기 때문이다.


2.6 흔한 오개념 — 하지 말 것

  1. softmax/sigmoid 이중 적용 (가장 흔함). CrossEntropyLossBCEWithLogitsLoss는 내부에서 softmax/sigmoid를 한다. 모델 마지막에 또 softmax를 넣고 그 출력을 이 손실에 먹이면 두 번 적용된다. 로짓이 뭉개지고 학습이 망가진다. 손실 함수에는 raw 로짓을 줘라. 추론에서 확률이 필요하면 그때 softmax/sigmoid를 명시적으로 적용한다.
  2. 확률에 다시 CE. 이미 확률인 값을 CrossEntropyLoss에 넣으면 PyTorch가 그걸 또 로짓으로 보고 log-softmax를 적용한다. 틀린다. 확률과 정수라벨로 NLL을 직접 쓰려면 NLLLoss(torch.log(p), y)처럼 로그 확률을 줘야 한다.
  3. multi-label에 softmax. 여러 라벨이 동시 참인데 softmax를 쓰면 확률이 강제로 합=1이 된다. "둘 다 참"을 표현 못 한다. 클래스별 sigmoid+BCE를 써라.
  4. one-hot 라벨을 CrossEntropyLoss에 정수처럼. PyTorch는 정수 인덱스 또는 클래스-확률(soft) 타깃을 받는다. 어느 쪽인지 API를 확인하라.

함정의 증상→원인→해결 체크리스트는 04장 §4.5에 단일화돼 있다.


분류 CE는 다중클래스든 이진이든 결국 "정답에 준 확률의 음로그"다(logqc=logpt-\log q_c = -\log p_t). softmax/sigmoid가 로짓을 확률로 짜고, 그 위에서 CE가 손실 한 숫자를 낸다. 다음 03장은 softmax+CE를 미분하면 왜 깔끔한 qyq-y(예측−정답)가 나오는지를 유도한다. 주 예제 z=(2,1,0.1)z=(2,1,0.1)를 그대로 이어받는다.

출처