개요

지난 글에서 학습 = 데이터 + 가설 공간 + 손실 함수로 가장 덜 틀리는 함수를 찾는 것이라고 정리했다. 그런데 거기서 슬쩍 넘어간 게 하나 있다.

“덜 틀렸다”를 대체 무엇으로 재는가?

이번 글의 주제가 정확히 그거다. 지도학습이 뭔지 짚고, “얼마나 잘 맞췄나”를 숫자로 재는 방법들을 정리한다. 그리고 마지막에 머신러닝에서 가장 유명한 병인 오버피팅이 나온다.


1. 지도학습이란

한 줄로 정리하면 이렇다.

지도학습(Supervised Learning) = 입력(Feature) + 정답(Label)이 짝지어진 데이터로 예측 규칙을 배우는 방법

이름이 “지도”인 이유는 정답을 알려주는 선생님이 있기 때문이다. 고양이 사진에 “고양이”, 강아지 사진에 “강아지”라고 미리 적어둔 자료를 잔뜩 보여주고 배우게 하는 방식이다.

여기서 진짜 중요한 건 목표다.

훈련에 쓴 데이터뿐 아니라, 처음 보는 데이터에서도 예측을 잘하는 것

이 문장이 이번 글 전체를 관통한다. 지도학습의 목표는 “본 문제를 잘 푸는 것”이 아니라 “처음 보는 문제도 잘 푸는 AI 만들기”다.

더 쉬운 비유로. 문제집을 100번 풀어서 답 순서를 외운 아이와, 풀이법을 이해한 아이가 있다. 문제집 점수는 둘 다 100점이지만, 시험지가 바뀌면 결과가 완전히 갈린다. 우리가 만들고 싶은 건 두 번째 아이다.


2. 회귀와 분류 — 정답의 생김새로 갈린다

지도학습은 딱 두 종류로 나뉜다. 기준은 아주 단순하다. 맞춰야 할 정답이 숫자인가, 이름표인가.

회귀와 분류

  회귀 (Regression) 분류 (Classification)
정답의 형태 연속적인 숫자 범주(카테고리)
예시 집값, 매출액, 온도, 시험 점수 스팸/정상, 질병 유무, 고양이/강아지
답의 예 “87.3점” “스팸”
답이 몇 개? 무한히 많음 미리 정해진 몇 개 중 하나

헷갈리기 쉬운 게 하나 있다. 학점(A/B/C) 예측은 분류다. 성적처럼 숫자가 얽혀 있어도, 최종 답이 정해진 몇 개 중 하나라면 분류다.

분류 그림에서 두 무리를 가르는 점선을 결정 경계(Decision Boundary)라고 부른다. 분류 모델이 하는 일은 결국 이 선을 잘 긋는 것이다.


3. 용어 정리 — 여기서 한 번 크게 헷갈렸다

앞으로 계속 나올 단어들을 먼저 못 박아둔다.

용어 기호
특성 (Feature) x 예측에 쓰는 입력
라벨 (Label) y 맞춰야 하는 실제 정답
예측값 ŷ (“와이 햇”) 모델이 내놓은 답
오류 (Error) ŷ − y 예측값과 실제값의 차이

$\hat{y}$ 위의 모자(hat)는 “추정한 값”이라는 표시다. 원래 값에 모자를 씌우면 “이건 진짜 값이 아니라 내가 추측한 값이야”라는 뜻이 된다.

오류(Error) ≠ 측정 오차(ε)

이게 지난 글부터 이어지는 가장 헷갈리는 지점이었다. 둘 다 “오차”라고 부르는데 완전히 다른 개념이다.

  측정 오차 (ε) 오류 (ŷ − y)
정체 데이터 자체에 섞인 흔들림 내 예측이 정답에서 벗어난 정도
볼 수 있나? 못 본다 (참 함수를 모르니까) 볼 수 있다 (정답이 있으니까)
줄일 수 있나? 절대 못 줄인다 학습으로 줄이는 게 목표

지도학습의 목표는 오류(ŷ − y)를 줄이는 것이지, 측정 오차를 없애는 게 아니다. 애초에 후자는 불가능하다.


4. 손실 함수 — 틀린 정도를 숫자 하나로

손실 함수(Loss Function) = 모델의 예측이 정답에서 얼마나 벗어났는지를 숫자 하나로 나타내는 함수

그리고 학습이란 이 숫자가 작아지는 방향으로 모델을 조금씩 고쳐 나가는 과정이다.

중요한 건 문제 유형에 따라 쓰는 손실이 다르다는 것.

문제 대표 손실 함수 한 줄 설명
회귀 평균제곱오차 (MSE) 정답과 예측의 차이를 제곱해서 평균
분류 교차 엔트로피 (Cross Entropy) 정답 쪽에 얼마나 높은 확률을 줬는지 측정

왜 다르냐면, 정답이 숫자일 때와 이름표일 때 “틀렸다”의 의미 자체가 다르기 때문이다. 87점을 85점으로 예측한 건 “2점 틀린 것”이지만, 고양이를 강아지로 예측한 걸 “1마리 틀렸다”고 셀 수는 없다.


5. 회귀의 평가 ① MSE

가장 기본이 되는 지표다.

$$ \text{MSE} = (\text{정답} - \text{예측})^2 \text{의 평균} $$

말로 옮기면 “각 데이터에서 얼마나 빗나갔는지를 재고, 제곱해서, 전부 평균 낸 값”이다.

