본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 11. 28. · 16 Views
정보 이론 기초 완벽 가이드
머신러닝의 핵심 기반인 정보 이론의 기초 개념을 다룹니다. 엔트로피부터 크로스 엔트로피, KL 발산까지 손실 함수의 수학적 원리를 이해할 수 있습니다.
목차
1. 엔트로피 개념
김개발 씨는 머신러닝 프로젝트를 진행하던 중 손실 함수 그래프를 보며 고개를 갸웃거렸습니다. "왜 하필 이런 수식을 쓰는 걸까요?" 옆에 있던 박시니어 씨가 웃으며 말했습니다.
"그걸 이해하려면 먼저 엔트로피부터 알아야 해요."
엔트로피는 한마디로 불확실성을 수치로 표현한 것입니다. 마치 동전 던지기의 결과를 예측하기 어려운 정도를 숫자로 나타내는 것과 같습니다.
엔트로피가 높으면 예측이 어렵고, 낮으면 예측이 쉽습니다. 이 개념을 이해하면 왜 머신러닝 모델이 특정 방식으로 학습하는지 명확해집니다.
다음 코드를 살펴봅시다.
import numpy as np
def entropy(probabilities):
# 확률이 0인 경우를 처리합니다
probs = np.array(probabilities)
probs = probs[probs > 0]
# 엔트로피 공식: -sum(p * log2(p))
return -np.sum(probs * np.log2(probs))
# 동전 던지기: 앞면 50%, 뒷면 50%
fair_coin = [0.5, 0.5]
print(f"공정한 동전 엔트로피: {entropy(fair_coin):.2f} bits")
# 편향된 동전: 앞면 90%, 뒷면 10%
biased_coin = [0.9, 0.1]
print(f"편향된 동전 엔트로피: {entropy(biased_coin):.2f} bits")
김개발 씨는 입사 6개월 차 주니어 개발자입니다. 오늘 팀 회의에서 선배가 "이 모델의 엔트로피가 높다"라고 말했는데, 도무지 무슨 뜻인지 이해가 되지 않았습니다.
회의가 끝난 후 박시니어 씨에게 조심스럽게 물었습니다. "선배, 엔트로피가 정확히 뭔가요?
물리학에서 배운 것 같기도 한데..." 박시니어 씨가 자판기 앞으로 김개발 씨를 데려갔습니다. "여기 음료가 10종류 있잖아요.
내가 어떤 음료를 뽑을지 맞춰보세요." 김개발 씨는 난감했습니다. 10개 중 하나라니, 도무지 감이 오지 않습니다.
"이번엔 다르게 해볼게요. 내가 매일 아침 아메리카노만 마신다는 걸 알고 있다면요?" 이번엔 쉽습니다.
"아메리카노요!" 엔트로피란 바로 이런 것입니다. 결과를 예측하기 어려운 정도를 숫자로 나타낸 것입니다.
10가지 음료 중 무작위로 선택하는 상황은 엔트로피가 높습니다. 반면 항상 아메리카노만 마시는 상황은 엔트로피가 낮습니다.
수학적으로 엔트로피는 -sum(p * log2(p)) 공식으로 계산합니다. 여기서 p는 각 사건이 일어날 확률입니다.
로그를 사용하는 이유는 정보량을 비트 단위로 표현하기 위해서입니다. 공정한 동전을 예로 들어봅시다.
앞면이 나올 확률 50%, 뒷면이 나올 확률 50%입니다. 이 경우 엔트로피는 정확히 1비트입니다.
결과를 알기 위해 "앞면인가요?"라는 질문 하나가 필요하다는 의미입니다. 반면 앞면이 90% 확률로 나오는 편향된 동전은 어떨까요?
엔트로피가 약 0.47비트로 낮아집니다. 대부분 앞면이 나올 것이라고 예측할 수 있기 때문입니다.
위의 코드를 살펴보겠습니다. entropy 함수는 확률 배열을 받아서 엔트로피를 계산합니다.
먼저 확률이 0인 경우를 제외합니다. 0에 로그를 취하면 무한대가 되기 때문입니다.
그 다음 엔트로피 공식을 적용합니다. 실행 결과를 보면 공정한 동전의 엔트로피는 1.00비트, 편향된 동전은 0.47비트입니다.
수치가 확실히 차이 납니다. 머신러닝에서 엔트로피가 중요한 이유는 무엇일까요?
모델이 내놓는 예측의 확신도를 측정할 수 있기 때문입니다. 모델이 "이 이미지는 고양이일 확률 99%"라고 말하면 엔트로피가 낮습니다.
반면 "고양이 33%, 개 33%, 새 34%"라고 말하면 엔트로피가 높습니다. 김개발 씨가 고개를 끄덕였습니다.
"그러니까 엔트로피가 낮을수록 모델이 확신을 가지고 예측한다는 거군요!" 박시니어 씨가 미소 지었습니다. "정확해요.
그리고 이 개념이 바로 손실 함수를 이해하는 첫 번째 열쇠예요."
실전 팁
💡 - 엔트로피는 항상 0 이상의 값을 가지며, 모든 사건이 동일한 확률일 때 최대가 됩니다
- 확률값에 0이 있으면 별도 처리가 필요합니다 (0 * log(0) = 0으로 정의)
2. 크로스 엔트로피
엔트로피를 배운 김개발 씨는 다음 날 코드를 보다가 또 막혔습니다. 손실 함수에 CrossEntropyLoss라고 적혀 있었기 때문입니다.
"엔트로피랑 크로스 엔트로피는 뭐가 다른 거지?" 김개발 씨는 다시 박시니어 씨를 찾아갔습니다.
크로스 엔트로피는 두 확률 분포 사이의 차이를 측정하는 방법입니다. 마치 정답지와 내 답안이 얼마나 다른지 점수로 매기는 것과 같습니다.
실제 분포 p와 예측 분포 q가 있을 때, q를 사용해 p를 설명하려면 얼마나 많은 정보가 필요한지를 나타냅니다.
다음 코드를 살펴봅시다.
import numpy as np
def cross_entropy(p_true, q_pred):
# p: 실제 분포, q: 예측 분포
p = np.array(p_true)
q = np.array(q_pred)
# 수치 안정성을 위해 작은 값 추가
q = np.clip(q, 1e-15, 1)
# 크로스 엔트로피: -sum(p * log(q))
return -np.sum(p * np.log(q))
# 실제 레이블: 고양이(원-핫 인코딩)
true_label = [1, 0, 0] # [고양이, 개, 새]
# 좋은 예측
good_pred = [0.9, 0.05, 0.05]
print(f"좋은 예측의 크로스 엔트로피: {cross_entropy(true_label, good_pred):.4f}")
# 나쁜 예측
bad_pred = [0.1, 0.6, 0.3]
print(f"나쁜 예측의 크로스 엔트로피: {cross_entropy(true_label, bad_pred):.4f}")
박시니어 씨가 화이트보드 앞에 섰습니다. "엔트로피가 혼자만의 불확실성이라면, 크로스 엔트로피는 두 가지를 비교하는 거예요." 비유를 들어보겠습니다.
여러분이 시험을 봤다고 생각해보세요. 정답지가 있고, 여러분의 답안이 있습니다.
크로스 엔트로피는 여러분의 답안이 정답지와 얼마나 다른지를 점수로 매긴 것입니다. 정답에 가까우면 점수가 낮고, 정답에서 멀면 점수가 높습니다.
여기서 점수가 낮을수록 좋다는 점을 기억하세요. 손실 함수니까요.
수학적으로 크로스 엔트로피는 -sum(p * log(q)) 입니다. p는 실제 분포(정답), q는 예측 분포(우리의 답)입니다.
엔트로피 공식과 비슷하지만, 로그 안에 들어가는 것이 p가 아니라 q라는 점이 다릅니다. 위의 코드를 살펴봅시다.
이미지 분류 문제를 가정했습니다. 실제로 그 이미지는 고양이입니다.
원-핫 인코딩으로 [1, 0, 0]이라고 표현했습니다. 좋은 모델은 "고양이 90%, 개 5%, 새 5%"라고 예측했습니다.
크로스 엔트로피는 약 0.1054입니다. 꽤 낮은 값이죠.
나쁜 모델은 "고양이 10%, 개 60%, 새 30%"라고 예측했습니다. 크로스 엔트로피는 약 2.3026입니다.
훨씬 높습니다. 여기서 중요한 점이 있습니다.
np.clip 함수로 q값의 최솟값을 1e-15로 제한했습니다. 왜일까요?
만약 예측값이 0이고 실제값이 1이면, log(0)이 되어 무한대가 나옵니다. 이를 방지하기 위한 안전장치입니다.
"그런데 선배, 실제 레이블이 원-핫 인코딩이면 어차피 1인 위치만 계산에 영향을 주지 않나요?" 박시니어 씨가 감탄했습니다. "정확해요!
p가 원-핫 인코딩일 때, 크로스 엔트로피는 결국 **-log(q_correct)**가 됩니다. 정답 클래스에 대한 예측 확률의 음의 로그값이죠." 이것이 바로 머신러닝에서 크로스 엔트로피 손실 함수가 작동하는 원리입니다.
모델이 정답 클래스에 높은 확률을 부여하도록 학습시키는 것입니다. 실무에서 PyTorch나 TensorFlow를 사용할 때 CrossEntropyLoss를 자주 보게 될 겁니다.
이제 그 안에서 무슨 일이 일어나는지 이해하셨을 겁니다. 김개발 씨가 환하게 웃었습니다.
"이제 손실 함수가 왜 그렇게 생겼는지 알겠어요!"
실전 팁
💡 - 크로스 엔트로피는 항상 엔트로피보다 크거나 같습니다 (두 분포가 같을 때만 동일)
- 예측값이 0에 가까워지면 손실이 무한대로 커지므로 수치 안정성 처리가 필수입니다
3. KL 발산
다음 주 팀 미팅에서 데이터 사이언티스트가 "두 모델의 출력 분포를 KL 발산으로 비교해봤습니다"라고 발표했습니다. 김개발 씨는 또 모르는 용어가 나왔습니다.
미팅이 끝나고 박시니어 씨에게 물었습니다. "KL 발산은 또 뭔가요?
크로스 엔트로피랑 다른 건가요?"
KL 발산(Kullback-Leibler Divergence)은 한 확률 분포가 다른 확률 분포와 얼마나 다른지를 측정합니다. 크로스 엔트로피에서 엔트로피를 뺀 값입니다.
두 분포가 완전히 같으면 0이 되고, 다를수록 커집니다.
다음 코드를 살펴봅시다.
import numpy as np
def kl_divergence(p, q):
# p: 기준 분포, q: 비교 분포
p = np.array(p)
q = np.array(q)
# 0인 확률 처리
mask = p > 0
p = p[mask]
q = np.clip(q[mask], 1e-15, 1)
# KL 발산: sum(p * log(p/q))
return np.sum(p * np.log(p / q))
# 실제 분포
p = [0.4, 0.3, 0.2, 0.1]
# 비슷한 예측 분포
q_similar = [0.35, 0.35, 0.2, 0.1]
print(f"비슷한 분포와의 KL 발산: {kl_divergence(p, q_similar):.4f}")
# 다른 예측 분포
q_different = [0.1, 0.1, 0.3, 0.5]
print(f"다른 분포와의 KL 발산: {kl_divergence(p, q_different):.4f}")
# 주의: KL(P||Q) != KL(Q||P)
print(f"역방향 KL 발산: {kl_divergence(q_different, p):.4f}")
박시니어 씨가 설명을 시작했습니다. "KL 발산은 쉽게 말해서 정보 손실을 측정하는 거예요." 비유를 들어보겠습니다.
여러분이 고향의 맛집 지도를 친구에게 알려준다고 생각해보세요. 여러분의 머릿속에 있는 완벽한 지도가 P입니다.
친구가 여러분의 설명을 듣고 그린 지도가 Q입니다. KL 발산은 친구의 지도가 여러분의 지도와 얼마나 다른지를 측정합니다.
수학적으로 KL 발산은 sum(p * log(p/q)) 입니다. 이를 풀어쓰면 sum(p * log(p)) - sum(p * log(q)) 가 됩니다.
첫 번째 항은 음의 엔트로피이고, 두 번째 항은 음의 크로스 엔트로피입니다. 따라서 KL 발산 = 크로스 엔트로피 - 엔트로피 라는 관계가 성립합니다.
여기서 중요한 특성이 있습니다. KL 발산은 비대칭적입니다.
KL(P||Q)와 KL(Q||P)는 다른 값입니다. 코드의 마지막 부분에서 이를 확인할 수 있습니다.
이 비대칭성은 실제로 의미가 있습니다. P가 실제 분포이고 Q가 모델의 예측이라면, KL(P||Q)는 "실제 상황에서 모델을 사용했을 때의 정보 손실"입니다.
반대로 KL(Q||P)는 "모델이 예측하는 상황에서 실제를 적용했을 때의 정보 손실"입니다. 머신러닝에서는 주로 KL(P||Q)를 사용합니다.
실제 데이터 분포 P에 맞춰서 모델 분포 Q를 학습시키기 때문입니다. "그런데 선배, 크로스 엔트로피를 손실 함수로 쓰는데 왜 KL 발산이 따로 필요한 거예요?" 좋은 질문입니다.
분류 문제에서 실제 레이블의 엔트로피는 상수입니다. 원-핫 인코딩된 레이블의 엔트로피는 항상 0이거든요.
따라서 크로스 엔트로피를 최소화하는 것과 KL 발산을 최소화하는 것이 동일합니다. 하지만 두 모델의 출력을 비교하거나, 생성 모델에서 잠재 분포를 학습할 때는 KL 발산 자체가 필요합니다.
VAE(Variational Autoencoder)가 대표적인 예입니다. 김개발 씨가 정리했습니다.
"크로스 엔트로피는 예측과 정답의 차이를 측정하고, KL 발산은 두 분포 사이의 순수한 차이를 측정하는 거군요!" 박시니어 씨가 고개를 끄덕였습니다. "맞아요.
그리고 실제로는 상황에 따라 적절한 것을 선택하면 됩니다."
실전 팁
💡 - KL 발산은 항상 0 이상이며, 두 분포가 같을 때만 0입니다
- 비대칭성 때문에 KL(P||Q)와 KL(Q||P) 중 어떤 것을 사용할지 신중히 선택해야 합니다
4. 정보 이득
김개발 씨는 의사결정나무(Decision Tree)를 공부하다가 "정보 이득"이라는 용어를 발견했습니다. "엔트로피가 여기서도 나오네?" 호기심이 생긴 김개발 씨는 정보 이득이 무엇인지 직접 구현해보기로 했습니다.
정보 이득(Information Gain)은 어떤 속성으로 데이터를 분할했을 때 불확실성이 얼마나 줄어드는지를 측정합니다. 분할 전 엔트로피에서 분할 후 가중 평균 엔트로피를 뺀 값입니다.
의사결정나무는 정보 이득이 가장 큰 속성을 선택하여 분할합니다.
다음 코드를 살펴봅시다.
import numpy as np
from collections import Counter
def entropy(labels):
n = len(labels)
if n == 0:
return 0
counts = Counter(labels)
probs = [count / n for count in counts.values()]
return -sum(p * np.log2(p) for p in probs if p > 0)
def information_gain(parent_labels, children_labels_list):
# 부모 노드의 엔트로피
parent_entropy = entropy(parent_labels)
# 자식 노드들의 가중 평균 엔트로피
total = len(parent_labels)
weighted_child_entropy = sum(
(len(child) / total) * entropy(child)
for child in children_labels_list
)
# 정보 이득 = 부모 엔트로피 - 자식 가중 평균 엔트로피
return parent_entropy - weighted_child_entropy
# 예시: 날씨에 따른 운동 여부
labels = ['Yes', 'Yes', 'No', 'Yes', 'No', 'No', 'Yes', 'Yes']
# 맑음/흐림으로 분할한 경우
sunny = ['Yes', 'Yes', 'Yes', 'Yes'] # 맑을 때
cloudy = ['No', 'No', 'No', 'Yes'] # 흐릴 때
print(f"정보 이득: {information_gain(labels, [sunny, cloudy]):.4f}")
김개발 씨는 의사결정나무를 공부하면서 문득 궁금해졌습니다. "나무가 어떻게 최적의 분기점을 찾는 걸까?" 비유를 들어보겠습니다.
스무고개 게임을 한다고 생각해보세요. 상대방이 생각하는 동물을 맞춰야 합니다.
어떤 질문을 해야 가장 효율적으로 답을 찾을 수 있을까요? "그것은 포유류인가요?"라는 질문은 좋은 질문입니다.
동물들을 거의 반반으로 나눌 수 있으니까요. 반면 "그것은 코끼리인가요?"는 좋지 않은 질문입니다.
대부분의 경우 "아니오"라는 답을 듣게 되어 정보를 많이 얻지 못합니다. 정보 이득은 바로 이 "좋은 질문"을 찾는 기준입니다.
질문 전의 불확실성에서 질문 후의 불확실성을 뺀 것입니다. 코드를 살펴보겠습니다.
운동을 할지 말지 예측하는 상황입니다. 전체 데이터는 Yes 5개, No 3개로 구성되어 있습니다.
날씨(맑음/흐림)로 분할하면 어떻게 될까요? 맑은 날에는 모두 Yes(운동함)이고, 흐린 날에는 No가 많습니다.
이 분할의 정보 이득을 계산합니다. information_gain 함수를 보면, 먼저 부모 노드의 엔트로피를 계산합니다.
Yes와 No가 섞여 있으니 엔트로피가 꽤 높습니다. 다음으로 각 자식 노드의 엔트로피를 계산하고, 크기에 비례하여 가중 평균을 구합니다.
맑은 날 자식 노드는 모두 Yes라서 엔트로피가 0입니다. 정보 이득은 부모 엔트로피에서 자식 가중 평균 엔트로피를 뺀 값입니다.
값이 클수록 그 속성으로 분할하는 것이 효과적이라는 뜻입니다. 의사결정나무 알고리즘은 모든 가능한 속성에 대해 정보 이득을 계산하고, 가장 큰 값을 가진 속성을 선택합니다.
이 과정을 재귀적으로 반복하여 나무를 구성합니다. "아, 그래서 의사결정나무가 어떤 속성을 먼저 선택하는지 이해됐어요!" 실무에서 scikit-learn의 DecisionTreeClassifier를 사용할 때, criterion='entropy'로 설정하면 바로 이 정보 이득 기반 분할이 적용됩니다.
기본값인 'gini'는 비슷하지만 조금 다른 불순도 지표를 사용합니다. 김개발 씨는 정보 이론의 개념이 머신러닝 곳곳에 녹아있다는 것을 새삼 느꼈습니다.
실전 팁
💡 - 정보 이득이 0이면 해당 속성으로 분할해도 불확실성이 줄지 않습니다
- 범주가 많은 속성은 정보 이득이 높게 나오는 경향이 있어 보정이 필요할 수 있습니다
5. 손실 함수와의 연결
김개발 씨가 드디어 궁금증의 핵심에 다다랐습니다. "그래서 이 모든 개념이 실제로 신경망 학습에서 어떻게 쓰이는 건가요?" 박시니어 씨가 웃으며 대답했습니다.
"이제 진짜 재미있는 부분이에요. 손실 함수와 연결해볼까요?"
머신러닝의 손실 함수는 모델의 예측이 얼마나 잘못되었는지를 측정합니다. 분류 문제에서 크로스 엔트로피 손실은 정보 이론에서 직접 유래했습니다.
모델이 정답에 높은 확률을 부여하도록 학습시키는 것이 곧 크로스 엔트로피를 최소화하는 것입니다.
다음 코드를 살펴봅시다.
import numpy as np
def softmax(logits):
# 수치 안정성을 위해 최댓값을 빼줍니다
exp_logits = np.exp(logits - np.max(logits))
return exp_logits / np.sum(exp_logits)
def cross_entropy_loss(logits, true_label_index):
# 소프트맥스로 확률 변환
probs = softmax(logits)
# 정답 클래스의 확률에 -log 적용
return -np.log(probs[true_label_index] + 1e-15)
# 모델의 출력 (logits)
logits = [2.0, 1.0, 0.1] # 클래스 3개에 대한 점수
true_label = 0 # 정답은 첫 번째 클래스
# 확률 변환 확인
probs = softmax(logits)
print(f"소프트맥스 확률: {probs}")
print(f"크로스 엔트로피 손실: {cross_entropy_loss(logits, true_label):.4f}")
# 학습이 진행되면서 logits이 개선된 경우
better_logits = [5.0, 0.5, 0.1]
print(f"개선된 손실: {cross_entropy_loss(better_logits, true_label):.4f}")
박시니어 씨가 화이트보드에 신경망 그림을 그렸습니다. "신경망의 마지막 층에서 나오는 값을 logits이라고 해요.
이건 아직 확률이 아닙니다." 신경망의 출력은 임의의 실수값입니다. 음수일 수도 있고, 합이 1이 아닐 수도 있습니다.
이를 확률로 바꾸기 위해 소프트맥스 함수를 사용합니다. 소프트맥스는 각 값에 지수 함수를 적용하고, 전체 합으로 나눕니다.
결과적으로 모든 값이 0과 1 사이가 되고, 합이 정확히 1이 됩니다. 코드에서 logits이 [2.0, 1.0, 0.1]일 때, 소프트맥스를 적용하면 약 [0.659, 0.242, 0.099]가 됩니다.
첫 번째 클래스에 가장 높은 확률이 부여됩니다. 이제 크로스 엔트로피 손실을 계산합니다.
정답이 첫 번째 클래스라면, 손실은 -log(0.659) = 약 0.417입니다. 학습이 진행되어 logits이 [5.0, 0.5, 0.1]로 개선되면 어떻게 될까요?
소프트맥스 결과에서 첫 번째 클래스의 확률이 더 높아지고, 손실은 약 0.007로 크게 줄어듭니다. 이것이 바로 역전파의 목표입니다.
손실을 줄이는 방향으로 가중치를 조정하면, 자연스럽게 모델이 정답에 높은 확률을 부여하게 됩니다. "선배, 그런데 왜 하필 크로스 엔트로피를 쓰는 거예요?
MSE(평균 제곱 오차)를 쓰면 안 되나요?" 좋은 질문입니다. 분류 문제에서 MSE를 사용하면 몇 가지 문제가 있습니다.
첫째, 확률의 특성을 고려하지 않습니다. 둘째, 그래디언트가 작아지는 구간이 있어 학습이 느려질 수 있습니다.
크로스 엔트로피는 확률 분포 비교에 최적화되어 있습니다. 예측 확률이 0에 가까운데 정답이 1이면 손실이 급격히 커집니다.
이 특성 덕분에 틀린 예측을 빠르게 교정할 수 있습니다. PyTorch에서 nn.CrossEntropyLoss()를 사용하면, 내부적으로 소프트맥스와 크로스 엔트로피가 결합되어 있습니다.
수치 안정성을 위해 log-softmax를 먼저 계산하는 최적화도 적용되어 있습니다. 김개발 씨가 감탄했습니다.
"정보 이론이 이렇게 직접적으로 딥러닝에 연결되는군요!"
실전 팁
💡 - PyTorch의 CrossEntropyLoss는 소프트맥스를 포함하므로, 모델 출력에 별도로 소프트맥스를 적용하면 안 됩니다
- 수치 안정성을 위해 직접 구현할 때는 log-sum-exp 트릭을 사용하세요
6. 분류 문제에서의 활용
이제 김개발 씨는 정보 이론의 개념들을 모두 배웠습니다. 마지막으로 박시니어 씨가 말했습니다.
"자, 이제 실제 분류 문제에서 이 모든 것을 종합해볼까요? 이진 분류와 다중 분류에서 어떻게 적용되는지 직접 구현해봅시다."
실제 분류 문제에서 크로스 엔트로피는 이진 분류와 다중 분류에서 조금 다르게 적용됩니다. 이진 분류에서는 Binary Cross Entropy(BCE)를, 다중 분류에서는 Categorical Cross Entropy(CCE)를 사용합니다.
두 가지 모두 정보 이론의 원리에 기반합니다.
다음 코드를 살펴봅시다.
import numpy as np
def binary_cross_entropy(y_true, y_pred):
# 이진 분류용 크로스 엔트로피
y_pred = np.clip(y_pred, 1e-15, 1 - 1e-15)
return -np.mean(
y_true * np.log(y_pred) + (1 - y_true) * np.log(1 - y_pred)
)
def categorical_cross_entropy(y_true_onehot, y_pred):
# 다중 분류용 크로스 엔트로피
y_pred = np.clip(y_pred, 1e-15, 1)
return -np.mean(np.sum(y_true_onehot * np.log(y_pred), axis=1))
# 이진 분류 예시: 스팸 메일 탐지
y_true_binary = np.array([1, 0, 1, 1, 0]) # 실제 레이블
y_pred_binary = np.array([0.9, 0.1, 0.8, 0.7, 0.3]) # 예측 확률
print(f"BCE 손실: {binary_cross_entropy(y_true_binary, y_pred_binary):.4f}")
# 다중 분류 예시: 이미지 분류 (고양이, 개, 새)
y_true_multi = np.array([[1,0,0], [0,1,0], [0,0,1]]) # 원-핫 레이블
y_pred_multi = np.array([[0.8,0.1,0.1], [0.2,0.7,0.1], [0.1,0.2,0.7]])
print(f"CCE 손실: {categorical_cross_entropy(y_true_multi, y_pred_multi):.4f}")
박시니어 씨가 마지막 강의를 시작했습니다. "실무에서 가장 많이 접하게 될 두 가지 상황을 정리해봅시다." 첫 번째는 이진 분류입니다.
스팸 메일인지 아닌지, 고객이 이탈할지 아닌지처럼 두 가지 중 하나를 예측하는 문제입니다. 이진 분류에서는 모델이 하나의 확률값만 출력합니다.
예를 들어 0.9라면 "스팸일 확률 90%"를 의미합니다. 이때 Binary Cross Entropy(BCE)를 사용합니다.
BCE 공식은 조금 특별합니다. 정답이 1일 때는 -log(p)를, 정답이 0일 때는 -log(1-p)를 계산합니다.
코드에서 y_true * np.log(y_pred) + (1 - y_true) * np.log(1 - y_pred) 부분이 이를 구현합니다. 두 번째는 다중 분류입니다.
이미지가 고양이인지, 개인지, 새인지처럼 여러 클래스 중 하나를 예측하는 문제입니다. 다중 분류에서는 모델이 각 클래스에 대한 확률을 출력합니다.
[0.8, 0.1, 0.1]이라면 "첫 번째 클래스일 확률 80%"를 의미합니다. Categorical Cross Entropy(CCE)를 사용합니다.
CCE는 앞서 배운 크로스 엔트로피와 동일합니다. 원-핫 인코딩된 레이블과 예측 확률 분포 사이의 크로스 엔트로피를 계산합니다.
"선배, 그러면 언제 어떤 걸 써야 하는지 정리해주세요!" 간단합니다. 클래스가 2개면 BCE, 3개 이상이면 CCE입니다.
하지만 실무에서는 2개인 경우에도 CCE를 쓰는 경우가 있습니다. 소프트맥스 출력을 그대로 활용할 수 있어서 코드가 일관되기 때문입니다.
PyTorch에서는 nn.BCELoss()와 nn.CrossEntropyLoss()를 사용합니다. TensorFlow에서는 binary_crossentropy와 categorical_crossentropy입니다.
주의할 점이 있습니다. PyTorch의 BCELoss는 입력이 이미 시그모이드를 통과한 확률이어야 합니다.
반면 CrossEntropyLoss는 logits을 직접 받습니다. 이 차이를 모르면 버그가 발생하기 쉽습니다.
김개발 씨가 정리했습니다. "엔트로피에서 시작해서 크로스 엔트로피, KL 발산을 거쳐 실제 손실 함수까지 연결되는 흐름이 이제 명확해졌어요!" 박시니어 씨가 미소 지었습니다.
"정보 이론을 이해하면 왜 모델이 그렇게 학습하는지, 손실 함수가 왜 그렇게 설계되었는지 깊이 있게 이해할 수 있어요. 앞으로 새로운 손실 함수를 만나도 당황하지 않을 거예요." 김개발 씨는 오늘 배운 내용을 노트에 정리하며 뿌듯한 마음으로 퇴근 준비를 했습니다.
실전 팁
💡 - 이진 분류에서 BCEWithLogitsLoss를 사용하면 시그모이드와 BCE가 결합되어 수치적으로 안정적입니다
- 클래스 불균형이 심한 경우 가중치를 부여한 손실 함수를 고려하세요
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
Helm 마이크로서비스 패키징 완벽 가이드
Kubernetes 환경에서 마이크로서비스를 효율적으로 패키징하고 배포하는 Helm의 핵심 기능을 실무 중심으로 학습합니다. Chart 생성부터 릴리스 관리까지 체계적으로 다룹니다.
보안 아키텍처 구성 완벽 가이드
프로젝트의 보안을 처음부터 설계하는 방법을 배웁니다. AWS 환경에서 VPC부터 WAF, 암호화, 접근 제어까지 실무에서 바로 적용할 수 있는 보안 아키텍처를 단계별로 구성해봅니다.
AWS Organizations 완벽 가이드
여러 AWS 계정을 체계적으로 관리하고 통합 결제와 보안 정책을 적용하는 방법을 실무 스토리로 쉽게 배워봅니다. 초보 개발자도 바로 이해할 수 있는 친절한 설명과 실전 예제를 제공합니다.
AWS KMS 암호화 완벽 가이드
AWS KMS(Key Management Service)를 활용한 클라우드 데이터 암호화 방법을 초급 개발자를 위해 쉽게 설명합니다. CMK 생성부터 S3, EBS 암호화, 봉투 암호화까지 실무에 필요한 모든 내용을 담았습니다.
AWS Secrets Manager 완벽 가이드
AWS에서 데이터베이스 비밀번호, API 키 등 민감한 정보를 안전하게 관리하는 Secrets Manager의 핵심 개념과 실무 활용법을 배워봅니다. 초급 개발자도 쉽게 따라할 수 있도록 실전 예제와 함께 설명합니다.