틀렸다는 것의 형태
요약
손실 함수(Loss Function)가 단순한 기술적 도구가 아니라 최대 가능도 추정(MLE)에서 유도되는 확률론적 결과임을 설명합니다. MSE와 Cross-Entropy가 각각 가우시안 분포와 범주형 분포를 가정했을 때 도출되는 수학적 근거를 다룹니다.
핵심 포인트
- 손실 함수는 최대 가능도 추정(MLE)의 음의 로그 가능도(NLL)로부터 유도됨
- MSE는 타겟 데이터에 가우시안 노이즈가 포함되어 있다는 가정에서 도출됨
- Cross-Entropy는 범주형 분포를 가정할 때의 음의 로그 가능도임
- 손실 함수 선택은 모델 출력 뒤에 숨겨진 확률 분포를 결정하는 과정임
세계에서 가장 우아한 신경망 (Neural Network) 구조를 설계할 수도 있겠지만, 한 가지 질문에 먼저 답하기 전까지는 그 모델은 아무것도 배우지 못할 것입니다. 정확히 무엇과 비교했을 때 틀렸다는 것인가?
그것이 바로 손실 함수 (Loss Function)입니다. 손실 함수는 네트워크 끝에 단순히 덧붙여진 기술적인 사후 고려 사항이 아닙니다. 그것은 "예측"을 "학습"으로 바꾸는 핵심 요소입니다. 이 시점부터 모든 것, 즉 모든 레이어를 통해 역전파 (Backpropagation)되는 모든 그래디언트 (Gradient)는 이 하나의 함수에 의해 생성된 숫자에서 시작됩니다. 여기서 틀린다면, 나머지 기계 장치들은 아무런 의미가 없습니다.
그러니 단순히 "회귀에는 MSE를, 분류에는 교차 엔트로피 (Cross-Entropy)를 사용하라"는 식의 경험칙을 암기하는 대신, 이러한 손실 함수들이 실제로 어디에서 유래하는지 유도해 봅시다.
손실 함수는 임의적인 것이 아닙니다 — 그것은 변장한 확률입니다
대부분의 입문용 설명에서 생략하는 사실이 있습니다. 손실 함수는 단순히 "느낌이 좋아서" 선택된 것이 아닙니다. 그것은 **최대 가능도 추정 (Maximum Likelihood Estimation, MLE)**에서 직접적으로 도출됩니다. 즉, 레이블 (Label)에 대한 확률 분포를 가정하면, 손실 함수는 단지 그 분포의 가능도 (Likelihood)에 음의 로그 (Negative Log)를 취한 것일 뿐입니다.
회귀 (Regression)부터 시작해 봅시다. 네트워크의 예측값이 약간의 노이즈가 포함된 가우시안 (Gaussian) 분포의 평균이라고 가정합니다:
$$p(y \mid x, w, \beta) = \mathcal{N}\big(\hat{y}(x, w), , 1/\beta\big)$$
전체 데이터셋에 대해 음의 로그 가능도 (Negative Log-Likelihood)를 취하고 가우시안을 전개하면, 깔끔한 결과가 나타납니다. 가중치 (Weights)에 의존하지 않는 모든 항(상수, 노이즈 분산 등)은 최적화 과정에서 사라집니다. 남는 것은 다음과 같습니다:
$$\frac{\beta}{2} \sum_{m=1}^{M} \big(y_m - \hat{y}(x_m, w)\big)^2$$
이것이 바로 평균 제곱 오차 (Mean Squared Error, MSE)입니다. "거리가 직관적으로 느껴져서" 선택된 것이 아니라, 연속적인 타겟 (Target)에 가우시안 노이즈를 가정했을 때 정확히 도출되는 결과이기 때문입니다. 만약 시험에서 "왜 회귀에 L2 손실을 사용하는가"라는 질문을 받는다면, "큰 오차에 더 큰 벌점을 주기 때문"이 아니라 이것이 실제 정답입니다.
이제 분류 (classification) 문제에 대해서도 똑같이 해봅시다. 다만 레이블 분포 (label distribution)가 가우시안 (Gaussian)이 아니라 범주형 (categorical)이라는 점이 다릅니다. 동전 던지기의 경우, 레이블 모델은 베르누이 분포 (Bernoulli distribution)가 됩니다. $K$개의 클래스의 경우, 이는 다항 베르누이 분포 (multinoulli)가 됩니다:
$$\mathfrak{C}(y \mid p) = \prod_{k} p_k^{,y_k}$$
여기에 음의 로그 가능도 (negative log-likelihood)를 취하면, 곱셈은 로그의 합으로 변합니다:
$$L(w) = -\sum_{m=1}^{M} \sum_{k} y_{k,m} , \ln \hat{y}_{k,m}$$
이것이 바로 교차 엔트로피 (cross-entropy)입니다. 유도 패턴은 동일하지만, 가정하는 분포가 다를 뿐입니다. 이런 방식으로 이해하고 나면, "어떤 손실 함수 (loss function)를 사용해야 하는가"라는 질문은 단순히 찾아보기 식 (lookup-table) 질문이 아니라 다음과 같은 질문이 됩니다. 내 출력값 뒤에 숨겨진 실제 확률론적 이야기는 무엇인가? 연속적이고 가우시안과 유사하다면 $\rightarrow$ L2. 이산적이고 범주형이라면 $\rightarrow$ 교차 엔트로피.
원-핫 인코딩 (one-hot encoding)이 단순한 형식 선택이 아닌 이유
만약 5개의 클래스가 있고 실제 레이블이 클래스 3이라면, 다음과 같이 작성합니다:
$$y = \begin{bmatrix}0\0\0\1\0\end{bmatrix}$$
설명하기에 너무 단순해 보일 수도 있지만, 이는 실제로 수학적인 역할을 수행하고 있습니다. 대신 레이블을 가공되지 않은 정수 (raw integers, 0, 1, 2, 3, 4)로 인코딩한다면, 당신은 의도치 않게 모델에게 클래스 4가 클래스 0보다 어떤 면에서 "더 크다"는 것을 알려주게 됩니다. 즉,
— 모델이 정답 클래스에 할당한 확률의 음의 로그(negative log) 값입니다. 그게 전부입니다. 원-핫(one-hot) 케이스에서 교차 엔트로피 손실 (Cross-entropy loss)은 단순히 "모델이 정답을 얼마나 의심했는가"를 나타냅니다. 확신이 있고 정답인 경우 → 손실은 0에 가깝습니다. 확신이 있지만 틀린 경우 → 손실은 무한대를 향해 폭발합니다. 이러한 비대칭성(asymmetry)이 핵심입니다. 이것이 바로 모델이 가장 확신했던 실수부터 먼저 수정하도록 강제하는 지점입니다.
Softmax와 Cross-entropy의 우아한 우연
Softmax는 네트워크의 가공되지 않은, 경계가 없는 출력 점수(logits)를 확률 분포 (probability distribution)처럼 작동하는 무언가로 변환합니다:
$$\hat{y}_k = \frac{e^{z_k}}{\sum_j e^{z_j}}$$
모든 출력은 0과 1 사이에 엄격하게 위치하며, 그 합은 정확히 1이 됩니다. 좋습니다. 하지만 Softmax 자체는 미분하기에 비용이 많이 듭니다. 분모에 있는 정규화 항 (normalization term) 때문에, 모든 출력은 모든 입력 로짓 (logit)에 의존하게 됩니다. 이는 그 기울기 (gradient)가 단순한 요소별 미분 (per-element derivative)이 아니라 전체 자코비안 행렬 (Jacobian matrix)임을 의미합니다.
여기서 진정으로 우아한 부분이 등장합니다. 당신이 훈련시킬 거의 모든 분류 네트워크 (classification network)에서 나타나는 조합인 Softmax와 교차 엔트로피 (cross-entropy)를 쌍으로 묶고, Softmax 이전의 로짓 (logits)에 대한 손실의 기울기를 구해보십시오. 모든 지수 함수 (exponentials)가 상쇄됩니다. 모든 로그 항 (log terms)도 상쇄됩니다. 복잡했던 자코비안 행렬은 다음과 같이 붕괴됩니다:
$$\frac{\partial L}{\partial z_k} = \hat{y}_k - y_k$$
예측된 확률에서 실제 원-핫 레이블 (one-hot label)을 뺀 값입니다. 이것이 기울기의 전부입니다. 지수 함수도, 행렬도 없이, 그저 벡터 뺄셈일 뿐입니다.
이것이 얼마나 기묘한 일인지 잠시 생각해보세요. 당신은 지수 정규화 (exponential normalization)와 로그 (logarithm)로 시작했고, 진정으로 비선형적이며 겉보기에 서로 관련 없어 보이는 두 함수를 겹쳐 놓았지만, 그 미분값은 초등학생도 계산할 수 있을 만큼 단순해졌습니다. 이것은 편의성에 의해 결정된 우연이 아닙니다. Softmax가 범주형 가능도 (categorical likelihood)를 위한 올바른 역 링크 함수 (inverse link function)이며, 교차 엔트로피 (cross-entropy)가 동일한 가능도에 대한 올바른 손실 함수 (loss function)이기 때문에 발생하는 직접적인 결과입니다. 수학적으로 일관된 쌍을 선택하면, 미적분학이 그 보상을 주는 것입니다.
실무적으로 이것은 딥러닝 프레임워크가 내부적으로 Softmax와 교차 엔트로피를 하나의 연산으로 결합하는 이유이기도 합니다. softmax_cross_entropy_with_logits 스타일의 구현은 Softmax를 계산하고, 로그를 취한 뒤, 이 둘을 각각 따로 역전파 (backpropagating)하는 불안정하고 낭비적인 경로를 건너뜁니다.
손실 표면 (loss surface) 내려가기
손실 값을 구했다면, 이제 실제로 이를 줄여야 합니다. 업데이트 규칙은 기만적일 정도로 간단합니다:
$$W_{\text{new}} = W - \eta \cdot \frac{\partial L}{\partial W}$$
기울기 (gradient)는 가장 가파른 증가 방향을 가리킵니다. 따라서 우리는 아래로 내려가기 위해 이를 빼줍니다. 학습률 (learning rate) $\eta$는 보폭의 길이를 조절합니다. 너무 크면 골짜기 바닥을 지나쳐 버려, 바닥에 안착하는 대신 벽 사이를 튕겨 다니게 됩니다. 최악의 경우 손실이 완전히 발산 (diverge)할 수도 있습니다. 너무 작으면 최소값(minimum)을 향해 너무 느리게 기어가기 때문에 합리적인 단계 내에 도달하지 못할 수도 있고, 혹은 탈출할 모멘텀 (momentum) 없이 도중에 나타난 얕은 웅덩이에 갇혀버릴 수도 있습니다.
너무 멀리 가서 진동하거나, 너무 적게 가서 기어가는 것 — 이 긴장 관계야말로 나머지 최적화 (optimization) 연구가 존재하는 이유 그 자체입니다.
첫 번째 갈림길은 각 그래디언트 단계 (gradient step)를 계산하기 위해 _얼마나 많은 데이터_를 사용하는가입니다. 매번 전체 데이터셋을 사용하면 (배치 경사 하강법 (batch gradient descent)) 그래디언트 추정치가 매끄럽고 정확하지만, 각 단계가 고통스러울 정도로 느립니다. 단 하나의 무작위 샘플을 사용하면 (확률적 경사 하강법 (stochastic gradient descent)) 각 단계는 거의 즉각적이지만, 매우 심하게 노이즈가 발생합니다. 미니 배치 경사 하강법 (Mini-batch gradient descent) — 단계당 수십 개에서 수백 개의 샘플 사용 — 은 거의 모든 사람이 실제로 사용하는 실질적인 타협안입니다. 단계당 충분히 빠르고, 실제적인 진전을 이룰 만큼 충분히 매끄러우며, 공교롭게도 GPU가 데이터를 공급받는 방식과 완벽하게 일치합니다.
옵티마이저 (optimizer)에 메모리와 자기 조절 기능 부여하기
일반적인 경사 하강법 (gradient descent)은 메모리가 없습니다. 모든 단계는 오직 현재의 그래디언트에만 반응하며 그 이전에 일어난 모든 것을 잊어버립니다. **모멘텀 (Momentum)**은 과거 그래디언트의 실행 중인 감쇠 평균 (running, decaying average)을 유지함으로써 이 문제를 해결합니다:
$$v^{(k)} = \mu , v^{(k-1)} + \nabla L(W^{(k)})$$
매 단계마다 멈췄다 다시 시작하는 점 질량 (point mass) 대신, 언덕 아래로 굴러 내려가는 무거운 공을 상상해 보세요. 그래디언트가 계속 같은 방향을 가리키는 방향에서는 공이 속도를 쌓아갑니다. 그래디언트의 부호가 계속 바뀌는 방향 — 손실 표면 (loss surface)에서 좁고 가파른 벽을 가진 협곡의 전형적인 증상 — 에서는 한 방향으로 축적된 모멘텀이 다른 방향의 모멘텀을 상쇄하여 진동 (oscillation)이 감쇄됩니다. 네스테로프 (Nesterov) 변형은 모멘텀이 이미 당신을 이끌고 있는 앞서 보기 (look-ahead) 위치에서 그래디언트를 계산함으로써 이를 더욱 정교하게 다듬으며, 경로를 약간 더 일찍 수정하고 상태가 좋지 않은 지형 (badly-conditioned landscapes)에서 진동을 더욱 줄여줍니다.
하지만 모멘텀 (Momentum)은 여전히 네트워크의 모든 파라미터에 대해 하나의 전역 학습률 (global learning rate)을 사용합니다. 그러나 모든 파라미터가 동일한 속도로 업데이트될 필요는 없습니다. 어떤 특징 (features)은 끊임없이 활성화되는 반면, 어떤 것들은 드물게 활성화됩니다. AdaGrad는 각 파라미터의 누적된 기울기 제곱 (accumulated squared gradient)을 추적하고, 개별 학습률을 그에 반비례하게 스케일링함으로써 이 문제를 해결했습니다. 즉, 기울기가 크고 빈번한 파라미터는 부드럽게 제어되고, 드문 파라미터는 상대적으로 더 큰 보폭을 갖게 됩니다. 이 방식의 결함은 누적값이 계속해서 커지기만 하여, 실제 학습이 완료되었는지 여부와 상관없이 학습률이 결국 0을 향해 감쇠 (decay)한다는 점입니다. RMSProp은 누적값을 영원히 더하는 대신 시간이 지남에 따라 감쇠시킴으로써 이 문제를 해결하며, 이를 통해 아주 오래된 기울기보다 최근의 기울기가 더 중요하게 작용하도록 합니다.
Adam — 실무에서 가장 흔히 접하게 될 옵티마이저 (optimizer) — 는 이 두 가지 아이디어를 결합합니다. 방향을 위한 모멘텀 (momentum) 항과 보폭을 위한 RMSProp 방식의 적응형 스케일 (adaptive scale)을 결합하되, 두 항 모두 0에서 시작하기 때문에 편향 수정 (bias correction)을 추가했습니다. 이것은 마법이 아니며, 완벽하지 않다는 점을 알아둘 가치가 있습니다. Adam의 원래 수렴 증명 (convergence proof)에는 실제 버그가 포함되어 있었음이 밝혀졌으며, 이후 AMSGrad라고 불리는 변형 모델을 통해 수정되었습니다. 또한 많은 최신 성능 (state-of-the-art) 결과물들을 보면, Adam이 별도의 설정 없이도 더 예측 가능하게 수렴함에도 불구하고, 네스테로프 모멘텀 (Nesterov momentum)을 적용한 정교하게 튜닝된 학습률 스케줄 (learning rate schedule)의 일반 SGD가 최종 성능 면에서 여전히 Adam을 근소하게 앞서기도 합니다. 솔직한 권장 사항이자 기억해 둘 만한 가치가 있는 조언은 다음과 같습니다: 미니 배치 SGD (mini-batch SGD)와 모멘텀으로 시작하고, 데이터에 대한 감을 잡은 후에 Adam을 시도하며, 어떤 것을 선택하든 항상 주의를 기울이십시오.
자신의 역전파 (backpropagation)를 신뢰하기
이 장에는 그 어떤 옵티마이저만큼이나 중요한, 조금 더 조용하고 덜 화려한 아이디어가 숨겨져 있습니다. 그것은 바로 여러분의 역전파 (backprop) 구현이 실제로 정확한지 어떻게 알 수 있는가 하는 점입니다.
미분을 전혀 사용하지 않는 버전, 즉 직접 근사된 미분의 정의 (definition of a derivative)를 통해 이를 검증할 수 있습니다:
$$\frac{\partial f}{\partial x} \approx \frac{f(x+\epsilon) - f(x-\epsilon)}{2\epsilon}$$ 이 중심화된 버전은 단순한 단방향 버전 $\frac{f(x+\epsilon) - f(x)}{\epsilon}$보다 의도적으로 더 정확합니다. 왜냐하면 빼기 과정에서 1차 오차 항들이 상쇄되어, $\epsilon$이 작아짐에 따라 오차가 선형적(linearly)으로 줄어드는 것이 아니라 이차적(quadratically)으로 줄어들기 때문입니다. 이 방식으로 기울기(gradient)를 계산하고, 이를 분석적인 역전파(analytical backprop) 구현 결과와 비교해 보세요. 만약 두 값이 매우 가깝게 일치한다면, 체인 룰(chain rule)이 올바르게 구현되었다는 확실한 증거를 얻은 것입니다. 그렇지 않다면 버그가 있다는 뜻이며, 이 경우 수 시간 또는 수일 동안 그 위에 학습을 진행하며 시간을 낭비하기 전에 발견할 수 있습니다.
이는 사소한 각주(footnote) 수준의 문제가 아닙니다. 역전파(Backprop) 관련 버그는 악명 높게 조용합니다. 손상된 기울기는 프로그램을 중단시키지 않고, 그저 조용히 더 나쁜 네트워크를 학습시킬 뿐이며, 우리는 실제 원인을 찾지 못하면서도 무언가
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기