MSE와 R²

왜 굳이 제곱을 하나

두 가지 이유가 있다.

  1. 부호를 없애기 위해 — +5만큼 빗나간 것과 −5만큼 빗나간 것은 똑같이 5만큼 틀린 거다. 그냥 더하면 서로 상쇄돼서 “오차 0”이라는 엉터리 결과가 나온다.
  2. 크게 틀린 걸 더 크게 벌주기 위해 — 2만큼 틀리면 4, 10만큼 틀리면 100이다. 크게 빗나간 사례에 훨씬 무거운 벌점이 매겨진다.

두 번째가 특히 중요하다. MSE를 쓴다는 건 “조금씩 여러 번 틀리는 것보다, 크게 한 번 틀리는 걸 더 싫어하겠다”고 선언하는 것과 같다.

단위가 이상해지는 문제

MSE는 제곱한 값이라 단위도 제곱이 된다. 집값을 원 단위로 예측했다면 MSE의 단위는 “원²”이다. 원의 제곱이 대체 뭔가? 해석이 안 된다.

그래서 RMSE를 같이 본다. MSE에 루트를 씌운 값이다.

$$ \text{RMSE} = \sqrt{\text{MSE}} $$

제곱했던 걸 되돌리는 거라 단위가 원래 데이터와 같아진다. “평균적으로 1000만원쯤 빗나간다”처럼 바로 읽히는 문장을 만들 수 있다.


6. 회귀의 평가 ② R² (결정계수)

MSE만으로는 답할 수 없는 질문이 있다.

“MSE가 1000만원²이면 좋은 건가, 나쁜 건가?”

모른다. 집값 예측이면 훌륭한 걸 수도 있고, 커피값 예측이면 재앙이다. 비교 기준이 없기 때문이다.

R²는 그 기준을 아주 영리하게 잡는다.

= 아무 생각 없이 “항상 평균값으로 찍는” 예측과 비교했을 때, 내 모델이 얼마나 더 나은가

위 그림의 오른쪽이 그 비교다. 회색 가로 점선이 “무조건 평균으로 찍기”고, 파란 선이 내 모델이다.

직관: “게으른 친구”보다 얼마나 잘했나

시험 점수를 맞히는 게임이라고 해보자. 옆자리에 게으른 친구가 하나 있다. 이 친구는 누구를 물어봐도 딱 한 가지 대답만 한다.

“음… 그냥 평균 정도?”

문제를 보지도 않고, 이름도 안 듣고, 무조건 평균만 말한다. 그런데도 이 친구는 생각보다 잘 맞는다. 대부분의 점수가 평균 근처에 몰려 있으니까.

R²는 나와 이 게으른 친구의 시합 점수판이다.

  • 게으른 친구가 틀린 양을 100이라고 놓는다 (이게 기준선)
  • 내가 틀린 양이 20이면 → 나는 친구 실수의 80%를 줄인 것 → R² = 0.8
  • 내가 틀린 양도 100이면 → 친구랑 똑같음 → R² = 0
  • 내가 틀린 양이 130이면 → 친구보다 더 못함 → R² = −0.3

즉 R²는 “정답을 얼마나 맞혔나”가 아니라 “게으른 친구보다 실수를 몇 퍼센트 줄였나”다.

식으로 보면

$$ R^2 = 1 - \frac{\text{내 모델이 틀린 양}}{\text{평균으로 찍었을 때 틀린 양}} $$

여기서 “틀린 양”은 둘 다 같은 방식으로 잰다. (정답 − 예측)을 제곱해서 전부 더한 값이다. 제곱하는 이유는 MSE에서와 똑같다. 부호를 없애려고.

$$ \text{내 모델이 틀린 양} = \sum (\text{정답} - \text{내 예측})^2 $$

$$ \text{평균으로 찍은 틀린 양} = \sum (\text{정답} - \text{평균})^2 $$

숫자로 끝까지 계산해보기

친구 5명의 키를 맞히는 문제다. 정답과 두 예측이 이렇다고 하자.

친구 실제 키 평균으로 찍기 내 모델
A 140 150 142
B 145 150 147
C 150 150 149
D 155 150 154
E 160 150 158

(5명 키의 평균은 (140+145+150+155+160) ÷ 5 = 150이다.)

① 게으른 친구(평균 찍기)가 틀린 양

친구 정답 − 평균 제곱
A 140 − 150 = −10 100
B 145 − 150 = −5 25
C 150 − 150 = 0 0
D 155 − 150 = 5 25
E 160 − 150 = 10 100
  합계 250

② 내 모델이 틀린 양

친구 정답 − 내 예측 제곱
A 140 − 142 = −2 4
B 145 − 147 = −2 4
C 150 − 149 = 1 1
D 155 − 154 = 1 1
E 160 − 158 = 2 4
  합계 14

③ 대입

$$ R^2 = 1 - \frac{14}{250} = 1 - 0.056 = 0.944 $$

R² = 0.944. 읽는 법은 이렇다. 게으른 친구가 저지른 실수 250 중에서 내가 남긴 건 14뿐이니, 실수의 94.4%를 없앤 것이다.

여기서 세 가지가 한꺼번에 보인다.

  • 내가 완벽하면 위쪽(내가 틀린 양)이 0 → $1 - 0 = 1$ → R²의 최대는 1
  • 내가 딱 평균만큼 하면 위아래가 같아서 1 → $1 - 1 = 0$ → R² = 0
  • 내가 평균보다 더 크게 틀리면 나눗셈 결과가 1보다 커짐 → $1 - 1.3 = -0.3$ → 음수

R²에 단위가 없는 이유도 여기서 나온다. cm²를 cm²로 나눴으니 단위가 서로 지워진다. 그래서 키를 재든 집값을 재든 똑같은 0~1 잣대로 비교할 수 있다.

R² 값 의미
1에 가까움 데이터의 변동을 거의 다 설명함. 아주 좋음
0.8 평균만 찍을 때 생기는 오차의 80%를 줄였다
0 평균으로 찍는 것과 똑같다 (모델이 있으나 마나)
음수 평균으로 찍느니만 못하다

R²가 음수가 나올 수 있다는 게 처음엔 이상했는데, 생각해보면 당연하다. 평균보다 못 맞추는 모델을 만드는 건 얼마든지 가능하니까. R²가 음수라면 그건 모델이 아니라 재앙이다.

MSE vs R² — 언제 뭘 보나

항목 MSE
값 범위 0 ~ 무한대 보통 0 ~ 1 (음수 가능)
단위 데이터 단위의 제곱 없음
알려주는 것 구체적인 오차 크기 상대적인 성능
좋은 값 0에 가까울수록 1에 가까울수록
약점 좋은지 나쁜지 감이 안 옴 실제로 얼마나 틀리는지 모름

정리하면 이렇다.

  • “평균 1000만원쯤 틀립니다” → MSE·RMSE가 답한다
  • “데이터 변동의 80%를 설명합니다” → R²가 답한다

둘은 경쟁 관계가 아니라 보완 관계다. 실무에서 손해 비용을 계산해야 하면 MSE, 여러 모델 중 뭐가 나은지 고를 땐 R²를 본다.


7. 분류의 평가 ① 정확도와 그 함정

분류는 정답이 범주라서 MSE를 쓸 수 없다. “고양이 − 강아지”를 뺄 수가 없으니까. 그래서 제일 먼저 나오는 게 정확도(Accuracy)다.

$$ \text{정확도} = \frac{\text{맞춘 개수}}{\text{전체 개수}} $$

단순하고 직관적이다. 그리고 이 단순함이 정확히 함정이다.

99% 정확도짜리 쓰레기 모델

강의에서 든 예시가 강렬했다. 1000명을 검사하는 질병 진단 모델을 만든다고 하자.

  • 실제 환자: 10명 (1%)
  • 건강한 사람: 990명 (99%)

여기서 이런 모델을 만든다.

“누가 오든 무조건 건강하다고 답하기”

이 모델의 정확도는? 990 ÷ 1000 = 99%다. 진단 로직이 단 한 줄도 없는데 99점짜리 모델이 나왔다.

그런데 이 모델은 환자 10명을 전부 놓쳤다. 우리가 이 모델을 만든 유일한 이유가 환자를 찾는 건데, 그 일만 완벽하게 실패했다.

이걸 불균형 데이터(imbalanced data) 문제라고 부른다. 정답 중 한쪽이 압도적으로 많으면, 정확도는 아무 의미가 없어진다.

이게 이번 강의에서 가장 무섭게 다가온 부분이었다. 숫자가 높다고 좋은 게 아니다. 오히려 “정확도 99%”라는 숫자는 문제를 덮어버린다. 아무도 의심하지 않게 되니까.

시각화를 정리하면서 “에러보다 조용한 무시가 더 무섭다”고 썼던 적이 있다. 히스토그램에 결측치가 있어도 에러 없이 그냥 빼고 그려주는 바람에, 화면에는 멀쩡한 그래프가 나오고 아무도 눈치를 못 챈다는 얘기였다. 정확도 99%가 정확히 같은 종류다. 에러는 나를 멈춰 세우지만, 그럴듯한 숫자는 나를 틀린 채로 계속 가게 만든다.


8. 분류의 평가 ② 혼동행렬

그래서 정확도 하나만 보면 안 되고, 틀린 방식까지 쪼개서 봐야 한다. 그게 혼동행렬(Confusion Matrix)이다.

혼동행렬

이름 붙이는 규칙만 알면 외울 게 없다.

  • 앞글자 T/F = 예측이 맞았나(True) 틀렸나(False)
  • 뒷글자 P/N = 모델이 양성(Positive)이라 했나 음성(Negative)이라 했나
약자 상황 별명
TP 진짜 환자를 환자라고 함 잘 잡음
TN 건강한 사람을 건강하다고 함 잘 넘어감
FP 건강한데 환자라고 함 오탐 (헛다리)
FN 환자인데 건강하다고 함 누락 (놓침)

두 종류의 틀림은 무게가 다르다

여기가 핵심이다. FP와 FN은 둘 다 “틀림”이지만 대가가 전혀 다르다.

  • 암 진단에서 FN — 환자를 집에 돌려보낸다. 사람이 죽을 수 있다.
  • 암 진단에서 FP — 건강한 사람이 정밀검사를 한 번 더 받는다. 번거롭고 비용이 들지만 되돌릴 수 있다.

반대인 경우도 있다. 스팸 필터에서 FP(정상 메일을 스팸함으로)는 중요한 메일을 놓치게 만들지만, FN(스팸이 받은편지함에 오는 것)은 그냥 짜증날 뿐이다.

어느 쪽 실수가 더 아픈지는 문제마다 다르다. 그래서 “정확도”라는 하나의 숫자로 뭉개면 안 된다. 이건 기술 문제가 아니라 도메인 판단이다.

정밀도, 재현율, F1

혼동행렬에서 두 지표가 나온다.

지표 계산 답하는 질문
정밀도 (Precision) TP ÷ (TP + FP) “양성이라고 외친 것 중 진짜는 몇 %?
재현율 (Recall) TP ÷ (TP + FN) “진짜 양성 중 몇 %나 잡아냈나?

앞서 나온 “무조건 건강하다고 답하는” 모델을 여기에 넣어보면 바로 드러난다. 양성이라 외친 적이 없으니 TP = 0, 결국 재현율 0%다. 정확도 99%와 재현율 0%가 같은 모델에서 나온다.

두 지표는 서로 밀고 당기는 관계다. 의심스러우면 전부 양성이라 외치면 재현율은 100%가 되지만 정밀도가 바닥나고, 확실할 때만 외치면 정밀도는 높지만 재현율이 떨어진다. 그래서 둘을 합친 F1-score를 쓴다.

$$ F_1 = \text{정밀도와 재현율의 조화평균} $$

조화평균은 한쪽이 심하게 낮으면 전체 값도 확 낮아지는 평균이다. 그냥 평균이면 (100% + 0%) ÷ 2 = 50%라는 그럴듯한 숫자가 나오지만, 조화평균은 이런 경우 0에 가까운 값을 뱉는다. 한쪽만 잘하는 걸 인정해주지 않는 평균이라고 보면 된다.

직관 ① 왕복 자전거

조화평균이 왜 필요한지는 자전거 왕복이 제일 잘 보여준다.

집에서 학교까지 6km. 갈 때는 신나서 시속 30km, 올 때는 지쳐서 시속 10km로 왔다. 그럼 왕복 평균 속도는?

그냥 평균으로 계산하면 (30 + 10) ÷ 2 = 20km/h. 그럴듯하지만 틀렸다. 실제로 세어보자.

  • 갈 때: 6km ÷ 30km/h = 0.2시간
  • 올 때: 6km ÷ 10km/h = 0.6시간
  • 합계: 12km를 0.8시간 동안 → 12 ÷ 0.8 = 15km/h

정답은 15km/h다. 왜 20보다 낮게 나오나? 느린 구간에 시간을 훨씬 오래 쓰기 때문이다. 빠른 30km/h 구간은 금방 끝나버리고, 느린 10km/h 구간에 시간의 대부분을 잡아먹힌다.

이게 조화평균이다. 느린 쪽·낮은 쪽이 결과를 끌고 간다.

직관 ② 사슬의 가장 약한 고리

F1이 이 평균을 쓰는 이유가 바로 그거다.

정밀도와 재현율은 둘 다 필요하다. 하나만 잘해선 쓸모없는 모델이다.

  • 재현율만 100% → 전부 “암입니다”라고 외친 것. 병원이 마비된다
  • 정밀도만 100% → 확실한 한 명만 잡고 나머지 환자를 다 놓친 것. 사람이 죽는다

산술평균은 이런 극단을 감싸준다. (100 + 0) ÷ 2 = 50점, 반타작한 것처럼 보인다. 조화평균은 감싸주지 않는다. 약한 쪽을 그대로 드러낸다.

사슬의 튼튼함은 가장 약한 고리가 정한다. 나머지 고리가 아무리 강해도 소용없다.

식으로 보면

조화평균의 정의는 이렇다.

$$ \text{조화평균} = \text{역수(뒤집기)의 평균을, 다시 뒤집은 값} $$

정밀도 P, 재현율 R로 쓰면 이렇게 된다.

$$ F_1 = \frac{1}{\dfrac{1}{2} \left( \dfrac{1}{P} + \dfrac{1}{R} \right)} $$

분수를 정리하면 흔히 보는 형태가 나온다.

$$ F_1 = \frac{2 \times P \times R}{P + R} $$

뒤집기(역수)가 핵심 장치다. 0.1처럼 작은 수를 뒤집으면 10처럼 큰 수가 된다. 즉 낮은 점수는 뒤집는 순간 거대해져서 평균을 지배해버리고, 그걸 다시 뒤집으면 전체가 확 낮아진다. 낮은 쪽에 확성기를 달아주는 평균인 셈이다.

숫자로 끝까지 계산해보기

경우 ① 둘 다 준수한 모델 — P = 0.6, R = 0.6

단계 계산
산술평균 $(0.6 + 0.6) \div 2$ 0.6
① 뒤집기 $1 \div 0.6 = 1.667$ / $1 \div 0.6 = 1.667$
② 평균 $(1.667 + 1.667) \div 2$ 1.667
③ 되뒤집기 $1 \div 1.667$ F₁ = 0.6

둘이 같으면 산술평균과 조화평균이 일치한다. 조화평균은 벌을 주려고 낮추는 게 아니라, 차이가 있을 때만 낮춘다.

경우 ② 한쪽으로 치우친 모델 — P = 0.9, R = 0.3

단계 계산
산술평균 $(0.9 + 0.3) \div 2$ 0.6 ← ①과 똑같다!
① 뒤집기 $1 \div 0.9 = 1.111$ / $1 \div 0.3 = 3.333$
② 평균 $(1.111 + 3.333) \div 2$ 2.222
③ 되뒤집기 $1 \div 2.222$ F₁ = 0.45

공식으로 확인해도 같다. $2 \times (0.9 \times 0.3) \div (0.9 + 0.3) = 2 \times 0.27 \div 1.2 = 0.45$

①과 ②는 산술평균이 똑같이 0.6이지만, F1은 0.6 vs 0.45로 갈린다. 재현율 0.3짜리 모델은 진짜 환자의 70%를 놓치고 있는데, 산술평균은 그걸 정밀도 0.9로 덮어버린다. F1은 안 덮어준다.

경우 ③ 극단 — P = 1.0, R = 0.01

“제일 확실한 1명만 암이라고 말하고 나머지 99명을 놓친” 모델이다.

단계 계산
산술평균 $(1.0 + 0.01) \div 2$ 0.505 ← 절반은 한 것처럼 보인다
① 뒤집기 $1 \div 1.0 = 1$ / $1 \div 0.01 = 100$
② 평균 $(1 + 100) \div 2$ 50.5
③ 되뒤집기 $1 \div 50.5$ F₁ ≈ 0.02

$1 \div 0.01 = 100$. 여기가 확성기가 작동하는 지점이다. 0.01이라는 작은 수가 뒤집히면서 100이 되어 평균을 완전히 장악한다. 결과는 0.02, 사실상 낙제다. 실제로 낙제가 맞다.

한쪽이 0이면? 뒤집을 수 없으니(1÷0) 규칙상 F1 = 0으로 정한다. 하나라도 0이면 그 모델은 0점이다.

경우 정밀도 재현율 산술평균 F1(조화평균)
① 균형 0.6 0.6 0.6 0.60
② 치우침 0.9 0.3 0.6 0.45
③ 극단 1.0 0.01 0.505 0.02
④ 한쪽 0 1.0 0 0.5 0

한 줄로 정리하면 이렇다. F1은 “둘 다 잘해야만 점수를 준다”는 요구를 숫자로 만든 것이다.


9. 분류의 평가 ③ 임계값과 ROC-AUC

ROC와 AUC

분류 모델은 처음부터 “암” 또는 “정상”이라고 딱 잘라 말하지 않는다. 보통은 양성일 가능성을 0과 1 사이 숫자로 내놓고, 사람이 정한 임계값을 넘으면 양성으로 판정한다.

예를 들어 같은 0.7이라는 예측도 기준에 따라 답이 달라진다.

임계값 0.7의 최종 판정 보통 생기는 변화
0.5 양성 더 많이 잡지만 FP도 늘기 쉽다
0.8 음성 확실한 것만 잡지만 FN이 늘기 쉽다

즉 정밀도와 재현율의 줄다리기는 모델만의 성질이 아니라 임계값을 어디에 두느냐의 문제이기도 하다. 병원처럼 놓치면 큰일 나는 곳은 임계값을 낮춰 재현율을 챙길 수 있고, 잘못 차단했을 때 피해가 큰 보안 시스템은 정밀도를 더 챙길 수 있다.

ROC 곡선은 임계값을 낮은 곳부터 높은 곳까지 바꿔가며 다음 두 값을 그린 그림이다.

  • TPR: 실제 양성 중 제대로 찾아낸 비율. 재현율과 같다
  • FPR: 실제 음성 중 양성이라고 잘못 외친 비율

좋은 모델은 FPR은 낮게 유지하면서 TPR을 빠르게 높인다. ROC 곡선 아래의 넓이가 AUC이며, 1에 가까울수록 여러 임계값에서 양성과 음성을 잘 구분했다는 뜻이다. 0.5 부근이면 동전 던지기와 비슷하다.

다만 AUC만 보고 끝내면 안 된다.

  • AUC는 어떤 임계값으로 서비스할지 정해주지 않는다
  • 양성이 아주 드문 데이터에서는 ROC-AUC가 좋아 보여도 실제 알림의 대부분이 오탐일 수 있다
  • 그래서 마지막에는 도메인 비용을 반영해 임계값을 정하고, 그 지점의 정밀도·재현율·혼동행렬을 함께 봐야 한다

실무 순서 — AUC로 모델의 전반적인 구분 능력을 비교하고, 실제 운영에서는 FP와 FN의 비용을 따져 임계값을 고른다.


10. 분류의 평가 ④ 교차 엔트로피

혼동행렬까지 봤으면 평가는 충분한 것 같은데, 학습에는 하나가 더 필요하다. 이유가 재밌다.

정확도와 혼동행렬은 맞음/틀림만 센다. 그런데 다음 두 모델을 생각해보자.

  스팸일 확률로 답한 값 최종 판정 정확도
모델 A 0.51 스팸 맞음
모델 B 0.95 스팸 맞음

정확도로는 완전히 똑같다. 하지만 B가 훨씬 좋은 모델이다. 확신을 가지고 맞췄으니까. A는 아슬아슬하게 넘긴 거라 조금만 데이터가 흔들려도 틀리게 된다.

정확도는 이 차이를 못 본다. 그래서 학습 중에는 “정답을 얼마나 확신했는지”까지 반영하는 손실이 필요하고, 그게 교차 엔트로피다.

$$ \text{손실} = -\log(\text{정답 범주에 준 확률}) $$

로그가 나와서 겁먹기 쉬운데, 하는 일은 딱 하나다. 정답에 높은 확률을 줬으면 벌점이 작고, 낮은 확률을 줬으면 벌점이 급격히 커진다.

정답에 준 확률 벌점 느낌
0.9 0.11 잘 맞췄네, 조금만
0.6 0.51 애매했네
0.1 2.30 자신 있게 틀렸네, 크게 벌준다

여기서 성격이 드러난다. 확률이 0에 가까워질수록 벌점은 끝없이 커진다. 즉 교차 엔트로피는 “확신을 갖고 틀리는 것”을 가장 심하게 처벌하는 손실이다. 개인적으로 이 성질이 굉장히 웃겻다. 모르면서 확신하는 게 제일 위험하다..!

직관: 도박판 배당

교차 엔트로피는 “정답에 얼마나 돈을 걸었냐” 게임으로 보면 쉽다.

모델은 매 문제마다 가진 돈 100원 전부를 보기들에 나눠 걸어야 한다. 남길 수도 없고 더 걸 수도 없다. 정답이 공개되면, 정답 칸에 걸어둔 돈만큼만 살아남는다.

  • 정답에 90원 걸었으면 → 거의 다 지킴 → 벌점 작음
  • 정답에 10원 걸었으면 → 90원 날림 → 벌점 큼
  • 정답에 0원 걸었으면 → 전부 날림 → 벌점 무한대

“전부 나눠 걸어야 한다”는 규칙이 핵심이다. 한 곳에 많이 걸려면 다른 곳을 줄여야 한다. 그래서 모델은 자연히 “확실할 때만 확신하는” 습관을 배운다.

이 규칙을 수식으로 만든 게 소프트맥스이고, 살아남은 돈을 벌점으로 바꾸는 게 −log다.

식의 정식 형태

앞의 $\text{손실} = -\log(\text{정답 범주에 준 확률})$ 은 줄인 표현이다. 원래 식은 이렇게 생겼다.

$$ L = -\left( y_1 \log p_1 + y_2 \log p_2 + \cdots + y_C \log p_C \right) $$

기호가 무섭게 생겼지만 뜻은 단순하다.

기호
$C$ 보기(범주)의 개수. 고양이/강아지/토끼면 3
$p_i$ 모델이 $i$ 번 보기에 건 돈(확률)
$y_i$ 정답이면 1, 아니면 0
전체에 붙은 $-$ 로그값이 음수라서 뒤집어 양수 벌점으로 만드는 장치

여기서 마술이 일어난다. $y_i$ 가 정답 칸에서만 1이고 나머지는 전부 0이니까, 곱하는 순간 정답이 아닌 항은 전부 사라진다.

보기가 3개고 정답이 2번일 때:

$$ L = -\left( 0 \times \log p_1 + 1 \times \log p_2 + 0 \times \log p_3 \right) = -\log p_2 $$

결국 “정답 칸에 건 확률 하나만 보면 된다.” 앞에 나온 줄임 표현이 그래서 맞는 말이다. 정답 칸만 1로 세우고 나머지를 0으로 두는 이 표기를 원-핫(one-hot)이라고 부른다.

그리고 데이터가 N개면 전부 계산해서 평균을 낸다.

$$ \text{전체 손실} = \frac{\text{데이터 1개당 } L \text{ 을 전부 더한 값}}{N} $$

log의 밑은? 보통 자연로그(ln, 밑 e)를 쓴다. 밑이 바뀌어도 전체가 일정 비율로만 커지거나 작아져서 최소가 되는 지점은 같다. 학습 결과에 영향이 없다.

갈림길 — 보기가 2개냐 3개 이상이냐

같은 교차 엔트로피인데, 보기 개수에 따라 확률 만드는 방식이 달라진다. 이게 이 절의 핵심이다.

  이진 분류 다중 분류
보기 2개 (스팸/정상) 3개 이상 (고양이/강아지/토끼)
출력 개수 숫자 1개 보기 수만큼 C개
확률로 바꾸는 함수 시그모이드 (Sigmoid) 소프트맥스 (Softmax)
손실 이름 BCE (Binary Cross Entropy) CCE (Categorical Cross Entropy)
라벨 표기 0 또는 1 원-핫 (또는 정수 인덱스)

왜 다르냐면, 보기가 2개일 땐 숫자 하나면 충분하기 때문이다. “스팸일 확률 0.8”이라고 말하는 순간 “정상일 확률 0.2”는 저절로 정해진다. 굳이 두 개를 출력할 이유가 없다.


경우 ① 이진 분류 — 시그모이드 + BCE

모델이 마지막에 뱉는 건 확률이 아니라 아무 범위의 날것 숫자다. 이걸 로짓(logit)이라 부른다. −3.7일 수도, 8.2일 수도 있다. 확률로 쓰려면 0~1 사이로 눌러 담아야 한다. 그 역할이 시그모이드다.

$$ \text{sigmoid}(z) = \frac{1}{1 + e^{-z}} $$

성질만 보면 된다.

로짓 z 시그모이드 결과 읽는 법
−2 0.12 아닐 것 같다
0 0.5 완전히 모르겠다
+2 0.88 맞을 것 같다
+10 0.9999 거의 확신

아무리 큰 수를 넣어도 1을 넘지 않고, 아무리 작은 수를 넣어도 0 밑으로 안 간다. S자로 눕는 모양이라 이름이 시그모이드다.

이렇게 나온 확률 p 하나로 손실을 쓰면 BCE가 된다.

$$ \text{BCE} = -\left( y \log p + (1 - y) \log (1 - p) \right) $$

$y$ 는 정답이 스팸이면 1, 정상이면 0이다. 스위치 두 개 중 하나만 켜지는 구조다.

정답이 스팸($y=1$)이면 뒤쪽 $(1-y)$ 가 0이 되어 사라진다.

$$ \text{BCE} = -\log p $$

정답이 정상($y=0$)이면 앞쪽 $y$ 가 0이 되어 사라진다.

$$ \text{BCE} = -\log (1 - p) $$

숫자로 계산해보기. 모델이 “스팸일 확률 0.8”이라고 답했다.

실제 정답 계산 벌점
스팸 (잘 맞췄다) $-\log(0.8)$ 0.223
정상 (자신 있게 틀렸다) $-\log(1 - 0.8) = -\log(0.2)$ 1.609

같은 예측 0.8인데 정답이 뭐냐에 따라 벌점이 7배 넘게 갈린다.


경우 ② 다중 분류 — 소프트맥스 + CCE

보기가 3개면 로짓도 3개 나온다. 예를 들어 [2.0, 1.0, 0.1] 같은 식이다. 문제는 이 숫자들이 확률이 아니라는 것이다. 음수도 섞이고, 다 더해도 1이 안 된다.

소프트맥스가 이 세 숫자를 “다 더하면 1이 되는 확률 세 개”로 바꿔준다.

$$ \text{softmax}(z_i) = \frac{e^{z_i}}{e^{z_1} + e^{z_2} + \cdots + e^{z_C}} $$

말로 옮기면 두 단계다.

  1. 각 숫자를 e의 지수로 올린다 ($e^z$) → 전부 양수가 되고, 큰 값이 더 크게 벌어진다
  2. 전체 합으로 나눈다 → 다 더하면 정확히 1이 된다

$e$ 를 쓰는 이유는 1단계 때문이다. 음수를 없애면서(e^음수도 양수) 순서는 그대로 유지하는 가장 다루기 쉬운 함수라서다.

숫자로 계산해보기. 로짓이 고양이 2.0, 강아지 1.0, 토끼 0.1이다.

1단계 — e의 지수로 올리기

보기 로짓 $z$ $e^z$
고양이 2.0 7.389
강아지 1.0 2.718
토끼 0.1 1.105
  합계 11.212

2단계 — 합으로 나누기

보기 계산 확률
고양이 7.389 ÷ 11.212 0.659
강아지 2.718 ÷ 11.212 0.242
토끼 1.105 ÷ 11.212 0.099
  합계 1.000

100원을 66원 / 24원 / 10원으로 나눠 건 셈이다. 딱 100원이다.

3단계 — 손실 계산

실제 정답 계산 벌점
고양이 (제일 크게 걸었다) $-\log(0.659)$ 0.417
토끼 (10원밖에 안 걸었다) $-\log(0.099)$ 2.313

로짓 차이가 2.0 vs 0.1로 겨우 1.9인데 벌점은 0.417 vs 2.313으로 5배 넘게 벌어진다. 지수와 로그를 거치면서 차이가 증폭된 결과다.


시그모이드와 소프트맥스의 관계

둘은 남남이 아니다. 소프트맥스에 보기를 2개만 넣으면 시그모이드가 된다. 즉 시그모이드는 소프트맥스의 2개짜리 특수한 경우다.

그래서 이진 분류를 소프트맥스(출력 2개)로 짜도 결과는 같다. 다만 출력 하나로 끝나는 시그모이드가 더 간단해서 관행적으로 그렇게 쓴다.

헷갈리기 쉬운 세 가지

1. 소프트맥스는 “합이 1”이고, 시그모이드는 아니다.

라벨을 여러 개 동시에 달아야 하는 문제(사진 한 장에 “고양이 + 실내 + 낮”이 전부 참인 경우)는 소프트맥스를 쓰면 안 된다. 서로 뺏어가는 구조라서 그렇다. 이럴 땐 라벨마다 시그모이드를 따로 붙인다.

상황 쓸 것
답이 딱 하나 (고양이 아니면 강아지) 소프트맥스
답이 여러 개 가능 (고양이면서 실내면서 낮) 라벨별 시그모이드

2. $\log(0)$ 은 계산할 수 없다.

정답에 확률 0을 줬다면 벌점이 무한대다. 컴퓨터는 무한대를 만나면 학습이 깨진다. 그래서 실제 코드는 확률을 0과 1에서 아주 살짝 떨어뜨려 놓거나, 소프트맥스와 손실 계산을 하나로 합친 함수를 쓴다. PyTorch의 CrossEntropyLoss가 소프트맥스를 이미 품고 있는 게 그 이유다. 그 함수엔 로짓을 그대로 넣어야 하고, 소프트맥스를 먼저 씌워서 넣으면 두 번 적용돼서 틀린다.

3. 이름이 여러 개다.

부르는 이름 실체
Binary Cross Entropy (BCE) 보기 2개, 시그모이드
Categorical Cross Entropy 보기 3개 이상, 라벨이 원-핫
Sparse Categorical Cross Entropy 위와 같지만 라벨이 정수(0, 1, 2···)
Log Loss 그냥 BCE의 다른 이름

전부 같은 식이다. 확률 만드는 방법과 라벨 적는 형식만 다를 뿐이다.

한 장 요약

  이진 분류 다중 분류
모델 출력 로짓 1개 로짓 C개
확률 변환 $\dfrac{1}{1 + e^{-z}}$ $\dfrac{e^{z_i}}{\text{전체 } e^z \text{의 합}}$
확률 합 1 아님 (혼자니까) 정확히 1
손실 $-\left( y \log p + (1-y) \log (1-p) \right)$ $-\log(\text{정답 칸 확률})$
정답 표기 0 또는 1 원-핫

정리 — 정확도·정밀도·재현율은 학습이 끝난 뒤 결과를 평가하는 지표, 교차 엔트로피는 학습 도중에 줄여 나가는 손실이다. 역할이 다르다.


11. 학습의 진짜 목적과 오버피팅

이제 시작에서 던진 문장으로 돌아온다.

학습의 목적은 훈련 데이터를 잘 맞추는 게 아니라, 처음 보는 데이터를 잘 맞추는 것이다.

그래서 성능 평가는 반드시 학습에 쓰지 않은 데이터로 해야 한다. 훈련 데이터로 평가하는 건 문제집으로 시험 보는 것과 같아서 아무 의미가 없다. 이 능력을 일반화(Generalization)라고 부른다.

그리고 일반화를 방해하는 대표적인 병이 오버피팅이다.

오버피팅과 언더피팅

  언더피팅 (과소적합) 오버피팅 (과대적합)
원인 모델이 너무 단순하거나 학습 부족 모델이 너무 복잡
증상 중요한 패턴조차 못 잡음 잡음까지 통째로 외움
훈련 성능 나쁨 아주 좋음
시험 성능 나쁨 나쁨

오버피팅이 무서운 이유는 훈련 성적표가 아주 좋아 보인다는 데 있다. 언더피팅은 훈련 점수부터 낮으니 바로 알아채지만, 오버피팅은 “우리 모델 정확도 99%!”라고 자랑하다가 실전에서 무너진다.

왜 나쁜가

  • 표본에 의존한다 — 훈련 데이터는 세상 전체의 일부일 뿐이고, 거기엔 우연한 잡음이 섞여 있다. 그 잡음까지 외우면 데이터 몇 개만 바뀌어도 예측이 크게 흔들린다.
  • 일반화에 실패한다 — 못 본 데이터에서 오류가 커진다. 결국 실전에서 못 쓴다.

더 쉬운 비유로. 문제집의 답 순서를 외운 아이다. “3번 문제는 ②번”까지 외웠으니 문제집 점수는 만점인데, 시험지 순서가 바뀌면 아무것도 못 한다.

오버피팅과 헷갈리기 쉬운 것

강의에서 짚어준 것 중 유용했던 구분이 있다.

오버피팅 ≠ 분포 변화(distribution shift)로 인한 성능 저하

훈련할 때 본 데이터와 실제 들어오는 데이터의 성격 자체가 달라져서 성능이 떨어지는 경우가 있다. 실사진으로만 학습했는데 만화 그림이 들어온다든지, 여름 데이터로 배웠는데 겨울이 온다든지, 센서를 새 걸로 바꿨다든지.

이건 모델이 과하게 학습해서 생긴 문제가 아니다. 모델이 아무리 적당히 학습했어도 발생한다. 원인이 다르니 해결책도 다르다. 오버피팅은 모델을 단순화해서 잡지만, 분포 변화는 데이터를 다시 모아야 한다.

그래서 어떻게 잡나

균형점을 찾아야 하는데, 실마리는 이렇다.

  • 데이터를 더 많이 모은다
  • 학습에 쓰지 않은 데이터로 성능을 확인하면서 모델을 고른다
  • 교차 검증을 쓴다

마지막 두 개가 다음 글의 주제다.


정리

  • 지도학습 = 입력 + 정답 쌍으로 배우고, 처음 보는 데이터에서 잘하는 게 목표
  • 정답이 숫자면 회귀, 범주면 분류
  • 오류(ŷ − y)는 줄이는 것, 측정 오차(ε)는 못 줄이는 것 — 다른 개념이다
  • 회귀 평가: MSE(구체적 오차 크기), (평균 찍기 대비 상대 성능). 둘은 보완 관계
  • 분류 평가: 정확도는 불균형 데이터에서 무력해진다 → 혼동행렬로 쪼개 봐야 한다
  • FP와 FN의 대가는 다르다. 어느 쪽이 더 아픈지는 도메인이 정한다
  • ROC-AUC는 임계값 전체에서 구분 능력을 비교한다. 실제 서비스 임계값은 FP·FN 비용으로 따로 정한다
  • 교차 엔트로피는 확신도까지 반영하는 손실. 자신 있게 틀리면 크게 벌준다
  • 오버피팅은 훈련 점수가 좋아서 더 위험하다. 분포 변화와는 다른 문제

다음 글에서

다음 글에서는 “처음 보는 데이터에서의 성능을 어떻게 미리 알아내는가”를 다룬다. 검증셋과 K-겹 교차검증, 그리고 정답이 아예 없는 비지도학습까지 정리한다.

한줄 평

  • AI 학습에 관하여 사용하는 여러 기법, 그리고 왜 이런 공식을 사용하게 되었는지에 대해 배울수록 세상엔 천재들이 많고 그 생각들을 공유받는 과정이 너무 고맙다고 느껴졌다. ( 그리고 나름 재밌다! )